libmonaa  0.5.2
zone_automaton.hh
1 #pragma once
2 
3 #include "timed_automaton.hh"
4 #include "zone.hh"
5 #include <stack>
6 #include <unordered_set>
7 #include <utility>
8 
9 struct ZAState {
10  bool isMatch;
11  // An epsilon transition is denoted by the null character (\0)
12  std::array<std::vector<std::weak_ptr<ZAState>>, CHAR_MAX> next;
13  TAState *taState;
14  Zone zone;
15  ZAState() : isMatch(false), next({}) {}
16  ZAState(TAState *taState, Zone zone)
17  : isMatch(taState->isMatch), next({}), taState(taState),
18  zone(std::move(zone)) {}
19  ZAState(bool isMatch) : isMatch(isMatch), next({}) {}
20  ZAState(bool isMatch,
21  std::array<std::vector<std::weak_ptr<ZAState>>, CHAR_MAX> next)
22  : isMatch(isMatch), next(next) {}
23  bool operator==(std::pair<TAState *, Zone> pair) {
24  return pair.first == taState && pair.second == zone;
25  }
26 };
27 
29  bool isMatch;
30  std::array<std::vector<std::weak_ptr<NoEpsilonZAState>>, CHAR_MAX> next;
31  std::unordered_set<std::shared_ptr<ZAState>> zaStates;
32  bool operator==(const std::unordered_set<std::shared_ptr<ZAState>> &zas) {
33  return zas == zaStates;
34  }
35 };
36 
39 static inline void
40 epsilonClosure(std::unordered_set<std::shared_ptr<ZAState>> &closure) {
41  auto waiting =
42  std::deque<std::shared_ptr<ZAState>>(closure.begin(), closure.end());
43  while (!waiting.empty()) {
44  for (auto wstate : waiting.front()->next[0]) {
45  auto state = wstate.lock();
46  if (state && closure.find(state) == closure.end()) {
47  closure.insert(state);
48  waiting.push_back(state);
49  }
50  }
51  waiting.pop_front();
52  }
53 }
54 
55 struct ZoneAutomaton : public Automaton<ZAState> {
56  using State = ::ZAState;
57 
60  // Find states unreachable to any accepting states
61  using Config = std::pair<std::shared_ptr<ZAState>,
62  std::unordered_set<std::shared_ptr<ZAState>>>;
63  std::stack<Config> States;
64  for (auto state : initialStates) {
65  States.push(Config(state, {}));
66  }
67  std::unordered_set<std::shared_ptr<ZAState>> reachable;
68  while (!States.empty()) {
69  Config conf = States.top();
70  States.pop();
71  if (conf.first->isMatch) {
72  reachable.insert(conf.first);
73  reachable.insert(conf.second.begin(), conf.second.end());
74  }
75  for (const auto &edges : conf.first->next) {
76  for (const auto &edge : edges) {
77  if (conf.second.find(conf.first) != conf.second.end()) {
78  // We are in a loop
79  continue;
80  }
81  if (reachable.find(edge.lock()) != reachable.end()) {
82  // The next state is reachable
83  reachable.insert(conf.first);
84  reachable.insert(conf.second.begin(), conf.second.end());
85  } else {
86  // The next state may be unreachable
87  auto parents = conf.second;
88  parents.insert(conf.first);
89  States.push(Config(edge.lock(), parents));
90  }
91  }
92  }
93  }
94 
95  // Remove unreachable states
96  for (auto it = states.begin(); it != states.end();) {
97  if (reachable.find(*it) == reachable.end()) {
98  it = states.erase(it);
99  } else {
100  it++;
101  }
102  }
103  for (auto it = initialStates.begin(); it != initialStates.end();) {
104  if (reachable.find(*it) == reachable.end()) {
105  it = initialStates.erase(it);
106  } else {
107  it++;
108  }
109  }
110  }
111 
117  const std::vector<std::shared_ptr<TAState>> taInitialStates) {
118  // update initial states
119  initialStates.clear();
120  for (std::shared_ptr<ZAState> s : states) {
121  if (std::find_if(taInitialStates.begin(), taInitialStates.end(),
122  [&](std::shared_ptr<TAState> taS) {
123  return taS.get() == s->taState;
124  }) != taInitialStates.end()) {
125  initialStates.push_back(s);
126  }
127  }
128 
129  // update accepting states
130  for (auto &state : states) {
131  state->isMatch = state->taState->isMatch;
132  }
133  }
134 
136  bool empty() const {
137  std::vector<std::shared_ptr<ZAState>> currentStates = initialStates;
138  std::unordered_set<std::shared_ptr<ZAState>> visited = {
139  initialStates.begin(), initialStates.end()};
140  while (!currentStates.empty()) {
141  std::vector<std::shared_ptr<ZAState>> nextStates;
142  for (auto state : currentStates) {
143  if (state->isMatch) {
144  return false;
145  }
146  for (const auto &edges : state->next) {
147  for (const auto &edge : edges) {
148  auto target = edge.lock();
149  if (target && visited.find(target) == visited.end()) {
150  // We have not visited the state
151  nextStates.push_back(target);
152  visited.insert(target);
153  }
154  }
155  }
156  }
157  currentStates = std::move(nextStates);
158  }
159  return true;
160  }
161 };
An automaton.
Definition: common_types.hh:13
std::vector< std::shared_ptr< ZAState > > states
The states of this automaton.
Definition: common_types.hh:14
std::vector< std::shared_ptr< ZAState > > initialStates
The initial states of this automaton.
Definition: common_types.hh:19
Definition: zone_automaton.hh:28
A state of timed automata.
Definition: timed_automaton.hh:19
bool isMatch
The value is true if and only if the state is an accepting state.
Definition: timed_automaton.hh:21
Definition: zone_automaton.hh:9
Definition: zone_automaton.hh:55
void updateInitAccepting(const std::vector< std::shared_ptr< TAState >> taInitialStates)
Propagate accepting states from the original timed automaton.
Definition: zone_automaton.hh:116
void removeDeadStates()
remove states unreachable to any accepting states
Definition: zone_automaton.hh:59
bool empty() const
emptiness check of the language
Definition: zone_automaton.hh:136
Implementation of a zone with DBM.
Definition: zone.hh:43