CBMC
nfa.h
Go to the documentation of this file.
1 
12 #ifndef CPROVER_UTIL_NFA_H
13 #define CPROVER_UTIL_NFA_H
14 
15 #include <algorithm>
16 #include <cstddef>
17 #include <fstream>
18 #include <iosfwd>
19 #include <iterator>
20 #include <unordered_map>
21 #include <unordered_set>
22 #include <vector>
23 
26 template <typename T>
27 struct nfat
28 {
29  using state_labelt = std::size_t;
33  struct statet
34  {
35  private:
36  std::unordered_set<state_labelt> possible_states;
37 
38  public:
39  friend struct nfat;
40 
41  bool contains(state_labelt state_label) const
42  {
43  return possible_states.count(state_label) != 0;
44  }
45  };
46 
47  nfat() = default;
48 
50  void add_transition(state_labelt from, T when, state_labelt to)
51  {
52  resize_if_necessary(from, to);
53  transitions[from].when[when].insert(to);
54  }
55 
60  {
61  resize_if_necessary(from, to);
62  transitions[from].arbitrary.insert(to);
63  }
64 
67  {
68  resize_if_necessary(from, to);
69  transitions[from].epsilon.insert(to);
70  }
71 
73  {
74  statet result{};
75  result.possible_states.insert(initial);
77  return result;
78  }
79 
80  statet next_state(const statet &current, const T &input) const
81  {
82  statet new_state{};
83  for(const auto label : current.possible_states)
84  {
85  const auto &transition = transitions[label];
86  const auto it = transition.when.find(input);
87  if(it != transition.when.end())
88  {
89  for(const auto result_state : it->second)
90  {
91  new_state.possible_states.insert(result_state);
92  }
93  }
94  for(const auto result_state : transition.arbitrary)
95  {
96  new_state.possible_states.insert(result_state);
97  }
98  }
99  follow_epsilon_transitions(new_state);
100  return new_state;
101  }
102 
105  void dump_automaton_dot_to(std::ostream &out) const
106  {
107  out << "digraph {\n";
108  for(state_labelt from = 0; from < transitions.size(); ++from)
109  {
110  for(const auto to : transitions[from].arbitrary)
111  {
112  out << 'S' << from << " -> S" << to << "[label=\"*\"]\n";
113  }
114  for(const auto to : transitions[from].epsilon)
115  {
116  out << 'S' << from << " -> S" << to << u8"[label=\"ε\"]\n";
117  }
118  for(const auto &pair : transitions[from].when)
119  {
120  const auto &in = pair.first;
121  const auto &tos = pair.second;
122  for(const auto to : tos)
123  {
124  out << 'S' << from << " -> S" << to << "[label=\"(" << in << ")\"]\n";
125  }
126  }
127  }
128  out << "}\n";
129  }
130 
131 private:
133  {
134  const auto min_size = std::max(from, to) + 1;
135  if(transitions.size() < min_size)
136  {
137  transitions.resize(min_size);
138  }
139  }
140 
142  {
143  std::vector<state_labelt> new_states{};
144  do
145  {
146  new_states.clear();
147  for(const auto from : state.possible_states)
148  {
149  for(const auto to : transitions[from].epsilon)
150  {
151  if(!state.contains(to))
152  {
153  new_states.push_back(to);
154  }
155  }
156  }
157  std::copy(
158  new_states.begin(),
159  new_states.end(),
160  std::inserter(state.possible_states, state.possible_states.end()));
161  } while(!new_states.empty());
162  }
163 
164  struct transitiont
165  {
166  std::unordered_set<state_labelt> epsilon;
167  std::unordered_set<state_labelt> arbitrary;
168  std::unordered_map<T, std::unordered_set<state_labelt>> when;
169  };
170 
171  std::vector<transitiont> transitions;
172 };
173 
174 #endif // CPROVER_UTIL_NFA_H
uint64_t u8
Definition: bytecode_info.h:58
A state is a set of possibly active transitions.
Definition: nfa.h:34
std::unordered_set< state_labelt > possible_states
Definition: nfa.h:36
bool contains(state_labelt state_label) const
Definition: nfa.h:41
std::unordered_map< T, std::unordered_set< state_labelt > > when
Definition: nfa.h:168
std::unordered_set< state_labelt > arbitrary
Definition: nfa.h:167
std::unordered_set< state_labelt > epsilon
Definition: nfa.h:166
Very simple NFA implementation Not super performant, but should be good enough for our purposes.
Definition: nfa.h:28
statet initial_state(state_labelt initial) const
Definition: nfa.h:72
statet next_state(const statet &current, const T &input) const
Definition: nfa.h:80
nfat()=default
std::size_t state_labelt
Definition: nfa.h:29
void resize_if_necessary(state_labelt from, state_labelt to)
Definition: nfa.h:132
void add_arbitrary_transition(state_labelt from, state_labelt to)
Add a transition from "from" to "to" when any input is consumed This is handled a special case so not...
Definition: nfa.h:59
std::vector< transitiont > transitions
Definition: nfa.h:171
void dump_automaton_dot_to(std::ostream &out) const
Write the automaton structure to out in graphviz dot format.
Definition: nfa.h:105
void follow_epsilon_transitions(statet &state) const
Definition: nfa.h:141
void add_transition(state_labelt from, T when, state_labelt to)
Add a transition from "from" to "to" exactly when "when" is consumed.
Definition: nfa.h:50
void add_epsilon_transition(state_labelt from, state_labelt to)
Add a transition from "from" to "to" that doesn’t consume input.
Definition: nfa.h:66