LearnTA  0.0.1
recognizable_languages.hh
1 
6 #pragma once
7 
8 #include <utility>
9 #include <vector>
10 #include <ostream>
11 #include "single_morphism.hh"
12 #include "forward_regional_elementary_language.hh"
13 
14 namespace learnta {
19  private:
20  std::vector<ElementaryLanguage> prefixes;
21  std::vector<ElementaryLanguage> final;
22  std::vector<SingleMorphism> morphisms;
23 
24  [[nodiscard]] TimedWord maps(const TimedWord &word) const {
25  if (this->inPrefixes(word)) {
26  return word;
27  } else {
28  return split(word)->apply();
29  }
30  }
31 
32  public:
33  RecognizableLanguage(std::vector<ElementaryLanguage> prefixes,
34  std::vector<ElementaryLanguage> final,
35  std::vector<SingleMorphism> morphisms) : prefixes(std::move(prefixes)),
36  final(std::move(final)),
37  morphisms(std::move(morphisms)) {
38  // Assert the precondition
39  assert(std::all_of(this->final.begin(), this->final.end(), [&] (const ElementaryLanguage &finalLanguage) {
40  return std::find(this->prefixes.begin(), this->prefixes.end(), finalLanguage) != this->prefixes.end();
41  }));
42  }
43 
47  [[nodiscard]] bool inPrefixes(const TimedWord &word) const {
48  return std::any_of(prefixes.begin(), prefixes.end(), [&] (const ElementaryLanguage &language) {
49  return language.contains(word);
50  });
51  }
52 
56  [[nodiscard]] bool isFinal(const TimedWord &word) const {
57  return std::any_of(final.begin(), final.end(), [&] (const ElementaryLanguage &language) {
58  return language.contains(word);
59  });
60  }
61 
62  struct SplitTriple {
63  TimedWord prefix;
64  TimedWord suffix;
65  SingleMorphism morphism;
66  [[nodiscard]] TimedWord apply() const {
67  BOOST_LOG_TRIVIAL(debug) << "applying: " << *this;
68  return morphism.maps(prefix) + suffix;
69  }
70 
71  bool operator==(const SplitTriple &rhs) const {
72  return prefix == rhs.prefix &&
73  suffix == rhs.suffix &&
74  morphism == rhs.morphism;
75  }
76 
77  bool operator!=(const SplitTriple &rhs) const {
78  return !(rhs == *this);
79  }
80 
81  friend std::ostream &operator<<(std::ostream &os, const SplitTriple &triple) {
82  os << "prefix: " << triple.prefix << " suffix: " << triple.suffix << " morphism: " << triple.morphism;
83  return os;
84  }
85  };
86 
92  [[nodiscard]] std::optional<SplitTriple> split(const TimedWord &word) const {
93  // Make the regional elementary language containing word
94  const auto regionalElementary = ForwardRegionalElementaryLanguage::fromTimedWord(word);
95  // Make the prefixes of it
96  const auto elemPrefixes = regionalElementary.prefixes();
97  // Find the corresponding morphism based on the prefixes
98  const auto it = std::find_if(this->morphisms.begin(), this->morphisms.end(), [&] (const auto &morphism) {
99  return std::any_of(elemPrefixes.begin(), elemPrefixes.end(), [&] (const auto& prefix) {
100  return morphism.isDomain(prefix);
101  });
102  });
103  if (it == this->morphisms.end()) {
104  return std::nullopt;
105  }
106  // When we do not have to split
107  if (it->getDomain().contains(word)) {
108  return SplitTriple {word, TimedWord{"", {0}}, *it};
109  }
110  // Split word using the prefix
111  auto prefixDomainTimedCondition = it->getDomain().getTimedCondition();
112  std::vector<double> prefixDurations;
113  prefixDurations.reserve(it->getDomain().wordSize());
114  for (std::size_t i = 0; i < it->getDomain().wordSize(); ++i) {
115  prefixDomainTimedCondition.restrictUpperBound(i, i, Bounds{word.getDurations().at(i), true});
116  prefixDomainTimedCondition.restrictLowerBound(i, i, Bounds{-word.getDurations().at(i), true});
117  prefixDurations.push_back(word.getDurations().at(i));
118  }
119  const auto upperBound = prefixDomainTimedCondition.getUpperBound(it->getDomain().wordSize(), it->getDomain().wordSize());
120  if (Bounds{word.getDurations().at(it->getDomain().wordSize()), true} <= upperBound) {
121  // We use the duration in the given timed word if it is in the bound
122  prefixDurations.push_back(word.getDurations().at(it->getDomain().wordSize()));
123  } else if (upperBound.second){
124  // We use the upper bound if it is non-strict
125  prefixDurations.push_back(upperBound.first);
126  } else {
127  // We sample a valuation if there is no longest duration
128  const auto tmpPrefix = ElementaryLanguage{it->getDomain().getWord(), prefixDomainTimedCondition}.sample();
129  prefixDurations.push_back(tmpPrefix.getDurations().back());
130  }
131  const auto prefix = TimedWord{it->getDomain().getWord(), prefixDurations};
132  // return the SplitTriple
133  return SplitTriple {prefix, word.getSuffix(prefix), *it};
134  }
135 
139  [[nodiscard]] bool contains(TimedWord word) const {
140  while (!this->inPrefixes(word)) {
141  word = this->maps(word);
142  }
143  return this->isFinal(word);
144  }
145 
146  friend std::ostream &operator<<(std::ostream &os, const RecognizableLanguage &language) {
147  os << "{\n";
148  for (const auto& morphism: language.morphisms) {
149  os << morphism << "\n";
150  }
151  os << "}";
152 
153  return os;
154  }
155  };
156 }
An elementary language.
Definition: elementary_language.hh:23
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
static ForwardRegionalElementaryLanguage fromTimedWord(const TimedWord &timedWord)
Construct the fractional elementary language containing the given timed word.
Definition: forward_regional_elementary_language.hh:46
Recognizable timed language in [MP04].
Definition: recognizable_languages.hh:18
bool inPrefixes(const TimedWord &word) const
Returns if the given timed word is in the prefixes.
Definition: recognizable_languages.hh:47
bool isFinal(const TimedWord &word) const
Returns if the given timed word is in the final prefixes.
Definition: recognizable_languages.hh:56
std::optional< SplitTriple > split(const TimedWord &word) const
Split the given timed word with the morphism.
Definition: recognizable_languages.hh:92
bool contains(TimedWord word) const
Returns if this recognizable timed language contains the given timed word.
Definition: recognizable_languages.hh:139
Morphism from an external elementary language to an internal one.
Definition: single_morphism.hh:18
TimedWord maps(const TimedWord &word) const
Apply this single morphism to the given timed word.
Definition: single_morphism.hh:55
A timed word.
Definition: timed_word.hh:25
TimedWord getSuffix(const TimedWord &prefix) const
Definition: timed_word.hh:139
Definition: experiment_runner.hh:23
Definition: recognizable_languages.hh:62