libmonaa  0.5.2
zone.hh
1 #pragma once
6 #include <algorithm>
7 #include <cmath>
8 #include <limits>
9 #include <utility>
10 #include <memory>
11 #include <tuple>
12 #include <vector>
13 #include <boost/unordered_map.hpp>
14 
15 #include "common_types.hh"
16 #include "constraint.hh"
17 
18 using Bounds = std::pair<double, bool>;
19 static inline Bounds operator+(const Bounds &a, const Bounds &b) {
20  return Bounds(a.first + b.first, a.second && b.second);
21 }
22 static inline Bounds operator-(const Bounds &a, const Bounds &b) {
23  return Bounds(a.first - b.first, a.second && b.second);
24 }
25 static inline void operator+=(Bounds &a, const Bounds b) {
26  a.first += b.first;
27  a.second = a.second && b.second;
28 }
29 static inline std::ostream &operator<<(std::ostream &os, const Bounds &b) {
30  os << "(" << b.first << ", " << b.second << ")";
31  return os;
32 }
33 
34 #include <Eigen/Core>
35 
43 struct Zone {
44  using Tuple = std::tuple<std::vector<Bounds>, Bounds>;
45  Eigen::Matrix<Bounds, Eigen::Dynamic, Eigen::Dynamic> value;
46  Bounds M;
47 
52  inline std::size_t getNumOfVar() const noexcept { return value.cols() - 1; }
53 
54  inline void cutVars(std::shared_ptr<Zone> &out, std::size_t from,
55  std::size_t to) {
56  out = std::make_shared<Zone>();
57  out->value.resize(to - from + 2, to - from + 2);
58  out->value.block(0, 0, 1, 1) << Bounds(0, true);
59  out->value.block(1, 1, to - from + 1, to - from + 1) =
60  value.block(from + 1, from + 1, to - from + 1, to - from + 1);
61  out->value.block(1, 0, to - from + 1, 1) =
62  value.block(from + 1, 0, to - from + 1, 1);
63  out->value.block(0, 1, 1, to - from + 1) =
64  value.block(0, from + 1, 1, to - from + 1);
65  out->M = M;
66  }
67 
68  static Zone zero(int size) {
69  static Zone zeroZone;
70  if (zeroZone.value.cols() == size) {
71  return zeroZone;
72  }
73  zeroZone.value.resize(size, size);
74  zeroZone.value.fill(Bounds(0, true));
75  return zeroZone;
76  }
77 
78  static Zone universal(int size) {
79  static Zone zeroZone;
80  static constexpr Bounds infinity =
81  Bounds(std::numeric_limits<double>::infinity(), false);
82  if (zeroZone.value.cols() == size + 1) {
83  return zeroZone;
84  }
85  zeroZone.value.resize(size + 1, size + 1);
86  zeroZone.value.fill(infinity);
87  zeroZone.value(0, 0) = Bounds(0, true);
88  return zeroZone;
89  }
90 
91  std::tuple<std::vector<Bounds>, Bounds> toTuple() const {
92  // omit (0,0)
93  return std::tuple<std::vector<Bounds>, Bounds>(
94  std::vector<Bounds>(value.data() + 1, value.data() + value.size()), M);
95  }
96 
98  void tighten(ClockVariables x, ClockVariables y, Bounds c) {
99  x++;
100  y++;
101  value(x, y) = std::min(value(x, y), c);
102  close1(x);
103  close1(y);
104  }
105 
106  void close1(ClockVariables x) {
107  for (int i = 0; i < value.rows(); i++) {
108  value.row(i) =
109  value.row(i).array().min(value.row(x).array() + value(i, x));
110  // for (int j = 0; j < value.cols(); j++) {
111  // value(i, j) = std::min(value(i, j), value(i, x) + value(x, j));
112  // }
113  }
114  }
115 
116  // The reset value is always (0, \le)
117  void reset(ClockVariables x) {
118  // 0 is the special varibale here
119  x++;
120  value(0, x) = Bounds(0, true);
121  value(x, 0) = Bounds(0, true);
122  value.col(x).tail(value.rows() - 1) = value.col(0).tail(value.rows() - 1);
123  value.row(x).tail(value.cols() - 1) = value.row(0).tail(value.cols() - 1);
124  }
125 
126  void elapse() {
127  static constexpr Bounds infinity =
128  Bounds(std::numeric_limits<double>::infinity(), false);
129  value.col(0).fill(Bounds(infinity));
130  for (int i = 0; i < value.row(0).size(); ++i) {
131  value.row(0)[i].second = false;
132  }
133  }
134 
135  /*
136  @brief make the zone canonical
137  */
138  void canonize() {
139  for (int k = 0; k < value.cols(); k++) {
140  close1(k);
141  }
142  }
143 
144  /*
145  @brief check if the zone is satisfiable
146  */
147  bool isSatisfiable() {
148  canonize();
149  return (value + value.transpose()).minCoeff() >= Bounds(0.0, true);
150  }
151 
152  /*
153  @brief truncate the constraints compared with a constant greater than or
154  equal to M
155  */
156  void abstractize() {
157  static constexpr Bounds infinity =
158  Bounds(std::numeric_limits<double>::infinity(), false);
159  for (auto it = value.data(); it < value.data() + value.size(); it++) {
160  if (*it >= M) {
161  *it = Bounds(infinity);
162  }
163  }
164  }
165 
169  void makeUnsat() {
170  value(0, 0) = Bounds(-std::numeric_limits<double>::infinity(), false);
171  }
172 
174  std::vector<Constraint> makeGuard() {
175  std::vector<Constraint> guard;
176  canonize();
177  abstractize();
178  for (int i = 0; i < getNumOfVar(); ++i) {
179  // the second element of Bound is true if the constraint is not strict,
180  // i.e., LE or GE.
181  Bounds lowerBound = value(0, i + 1);
182  if (lowerBound.first > 0 or
183  (lowerBound.first == 0 and lowerBound.second == false)) {
184  if (lowerBound.second) {
185  guard.push_back(ConstraintMaker(i) >= lowerBound.first);
186  } else {
187  guard.push_back(ConstraintMaker(i) > lowerBound.first);
188  }
189  }
190  Bounds upperBound = value(i + 1, 0);
191  if (upperBound < M) {
192  if (upperBound.second) {
193  guard.push_back(ConstraintMaker(i) <= upperBound.first);
194  } else {
195  guard.push_back(ConstraintMaker(i) < upperBound.first);
196  }
197  }
198  }
199  return guard;
200  }
201 
202  bool operator==(Zone z) const {
203  z.value(0, 0) = value(0, 0);
204  return value == z.value;
205  }
206 
207  void intersectionAssign(Zone z) {
208  assert(value.size() == z.value.size());
209  value.cwiseMin(z.value);
210  }
211 };
Definition: constraint.hh:73
static Interval operator+(Interval left, const Interval &right)
The sum of two intervals. The formal definition is as follows.
Definition: interval.hh:168
static void operator+=(std::vector< std::shared_ptr< Interval >> &left, const std::vector< std::shared_ptr< Interval >> &right)
The sum of two sets of intervals.
Definition: interval.hh:189
Implementation of a zone with DBM.
Definition: zone.hh:43
void makeUnsat()
make the zone unsatisfiable
Definition: zone.hh:169
void tighten(ClockVariables x, ClockVariables y, Bounds c)
add the constraint x - y \le (c,s)
Definition: zone.hh:98
std::size_t getNumOfVar() const noexcept
Definition: zone.hh:52
std::vector< Constraint > makeGuard()
make the strongest guard including the zone
Definition: zone.hh:174