LearnTA  0.0.1
symbolic_run.hh
1 
6 #pragma once
7 
8 #include <vector>
9 #include <string>
10 #include <list>
11 
12 #include <boost/log/trivial.hpp>
13 #include <boost/log/core.hpp>
14 #include <boost/log/expressions.hpp>
15 
16 #include "timed_word.hh"
17 #include "zone.hh"
18 #include "timed_automaton.hh"
19 #include "zone_automaton_state.hh"
20 
21 namespace std {
22  inline static std::ostream& operator<<(std::ostream& stream, const std::vector<double> &valuation) {
23  stream << "{";
24  for (std::size_t i = 0; i < valuation.size(); ++i) {
25  if (i > 0) {
26  stream << ", ";
27  }
28  stream << valuation.at(i);
29  }
30  stream << "}";
31  return stream;
32  }
33 }
34 namespace learnta {
40  class SymbolicRun {
41  private:
42  std::vector<std::shared_ptr<ZAState>> states;
43  // A sequence of the visited zones without abstraction
44  std::vector<Zone> tightZones;
45  std::vector<learnta::TATransition> edges;
46  std::string word;
47  public:
48  explicit SymbolicRun(const std::shared_ptr<ZAState> &initialState) : states({initialState}), edges() {
49  tightZones = {this->states.front()->zone};
50  }
51 
53  void push_back(const learnta::TATransition &transition, char action, const std::shared_ptr<ZAState> &state) {
54  assert(this->states.size() == this->tightZones.size());
55  assert(this->states.size() - 1 == this->word.size());
56  assert(this->word.size() == this->edges.size());
57  this->states.push_back(state);
58  word.push_back(action);
59  this->edges.push_back(transition);
60  tightZones.push_back(tightZones.back());
61  tightZones.back().elapse();
62  tightZones.back().tighten(this->edges.back().guard);
63  tightZones.back().applyResets(this->edges.back().resetVars);
64  tightZones.back().canonize();
65  }
66 
68  [[nodiscard]] std::shared_ptr<ZAState> stateAt(int i) const {
69  return this->states.at(i);
70  }
71 
73  [[nodiscard]] learnta::TATransition edgeAt(int i) const {
74  return this->edges.at(i);
75  }
76 
77  [[nodiscard]] learnta::Zone tightZoneAt(int i) const {
78  return this->tightZones.at(i);
79  }
80 
82  [[nodiscard]] std::shared_ptr<ZAState> back() const {
83  return this->states.back();
84  }
85 
93  [[nodiscard]] std::optional<TimedWord> reconstructWord() const {
94  BOOST_LOG_TRIVIAL(trace) << "Started reconstructWord";
95  // The zone after the jump (here, this is the last zone)
96  auto postZone = this->tightZones.back();
97  if (!postZone.isSatisfiable()) {
98  return std::nullopt;
99  }
100  // Sample the last concrete state
101  auto postValuation = postZone.sample();
102 
103  const auto N = this->edges.size();
104  std::list<double> durations;
105 
106  for (int i = N - 1; i >= 0; --i) {
107  BOOST_LOG_TRIVIAL(trace) << "postValuation: " << postValuation;
108  // The zone just after the previous jump
109  auto preZone = this->tightZoneAt(i);
110  preZone.canonize();
111 
112  // Construct the zone just before jump
113  auto zoneBeforeJump = Zone{postValuation, postZone.M};
114  if (!zoneBeforeJump.isSatisfiableNoCanonize()) {
115  BOOST_LOG_TRIVIAL(error) << "Failed to reconstruct word from a symbolic run\n" << *this;
116  return std::nullopt;
117  }
118  const auto transition = this->edgeAt(i);
119  // Handle the reset
120  zoneBeforeJump.revertResets(transition.resetVars);
121  assert(zoneBeforeJump.isSatisfiableNoCanonize());
122  // Handle the guard
123  for (const auto guard: transition.guard) {
124  zoneBeforeJump.tighten(guard);
125  if (!zoneBeforeJump.isSatisfiableNoCanonize()) {
126  BOOST_LOG_TRIVIAL(error) << "Failed to reconstruct word from a symbolic run\n" << *this;
127  BOOST_LOG_TRIVIAL(error) << "The unsatisfiable zone\n" << zoneBeforeJump;
128  return std::nullopt;
129  }
130  }
131  {
132  // Use the precondition
133  auto tmpZoneBeforeJump = zoneBeforeJump;
134  tmpZoneBeforeJump.reverseElapse();
135  tmpZoneBeforeJump &= preZone;
136  if (!tmpZoneBeforeJump.isSatisfiable()) {
137  // The word reconstruction may fail due to state mering
138  BOOST_LOG_TRIVIAL(debug) << "Failed to reconstruct word from a symbolic run\n" << *this;
139  return std::nullopt;
140  }
141  tmpZoneBeforeJump.elapse();
142  zoneBeforeJump &= tmpZoneBeforeJump;
143  }
144 
145  // Sample the valuation just before discrete jump
146  assert(zoneBeforeJump.isSatisfiableNoCanonize());
147  const auto valuationBeforeJump = zoneBeforeJump.sample();
148  assert(std::all_of(transition.guard.begin(), transition.guard.end(), [&] (const auto &guard) {
149  return guard.satisfy(valuationBeforeJump);
150  }));
151  auto backwardPreZone = Zone{valuationBeforeJump, postZone.M};
152  backwardPreZone.reverseElapse();
153  const auto preValuation = (preZone && backwardPreZone).sample();
154  if (preValuation.empty()) {
155  durations.push_front(0);
156  } else {
157  BOOST_LOG_TRIVIAL(trace) << "valuationBeforeJump: " << valuationBeforeJump;
158  BOOST_LOG_TRIVIAL(trace) << "preValuation: " << preValuation;
159  durations.push_front(valuationBeforeJump.at(0) - preValuation.at(0));
160  }
161 
162  // Update the variables
163  postZone = std::move(preZone);
164  postValuation = preValuation;
165  }
166  // Return the timed word
167  std::vector<double> durationsVector;
168  durationsVector.resize(durations.size());
169  std::move(durations.begin(), durations.end(), durationsVector.begin());
170  durationsVector.push_back(0);
171 
172  assert(validate(durationsVector));
173  return std::make_optional(TimedWord{word, durationsVector});
174  }
175 
179  [[nodiscard]] bool validate(const std::vector<double> &durations) const {
180  std::vector<double> valuation;
181  valuation.resize(this->tightZones.front().getNumOfVar());
182  for (std::size_t i = 0; i < this->edges.size(); ++i) {
183  std::transform(valuation.begin(), valuation.end(), valuation.begin(), [&] (const auto &value) {
184  return value + durations.at(i);
185  });
186  const auto transition = this->edges.at(i);
187  if (std::all_of(transition.guard.begin(), transition.guard.end(), [&](const Constraint &guard) {
188  return guard.satisfy(valuation);
189  })) {
190  // Reset the clock variables
191  const auto oldValuation = valuation;
192  for (const auto &[resetVariable, targetVariable]: transition.resetVars) {
193  if (targetVariable.index() == 1) {
194  valuation.at(resetVariable) = oldValuation.at(std::get<ClockVariables>(targetVariable));
195  } else {
196  valuation.at(resetVariable) = std::get<double>(targetVariable);
197  }
198  }
199  BOOST_LOG_TRIVIAL(trace) << "valuation: " << valuation;
200  } else {
201  return false;
202  }
203  }
204 
205  return true;
206  }
207 
209  static inline std::ostream &print(std::ostream &os, const learnta::SymbolicRun &run) {
210  os << run.tightZones.front();
211 
212  for (std::size_t i = 0; i < run.word.size(); ++i) {
213  os << run.word.at(i) << "\n";
214  os << run.edges.at(i).guard << run.edges.at(i).resetVars;
215  os << "\n" << run.tightZoneAt(i + 1);
216  }
217 
218  return os;
219  }
220  };
221 
223  static inline std::ostream &operator<<(std::ostream &os, const learnta::SymbolicRun &run) {
224  return learnta::SymbolicRun::print(os, run);
225  }
226 }
Run of a zone automaton.
Definition: symbolic_run.hh:40
std::shared_ptr< ZAState > stateAt(int i) const
Returns the i-th state in the symbolic run.
Definition: symbolic_run.hh:68
std::shared_ptr< ZAState > back() const
Returns the last state in the symbolic run.
Definition: symbolic_run.hh:82
void push_back(const learnta::TATransition &transition, char action, const std::shared_ptr< ZAState > &state)
Push a new edge and state in the end of the run.
Definition: symbolic_run.hh:53
learnta::TATransition edgeAt(int i) const
Returns the i-th edge in the symbolic run.
Definition: symbolic_run.hh:73
static std::ostream & print(std::ostream &os, const learnta::SymbolicRun &run)
Print the symbolic run.
Definition: symbolic_run.hh:209
std::optional< TimedWord > reconstructWord() const
Reconstruct a timed word from a symbolic run.
Definition: symbolic_run.hh:93
bool validate(const std::vector< double > &durations) const
Check if the given list of durations is consistent with the symbolic run.
Definition: symbolic_run.hh:179
A timed word.
Definition: timed_word.hh:25
Definition: experiment_runner.hh:23
Definition: external_transition_maker.hh:149
A constraint in a guard of transitions.
Definition: constraint.hh:32
A state of timed automata.
Definition: timed_automaton.hh:82
Implementation of a zone with DBM.
Definition: zone.hh:24
Bounds M
The threshold for the normalization.
Definition: zone.hh:28