reglibcpp  1.0.0
(Naïve) C++ implementation of models for regular languages
dfa.cpp
Go to the documentation of this file.
1 #include "dfa.h"
3 using std::valarray;
4 using std::vector;
5 using std::string;
6 using std::unique_ptr;
7 using std::u32string;
8 
9 using std::distance;
10 using std::to_string;
11 using std::move;
12 
13 #include <unordered_set>
14 using std::unordered_set;
15 
16 #include <unordered_map>
17 using std::unordered_map;
18 
19 #include <forward_list>
20 using std::forward_list;
21 
22 #include <algorithm>
23 using std::find;
24 using std::sort;
25 using std::none_of;
26 
27 #include <cstdint>
28 
29 #include "nfa.h"
30 #include "expression.h"
31 
32 namespace reg {
33 
35 struct dfa::pImpl {
36  valarray<bool> accepting;
37  vector<char32_t> alphabet;
38  vector<string> utf8Alphabet;
39  vector<string> labels;
40  vector<vector<size_t>> transitions;
41 
43  pImpl() : accepting(false, 1), alphabet(0), utf8Alphabet(0), labels(1), transitions(0) {}
44 
46  pImpl(vector<char32_t>& alphabet, vector<vector<size_t>>& transitions,
47  vector<string>& labels, valarray<bool>& accepting) :
48  accepting(move(accepting)),
49  alphabet(move(alphabet)),
50  labels(move(labels)),
51  transitions(move(transitions)) {
52  utf8Alphabet.reserve(this->alphabet.size());
53  for (char32_t symbol : this->alphabet) {
54  utf8Alphabet.push_back(expression::converter->to_bytes(symbol));
55  }
56  }
57 
59 
64  static vector<valarray<bool>> indistinguishableStates(
65  vector<vector<size_t>> const& transitions, valarray<bool> const& accepting) {
66  vector<valarray<bool>> distinguishable;
67  distinguishable.reserve(transitions.size());
68  for (size_t q(0); q < transitions.size(); q++) {
69  bool qAcc(accepting[q]);
70  distinguishable.push_back(valarray<bool>(false, transitions.size()));
71  for (size_t p(0); p < q; p++) {
72  bool pAcc(accepting[p]);
73  distinguishable[q][p] = (qAcc != pAcc);
74  distinguishable[p][q] = (qAcc != pAcc);
75  }
76  }
77  bool changes(true);
78  while (changes) {
79  changes = false;
80  for (size_t q(0); q < transitions.size(); q++) {
81  for (size_t p(0); p < q; p++) {
82  if (distinguishable[q][p]) {
83  continue;
84  }
85  for (size_t s(0); s < transitions[q].size(); s++) {
86  size_t qS(transitions[q][s]);
87  size_t pS(transitions[p][s]);
88  if (distinguishable[qS][pS]) {
89  changes = true;
90  distinguishable[q][p] = true;
91  distinguishable[p][q] = true;
92  break;
93  }
94  }
95  }
96  }
97  }
98  valarray<bool> allTrue(true, transitions.size());
99  for (size_t i(0); i < distinguishable.size(); i++) {
100  distinguishable[i] ^= allTrue;
101  }
102  return distinguishable;
103  }
104 };
105 
107 dfa::dfa() : p(new pImpl) {}
108 
110 dfa::dfa(vector<char32_t>& alphabet,
111  vector<vector<size_t>>& transitions,
112  vector<string>& labels,
113  valarray<bool>& acceptingStates) :
114  p(unique_ptr<pImpl>(new pImpl(alphabet, transitions, labels, acceptingStates))) {}
115 
117 dfa::dfa(dfa& d) : p(new pImpl(*(d.p))) {}
118 
120 
121 dfa::dfa(dfa&& d) : p(new pImpl) {p.swap(d.p);}
122 
124 dfa::dfa(dfa::builder& b) : p(move(b.build().p)) {}
125 
127 dfa& dfa::operator=(const dfa& d) {
128  if (this != &d) {
129  p.reset(new pImpl(*(d.p)));
130  }
131  return *this;
132 }
133 
135 
137  if (this != &d) {
138  p.reset(new pImpl);
139  p.swap(d.p);
140  }
141  return *this;
142 }
143 
144 dfa::~dfa() = default;
145 
147 
152 bool dfa::operator==(dfa const& d) const {
153  forward_list<char32_t> unitedAlphabet(p->alphabet.begin(), p->alphabet.end());
154  size_t unitedAlphabetSize(p->alphabet.size());
155  for (char32_t symbol : d.getAlphabet()) {
156  if (find(p->alphabet.begin(), p->alphabet.end(), symbol) == p->alphabet.end()) {
157  unitedAlphabet.push_front(symbol);
158  unitedAlphabetSize++;
159  }
160  }
161  vector<vector<size_t>> tTable(getNumberOfStates()+d.getNumberOfStates()+1, vector<size_t>(unitedAlphabetSize));
162  valarray<bool> accepting(false, getNumberOfStates()+d.getNumberOfStates()+1);
163  for (size_t q(0); q < getNumberOfStates(); q++) {
164  size_t s(0);
165  vector<size_t>& row = tTable[q];
166  for (char32_t symbol : unitedAlphabet) {
167  #ifdef __EXCEPTIONS
168  try {
169  row[s] = delta(q, symbol);
170  } catch (std::domain_error e) {
171  row[s] = getNumberOfStates()+d.getNumberOfStates();
172  }
173  #else
174  size_t r(delta(q, symbol));
175  if (r >= SIZE_MAX-1) {
176  row[s] = getNumberOfStates()+d.getNumberOfStates();
177  } else {
178  row[s] = r;
179  }
180  #endif
181  s++;
182  }
183  accepting[q] = isAccepting(q);
184  }
185  for (size_t q(0); q < d.getNumberOfStates(); q++) {
186  size_t s(0);
187  vector<size_t>& row = tTable[q+getNumberOfStates()];
188  for (char32_t symbol : unitedAlphabet) {
189  #ifdef __EXCEPTIONS
190  try {
191  row[s] = getNumberOfStates()+d.delta(q, symbol);
192  } catch (std::domain_error e) {
193  row[s] = getNumberOfStates()+d.getNumberOfStates();
194  }
195  #else
196  size_t r(delta(q, symbol));
197  if (r >= SIZE_MAX-1) {
198  row[s] = getNumberOfStates()+d.getNumberOfStates();
199  } else {
200  row[s] = r;
201  }
202  #endif
203  s++;
204  }
205  accepting[q+getNumberOfStates()] = d.isAccepting(q);
206  }
207  for (size_t s(0); s < unitedAlphabetSize; s++) {
209  }
210  return pImpl::indistinguishableStates(tTable, accepting)[0][getNumberOfStates()];
211 }
212 
214 bool dfa::operator!=(dfa const& d) const {return !operator==(d);}
215 
217 
223 size_t dfa::delta(size_t q, char32_t symbol) const {
224  size_t i = distance(
225  p->alphabet.begin(),
226  find(p->alphabet.begin(), p->alphabet.end(), symbol)
227  );
228  if (i >= p->alphabet.size()) {
229  #ifdef __EXCEPTIONS
230  throw std::domain_error(
231  string(u8"δ is not defined for symbol ").append(1, symbol)
232  );
233  #else
234  return SIZE_MAX;
235  #endif
236  }
237  if (q >= p->labels.size()) {
238  #ifdef __EXCEPTIONS
239  throw std::out_of_range(
240  string("There is no state with index ").append(std::to_string(q))
241  );
242  #else
243  return SIZE_MAX-1;
244  #endif
245  }
246  return p->transitions[q][i];
247 }
248 
250 size_t dfa::delta(size_t q, string const& utf8Symbol) const {
251  return delta(q, expression::converter->from_bytes(utf8Symbol)[0]);
252 }
253 
255 
261 size_t dfa::deltaHat(size_t q, std::u32string const& word) const {
262  for (char32_t symbol : word) {
263  q = delta(q, symbol);
264  }
265  return q;
266 }
267 
269 size_t dfa::deltaHat(size_t q, string const& utf8Word) const {
270  return deltaHat(q, expression::converter->from_bytes(utf8Word));
271 }
272 
274 
278 string const& dfa::getLabelOf(size_t q) const {
279  return p->labels[q];
280 }
281 
283 
287 vector<char32_t> const& dfa::getAlphabet() const {
288  return p->alphabet;
289 }
290 
292 
296 vector<string> const& dfa::getUtf8Alphabet() const {
297  return p->utf8Alphabet;
298 }
299 
301 
305 size_t dfa::getNumberOfStates() const {
306  return p->labels.size();
307 }
308 
310 
315 bool dfa::isAccepting(size_t q) const {
316  return p->accepting[q];
317 }
318 
321  string initial;
322  unordered_set<char32_t> alphabet;
323  unordered_set<string> acceptingStates;
324  unordered_map<string,unordered_map<char32_t,string>> transitions;
326 
328  pImpl() = default;
330 
333  string& initial,
334  unordered_set<char32_t>& alphabet,
335  unordered_set<string>& acceptingStates,
336  unordered_map<string,unordered_map<char32_t,string>>& transitions
337  ) : initial(move(initial)),
338  alphabet(move(alphabet)),
340  transitions(move(transitions)) {}
341 
343  bool isTrashState(string const& q) const {
344  if (acceptingStates.count(q) != 0) {
345  return false;
346  }
347  auto const& from = transitions.at(q);
348  for (char32_t symbol : alphabet) {
349  auto via = from.find(symbol);
350  if (via != from.end() && (*via).second != q) {
351  return false;
352  }
353  }
354  return true;
355  }
356 
358  string const& generateNewState() {
359  size_t q(0);
360  string newState;
361  while (transitions.find(newState = string("q").append(to_string(q))) != transitions.end()) {
362  q++;
363  }
364  if (transitions.empty()) {
365  initial = newState;
366  }
367  return transitions.insert(std::make_pair(newState, unordered_map<char32_t, string>())).first->first;
368  }
369 
371 
372  void complete() {
373  bool trashUsed(false);
374  string const& trashState = [&]{
375  for (auto const& entry : this->transitions) {
376  if (this->isTrashState(entry.first)) {
377  trashUsed = true;
378  return entry.first;
379  }
380  }
381  return this->generateNewState();
382  }();
383  for (auto& from : transitions) {
384  for (char32_t symbol : alphabet) {
385  if (from.second.find(symbol) == from.second.end()) {
386  from.second[symbol] = trashState;
387  trashUsed |= (from.first != trashState);
388  }
389  }
390  }
391  if (!trashUsed) {
392  transitions.erase(trashState);
393  }
394  }
395 
398  size_t operator()(valarray<bool> const& value) const {
399  size_t hash = 0;
400  for (bool v : value) {
401  hash <<= 1;
402  hash |= v;
403  }
404  return hash;
405  }
406  };
407 
409  static bool valarrayFullTrue(valarray<bool> const& a) {
410  bool fullTrue = true;
411  for (bool b : a) {
412  fullTrue &= b;
413  }
414  return fullTrue;
415  }
416 
419  valarray<bool> const& val;
420 
421  ValarrayBoolEqualTo(valarray<bool> const& val) : val(val) {}
422 
423  bool operator()(valarray<bool> const& other) const {
424  return (val.size() == other.size() && valarrayFullTrue(val == other));
425  }
426  };
427 
430  bool operator()(valarray<bool> const& a, valarray<bool> const& b) const {
431  return ValarrayBoolEqualTo(a)(b);
432  }
433  };
434 };
435 
438 
441  auto initial = dfa.getLabelOf(0);
442  auto alphabet = unordered_set<char32_t>(dfa.getAlphabet().begin(), dfa.getAlphabet().end());
443  auto labels = unordered_set<string>(dfa.getNumberOfStates());
444  auto transitions = unordered_map<string,unordered_map<char32_t,string>>(dfa.getNumberOfStates());
445  p = unique_ptr<pImpl>(new pImpl(
446  initial,
447  alphabet,
448  labels,
449  transitions
450  ));
451  for (size_t q = 0; q < dfa.getNumberOfStates(); ++q) {
452  for (char32_t symbol : dfa.getAlphabet()) {
453  defineTransition(dfa.getLabelOf(q), dfa.getLabelOf(dfa.delta(q, symbol)), symbol);
454  }
455  setAccepting(dfa.getLabelOf(q), dfa.isAccepting(q));
456  }
457 }
458 
461  unordered_set<valarray<bool>, pImpl::ValarrayBoolHasher, pImpl::ValarrayBoolEqual> done;
462  forward_list<valarray<bool>> stack(1, nfa.epsilonClosure(0));
463  size_t stackSize(1);
464  auto initial = nfa.getLabelOf(stack.front());
465  auto alphabet = nfa.getAlphabet();
466  alphabet.erase(alphabet.begin());
467  unordered_set<char32_t> alphabetS(alphabet.begin(), alphabet.end());
468  unordered_set<string> acceptingStates;
469  unordered_map<string,unordered_map<char32_t,string>> transitions;
470  transitions[initial];
471  p = unique_ptr<pImpl>(new pImpl(
472  initial,
473  alphabetS,
474  acceptingStates,
475  transitions
476  ));
477  while (stackSize != 0) {
478  valarray<bool> current(move(stack.front()));
479  stack.pop_front();
480  stackSize--;
481  for (char32_t symbol : p->alphabet) {
482  valarray<bool> next(nfa.deltaHat(current, u32string(1, symbol)));
483  defineTransition(nfa.getLabelOf(current), nfa.getLabelOf(next), symbol);
484  pImpl::ValarrayBoolEqualTo equalToNext(next);
485  if (!equalToNext(current) &&
486  none_of(stack.begin(), stack.end(), equalToNext) &&
487  none_of(done.begin(), done.end(), equalToNext)) {
488  stack.push_front(next);
489  stackSize++;
490  }
491  }
492  for (size_t qi(0); qi < current.size(); qi++) {
493  if (current[qi] && nfa.isAccepting(qi)) {
494  setAccepting(nfa.getLabelOf(current), true);
495  break;
496  }
497  }
498  done.insert(current);
499  }
500 }
501 
503 dfa::builder::builder(builder& b) : p(new pImpl(*(b.p))) {}
504 
506 
507 dfa::builder::builder(builder&& b) : p(new pImpl) {p.swap(b.p);}
508 
511  if (this != &b) {
512  p.reset(new pImpl(*(b.p)));
513  }
514  return *this;
515 }
516 
518 
520  if (this != &b) {
521  p.reset(new pImpl);
522  p.swap(b.p);
523  }
524  return *this;
525 }
526 
527 dfa::builder::~builder() = default;
528 
530 
536  p->alphabet.insert(symbol);
537  return *this;
538 }
539 
541 dfa::builder& dfa::builder::addSymbol(string const& utf8Symbol) {
542  return addSymbol(expression::converter->from_bytes(utf8Symbol)[0]);
543 }
544 
546 
552 dfa::builder& dfa::builder::setAccepting(string const& state, bool accept) {
553  if (p->transitions.empty()) {
554  p->initial = state;
555  }
556  p->transitions[state];
557  if (accept) {
558  p->acceptingStates.insert(state);
559  } else {
560  p->acceptingStates.erase(state);
561  }
562  return *this;
563 }
564 
566 
572  p->initial = state;
573  p->transitions[state];
574  return *this;
575 }
576 
578 
587 dfa::builder& dfa::builder::defineTransition(string const& from, string const& to, char32_t symbol) {
588  if (p->transitions.empty()) {
589  p->initial = from;
590  }
591  p->transitions[to];
592  p->transitions[from][symbol] = to;
593  addSymbol(symbol);
594  return *this;
595 }
596 
598 dfa::builder& dfa::builder::defineTransition(string const& from, string const& to, string const& utf8Symbol) {
599  return defineTransition(from, to, expression::converter->from_bytes(utf8Symbol)[0]);
600 }
602 
612  p->complete();
613  vector<vector<size_t>> tTable(p->transitions.size());
614  valarray<bool> accepting(false, p->transitions.size());
615  vector<char32_t> sortedAlphabet(p->alphabet.begin(), p->alphabet.end());
616  sort(sortedAlphabet.begin(), sortedAlphabet.end());
617  vector<string> orderedStates;
618  orderedStates.reserve(p->transitions.size());
619  orderedStates.push_back(p->initial);
620  for (auto const& entry : p->transitions) {
621  if (entry.first != p->initial) {
622  orderedStates.push_back(entry.first);
623  }
624  }
625  for (size_t q(0); q < orderedStates.size(); q++) {
626  string const& qLabel(orderedStates[q]);
627  if (p->acceptingStates.find(qLabel) != p->acceptingStates.end()) {
628  accepting[q] = true;
629  }
630  for (size_t s(0); s < sortedAlphabet.size(); s++) {
631  tTable[q].push_back(distance(orderedStates.begin(), find(orderedStates.begin(), orderedStates.end(), p->transitions[qLabel][sortedAlphabet[s]])));
632  }
633  }
634  vector<valarray<bool>> equivalences(dfa::pImpl::indistinguishableStates(tTable, accepting));
635  for (size_t q(0); q < orderedStates.size(); q++) {
636  for (size_t first(0); first < equivalences[q].size(); first++) {
637  if (equivalences[q][first] && q > first) {
638  string const& superfluous(orderedStates[q]);
639  string const& remaining(orderedStates[first]);
640  p->acceptingStates.erase(superfluous);
641  p->transitions.erase(superfluous);
642  for (auto& from : p->transitions) {
643  for (auto& via : from.second) {
644  if (via.second == superfluous) {
645  via.second = remaining;
646  }
647  }
648  }
649  break;
650  }
651  }
652  }
653  return *this;
654 }
655 
657 
664  unordered_set<string> reachable(&(p->initial), &(p->initial)+1);
665  unordered_set<string> newReachable(reachable);
666  while (newReachable.size() > 0) {
667  unordered_set<string> oldReachable(move(newReachable));
668  newReachable.clear();
669  for (string const& reachableState : oldReachable) {
670  for (auto const& reachedState : p->transitions[reachableState]) {
671  if (reachable.insert(reachedState.second).second) {
672  newReachable.insert(reachedState.second);
673  }
674  }
675  }
676  }
677  for (auto it = p->transitions.begin(); it != p->transitions.end(); ) {
678  if (reachable.find(it->first) == reachable.end()) {
679  p->acceptingStates.erase(it->first);
680  it = p->transitions.erase(it);
681  } else {
682  it++;
683  }
684  }
685  unordered_set<string> producing(p->acceptingStates);
686  unordered_set<string> newProducing(producing);
687  while (newProducing.size() > 0) {
688  unordered_set<string> oldProducing(move(newProducing));
689  newProducing.clear();
690  for (auto const& from : p->transitions) {
691  for (auto const& via : from.second) {
692  if (producing.find(via.second) != producing.end()) {
693  if (producing.insert(from.first).second) {
694  newProducing.insert(from.first);
695  }
696  break;
697  }
698  }
699  }
700  }
701  for (auto it = p->transitions.begin(); it != p->transitions.end(); ) {
702  if (producing.find(it->first) == producing.end() && it->first != p->initial) {
703  p->acceptingStates.erase(it->first);
704  for (auto& via : p->transitions) {
705  for (auto itv = via.second.begin(); itv != via.second.end(); ) {
706  if (itv->second == it->first) {
707  itv = via.second.erase(itv);
708  } else {
709  itv++;
710  }
711  }
712  }
713  it = p->transitions.erase(it);
714  } else {
715  it++;
716  }
717  }
718  return *this;
719 }
720 
722 
727  vector<char32_t> alphabetV(p->alphabet.begin(), p->alphabet.end());
728  sort(alphabetV.begin(), alphabetV.end());
729  p->complete();
730  vector<string> labelV;
731  labelV.reserve(p->transitions.size());
732  labelV.push_back(p->initial);
733  valarray<bool> acceptingV(labelV.size(), false);
734  for (auto const& tr : p->transitions) {
735  if (tr.first == p->initial) {
736  continue;
737  }
738  labelV.push_back(tr.first);
739  }
740  vector<vector<size_t>> transitionV(labelV.size(), vector<size_t>(alphabetV.size()));
741  for (size_t q(0); q < labelV.size(); q++) {
742  string const& qLabel = labelV[q];
743  acceptingV[q] = (p->acceptingStates.find(qLabel) != p->acceptingStates.end());
744  for (size_t s(0); s < alphabetV.size(); s++) {
745  transitionV[q][s] = distance(
746  labelV.begin(),
747  find(labelV.begin(), labelV.end(), p->transitions[qLabel][alphabetV[s]])
748  );
749  }
750  }
751  return {alphabetV, transitionV, labelV, acceptingV};
752 }
753 } // namespace reg::dfa
bool isAccepting(size_t q) const
Tests whether a state is an accept state within this DFA.
Definition: dfa.cpp:315
bool operator!=(const dfa &d) const
Tests whether this DFA doesn&#39;t accept the same language as another one.
Definition: dfa.cpp:214
unordered_map< string, unordered_map< char32_t, string > > transitions
Transition function (state × symbol → state) of the prospective DFA.
Definition: dfa.cpp:324
builder & setAccepting(std::string const &state, bool accept)
Sets whether or not a state will be accepting within the prospective DFA.
Definition: dfa.cpp:552
static std::unique_ptr< std::wstring_convert< std::codecvt_utf8< char32_t >, char32_t > > const converter
Converts between UTF-8-encoded and UTF-32-encoded strings.
Definition: expression.h:97
Comparison object for valarray<bool>s against a specific instance.
Definition: dfa.cpp:418
bool isTrashState(string const &q) const
Tests whether all of a state&#39;s outgoing transitions point to itself.
Definition: dfa.cpp:343
size_t delta(size_t q, char32_t symbol) const
Computes this DFA&#39;s transition function for a state and a symbol.
Definition: dfa.cpp:223
vector< char32_t > alphabet
Represents the set of processable symbols.
Definition: dfa.cpp:37
dfa()
Constructs a DFA accepting the empty language ∅.
Definition: dfa.cpp:107
Represents nondeterministic finite automata with ε-moves.
Definition: nfa.h:22
valarray< bool > accepting
A true value marks an index as belonging to an accept state.
Definition: dfa.cpp:36
std::vector< char32_t > const & getAlphabet() const
Fetches this NFA&#39;s set of processable symbols.
Definition: nfa.cpp:268
vector< string > utf8Alphabet
Represents the set of processable symbols as UTF-8-encoded strings.
Definition: dfa.cpp:38
std::string const & getLabelOf(size_t q) const
Puts a name to an index.
Definition: nfa.cpp:237
Comparison object for valarray<bool>s, so they can be used as unordered_set keys. ...
Definition: dfa.cpp:429
Represents deterministic finite automata.
Definition: dfa.h:22
Private implementation details of DFAs.
Definition: dfa.cpp:35
std::valarray< bool > deltaHat(size_t q, std::u32string const &word) const
Computes this NFA&#39;s transition function recursively for a string of symbols, starting in a specified ...
Definition: nfa.cpp:140
vector< string > labels
Stores the names of states.
Definition: dfa.cpp:39
Hasher object for valarray<bool>s, so they can be used as unordered_set keys.
Definition: dfa.cpp:397
vector< vector< size_t > > transitions
Stores the transition function as a table viz state index × symbol index → state index...
Definition: dfa.cpp:40
bool isAccepting(size_t q) const
Tests whether a state is an accept state within this NFA.
Definition: nfa.cpp:296
builder & purge()
Purges the prospective DFA of unreachable and non-producing states, allowing for minimization.
Definition: dfa.cpp:663
unordered_set< char32_t > alphabet
Set of symbols processable by the prospective DFA.
Definition: dfa.cpp:322
pImpl(string &initial, unordered_set< char32_t > &alphabet, unordered_set< string > &acceptingStates, unordered_map< string, unordered_map< char32_t, string >> &transitions)
Constructs private implementation object with provided members.
Definition: dfa.cpp:332
std::vector< char32_t > const & getAlphabet() const
Fetches this DFA&#39;s set of processable symbols.
Definition: dfa.cpp:287
pImpl(vector< char32_t > &alphabet, vector< vector< size_t >> &transitions, vector< string > &labels, valarray< bool > &accepting)
Constructs private implementation object with provided members.
Definition: dfa.cpp:46
static vector< valarray< bool > > indistinguishableStates(vector< vector< size_t >> const &transitions, valarray< bool > const &accepting)
Builds the table of indistinguishable states w.r.t. a transition function.
Definition: dfa.cpp:64
dfa & operator=(const dfa &d)
Copy-assigns this DFA by copying another one&#39;s private implementation object.
Definition: dfa.cpp:127
Private implementation details of DFA builders.
Definition: dfa.cpp:320
Contains the reg::nfa class definition.
Contains the reg::expression class defintion.
static bool valarrayFullTrue(valarray< bool > const &a)
Tests whether all of a valarray<bool>&#39;s entries are true.
Definition: dfa.cpp:409
bool operator==(const dfa &d) const
Tests whether this DFA accepts exactly the same language as another one.
Definition: dfa.cpp:152
void complete()
Totalizes a partial transition function by pointing any undefined transitions towards a trash state...
Definition: dfa.cpp:372
builder & makeInitial(std::string const &state)
Resets the initial state for the prospective DFA.
Definition: dfa.cpp:571
builder & merge()
Merges the prospective DFA&#39;s indistinguishable states, allowing for minimization. ...
Definition: dfa.cpp:611
Constructs DFAs step by step.
Definition: dfa.h:49
size_t deltaHat(size_t q, std::u32string const &word) const
Computes this DFA&#39;s transition function recursively for a string of symbols, starting in a specified ...
Definition: dfa.cpp:261
size_t getNumberOfStates() const
Counts this DFA&#39;s states.
Definition: dfa.cpp:305
string initial
Name of the prospective DFA&#39;s initial state.
Definition: dfa.cpp:321
builder()
Constructs a blank builder object.
Definition: dfa.cpp:437
string const & generateNewState()
Generates a uniquely named new state and adds it to the set of states.
Definition: dfa.cpp:358
Definition: dfa.cpp:32
unordered_set< string > acceptingStates
Set of names of the prospective DFA&#39;s accept states.
Definition: dfa.cpp:323
builder & operator=(const builder &b)
Copy-assigns a builder by copying another one&#39;s private implementation object.
Definition: dfa.cpp:510
pImpl()
Constructs private implementation object for a DFA accepting the empty language ∅.
Definition: dfa.cpp:43
pImpl()=default
Constructs empty private implementation object.
std::string const & getLabelOf(size_t q) const
Puts a name to an index.
Definition: dfa.cpp:278
dfa build()
Builds the DFA, as defined by previous operations, including completion.
Definition: dfa.cpp:726
std::vector< std::string > const & getUtf8Alphabet() const
Fetches this DFA&#39;s set of processable symbols as UTF-8-encoded strings.
Definition: dfa.cpp:296
builder & defineTransition(std::string const &from, std::string const &to, char32_t symbol)
(Re-)Defines a transition for the prospective DFA.
Definition: dfa.cpp:587
std::valarray< bool > const & epsilonClosure(size_t q) const
Computes a state&#39;s ε-closure.
Definition: nfa.cpp:185
Contains the reg::dfa class definition.
builder & addSymbol(char32_t symbol)
Adds a symbol to the prospective DFA&#39;s alphabet.
Definition: dfa.cpp:535