libmonaa 0.5.2
Loading...
Searching...
No Matches
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
18using Bounds = std::pair<double, bool>;
19static inline Bounds operator+(const Bounds &a, const Bounds &b) {
20 return Bounds(a.first + b.first, a.second && b.second);
21}
22static inline Bounds operator-(const Bounds &a, const Bounds &b) {
23 return Bounds(a.first - b.first, a.second && b.second);
24}
25static inline void operator+=(Bounds &a, const Bounds b) {
26 a.first += b.first;
27 a.second = a.second && b.second;
28}
29static 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
43struct 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
Implementation of a zone with DBM.
Definition zone.hh:43
void makeUnsat()
make the zone unsatisfiable
Definition zone.hh:169
std::vector< Constraint > makeGuard()
make the strongest guard including the zone
Definition zone.hh:174
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