LearnTA  0.0.1
renaming_relation.hh
1 
6 #pragma once
7 
8 #include <vector>
9 #include <unordered_set>
10 #include <utility>
11 #include <ostream>
12 
13 #include "timed_condition.hh"
14 
15 namespace learnta {
16  class RenamingRelation : public std::vector<std::pair<std::size_t, std::size_t>> {
17  public:
23  static std::vector<double> toValuation(TimedCondition condition) {
24  std::vector<double> result;
25  result.resize(condition.size());
26  for (std::size_t i = 0; i < condition.size(); ++i) {
27  const auto lowerBound = condition.getLowerBound(i, condition.size() - 1);
28  const auto upperBound = condition.getUpperBound(i, condition.size() - 1);
29  if (lowerBound.first == -upperBound.first && lowerBound.second && upperBound.second) {
30  // When the bound is a point
31  result.at(i) = upperBound.first;
32  } else {
33  // When the bound is not a point
34  auto middlePoint = (upperBound.first - lowerBound.first) / 2.0;
35  result.at(i) = middlePoint;
36  condition.restrictLowerBound(i, condition.size() - 1, Bounds{-middlePoint, true}, false);
37  condition.restrictUpperBound(i, condition.size() - 1, Bounds{middlePoint, true}, false);
38  }
39  }
40 
41  return result;
42  }
43 
44  [[nodiscard]] std::vector<std::pair<ClockVariables, std::variant<double, ClockVariables>>>
45  toReset(const TimedCondition &sourceCondition, const TimedCondition &targetCondition) const {
46  // Construct the reset from the renaming relation
47  std::vector<std::pair<ClockVariables, std::variant<double, ClockVariables>>> result;
48  result.resize(this->size());
49  std::transform(this->begin(), this->end(), result.begin(), [&](const auto &renamingPair) {
50  return std::make_pair(renamingPair.second, static_cast<ClockVariables>(renamingPair.first));
51  });
52 
53  // Construct the reset from the timed conditions
54  const auto targetValuation = toValuation(targetCondition);
55  // Map the clock variables to the target timed condition if it is not mapped with the renaming relation
56  for (std::size_t resetVariable = 0; resetVariable < targetCondition.size(); ++resetVariable) {
57  auto it = std::find_if(result.begin(), result.end(), [&](const auto &pair) {
58  return pair.first == resetVariable;
59  });
60  if (it == result.end()) {
61  result.emplace_back(resetVariable, targetValuation.at(resetVariable));
62  } else if (targetValuation.at(resetVariable) == std::floor(targetValuation.at(resetVariable))) {
63  // We overwrite the assigned value if it is a constant
64  it->second = targetValuation.at(resetVariable);
65  }
66  }
67 
68  return result;
69  }
70 
71  template<class T>
72  std::vector<T> apply(const std::vector<T> &value) const {
73  assert(std::all_of(this->begin(), this->end(), [&value] (const auto pair) {
74  return value.size() > pair.first;
75  }));
76  std::vector<T> result = value;
77  for (const auto &[source, target]: *this) {
78  if (result.size() <= target) {
79  result.resize(target);
80  }
81  result.at(target) = result.at(source);
82  }
83 
84  return result;
85  }
86 
92  [[nodiscard]] auto rightVariables() const {
93  std::vector<ClockVariables> result;
94  result.reserve(this->size());
95  std::transform(this->begin(), this->end(), std::back_inserter(result), second<std::size_t, std::size_t>);
96  std::sort(result.begin(), result.end());
97  result.erase(std::unique(result.begin(), result.end()), result.end());
98  assert(is_strict_ascending(result));
99  return result;
100  }
101 
105  void eraseLeft(std::size_t left) {
106  this->erase(std::remove_if(this->begin(), this->end(), is_first<std::size_t, std::size_t>(left)), this->end());
107  }
108 
112  [[nodiscard]] bool onlyTrivial(const TimedCondition &targetCondition) const {
113  return std::all_of(this->begin(), this->end(), [&] (const auto &renamingPair) {
114  return targetCondition.isPoint(renamingPair.second);
115  });
116  }
117 
121  [[nodiscard]] bool containsAllTrivial(const TimedCondition &sourceCondition,
122  const TimedCondition &targetCondition) const {
123  for (auto targetClock = 0; targetClock < static_cast<ClockVariables>(targetCondition.size()); ++targetClock) {
124  const auto targetUpperBound = targetCondition.getUpperBound(targetClock, targetCondition.size() - 1);
125  const auto targetLowerBound = targetCondition.getLowerBound(targetClock, targetCondition.size() - 1);
126  if (isPoint(targetUpperBound, targetLowerBound)) {
127  bool hasEqual = false;
128  for (auto sourceClock = 0; sourceClock < static_cast<ClockVariables>(sourceCondition.size()); ++sourceClock) {
129  const auto sourceUpperBound = sourceCondition.getUpperBound(sourceClock, sourceCondition.size() - 1);
130  const auto sourceLowerBound = sourceCondition.getLowerBound(sourceClock, sourceCondition.size() - 1);
131  if (isPoint(sourceUpperBound, sourceLowerBound) &&
132  sourceUpperBound == targetUpperBound && sourceLowerBound == targetLowerBound) {
133  hasEqual = true;
134  }
135  }
136  if (hasEqual) {
137  auto it = std::find_if(this->begin(), this->end(), [&] (const auto &pair) {
138  return pair.second == static_cast<std::size_t>(targetClock);
139  });
140  if (it == this->end()) {
141  return false;
142  }
143  }
144  }
145  }
146 
147  return true;
148  }
149 
153  [[nodiscard]] bool full(const TimedCondition &condition) const {
154  std::vector<ClockVariables> restrictedVariables = this->rightVariables();
155  restrictedVariables.reserve(condition.size());
156  for (std::size_t clock = 0; clock < condition.size(); ++clock) {
157  if (condition.isPoint(clock)) {
158  restrictedVariables.push_back(clock);
159  }
160  }
161  std::sort(restrictedVariables.begin(), restrictedVariables.end());
162  restrictedVariables.erase(std::unique(restrictedVariables.begin(), restrictedVariables.end()),
163  restrictedVariables.end());
164 
165  return restrictedVariables.size() == condition.size();
166  }
167 
171  [[nodiscard]] bool hasImpreciseClocks(const TimedCondition &target) const {
172  return !this->empty() && !this->full(target) && !this->onlyTrivial(target);
173  }
174 
178  [[nodiscard]] std::vector<ClockVariables> impreciseClocks(const TimedCondition &target) const {
179  if (!hasImpreciseClocks(target)) {
180  return {};
181  }
182  std::vector<ClockVariables> result;
183  for (std::size_t clock = 0; clock < target.size(); ++clock) {
184  if(!target.isPoint(clock) && std::none_of(begin(), end(), is_second<std::size_t, std::size_t>(clock))) {
185  result.push_back(clock);
186  }
187  }
188 
189  return result;
190  }
191 
195  void addImplicitConstraints(JuxtaposedZone juxtaposedCondition) {
196  juxtaposedCondition.addRenaming(*this);
197  auto newRenaming = juxtaposedCondition.makeRenaming();
198  std::move(newRenaming.begin(), newRenaming.end(), std::back_inserter(*this));
199  // Make it unique in terms of the right variables
200  std::sort(this->begin(), this->end(), [] (const auto &left, const auto& right) {
201  return left.second < right.second || (left.second == right.second && left.first < right.first);
202  });
203  this->erase(std::unique(this->begin(), this->end(), [] (const auto &left, const auto &right) {
204  return left.second == right.second;
205  }), this->end());
206  }
207 
211  void addImplicitConstraints(const TimedCondition &source, const TimedCondition &target) {
212  addImplicitConstraints(source ^ target);
213  }
214 
218  [[nodiscard]] bool isRightUnique() const {
219  return this->rightVariables().size() == this->size();
220  }
221 
222  friend std::ostream &operator<<(std::ostream &os, const RenamingRelation &relation) {
223  bool isFirst = true;
224  os << '{';
225  for (const auto & pair: relation) {
226  if (!isFirst) {
227  os << " && ";
228  }
229  os << "t" << pair.first << " == t'" << pair.second;
230  isFirst = false;
231  }
232  os << '}';
233  return os;
234  }
235  };
236 }
237 
238 namespace std {
239  template<class T, class U>
240  std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &pair) {
241  os << '{' << pair.first << ", " << pair.second << "}";
242 
243  return os;
244  }
245 }
A zone constructed by juxtaposing two zones with or without shared variables.
Definition: juxtaposed_zone.hh:12
auto makeRenaming() const
Make renaming constraints.
Definition: juxtaposed_zone.hh:149
void addRenaming(const std::vector< std::pair< std::size_t, std::size_t >> &renaming)
Add renaming constraints.
Definition: juxtaposed_zone.hh:127
Definition: renaming_relation.hh:16
auto rightVariables() const
The clock variables on the right hand side of the renaming relation.
Definition: renaming_relation.hh:92
bool containsAllTrivial(const TimedCondition &sourceCondition, const TimedCondition &targetCondition) const
Check if the renaming relation contains all the trivial equations from the timed conditions.
Definition: renaming_relation.hh:121
void addImplicitConstraints(JuxtaposedZone juxtaposedCondition)
Add renaming equations from target and source conditions.
Definition: renaming_relation.hh:195
bool onlyTrivial(const TimedCondition &targetCondition) const
Check if the renaming relation contains only the trivial equations from the timed conditions.
Definition: renaming_relation.hh:112
bool hasImpreciseClocks(const TimedCondition &target) const
Check if the application of this renaming causes implicit clocks.
Definition: renaming_relation.hh:171
static std::vector< double > toValuation(TimedCondition condition)
Construct a valuation from a timed condition.
Definition: renaming_relation.hh:23
void addImplicitConstraints(const TimedCondition &source, const TimedCondition &target)
Add renaming equations from target and source conditions.
Definition: renaming_relation.hh:211
bool isRightUnique() const
Check if the renaming relation is right unique, i.e, (i, k) and (j, k) in this implies i == j.
Definition: renaming_relation.hh:218
void eraseLeft(std::size_t left)
Erase pairs such that (left, right) for some right.
Definition: renaming_relation.hh:105
std::vector< ClockVariables > impreciseClocks(const TimedCondition &target) const
Return the imprecise clocks by this renaming.
Definition: renaming_relation.hh:178
bool full(const TimedCondition &condition) const
Check if the renaming relation is full, i.e., all the right variables are restricted.
Definition: renaming_relation.hh:153
A timed condition, a finite conjunction of inequalities of the form , where and .
Definition: timed_condition.hh:19
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
Bounds getUpperBound(std::size_t i, std::size_t j) const
Returns the upper bound of .
Definition: timed_condition.hh:232
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
size_t size() const
Return the number of the variables in this timed condition.
Definition: timed_condition.hh:89
bool isPoint(std::size_t i) const
Check if T_{i, |T|} is a point.
Definition: timed_condition.hh:774
Definition: experiment_runner.hh:23
bool is_strict_ascending(const std::vector< T > &container)
Check if the elements are sorted in the strict ascending order.
Definition: common_types.hh:54
static bool isPoint(const Bounds &upperBound, const Bounds &lowerBound)
Check if the upper and lower bounds define a point.
Definition: bounds.hh:17
Definition: external_transition_maker.hh:149