LearnTA  0.0.1
elementary_language.hh
1 
6 #pragma once
7 
8 #include <string>
9 #include <utility>
10 #include <ostream>
11 #include <list>
12 
13 #include "timed_condition.hh"
14 #include "timed_word.hh"
15 
16 namespace learnta {
24  protected:
25  std::string word;
26  TimedCondition timedCondition;
27  public:
28  ElementaryLanguage() = default;
29 
30  ElementaryLanguage(std::string word, TimedCondition timedCondition) :
31  word(std::move(word)), timedCondition(std::move(timedCondition)) {
32  assert(this->word.size() + 1 == this->timedCondition.size());
33  }
34 
39  ElementaryLanguage elementary {"", TimedCondition::empty()};
40  assert(elementary.word.size() + 1 == elementary.timedCondition.size());
41  return elementary;
42  }
43 
49  static ElementaryLanguage convexHull(const std::list<ElementaryLanguage>& elementaryLanguages) {
50  if (elementaryLanguages.empty()) {
51  return empty();
52  }
53  ElementaryLanguage result = elementaryLanguages.front();
54  for (const auto& elementary: elementaryLanguages) {
55  assert(elementary.word == result.word);
56  result.timedCondition.convexHullAssign(elementary.timedCondition);
57  }
58  assert(result.word.size() + 1 == result.timedCondition.size());
59 
60  return result;
61  }
62 
66  [[nodiscard]] bool isSimple() const {
67  return this->timedCondition.isSimple();
68  }
69 
73  [[nodiscard]] std::size_t wordSize() const {
74  return this->word.size();
75  }
76 
81  return {this->word + another.word, this->timedCondition + another.timedCondition};
82  }
83 
87  void enumerate(std::vector<ElementaryLanguage> &result) const {
88  if (this->isSimple()) {
89  result = {*this};
90  return;
91  }
92  std::vector<TimedCondition> simpleTimedConditions;
93  this->timedCondition.enumerate(simpleTimedConditions);
94  result.resize(simpleTimedConditions.size());
95  std::transform(simpleTimedConditions.begin(), simpleTimedConditions.end(), result.begin(),
96  [&](const TimedCondition &cond) {
97  return ElementaryLanguage{this->word, cond};
98  });
99  }
100 
104  [[nodiscard]] std::vector<ElementaryLanguage> enumerate() const {
105  std::vector<ElementaryLanguage> result;
106  this->enumerate(result);
107 
108  return result;
109  }
110 
114  [[nodiscard]] TimedWord sample() const {
115  std::vector<double> durations;
116  std::size_t N = this->wordSize() + 1;
117  durations.resize(N);
118  for (std::size_t i = 0; i < N; i++) {
119  Bounds lowerBound = this->timedCondition.getLowerBound(i, i);
120  Bounds upperBound = this->timedCondition.getUpperBound(i, i);
121  if (isPoint(upperBound, lowerBound)) {
122  durations[i] = upperBound.first;
123  } else {
124  double lower = -lowerBound.first;
125  double upper = upperBound.first;
126  double sum = 0;
127  for (int j = i - 1; j >= 0; j--) {
128  // sum = durations[j] + durations[j + 1] + ... + durations[i - 1]
129  sum += durations[j];
130  Bounds tmpLowerBound = this->timedCondition.getLowerBound(j, i);
131  Bounds tmpUpperBound = this->timedCondition.getUpperBound(j, i);
132  lower = std::max(lower, -tmpLowerBound.first - sum);
133  upper = std::min(upper, tmpUpperBound.first - sum);
134  }
135  assert(lower <= upper);
136  durations[i] = (lower + upper) * 0.5;
137  }
138  }
139 
140  // The resulting timed word must be in this language.
141  assert(this->contains(TimedWord{this->word, durations}));
142  return {this->word, durations};
143  }
144 
145  void removeEqualityUpperBoundAssign() {
146  assert(word.size() + 1 == timedCondition.size());
147  timedCondition.removeEqualityUpperBoundAssign();
148  };
149 
150  void removeUpperBoundAssign() {
151  assert(word.size() + 1 == timedCondition.size());
152  timedCondition.removeUpperBoundAssign();
153  };
154 
155  [[nodiscard]] ElementaryLanguage removeUpperBound() const {
156  assert(word.size() + 1 == timedCondition.size());
157  auto result = *this;
158  result.removeUpperBoundAssign();
159 
160  return result;
161  };
162 
167  [[nodiscard]] ElementaryLanguage constrain(const TimedWord& prefix) const {
168  // Check the precondition
169  assert(this->word.compare(0, prefix.wordSize(), prefix.getWord()) == 0);
170  TimedCondition resultingCondition = this->timedCondition;
171  for (std::size_t i = 0; i < prefix.wordSize(); ++i) {
172  assert(-resultingCondition.getLowerBound(i, i).first <= prefix.getDurations().at(i));
173  resultingCondition.restrictLowerBound(i, i, Bounds{-prefix.getDurations().at(i), true}, false);
174  assert(resultingCondition.getUpperBound(i, i).first >= prefix.getDurations().at(i));
175  resultingCondition.restrictUpperBound(i, i, Bounds{prefix.getDurations().at(i), true}, false);
176  }
177  assert(resultingCondition.getUpperBound(prefix.wordSize(), prefix.wordSize()).first >= prefix.getDurations().at(prefix.wordSize()));
178 
179  return ElementaryLanguage{this->word, resultingCondition};
180  }
181 
185  [[nodiscard]] bool contains(const TimedWord& testedWord) const {
186  if (testedWord.getWord() != this->getWord()) {
187  return false;
188  }
189  auto condition = this->timedCondition;
190  for (std::size_t i = 0; i < condition.size(); ++i) {
191  condition.restrictUpperBound(i, i, {testedWord.getDurations().at(i), true}, false);
192  condition.restrictLowerBound(i, i, {-testedWord.getDurations().at(i), true}, false);
193  }
194 
195  return static_cast<bool>(condition);
196  }
197 
198  [[nodiscard]] const std::string &getWord() const {
199  return word;
200  }
201 
202  [[nodiscard]] const TimedCondition &getTimedCondition() const {
203  return timedCondition;
204  }
205 
206  friend std::ostream &operator<<(std::ostream &os, const ElementaryLanguage &language);
207 
208  bool operator==(const ElementaryLanguage &another) const {
209  return word == another.word && timedCondition == another.timedCondition;
210  }
211 
212  bool operator!=(const ElementaryLanguage &another) const {
213  return !(another == *this);
214  }
215  };
216 
217  inline std::ostream &operator<<(std::ostream &os, const ElementaryLanguage &language) {
218  os << "(" << language.word << ", " << language.timedCondition << ")";
219  return os;
220  }
221 
222  inline std::size_t hash_value(learnta::ElementaryLanguage const &lang) {
223  return boost::hash_value(std::make_tuple(lang.getWord(), lang.getTimedCondition()));
224  }
225 }
An elementary language.
Definition: elementary_language.hh:23
bool isSimple() const
Returns if this elementary language is simple.
Definition: elementary_language.hh:66
ElementaryLanguage constrain(const TimedWord &prefix) const
Constrain the valuation using a timed word.
Definition: elementary_language.hh:167
static ElementaryLanguage empty()
Construct the empty elementary language containing only 0.
Definition: elementary_language.hh:38
std::size_t wordSize() const
Returns the number of the events in this elementary language.
Definition: elementary_language.hh:73
void enumerate(std::vector< ElementaryLanguage > &result) const
Make a vector of simple elementary languages in this elementary language.
Definition: elementary_language.hh:87
bool contains(const TimedWord &testedWord) const
Check if the given the timed word is a member of this elementary languages.
Definition: elementary_language.hh:185
TimedWord sample() const
Return a timed word in this elementary language.
Definition: elementary_language.hh:114
static ElementaryLanguage convexHull(const std::list< ElementaryLanguage > &elementaryLanguages)
Construct a convex-hull of the given timed conditions.
Definition: elementary_language.hh:49
ElementaryLanguage operator+(const ElementaryLanguage &another) const
Concatenate two elementary languages.
Definition: elementary_language.hh:80
std::vector< ElementaryLanguage > enumerate() const
Make a vector of simple elementary languages in this elementary language.
Definition: elementary_language.hh:104
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
bool isSimple() const
Returns if this timed condition is simple.
Definition: timed_condition.hh:98
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
void enumerate(std::vector< TimedCondition > &simpleConditions) const
Make a vector of simple timed conditions in this timed condition.
Definition: timed_condition.hh:299
static TimedCondition empty()
Construct the empty timed condition, i.e. .
Definition: timed_condition.hh:79
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
A timed word.
Definition: timed_word.hh:25
std::size_t wordSize() const
Return the number of the actions in this timed word.
Definition: timed_word.hh:150
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