LearnTA  0.0.1
timed_condition.hh
1 #pragma once
2 
3 #include <utility>
4 #include <deque>
5 #include <iostream>
6 
7 #include "zone.hh"
8 #include "juxtaposed_zone.hh"
9 #include "timed_automaton.hh"
10 
11 namespace learnta {
23  protected:
25 
26  explicit TimedCondition(Zone &&zone) : zone(zone) {}
27 
28  public:
29  TimedCondition() : zone(Zone::zero(2)) {}
30 
37  explicit TimedCondition(const std::vector<double> &accumulatedDuration) {
38  this->zone = Zone::top(accumulatedDuration.size() + 1);
39  for (std::size_t i = 0; i < accumulatedDuration.size(); ++i) {
40  for (std::size_t j = i; j < accumulatedDuration.size(); ++j) {
41  // T_{i, j} = accumulatedDuration.at(i) - accumulatedDuration.at(j + 1)
42  const auto concreteDifference = accumulatedDuration.at(i) -
43  ((j + 1 < accumulatedDuration.size()) ? accumulatedDuration.at(j + 1) : 0);
44  if (std::floor(concreteDifference) == concreteDifference) {
45  this->restrictUpperBound(i, j, Bounds{concreteDifference, true}, true);
46  this->restrictLowerBound(i, j, Bounds{-concreteDifference, true}, true);
47  } else {
48  this->restrictUpperBound(i, j, Bounds{std::floor(concreteDifference) + 1, false}, true);
49  this->restrictLowerBound(i, j, Bounds{-std::floor(concreteDifference), false}, true);
50  }
51  }
52  }
53  }
54 
61  static TimedCondition makeExact(const std::vector<double> &accumulatedDuration) {
62  TimedCondition result{Zone::top(accumulatedDuration.size() + 1)};
63  for (std::size_t i = 0; i < accumulatedDuration.size(); ++i) {
64  for (std::size_t j = i; j < accumulatedDuration.size(); ++j) {
65  // T_{i, j} = accumulatedDuration.at(i) - accumulatedDuration.at(j + 1)
66  const auto concreteDifference = accumulatedDuration.at(i) -
67  ((j + 1 < accumulatedDuration.size()) ? accumulatedDuration.at(j + 1) : 0);
68  result.restrictUpperBound(i, j, Bounds{concreteDifference, true}, true);
69  result.restrictLowerBound(i, j, Bounds{-concreteDifference, true}, true);
70  }
71  }
72 
73  return result;
74  }
75 
79  static TimedCondition empty() {
80  TimedCondition timedCondition;
81  // The size of the DBM is 2 for \f$\tau_0\f$ and the special dimension for the constant zero.
82  timedCondition.zone = Zone::zero(2);
83  return timedCondition;
84  }
85 
89  [[nodiscard]] size_t size() const {
90  return this->zone.getNumOfVar();
91  }
92 
98  [[nodiscard]] bool isSimple() const {
99  for (int i = 0; i < zone.value.cols(); i++) {
100  for (int j = i + 1; j < zone.value.cols(); j++) {
101  // Note: zone.value(i, j) is not larger than zone.value(i, j)
102  Bounds upperBound = zone.value(i, j); // i - j \le (c, s)
103  Bounds lowerBound = zone.value(j, i); // j - i \le (c, s)
104  if ((!learnta::isPoint(upperBound, lowerBound)) and (!isUnitOpen(upperBound, lowerBound))) {
105  return false;
106  }
107  }
108  }
109  return true;
110  }
111 
152  [[nodiscard]] TimedCondition operator+(const TimedCondition &another) const {
153  const size_t N = this->size();
154  const size_t M = another.size();
155  Zone result = Zone::top(N + M);
156  // Copy \f$A_{(0, 0), (N + 1, N + 1)}\f$ to \f$C_{(0, 0), (N + 1, N + 1)}\f$.
157  result.value.block(0, 0, N + 1, N + 1) = this->zone.value;
158  for (std::size_t i = N + 1; i < N + M; ++i) {
159  // Copy \f$A_{(1, 0), (N, 1)}\f$ to \f$C_{(1, i), (N, 1)}\f$ for each \f$i \in \{N, N + 1, \dots, N + M - 1\}\f$.
160  result.value.block(1, i, N, 1) = this->zone.value.block(1, 0, N, 1);
161  // Copy \f$A_{(0, 1), (1, N)}\f$ to \f$C_{(i, 1), (1, N)}\f$ for each \f$i \in \{N, N + 1, \dots, N + M - 1\}\f$.
162  result.value.block(i, 1, 1, N) = this->zone.value.block(0, 1, 1, N);
163  }
164  if (M >= 2) {
165  // Copy \f$B_{(2, 2), (M - 1, M - 1)}\f$ to \f$C_{(N + 1, N + 1), (M - 1, M - 1)}\f$.
166  result.value.block(N + 1, N + 1, M - 1, M - 1) = another.zone.value.block(2, 2, M - 1, M - 1);
167  // Copy \f$B_{(2, 0), (M - 1, 1)}\f$ to \f$C_{(N + 1, 0), (M - 1, 1)}\f$.
168  result.value.block(N + 1, 0, M - 1, 1) = another.zone.value.block(2, 0, M - 1, 1);
169  // Copy \f$B_{(0, 2), (1, M - 1)}\f$ to \f$C_{(0, N + 1), (1, M - 1)}\f$.
170  result.value.block(0, N + 1, 1, M - 1) = another.zone.value.block(0, 2, 1, M - 1);
171  }
172  for (std::size_t i = 1; i <= N; ++i) {
173  // Add \f$B_{(2, 1), (M - 1, 1)}\f$ to \f$C_{(N + 1, i), (M - 1, 1)}\f$ for each \f$i \in \{1, \dots, N\}\f$.
174  result.value.block(N + 1, i, M - 1, 1).array() += another.zone.value.block(2, 1, M - 1, 1).array();
175  // Add \f$B_{(1, 2), (1, M - 1)}\f$ to \f$C_{(i, N + 1), (1, M - 1)}\f$ for each \f$i \in \{1, \dots, N\}\f$.
176  result.value.block(i, N + 1, 1, M - 1).array() += another.zone.value.block(1, 2, 1, M - 1).array();
177  }
178  // Add \f$B_{(1, 0)}\f$ to \f$C_{(1, 0), (N, 1)}\f$.
179  result.value.block(1, 0, N, 1).array() += another.zone.value(1, 0);
180  // Add \f$B_{(0, 1)}\f$ to \f$C_{(0, 1), (1, N)}\f$.
181  result.value.block(0, 1, 1, N).array() += another.zone.value(0, 1);
182 
183  result.canonize();
184 
185  return TimedCondition{std::move(result)};
186  }
187 
194  [[nodiscard]] JuxtaposedZone operator^(const TimedCondition &another) const {
195  return JuxtaposedZone{this->zone, another.zone};
196  }
197 
203  [[nodiscard]] JuxtaposedZone juxtaposeRight(const TimedCondition &right, Eigen::Index commonVariableSize) const {
204  return JuxtaposedZone{this->zone, right.zone, commonVariableSize};
205  }
206 
212  [[nodiscard]] JuxtaposedZone juxtaposeLeft(const TimedCondition &left, Eigen::Index commonVariableSize) const {
213  return JuxtaposedZone{left.zone, this->zone, commonVariableSize};
214  }
215 
219  [[nodiscard]] Bounds getLowerBound(std::size_t i, std::size_t j) const {
220  assert(0 <= i && i < this->size());
221  assert(0 <= j && j < this->size());
222  if (j == this->size() - 1) {
223  return this->zone.value(0, i + 1);
224  } else {
225  return this->zone.value(j + 2, i + 1);
226  }
227  }
228 
232  [[nodiscard]] Bounds getUpperBound(std::size_t i, std::size_t j) const {
233  assert(0 <= i && i < this->size());
234  assert(0 <= j && j < this->size());
235  if (j == this->size() - 1) {
236  return this->zone.value(i + 1, 0);
237  } else {
238  return this->zone.value(i + 1, j + 2);
239  }
240  }
241 
247  void restrictLowerBound(std::size_t i, std::size_t j, Bounds lowerBound, bool force = false) {
248  assert(0 <= i && i < this->size());
249  assert(0 <= j && j < this->size());
250  if (j == this->size() - 1) {
251  this->zone.value(0, i + 1) = force ? lowerBound : std::min(lowerBound, this->zone.value(0, i + 1));
252  } else {
253  this->zone.value(j + 2, i + 1) = force ? lowerBound : std::min(lowerBound, this->zone.value(j + 2, i + 1));
254  }
255  this->zone.canonize();
256  }
257 
263  void restrictUpperBound(std::size_t i, std::size_t j, Bounds upperBound, bool force = false) {
264  assert(0 <= i && i < this->size());
265  assert(0 <= j && j < this->size());
266  if (j == this->size() - 1) {
267  this->zone.value(i + 1, 0) = force ? upperBound : std::min(upperBound, this->zone.value(i + 1, 0));
268  } else {
269  this->zone.value(i + 1, j + 2) = force ? upperBound : std::min(upperBound, this->zone.value(i + 1, j + 2));
270  }
271  this->zone.canonize();
272  }
273 
277  void convexHullAssign(const TimedCondition &condition) {
278  this->zone.value = this->zone.value.cwiseMax(condition.zone.value);
279  }
280 
284  [[nodiscard]] TimedCondition convexHull(const TimedCondition &condition) const {
285  return TimedCondition{Zone{this->zone.value.cwiseMax(condition.zone.value)}};
286  }
287 
299  void enumerate(std::vector<TimedCondition> &simpleConditions) const {
300  if (this->isSimple()) {
301  simpleConditions = {*this};
302  return;
303  }
304  std::vector<TimedCondition> currentConditions = {*this};
305  for (std::size_t i = 0; i < this->size(); i++) {
306  for (std::size_t j = i; j < this->size(); j++) {
307  std::vector<TimedCondition> nextConditions;
308  for (const TimedCondition &timedCondition: currentConditions) {
309  if (timedCondition.isSimple()) {
310  simpleConditions.push_back(timedCondition);
311  continue;
312  }
313  auto lowerBound = timedCondition.getLowerBound(i, j);
314  const auto upperBound = timedCondition.getUpperBound(i, j);
315  if (learnta::isPoint(upperBound, lowerBound) or isUnitOpen(upperBound, lowerBound)) {
316  nextConditions.push_back(timedCondition);
317  } else {
318  Bounds currentUpperBound = lowerBound.second ? -lowerBound : std::make_pair(-lowerBound.first + 1, false);
319  while (currentUpperBound <= upperBound) {
320  auto currentTimedCondition = timedCondition;
321  currentTimedCondition.restrictLowerBound(i, j, lowerBound, false);
322  currentTimedCondition.restrictUpperBound(i, j, currentUpperBound, false);
323  if (lowerBound.second) {
324  currentUpperBound = {-lowerBound.first + 1, false};
325  lowerBound.second = false;
326  } else {
327  currentUpperBound = std::make_pair(-lowerBound.first + 1, true);
328  lowerBound = {lowerBound.first - 1, true};
329  }
330  if (currentTimedCondition.isSimple()) {
331  simpleConditions.push_back(currentTimedCondition);
332  } else {
333  nextConditions.push_back(currentTimedCondition);
334  }
335  }
336  }
337  }
338  currentConditions = std::move(nextConditions);
339  if (currentConditions.empty()) {
340  return;
341  }
342  }
343  }
344  }
345 
357  [[nodiscard]] std::vector<TimedCondition> enumerate() const {
358  std::vector<TimedCondition> simpleConditions;
359  this->enumerate(simpleConditions);
360 
361  return simpleConditions;
362  }
363 
367  [[nodiscard]] TimedCondition successor(const std::deque<ClockVariables> &variables) const {
368  Zone result = this->zone;
369 
370  for (const auto i: variables) {
371  // Bound of \f$\mathbb{T}_{i,N}
372  Bounds &upperBound = result.value(i + 1, 0);
373  Bounds &lowerBound = result.value(0, i + 1);
374  if (lowerBound.second) {
375  upperBound.first++;
376  upperBound.second = false;
377  lowerBound.second = false;
378  } else {
379  lowerBound.first--;
380  lowerBound.second = true;
381  upperBound.second = true;
382  }
383  }
384 
385  return TimedCondition(std::move(result));
386  }
387 
391  void successorAssign(const std::deque<ClockVariables> &variables) {
392  for (const auto i: variables) {
393  // Bound of \f$\mathbb{T}_{i,N}
394  Bounds &upperBound = this->zone.value(i + 1, 0);
395  Bounds &lowerBound = this->zone.value(0, i + 1);
396  if (lowerBound.second) {
397  upperBound.first++;
398  upperBound.second = false;
399  lowerBound.second = false;
400  } else {
401  lowerBound.first--;
402  lowerBound.second = true;
403  upperBound.second = true;
404  }
405  }
406  }
407 
412 
413  for (std::size_t i = 0; i < this->zone.getNumOfVar(); i++) {
414  // Bound of \f$\mathbb{T}_{i,N}
415  Bounds &upperBound = this->zone.value(i + 1, 0);
416  if (upperBound.second) {
417  upperBound = Bounds{std::numeric_limits<double>::max(), false};
418  }
419  }
420  }
421 
426  for (std::size_t i = 0; i < this->zone.getNumOfVar(); i++) {
427  // Bound of \f$\mathbb{T}_{i,N}
428  this->zone.value(i + 1, 0) = Bounds{std::numeric_limits<double>::max(), false};
429  }
430  }
431 
435  [[nodiscard]] TimedCondition predecessor(const std::deque<ClockVariables> &variables) const {
436  Zone result = this->zone;
437 
438  for (const auto i: variables) {
439  // Bound of \f$\mathbb{T}_{0, i} = \mathbb{T}_{0, N} - \mathbb{T}_{i + 1, N}\f$
440  Bounds &upperBound = result.value(1, (i + 2) % result.value.cols());
441  Bounds &lowerBound = result.value((i + 2) % result.value.cols(), 1);
442  if (learnta::isPoint(upperBound, lowerBound)) {
443  upperBound.first++;
444  upperBound.second = false;
445  lowerBound.second = false;
446  } else {
447  lowerBound.first--;
448  lowerBound.second = true;
449  upperBound.second = true;
450  }
451  }
452 
453  return TimedCondition(std::move(result));
454  }
455 
459  [[nodiscard]] TimedCondition prefix(const std::deque<ClockVariables> &variables) const {
460  Zone result = this->zone;
461 
462  for (const auto i: variables) {
463  // Bound of \f$\mathbb{T}_{i, N}
464  Bounds &upperBound = result.value(i + 1, 0);
465  Bounds &lowerBound = result.value(0, i + 1);
466  if (learnta::isPoint(upperBound, lowerBound)) {
467  upperBound.second = false;
468  lowerBound.first++;
469  lowerBound.second = false;
470  } else {
471  lowerBound.second = true;
472  upperBound.first--;
473  upperBound.second = true;
474  }
475  }
476 
477  return TimedCondition(std::move(result));
478  }
479 
483  [[nodiscard]] TimedCondition suffix(const std::deque<ClockVariables> &variables) const {
484  Zone result = this->zone;
485 
486  for (const auto i: variables) {
487  // Bound of \f$\mathbb{T}_{0, i}
488  Bounds &upperBound = (i == this->size() - 1) ? result.value(1, 0) : result.value(1, i + 2);
489  Bounds &lowerBound = (i == this->size() - 1) ? result.value(0, 1) : result.value(i + 2, 1);
490  if (learnta::isPoint(upperBound, lowerBound)) {
491  upperBound.second = false;
492  lowerBound.first++;
493  lowerBound.second = false;
494  } else {
495  lowerBound.second = true;
496  upperBound.first--;
497  upperBound.second = true;
498  }
499  }
500 
501  return TimedCondition(std::move(result));
502  }
503 
507  [[nodiscard]] TimedCondition extendN() const {
508  TimedCondition result = *this;
509  const auto N = result.zone.value.cols();
510  result.zone.value.conservativeResize(N + 1, N + 1);
511  result.zone.value.col(N) = result.zone.value.col(0);
512  result.zone.value.row(N) = result.zone.value.row(0);
513  // Add \f$x_n = x_{n+1}\f$
514  result.zone.value(N, 0) = {0, true};
515  result.zone.value(0, N) = {0, true};
516 
517  return result;
518  }
519 
523  [[nodiscard]] TimedCondition removeN() const {
524  TimedCondition result = *this;
525  const auto N = result.zone.value.cols();
526  result.zone.value.conservativeResize(N - 1, N - 1);
527 
528  return result;
529  }
530 
535  [[nodiscard]] TimedCondition removeZero() const {
536  TimedCondition result = *this;
537  const auto N = result.zone.value.cols();
538  result.zone.value.conservativeResize(N - 1, N - 1);
539 
540  return result;
541  }
542 
548  [[nodiscard]] bool hasEqualityN() const {
549  // By simplicity of the timed condition, we can check only the one side
550  return this->zone.value.col(0).tail(this->size()).unaryExpr([](const Bounds &bound) {
551  return bound.second;
552  }).any();
553  }
554 
558  [[nodiscard]] TimedCondition extendZero() const {
559  const auto N = this->zone.value.cols();
560  auto result = Zone::top(N + 1);
561  // Fill the constraints with shift
562  result.value.block(2, 2, N - 1, N - 1) = this->zone.value.block(1, 1, N - 1, N - 1);
563  result.value.block(0, 2, 1, N - 1) = this->zone.value.block(0, 1, 1, N - 1);
564  result.value.block(2, 0, N - 1, 1) = this->zone.value.block(1, 0, N - 1, 1);
565  // Copy the constraints of \f$x_1\f$ to \f$x_{0}\f$.
566  result.value.col(1) = result.value.col(2);
567  result.value.row(1) = result.value.row(2);
568  // Add \f$x_0 = x_1\f$
569  result.value(1, 2) = {0, true};
570  result.value(2, 1) = {0, true};
571 
572  return TimedCondition(std::move(result));
573  }
574 
580  [[nodiscard]] std::vector<std::size_t> getStrictlyConstrainedVariables(const TimedCondition &originalCondition,
581  const size_t examinedVariableSize) const {
582  std::vector<std::size_t> result;
583  for (std::size_t i = 1; i <= examinedVariableSize; ++i) {
584  if (this->zone.value.col(i) != originalCondition.zone.value.col(i) ||
585  this->zone.value.row(i) != originalCondition.zone.value.row(i)) {
586  result.push_back(i - 1);
587  }
588  }
589  return result;
590  }
591 
592  bool operator==(const TimedCondition &condition) const {
593  return this->size() == condition.size() && this->zone.strictEqual(condition.zone);
594  }
595 
596  bool operator!=(const TimedCondition &condition) const {
597  return this->size() != condition.size() || !this->zone.strictEqual(condition.zone);
598  }
599 
603  [[nodiscard]] std::vector<Constraint> toGuard() const {
604 #ifdef DEBUG
605  BOOST_LOG_TRIVIAL(trace) << "Constraint:" << *this;
606 #endif
607  std::vector<Constraint> result;
608  const auto N = this->size();
609  result.reserve(N * 2);
610  for (std::size_t i = 0; i < this->size(); ++i) {
611  const auto lowerBound = this->getLowerBound(i, N - 1);
612  const auto upperBound = this->getUpperBound(i, N - 1);
613  if (lowerBound.first != std::numeric_limits<double>::max() && lowerBound != Bounds{0, true}) {
614  if (lowerBound.second) {
615  result.push_back(ConstraintMaker(i) >= -int(lowerBound.first));
616  } else {
617  result.push_back(ConstraintMaker(i) > -int(lowerBound.first));
618  }
619  }
620  if (upperBound.first != std::numeric_limits<double>::max()) {
621  if (upperBound.second) {
622  result.push_back(ConstraintMaker(i) <= int(upperBound.first));
623  } else {
624  result.push_back(ConstraintMaker(i) < int(upperBound.first));
625  }
626  }
627  }
628 
629 #ifdef DEBUG
630  BOOST_LOG_TRIVIAL(trace) << "Guard: " << result;
631 #endif
632  return result;
633  }
634 
638  [[nodiscard]] bool hasPrefix() const {
639  const auto N = zone.value.cols() - 1;
640 
641  return !(this->getUpperBound(N - 1, N - 1) == Bounds{0, true} &&
642  this->getLowerBound(N - 1, N - 1) == Bounds{0, true});
643  }
644 
648  [[nodiscard]] bool hasSuffix() const {
649 
650  return !(this->getUpperBound(0, 0) == Bounds{0, true} &&
651  this->getLowerBound(0, 0) == Bounds{0, true});
652  }
653 
657  [[nodiscard]] bool includes(const TimedCondition &condition) const {
658  return this->zone.includes(condition.zone);
659  }
660 
664  TimedCondition operator&&(const TimedCondition &another) const {
665  return TimedCondition{this->zone && another.zone};
666  }
667 
671  [[nodiscard]] bool isSatisfiableNoCanonize() const {
672  return this->zone.isSatisfiableNoCanonize();
673  }
674 
678  [[nodiscard]] explicit operator bool() {
679  return this->zone.isSatisfiable();
680  }
681 
682  [[nodiscard]] TimedCondition applyResets(const TATransition::Resets &resets) const {
683  auto newCondition = *this;
684  for (const auto &[updatedVariable, assignedValue]: resets) {
685  // We do not support renaming here.
686  assert(assignedValue.index() == 0);
687  // Unconstrain the assigned variable
688  newCondition.zone.unconstrain(updatedVariable);
689  if (std::get<double>(assignedValue) == std::floor(std::get<double>(assignedValue))) {
690  newCondition.restrictLowerBound(updatedVariable, newCondition.size() - 1,
691  Bounds{-std::get<double>(assignedValue), true}, true);
692  newCondition.restrictUpperBound(updatedVariable, newCondition.size() - 1,
693  Bounds{std::get<double>(assignedValue), true}, true);
694  } else {
695  newCondition.restrictLowerBound(updatedVariable, newCondition.size() - 1,
696  Bounds{-std::floor(std::get<double>(assignedValue)), false}, true);
697  newCondition.restrictUpperBound(updatedVariable, newCondition.size() - 1,
698  Bounds{std::ceil(std::get<double>(assignedValue)), false}, true);
699  }
700  }
701 
702  return newCondition;
703  }
704 
713  [[nodiscard]] TimedCondition applyResets(const TATransition::Resets &resets,
714  const std::size_t targetClockSize) const {
715  TimedCondition newCondition {Zone::top(targetClockSize + 1)};
716  std::vector<std::pair<std::size_t, std::size_t>> renaming;
717  for (const auto &[updatedVariable, assignedValue]: resets) {
718  if (updatedVariable >= targetClockSize) {
719  continue;
720  }
721  if(assignedValue.index() == 0) {
722  // Apply non-renaming resets
723  if (std::get<double>(assignedValue) == std::floor(std::get<double>(assignedValue))) {
724  newCondition.restrictLowerBound(updatedVariable, newCondition.size() - 1,
725  Bounds{-std::get<double>(assignedValue), true}, true);
726  newCondition.restrictUpperBound(updatedVariable, newCondition.size() - 1,
727  Bounds{std::get<double>(assignedValue), true}, true);
728  } else {
729  newCondition.restrictLowerBound(updatedVariable, newCondition.size() - 1,
730  Bounds{-std::floor(std::get<double>(assignedValue)), false}, true);
731  newCondition.restrictUpperBound(updatedVariable, newCondition.size() - 1,
732  Bounds{std::ceil(std::get<double>(assignedValue)), false}, true);
733  }
734  for (const auto &[updatedVariable2, assignedValue2]: resets) {
735  if (updatedVariable2 < updatedVariable && assignedValue2.index() == 0) {
736  double difference = std::get<double>(assignedValue2) - std::get<double>(assignedValue);
737  // Apply non-renaming resets
738  if (difference == std::floor(difference)) {
739  newCondition.restrictLowerBound(updatedVariable2, updatedVariable - 1,
740  Bounds{-difference, true}, true);
741  newCondition.restrictUpperBound(updatedVariable2, updatedVariable - 1,
742  Bounds{difference, true}, true);
743  } else {
744  newCondition.restrictLowerBound(updatedVariable2, updatedVariable - 1,
745  Bounds{-std::floor(difference), false}, true);
746  newCondition.restrictUpperBound(updatedVariable2, updatedVariable - 1,
747  Bounds{std::ceil(difference), false}, true);
748  }
749  }
750  }
751  } else {
752  // add to renaming
753  renaming.emplace_back(std::get<ClockVariables>(assignedValue), updatedVariable);
754  }
755  }
756  // add implicit renaming
757  for (ClockVariables clock = 0; clock < targetClockSize; ++clock) {
758  auto it = std::find_if(resets.begin(), resets.end(), [&clock] (const auto &reset) {
759  return reset.first == clock;
760  });
761  if (it == resets.end()) {
762  renaming.emplace_back(clock, clock);
763  }
764  }
765  auto juxtaposed = *this ^ newCondition;
766  juxtaposed.addRenaming(renaming);
767 
768  return TimedCondition{juxtaposed.getRight()};
769  }
770 
774  [[nodiscard]] bool isPoint(std::size_t i) const {
775  return learnta::isPoint(this->getUpperBound(i, this->size() - 1), this->getLowerBound(i, this->size() - 1));
776  }
777 
778  [[nodiscard]] std::size_t hash_value() const {
779  return learnta::hash_value(this->zone);
780  }
781 
782  std::ostream &print(std::ostream &os) const {
783  for (std::size_t i = 0; i < this->size(); ++i) {
784  for (std::size_t j = i; j < this->size(); ++j) {
785  const auto upperBound = this->getUpperBound(i, j);
786  const auto lowerBound = this->getLowerBound(i, j);
787  os << -lowerBound.first << (lowerBound.second ? " <= " : " < ")
788  << "T_{" << i << ", " << j << "} "
789  << (upperBound.second ? " <= " : " < ") << upperBound.first;
790  if (i != this->size() - 1 || j != this->size() - 1) {
791  os << " && ";
792  }
793  }
794  }
795  return os;
796  }
797 
798  friend class NeighborConditions;
799  };
800 }
801 
802 
803 namespace learnta {
804  static inline std::ostream &print(std::ostream &os, const learnta::TimedCondition &cond) {
805  for (std::size_t i = 0; i < cond.size(); ++i) {
806  for (std::size_t j = i; j < cond.size(); ++j) {
807  const auto upperBound = cond.getUpperBound(i, j);
808  const auto lowerBound = cond.getLowerBound(i, j);
809  os << -lowerBound.first << (lowerBound.second ? " <= " : " < ")
810  << "T_{" << i << ", " << j << "} "
811  << (upperBound.second ? " <= " : " < ") << upperBound.first;
812  if (i != cond.size() - 1 || j != cond.size() - 1) {
813  os << " && ";
814  }
815  }
816  }
817  return os;
818  }
819 
820  static inline std::ostream &operator<<(std::ostream &os, const learnta::TimedCondition &b) {
821  return learnta::print(os, b);
822  }
823 
824  inline std::size_t hash_value(learnta::TimedCondition const &timedCondition) {
825  return timedCondition.hash_value();
826  }
827 }
Definition: constraint.hh:210
A zone constructed by juxtaposing two zones with or without shared variables.
Definition: juxtaposed_zone.hh:12
A timed condition, a finite conjunction of inequalities of the form , where and .
Definition: timed_condition.hh:19
TimedCondition removeN() const
Remove .
Definition: timed_condition.hh:523
std::vector< std::size_t > getStrictlyConstrainedVariables(const TimedCondition &originalCondition, const size_t examinedVariableSize) const
Returns the set of variables strictly constrained compared with the original condition.
Definition: timed_condition.hh:580
TimedCondition extendZero() const
Rename each variable to and add such that .
Definition: timed_condition.hh:558
void restrictUpperBound(std::size_t i, std::size_t j, Bounds upperBound, bool force=false)
Restrict the upper bound of .
Definition: timed_condition.hh:263
bool hasEqualityN() const
Return if there is .
Definition: timed_condition.hh:548
bool isSimple() const
Returns if this timed condition is simple.
Definition: timed_condition.hh:98
TimedCondition operator&&(const TimedCondition &another) const
Returns the intersection of two timed conditions.
Definition: timed_condition.hh:664
void removeUpperBoundAssign()
Remove the upper bounds.
Definition: timed_condition.hh:425
static TimedCondition makeExact(const std::vector< double > &accumulatedDuration)
Construct a timed condition from concrete values of T_{i,j}. The generated timed condition only conta...
Definition: timed_condition.hh:61
TimedCondition applyResets(const TATransition::Resets &resets, const std::size_t targetClockSize) const
Return the timed condition after applying the given reset.
Definition: timed_condition.hh:713
bool hasPrefix() const
Return if this timed condition has a (continuous) prefix.
Definition: timed_condition.hh:638
TimedCondition predecessor(const std::deque< ClockVariables > &variables) const
Make a continuous predecessor by backward-elapsing variables.
Definition: timed_condition.hh:435
bool hasSuffix() const
Return if this timed condition has a (continuous) suffix.
Definition: timed_condition.hh:648
TimedCondition suffix(const std::deque< ClockVariables > &variables) const
Make a continuous suffix.
Definition: timed_condition.hh:483
Bounds getUpperBound(std::size_t i, std::size_t j) const
Returns the upper bound of .
Definition: timed_condition.hh:232
void successorAssign(const std::deque< ClockVariables > &variables)
Make a continuous successor by elapsing variables.
Definition: timed_condition.hh:391
TimedCondition successor(const std::deque< ClockVariables > &variables) const
Make a continuous successor by elapsing variables.
Definition: timed_condition.hh:367
void restrictLowerBound(std::size_t i, std::size_t j, Bounds lowerBound, bool force=false)
Restrict the lower bound of .
Definition: timed_condition.hh:247
Bounds getLowerBound(std::size_t i, std::size_t j) const
Returns the lower bound of .
Definition: timed_condition.hh:219
TimedCondition(const std::vector< double > &accumulatedDuration)
Construct a timed condition from concrete values of T_{i,j}. The generated timed condition is the sim...
Definition: timed_condition.hh:37
std::vector< Constraint > toGuard() const
Definition: timed_condition.hh:603
size_t size() const
Return the number of the variables in this timed condition.
Definition: timed_condition.hh:89
TimedCondition removeZero() const
Remove TODO: Implement it.
Definition: timed_condition.hh:535
TimedCondition prefix(const std::deque< ClockVariables > &variables) const
Make a continuous prefix.
Definition: timed_condition.hh:459
JuxtaposedZone juxtaposeRight(const TimedCondition &right, Eigen::Index commonVariableSize) const
Juxtapose two timed conditions renaming variable.
Definition: timed_condition.hh:203
std::vector< TimedCondition > enumerate() const
Make a vector of simple timed conditions in this timed condition.
Definition: timed_condition.hh:357
TimedCondition extendN() const
Add another variable such that .
Definition: timed_condition.hh:507
bool includes(const TimedCondition &condition) const
Return if this timed condition includes the given timed condition.
Definition: timed_condition.hh:657
void enumerate(std::vector< TimedCondition > &simpleConditions) const
Make a vector of simple timed conditions in this timed condition.
Definition: timed_condition.hh:299
JuxtaposedZone operator^(const TimedCondition &another) const
Juxtapose two timed conditions.
Definition: timed_condition.hh:194
Zone zone
A zone to represent the timing constraint.
Definition: timed_condition.hh:24
bool isSatisfiableNoCanonize() const
Returns if the timed condition is satisfiable.
Definition: timed_condition.hh:671
void removeEqualityUpperBoundAssign()
Remove the equality upper bound.
Definition: timed_condition.hh:411
TimedCondition convexHull(const TimedCondition &condition) const
Return the convex hull of this timed condition and the given timed condition.
Definition: timed_condition.hh:284
bool isPoint(std::size_t i) const
Check if T_{i, |T|} is a point.
Definition: timed_condition.hh:774
static TimedCondition empty()
Construct the empty timed condition, i.e. .
Definition: timed_condition.hh:79
TimedCondition operator+(const TimedCondition &another) const
Concatenate two timed conditions.
Definition: timed_condition.hh:152
void convexHullAssign(const TimedCondition &condition)
Make it to be the convex hull of this timed condition and the given timed condition.
Definition: timed_condition.hh:277
JuxtaposedZone juxtaposeLeft(const TimedCondition &left, Eigen::Index commonVariableSize) const
Juxtapose two timed conditions renaming variable.
Definition: timed_condition.hh:212
Definition: experiment_runner.hh:23
static bool isPoint(const Bounds &upperBound, const Bounds &lowerBound)
Check if the upper and lower bounds define a point.
Definition: bounds.hh:17
Implementation of a zone with DBM.
Definition: zone.hh:24
std::size_t getNumOfVar() const noexcept
Definition: zone.hh:66
static Zone zero(int size)
Make the zone of size size such that all the values are zero.
Definition: zone.hh:71
bool strictEqual(Zone z) const
Check the equivalence of two zones.
Definition: zone.hh:425
bool includes(const Zone &zone) const
Return if this zone includes the given zone.
Definition: zone.hh:397
void canonize()
make the zone canonical
Definition: zone.hh:314
bool isSatisfiableNoCanonize() const
check if the zone is satisfiable
Definition: zone.hh:333
Eigen::Matrix< Bounds, Eigen::Dynamic, Eigen::Dynamic > value
The matrix representing the DBM.
Definition: zone.hh:26
static Zone top(std::size_t size)
Make the zone of size size with no constraints.
Definition: zone.hh:84
bool isSatisfiable()
check if the zone is satisfiable
Definition: zone.hh:323