3 #include <boost/variant.hpp>
11 std::vector<bool> isAllocated;
12 static constexpr ClockVariables initialClock = 1;
15 ClockVariables newestClock;
20 std::vector<Interval> intervals;
27 : intervals({std::move(interval)}) {
29 intervals[0].lowerBound.first *= -1;
40 :
Zone(std::move(zone)) {
44 assert(value.cols() == value.rows());
45 assert(value.cols() > 1);
47 isAllocated.resize(value.cols(),
false);
48 if (currentNewestClock) {
49 newestClock = currentNewestClock;
50 for (ClockVariables x = currentNewestClock + 1; x < value.cols(); x++) {
54 newestClock = value.cols() - 1;
56 isAllocated[0] =
true;
57 isAllocated[initialClock] =
true;
58 isAllocated[newestClock] =
true;
62 ClockVariables
alloc(
const std::pair<double, bool> &upperBound,
63 const std::pair<double, bool> &lowerBound) {
64 static constexpr Bounds infinity =
65 Bounds(std::numeric_limits<double>::infinity(),
false);
66 ClockVariables newClock;
67 #define likely(x) __builtin_expect(!!(x), 1)
69 if (likely(useInterval && intervals.size() == 1)) {
71 if (useInterval && intervals.size() == 1) {
75 intervals.emplace_back(std::move(lowerBound), std::move(upperBound));
78 intervals.emplace_back(
79 std::min(intervals[0].upperBound + intervals[1].lowerBound,
81 intervals[1].upperBound + intervals[0].lowerBound);
82 return newestClock = 2;
83 }
else if (useInterval) {
86 isAllocated.resize(4,
true);
88 value.fill(Bounds(infinity));
89 for (
int i = 0; i < 4; i++) {
90 value(i, i) = Bounds{0,
true};
92 value(1, 0) = intervals[0].upperBound;
93 value(0, 1) = intervals[0].lowerBound;
94 value(2, 0) = intervals[1].upperBound;
95 value(0, 2) = intervals[1].lowerBound;
96 value(2, 1) = intervals[2].upperBound;
97 value(1, 2) = intervals[2].lowerBound;
98 value(2, 3) = Bounds{0,
true};
99 value(3, 0) = std::move(upperBound);
100 value(0, 3) = std::move(lowerBound);
105 std::find(isAllocated.begin(), isAllocated.end(),
false);
107 assert(value.cols() == value.rows());
110 if (newPos != isAllocated.end()) {
112 newClock = newPos - isAllocated.begin();
118 value.conservativeResize(value.cols() + 1, value.cols() + 1);
119 newClock = value.cols() - 1;
120 isAllocated.resize(value.cols());
121 value.row(newClock).fill(infinity);
122 value.col(newClock).fill(infinity);
123 value(newClock, newClock) = Bounds(0,
true);
125 isAllocated[newClock] =
true;
126 value(newClock, 0) = std::move(upperBound);
127 value(0, newClock) = std::move(lowerBound);
128 value(newClock, newestClock) = Bounds(infinity);
129 value(newestClock, newClock) = {0,
true};
131 assert(value.cols() == value.rows());
134 for (
int i = 0; i < value.rows(); i++) {
140 std::min(value(i, newClock),
141 (value.row(i) + value.col(newClock).transpose()).minCoeff());
143 for (
int x = 0; x < value.rows(); x++) {
144 for (
int j = 0; j < value.cols(); j++) {
146 std::min(value(newClock, j), value(newClock, x) + value(x, j));
149 return newestClock = newClock;
153 update(
const std::vector<boost::variant<double, ClockVariables>> &resetTime) {
158 assert(value.cols() == value.rows());
160 std::fill(isAllocated.begin(), isAllocated.end(),
false);
161 isAllocated[0] =
true;
162 isAllocated[initialClock] =
true;
163 isAllocated[newestClock] =
true;
164 for (
auto rtime : resetTime) {
165 const ClockVariables *p_x = boost::get<ClockVariables>(&rtime);
167 isAllocated[*p_x] =
true;
170 for (ClockVariables x = 1; x < value.cols(); x++) {
171 if (!isAllocated[x]) {
177 void toAns(
Zone &ansZone)
const {
178 ansZone = Zone::zero(3);
180 if (intervals.size() < 3) {
183 ansZone.value(0, 1) = intervals[0].lowerBound;
184 ansZone.value(1, 0) = intervals[0].upperBound;
185 ansZone.value(0, 2) = intervals[1].lowerBound;
186 ansZone.value(2, 0) = intervals[1].upperBound;
187 ansZone.value(1, 2) = intervals[2].lowerBound;
188 ansZone.value(2, 1) = intervals[2].upperBound;
190 ansZone.value(0, 1) = value(0, 1);
191 ansZone.value(1, 0) = value(1, 0);
192 ansZone.value(0, 2) = value(0, newestClock);
193 ansZone.value(2, 0) = value(newestClock, 0);
194 ansZone.value(1, 2) = value(1, newestClock);
195 ansZone.value(2, 1) = value(newestClock, 1);
204 void tighten(
const ClockVariables x,
const ClockVariables y, Bounds c) {
206 if (x == 0 && y == 1) {
207 intervals[0].lowerBound = std::min(intervals[0].lowerBound, c);
208 if (intervals.size() > 1) {
210 intervals[1].lowerBound =
211 std::min(intervals[1].lowerBound,
212 intervals[0].lowerBound + intervals[2].lowerBound);
214 intervals[2].upperBound =
215 std::min(intervals[2].upperBound,
216 intervals[1].upperBound + intervals[0].lowerBound);
218 }
else if (x == 1 && y == 0) {
219 intervals[0].upperBound = std::min(intervals[0].upperBound, c);
220 if (intervals.size() > 1) {
222 intervals[1].upperBound =
223 std::min(intervals[1].upperBound,
224 intervals[2].upperBound + intervals[0].upperBound);
226 intervals[2].lowerBound =
227 std::min(intervals[2].lowerBound,
228 intervals[0].upperBound + intervals[1].lowerBound);
230 }
else if (x == 0 && y == 2) {
231 intervals[1].lowerBound = std::min(intervals[1].lowerBound, c);
232 intervals[0].lowerBound =
233 std::min(intervals[0].lowerBound,
234 intervals[1].lowerBound + intervals[2].upperBound);
235 intervals[2].lowerBound =
236 std::min(intervals[2].lowerBound,
237 intervals[1].lowerBound + intervals[0].upperBound);
238 }
else if (x == 2 && y == 0) {
239 intervals[1].upperBound = std::min(intervals[1].upperBound, c);
240 intervals[0].upperBound =
241 std::min(intervals[0].upperBound,
242 intervals[1].upperBound + intervals[2].lowerBound);
243 intervals[2].upperBound =
244 std::min(intervals[2].upperBound,
245 intervals[1].upperBound + intervals[0].lowerBound);
246 }
else if (x == 1 && y == 2) {
247 intervals[2].lowerBound = std::min(intervals[2].lowerBound, c);
248 intervals[0].upperBound =
249 std::min(intervals[0].upperBound,
250 intervals[1].upperBound + intervals[2].lowerBound);
251 intervals[1].lowerBound =
252 std::min(intervals[1].lowerBound,
253 intervals[2].lowerBound + intervals[0].lowerBound);
254 }
else if (x == 2 && y == 1) {
255 intervals[2].upperBound = std::min(intervals[2].upperBound, c);
256 intervals[1].upperBound =
257 std::min(intervals[1].upperBound,
258 intervals[2].upperBound + intervals[0].upperBound);
259 intervals[0].lowerBound =
260 std::min(intervals[0].lowerBound,
261 intervals[1].lowerBound + intervals[2].upperBound);
264 value(x, y) = std::min(value(x, y), c);
265 if (value(x, y) == c && newestClock != initialClock) {
273 const ClockVariables reset = 0) {
275 case Constraint::Order::lt:
276 tighten(x, reset, Bounds{c.c,
false});
278 case Constraint::Order::le:
279 tighten(x, reset, Bounds{c.c,
true});
281 case Constraint::Order::gt:
282 tighten(reset, x, Bounds{-c.c,
false});
284 case Constraint::Order::ge:
285 tighten(reset, x, Bounds{-c.c,
true});
292 case Constraint::Order::lt:
293 tighten(x, 0, Bounds{c.c + t,
false});
295 case Constraint::Order::le:
296 tighten(x, 0, Bounds{c.c + t,
true});
298 case Constraint::Order::gt:
299 tighten(0, x, Bounds{-c.c - t,
false});
301 case Constraint::Order::ge:
302 tighten(0, x, Bounds{-c.c - t,
true});
308 const std::vector<Constraint> &constraints,
309 const std::vector<boost::variant<double, ClockVariables>> &resetTime) {
311 const double *p_resetDouble = boost::get<double>(&resetTime[guard.x]);
312 const ClockVariables *p_resetClock =
313 boost::get<ClockVariables>(&resetTime[guard.x]);
315 tighten(newestClock, guard, *p_resetDouble);
317 tighten(newestClock, guard, *p_resetClock);
323 tighten(
const std::vector<Constraint> &constraints,
324 const std::vector<boost::variant<double, ClockVariables>> &resetTime,
327 const double *p_resetDouble = boost::get<double>(&resetTime[guard.x]);
328 const ClockVariables *p_resetClock =
329 boost::get<ClockVariables>(&resetTime[guard.x]);
332 if (!guard.satisfy(t - *p_resetDouble)) {
334 static constexpr Bounds negInfinity =
335 Bounds(-std::numeric_limits<double>::infinity(),
false);
336 intervals[0].lowerBound = negInfinity;
343 case Constraint::Order::lt:
344 tighten(0, *p_resetClock, Bounds{guard.c - t,
false});
346 case Constraint::Order::le:
347 tighten(0, *p_resetClock, Bounds{guard.c - t,
true});
349 case Constraint::Order::gt:
350 tighten(*p_resetClock, 0, Bounds{t - guard.c,
false});
352 case Constraint::Order::ge:
353 tighten(*p_resetClock, 0, Bounds{t - guard.c,
true});
360 bool isSatisfiableCanonized() {
362 return std::all_of(intervals.begin(), intervals.end(),
364 return interval.upperBound + interval.lowerBound >=
368 return (value + value.transpose()).minCoeff() >= Bounds(0.0,
true);
372 void deallocate(
const ClockVariables x) {
373 static constexpr Bounds infinity =
374 Bounds(std::numeric_limits<double>::infinity(),
false);
375 static constexpr Bounds zero = Bounds(0,
true);
376 value.col(x).fill(infinity);
377 value.row(x).fill(infinity);
The implementation of the class Interval and related functions.
A constraint in a guard of transitions.
Definition: constraint.hh:16
Class for an interval.
Definition: interval.hh:15
Implementation of a zone with DBM.
Definition: zone.hh:43
void makeUnsat()
make the zone unsatisfiable
Definition: zone.hh:169