reglibcpp  1.6.0
(Naïve) C++ implementation of models for regular languages
Classes | Public Member Functions | List of all members
reg::dfa::builder Class Reference

Constructs DFAs step by step. More...

#include <dfa.h>

Classes

struct  pImpl
 Private implementation details of DFA builders. More...
 

Public Member Functions

 builder ()
 Constructs a blank builder object. More...
 
 builder (dfa const &dfa)
 Constructs a builder object with exactly the same states, symbols, transitions, initial state and accept states as a given DFA. More...
 
 builder (nfa const &nfa)
 Constructs a builder object with exactly the same states, symbols, transitions, initial state and accept states as a DFA resulting from a powerset construction. More...
 
 builder (builder const &b)
 Copy-constructs a builder by copying another one's private implementation object. More...
 
 builder (builder &&b)
 Move-constructs a builder by stealing another one's private implementation object. More...
 
builderoperator= (const builder &b)
 Copy-assigns a builder by copying another one's private implementation object. More...
 
builderoperator= (builder &&b)
 Move-assigns a builder by stealing another one's private implementation object. More...
 
builderaddSymbol (char32_t symbol)
 Adds a symbol to the prospective DFA's alphabet. More...
 
builderaddSymbol (std::string const &utf8Symbol)
 Same as above for a a UTF-8-encoded symbol. More...
 
buildersetAccepting (std::string const &state, bool accept)
 Sets whether or not a state will be accepting within the prospective DFA. More...
 
buildermakeInitial (std::string const &state)
 Resets the initial state for the prospective DFA. More...
 
builderdefineTransition (std::string const &from, std::string const &to, char32_t symbol)
 (Re-)Defines a transition for the prospective DFA. More...
 
builderdefineTransition (std::string const &from, std::string const &to, std::string const &utf8Symbol)
 Same as above for a UTF-8-encoded symbol. More...
 
buildermerge ()
 Merges the prospective DFA's indistinguishable states, allowing for minimization. More...
 
builderpurge ()
 Purges the prospective DFA of unreachable and non-producing states, allowing for minimization. More...
 
builderminimize ()
 Convenience method for chaining purge and merge to achieve proper minimization. More...
 
builderunite (dfa const &other)
 Makes the prospective DFA also accept every word of another DFA's language. More...
 
builderintersect (dfa const &other)
 Makes the prospective DFA accept only words accepted also by another DFA. More...
 
buildercomplement ()
 Inverts the prospective DFA's language with respect to all possible strings over its alphabet. More...
 
buildernormalizeStateNames (std::string const &prefix)
 Reduces the prospective NFA's state names to consecutive numbers, prefixed with a given string. More...
 
dfa build ()
 Builds the DFA, as defined by previous operations, including completion. More...
 

Detailed Description

Constructs DFAs step by step.

Any mention of a symbol or state will add them to the alphabet/set of states. The first state mentioned will be designated initial state.

Definition at line 72 of file dfa.h.

Constructor & Destructor Documentation

◆ builder() [1/5]

reg::dfa::builder::builder ( )

Constructs a blank builder object.

Definition at line 571 of file dfa.cpp.

571 : p(new pImpl) {}

◆ builder() [2/5]

reg::dfa::builder::builder ( dfa const &  dfa)

Constructs a builder object with exactly the same states, symbols, transitions, initial state and accept states as a given DFA.

Definition at line 574 of file dfa.cpp.

574  {
575  auto initial = dfa.getLabelOf(0);
576  auto alphabet = unordered_set<char32_t>(dfa.getAlphabet().begin(), dfa.getAlphabet().end());
577  auto labels = unordered_set<string>(dfa.getNumberOfStates());
578  auto transitions = Dtransitionmap(dfa.getNumberOfStates());
579  p = make_unique<pImpl>(initial, alphabet, labels, transitions);
580  for (size_t q = 0; q < dfa.getNumberOfStates(); ++q) {
581  for (char32_t symbol : dfa.getAlphabet()) {
582  defineTransition(dfa.getLabelOf(q), dfa.getLabelOf(dfa.delta(q, symbol)), symbol);
583  }
584  setAccepting(dfa.getLabelOf(q), dfa.isAccepting(q));
585  }
586 }
builder & setAccepting(std::string const &state, bool accept)
Sets whether or not a state will be accepting within the prospective DFA.
Definition: dfa.cpp:674
dfa()
Constructs a DFA accepting the empty language ∅.
Definition: dfa.cpp:126
builder & defineTransition(std::string const &from, std::string const &to, char32_t symbol)
(Re-)Defines a transition for the prospective DFA.
Definition: dfa.cpp:708
unordered_map< string, unordered_map< char32_t, string > > Dtransitionmap
Shorthand for the map from state name and transition symbol to target state.
Definition: dfa.cpp:490

◆ builder() [3/5]

reg::dfa::builder::builder ( nfa const &  nfa)

Constructs a builder object with exactly the same states, symbols, transitions, initial state and accept states as a DFA resulting from a powerset construction.

Definition at line 589 of file dfa.cpp.

589  {
591  forward_list<valarray<bool>> stack(1, nfa.epsilonClosure(0));
592  size_t stackSize(1);
593  auto initial = nfa.getLabelOf(stack.front());
594  auto alphabet = nfa.getAlphabet();
595  alphabet.erase(alphabet.begin());
596  unordered_set<char32_t> alphabetS(alphabet.begin(), alphabet.end());
597  unordered_set<string> acceptingStates;
598  Dtransitionmap transitions;
599  transitions[initial];
600  p = make_unique<pImpl>(initial, alphabetS, acceptingStates, transitions);
601  while (stackSize != 0) {
602  valarray<bool> current(move(stack.front()));
603  stack.pop_front();
604  stackSize--;
605  for (char32_t symbol : p->alphabet) {
606  valarray<bool> next(nfa.deltaHat(current, u32string(1, symbol)));
607  defineTransition(nfa.getLabelOf(current), nfa.getLabelOf(next), symbol);
608  auto equalToNext = [&](valarray<bool> const& ref)->bool{return (next == ref).min() == true;};
609  if (!equalToNext(current) &&
610  none_of(stack.begin(), stack.end(), equalToNext) &&
611  none_of(done.begin(), done.end(), equalToNext)) {
612  stack.push_front(next);
613  stackSize++;
614  }
615  }
616  for (size_t qi(0); qi < current.size(); qi++) {
617  if (current[qi] && nfa.isAccepting(qi)) {
618  setAccepting(nfa.getLabelOf(current), true);
619  break;
620  }
621  }
622  done.insert(current);
623  }
624 }
builder & setAccepting(std::string const &state, bool accept)
Sets whether or not a state will be accepting within the prospective DFA.
Definition: dfa.cpp:674
T next(T... args)
T move(T... args)
T ref(T... args)
T none_of(T... args)
builder & defineTransition(std::string const &from, std::string const &to, char32_t symbol)
(Re-)Defines a transition for the prospective DFA.
Definition: dfa.cpp:708
unordered_map< string, unordered_map< char32_t, string > > Dtransitionmap
Shorthand for the map from state name and transition symbol to target state.
Definition: dfa.cpp:490

◆ builder() [4/5]

reg::dfa::builder::builder ( builder const &  b)

Copy-constructs a builder by copying another one's private implementation object.

Definition at line 627 of file dfa.cpp.

627 : p(new pImpl(*(b.p))) {}

◆ builder() [5/5]

reg::dfa::builder::builder ( builder &&  b)

Move-constructs a builder by stealing another one's private implementation object.

The other builder will be blank afterwards.

Definition at line 631 of file dfa.cpp.

631 : p(new pImpl) {p.swap(b.p);}

Member Function Documentation

◆ addSymbol() [1/2]

dfa::builder & reg::dfa::builder::addSymbol ( char32_t  symbol)

Adds a symbol to the prospective DFA's alphabet.

Parameters
symbolthe symbol to add
Returns
reference to this object, for chaining operations

Definition at line 658 of file dfa.cpp.

658  {
659  p->alphabet.insert(symbol);
660  return *this;
661 }

◆ addSymbol() [2/2]

dfa::builder & reg::dfa::builder::addSymbol ( std::string const &  utf8Symbol)

Same as above for a a UTF-8-encoded symbol.

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Definition at line 664 of file dfa.cpp.

664  {
665  return addSymbol(converter.from_bytes(utf8Symbol)[0]);
666 }
std::wstring_convert< std::codecvt_utf8< char32_t >, char32_t > converter
Converts between UTF-8-encoded and UTF-32-encoded strings.
Definition: dfa.cpp:1060
builder & addSymbol(char32_t symbol)
Adds a symbol to the prospective DFA's alphabet.
Definition: dfa.cpp:658

◆ build()

dfa reg::dfa::builder::build ( )

Builds the DFA, as defined by previous operations, including completion.

Returns
a DFA object with exactly the states, alphabet and transitions that were defined and a trash state if needed

Definition at line 1035 of file dfa.cpp.

1035  {
1036  vector<char32_t> alphabetV(p->alphabet.begin(), p->alphabet.end());
1037  std::sort(alphabetV.begin(), alphabetV.end());
1038  p->complete();
1039  vector<string> labelV;
1040  labelV.reserve(p->transitions.size());
1041  labelV.push_back(p->initial);
1042  for (auto const& tr : p->transitions) {
1043  if (tr.first == p->initial) {
1044  continue;
1045  }
1046  labelV.push_back(tr.first);
1047  }
1048  valarray<bool> acceptingV(false, labelV.size());
1049  vector<vector<size_t>> transitionV(labelV.size(), vector<size_t>(alphabetV.size()));
1050  for (size_t q(0); q < labelV.size(); q++) {
1051  string const& qLabel = labelV[q];
1052  acceptingV[q] = (p->acceptingStates.find(qLabel) != p->acceptingStates.end());
1053  for (size_t s(0); s < alphabetV.size(); s++) {
1054  transitionV[q][s] = index_of(labelV, p->transitions[qLabel][alphabetV[s]]);
1055  }
1056  }
1057  return {alphabetV, transitionV, labelV, acceptingV};
1058 }
size_t index_of(C const &container, T const &element)
Basically Java&#39;s List interface&#39;s indexOf, but as a non-member function and returning the container&#39;s...
Definition: dfa.h:120

◆ complement()

dfa::builder & reg::dfa::builder::complement ( )

Inverts the prospective DFA's language with respect to all possible strings over its alphabet.

Definition at line 990 of file dfa.cpp.

990  {
991  p->complete();
992  for (auto const& fromVia : p->transitions) {
993  if (!p->acceptingStates.erase(fromVia.first)) {
994  p->acceptingStates.insert(fromVia.first);
995  }
996  }
997  return *this;
998 }

◆ defineTransition() [1/2]

dfa::builder & reg::dfa::builder::defineTransition ( std::string const &  from,
std::string const &  to,
char32_t  symbol 
)

(Re-)Defines a transition for the prospective DFA.

If there's already a transition defined from from to to, it will be redefined with the new symbol.

Parameters
fromthe starting state for the transition
tothe destination state for the transition
symbolthe symbol triggering the transition
Returns
reference to this object, for chaining operations

Definition at line 708 of file dfa.cpp.

708  {
709  if (p->transitions.empty()) {
710  p->initial = from;
711  }
712  p->transitions[to];
713  p->transitions[from][symbol] = to;
714  addSymbol(symbol);
715  return *this;
716 }
builder & addSymbol(char32_t symbol)
Adds a symbol to the prospective DFA's alphabet.
Definition: dfa.cpp:658

◆ defineTransition() [2/2]

dfa::builder & reg::dfa::builder::defineTransition ( std::string const &  from,
std::string const &  to,
std::string const &  utf8Symbol 
)

Same as above for a UTF-8-encoded symbol.

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Definition at line 719 of file dfa.cpp.

719  {
720  return defineTransition(from, to, converter.from_bytes(utf8Symbol)[0]);
721 }
std::wstring_convert< std::codecvt_utf8< char32_t >, char32_t > converter
Converts between UTF-8-encoded and UTF-32-encoded strings.
Definition: dfa.cpp:1060
builder & defineTransition(std::string const &from, std::string const &to, char32_t symbol)
(Re-)Defines a transition for the prospective DFA.
Definition: dfa.cpp:708

◆ intersect()

dfa::builder & reg::dfa::builder::intersect ( dfa const &  other)

Makes the prospective DFA accept only words accepted also by another DFA.

Concatenates the names of states defined so far with the other DFA's state names and resolves conflicts by appending _.

Parameters
otherthe NFA whose language should also be accepted
Returns
reference to this object, for chaining operations

Definition at line 933 of file dfa.cpp.

933  {
934  if (!p->transitions.empty()) {
935  vector<string> stateNames;
936  stateNames.reserve(p->transitions.size());
937  stateNames.push_back(p->initial);
938  for (auto const& fromTo : p->transitions) {
939  if (fromTo.first != p->initial) {
940  stateNames.push_back(fromTo.first);
941  }
942  }
943  auto const& oAlph = other.getAlphabet();
944  size_t commonSymbols = 0;
945  for (char32_t symbol : p->alphabet) {
946  if (index_of(oAlph, symbol) < oAlph.size()) {
947  commonSymbols++;
948  } else {
949  for (auto & fromVia : p->transitions) {
950  fromVia.second.erase(symbol);
951  }
952  }
953  }
954  p->alphabet.insert(oAlph.begin(), oAlph.end());
955  Dtransitionmap newTr(stateNames.size() * other.getNumberOfStates());
956  unordered_set<string> newAcc(stateNames.size() * other.getNumberOfStates());
957  unordered_map<size_t, unordered_map<size_t, string const*>> pairToName(stateNames.size() * other.getNumberOfStates());
958  for (size_t q = 0; q < stateNames.size(); q++) {
959  for (size_t qq = 0; qq < other.getNumberOfStates(); qq++) {
960  string potentialName = stateNames[q] + other.getLabelOf(qq);
961  for (auto nameIt = newTr.find(potentialName); nameIt != newTr.end(); nameIt = newTr.find(potentialName)) {
962  potentialName.append("_");
963  }
964  auto nameIt = newTr.emplace(potentialName, commonSymbols);
965  pairToName.emplace(q, 1).first->second.emplace(qq, &(nameIt.first->first));
966  if (p->acceptingStates.find(stateNames[q]) != p->acceptingStates.end() && other.isAccepting(qq)) {
967  newAcc.insert(potentialName);
968  }
969  }
970  }
971  for (size_t q = 0; q < stateNames.size(); q++) {
972  auto const& qLabel = stateNames[q];
973  auto const& viaTos = p->transitions[qLabel];
974  for (auto const& viaTo : viaTos) {
975  size_t p = index_of(stateNames, viaTo.second);
976  for (size_t qq = 0; qq < other.getNumberOfStates(); qq++) {
977  size_t pp = other.delta(qq, viaTo.first);
978  newTr[*(pairToName[q][qq])][viaTo.first] = *(pairToName[p][pp]);
979  }
980  }
981  }
982  p->transitions = newTr;
983  p->acceptingStates = newAcc;
984  p->initial = *(pairToName[0][0]);
985  }
986  return *this;
987 }
size_t index_of(C const &container, T const &element)
Basically Java&#39;s List interface&#39;s indexOf, but as a non-member function and returning the container&#39;s...
Definition: dfa.h:120
unordered_map< string, unordered_map< char32_t, string > > Dtransitionmap
Shorthand for the map from state name and transition symbol to target state.
Definition: dfa.cpp:490

◆ makeInitial()

dfa::builder & reg::dfa::builder::makeInitial ( std::string const &  state)

Resets the initial state for the prospective DFA.

Parameters
statethe new initial state
Returns
reference to this object, for chaining operations

Definition at line 692 of file dfa.cpp.

692  {
693  p->initial = state;
694  p->transitions[state];
695  return *this;
696 }

◆ merge()

dfa::builder & reg::dfa::builder::merge ( )

Merges the prospective DFA's indistinguishable states, allowing for minimization.

This method doesn't change the prospective DFA's accepted language, but it will be built with the minimum of reachable states to fulfill that purpose. Unreachable states will be merged since they are indistinguishable, but they won't be removed, hence preventing true minimization; that's what purge is for.

Returns
reference to this object, for chaining operations

Definition at line 733 of file dfa.cpp.

733  {
734  p->complete();
735  vector<vector<size_t>> tTable(p->transitions.size());
736  valarray<bool> accepting(false, p->transitions.size());
737  vector<char32_t> sortedAlphabet(p->alphabet.begin(), p->alphabet.end());
738  std::sort(sortedAlphabet.begin(), sortedAlphabet.end());
739  vector<string> orderedStates;
740  orderedStates.reserve(p->transitions.size());
741  orderedStates.push_back(p->initial);
742  for (auto const& entry : p->transitions) {
743  if (entry.first != p->initial) {
744  orderedStates.push_back(entry.first);
745  }
746  }
747  for (size_t q(0); q < orderedStates.size(); q++) {
748  string const& qLabel(orderedStates[q]);
749  if (p->acceptingStates.find(qLabel) != p->acceptingStates.end()) {
750  accepting[q] = true;
751  }
752  for (size_t s(0); s < sortedAlphabet.size(); s++) {
753  tTable[q].push_back(index_of(orderedStates, p->transitions[qLabel][sortedAlphabet[s]]));
754  }
755  }
756  vector<valarray<bool>> equivalences(dfa::pImpl::indistinguishableStates(tTable, accepting));
757  for (size_t q(0); q < orderedStates.size(); q++) {
758  for (size_t first(0); first < equivalences[q].size(); first++) {
759  if (equivalences[q][first] && q > first) {
760  string const& superfluous(orderedStates[q]);
761  string const& remaining(orderedStates[first]);
762  p->acceptingStates.erase(superfluous);
763  p->transitions.erase(superfluous);
764  for (auto& from : p->transitions) {
765  for (auto& via : from.second) {
766  if (via.second == superfluous) {
767  via.second = remaining;
768  }
769  }
770  }
771  break;
772  }
773  }
774  }
775  return *this;
776 }
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:83
size_t index_of(C const &container, T const &element)
Basically Java&#39;s List interface&#39;s indexOf, but as a non-member function and returning the container&#39;s...
Definition: dfa.h:120

◆ minimize()

dfa::builder & reg::dfa::builder::minimize ( )

Convenience method for chaining purge and merge to achieve proper minimization.

Definition at line 844 of file dfa.cpp.

844  {
845  return purge().merge();
846 }
builder & purge()
Purges the prospective DFA of unreachable and non-producing states, allowing for minimization.
Definition: dfa.cpp:785
builder & merge()
Merges the prospective DFA's indistinguishable states, allowing for minimization. ...
Definition: dfa.cpp:733

◆ normalizeStateNames()

dfa::builder & reg::dfa::builder::normalizeStateNames ( std::string const &  prefix)

Reduces the prospective NFA's state names to consecutive numbers, prefixed with a given string.

Definition at line 1001 of file dfa.cpp.

1001  {
1002  if (!p->transitions.empty()) {
1003  vector<string> stateNames;
1004  stateNames.reserve(p->transitions.size());
1005  stateNames.push_back(p->initial);
1006  for (auto const& fromTo : p->transitions) {
1007  if (fromTo.first != p->initial) {
1008  stateNames.push_back(fromTo.first);
1009  }
1010  }
1011  Dtransitionmap newTr(p->transitions.size());
1012  unordered_set<string> newAcc(p->acceptingStates.size());
1013  for (size_t q = 0; q < stateNames.size(); q++) {
1014  auto const& vias = p->transitions[stateNames[q]];
1015  unordered_map<char32_t,string> newVias(vias.size());
1016  for (auto const& viaTo : vias) {
1017  newVias.insert(make_pair(viaTo.first, prefix + to_string(index_of(stateNames, viaTo.second))));
1018  }
1019  newTr.insert(make_pair(prefix + to_string(q), newVias));
1020  if (p->acceptingStates.find(stateNames[q]) != p->acceptingStates.end()) {
1021  newAcc.insert(prefix + to_string(q));
1022  }
1023  }
1024  p->initial = prefix + "0";
1025  p->transitions = newTr;
1026  p->acceptingStates = newAcc;
1027  }
1028  return *this;
1029 }
T to_string(T... args)
size_t index_of(C const &container, T const &element)
Basically Java&#39;s List interface&#39;s indexOf, but as a non-member function and returning the container&#39;s...
Definition: dfa.h:120
T make_pair(T... args)
unordered_map< string, unordered_map< char32_t, string > > Dtransitionmap
Shorthand for the map from state name and transition symbol to target state.
Definition: dfa.cpp:490

◆ operator=() [1/2]

dfa::builder & reg::dfa::builder::operator= ( const builder b)

Copy-assigns a builder by copying another one's private implementation object.

Definition at line 634 of file dfa.cpp.

634  {
635  if (this != &b) {
636  p.reset(new pImpl(*(b.p)));
637  }
638  return *this;
639 }

◆ operator=() [2/2]

dfa::builder & reg::dfa::builder::operator= ( dfa::builder &&  b)

Move-assigns a builder by stealing another one's private implementation object.

The other builder will be blank afterwards.

Definition at line 643 of file dfa.cpp.

643  {
644  if (this != &b) {
645  p.reset(new pImpl);
646  p.swap(b.p);
647  }
648  return *this;
649 }

◆ purge()

dfa::builder & reg::dfa::builder::purge ( )

Purges the prospective DFA of unreachable and non-producing states, allowing for minimization.

This method doesn't change the prospective DFA's accepted language, but it will be built without states that will never be reached.

Returns
reference to this object, for chaining operations

Definition at line 785 of file dfa.cpp.

785  {
786  unordered_set<string> reachable(&(p->initial), &(p->initial)+1);
787  unordered_set<string> newReachable(reachable);
788  while (newReachable.size() > 0) {
789  unordered_set<string> oldReachable(move(newReachable));
790  newReachable.clear();
791  for (string const& reachableState : oldReachable) {
792  for (auto const& reachedState : p->transitions[reachableState]) {
793  if (reachable.insert(reachedState.second).second) {
794  newReachable.insert(reachedState.second);
795  }
796  }
797  }
798  }
799  for (auto it = p->transitions.begin(); it != p->transitions.end(); ) {
800  if (reachable.find(it->first) == reachable.end()) {
801  p->acceptingStates.erase(it->first);
802  it = p->transitions.erase(it);
803  } else {
804  it++;
805  }
806  }
807  unordered_set<string> producing(p->acceptingStates);
808  unordered_set<string> newProducing(producing);
809  while (newProducing.size() > 0) {
810  unordered_set<string> oldProducing(move(newProducing));
811  newProducing.clear();
812  for (auto const& from : p->transitions) {
813  for (auto const& via : from.second) {
814  if (producing.find(via.second) != producing.end()) {
815  if (producing.insert(from.first).second) {
816  newProducing.insert(from.first);
817  }
818  break;
819  }
820  }
821  }
822  }
823  for (auto it = p->transitions.begin(); it != p->transitions.end(); ) {
824  if (producing.find(it->first) == producing.end() && it->first != p->initial) {
825  p->acceptingStates.erase(it->first);
826  for (auto& via : p->transitions) {
827  for (auto itv = via.second.begin(); itv != via.second.end(); ) {
828  if (itv->second == it->first) {
829  itv = via.second.erase(itv);
830  } else {
831  itv++;
832  }
833  }
834  }
835  it = p->transitions.erase(it);
836  } else {
837  it++;
838  }
839  }
840  return *this;
841 }
T move(T... args)

◆ setAccepting()

dfa::builder & reg::dfa::builder::setAccepting ( std::string const &  state,
bool  accept 
)

Sets whether or not a state will be accepting within the prospective DFA.

Parameters
statethe state's name
accepttrue if the state should be an accept state afterwards, false else
Returns
reference to this object, for chaining operations

Definition at line 674 of file dfa.cpp.

674  {
675  if (p->transitions.empty()) {
676  p->initial = state;
677  }
678  p->transitions[state];
679  if (accept) {
680  p->acceptingStates.insert(state);
681  } else {
682  p->acceptingStates.erase(state);
683  }
684  return *this;
685 }

◆ unite()

dfa::builder & reg::dfa::builder::unite ( dfa const &  other)

Makes the prospective DFA also accept every word of another DFA's language.

Concatenates the names of states defined so far with the other DFA's state names and resolves conflicts by appending _.

Parameters
otherthe DFA whose language should also be accepted
Returns
reference to this object, for chaining operations

Definition at line 855 of file dfa.cpp.

855  {
856  if (!p->transitions.empty()) {
857  auto const& oAlph = other.getAlphabet();
858  for (char32_t symbol : oAlph) {
859  addSymbol(symbol);
860  }
861  size_t trash = other.getNumberOfStates() * !!(p->alphabet.size() - oAlph.size());
862  p->complete();
863  vector<string> stateNames;
864  stateNames.reserve(p->transitions.size());
865  stateNames.push_back(p->initial);
866  for (auto const& fromVia : p->transitions) {
867  if (fromVia.first != p->initial) {
868  stateNames.push_back(fromVia.first);
869  }
870  }
871  Dtransitionmap newTr(stateNames.size() * other.getNumberOfStates());
872  unordered_set<string> newAcc(stateNames.size() * other.getNumberOfStates());
873  unordered_map<size_t, unordered_map<size_t, string const*>> pairToName(stateNames.size() * other.getNumberOfStates());
874  for (size_t q = 0; q < stateNames.size(); q++) {
875  for (size_t qq = 0; qq < other.getNumberOfStates() + !!trash; qq++) {
876  string potentialName = stateNames[q];
877  try {
878  potentialName.append(other.getLabelOf(qq));
879  } catch (std::out_of_range e) {
880  // We hit the trash state.
881  }
882  for (auto nameIt = newTr.find(potentialName); nameIt != newTr.end(); nameIt = newTr.find(potentialName)) {
883  potentialName.append("_");
884  }
885  auto nameIt = newTr.emplace(potentialName, p->alphabet.size());
886  pairToName.emplace(q, 1).first->second.emplace(qq, &(nameIt.first->first));
887  try {
888  if (p->acceptingStates.find(stateNames[q]) != p->acceptingStates.end() || other.isAccepting(qq)) {
889  newAcc.insert(potentialName);
890  }
891  } catch (std::out_of_range e) {
892  // We hit the trash state AND q is not accepting.
893  }
894  }
895  }
896  for (size_t q = 0; q < stateNames.size(); q++) {
897  auto const& qLabel = stateNames[q];
898  auto const& viaTos = p->transitions[qLabel];
899  for (auto const& viaTo : viaTos) {
900  size_t p = index_of(stateNames, viaTo.second);
901  for (size_t qq = 0; qq < other.getNumberOfStates() + !!trash; qq++) {
902  size_t pp;
903  try {
904  pp = other.delta(qq, viaTo.first);
905  } catch (std::logic_error e) {
906  pp = trash;
907  }
908  newTr[*(pairToName[q][qq])][viaTo.first] = *(pairToName[p][pp]);
909  }
910  }
911  }
912  p->transitions = newTr;
913  p->acceptingStates = newAcc;
914  p->initial = *(pairToName[0][0]);
915  } else {
916  for (size_t q = 0; q < other.getNumberOfStates(); ++q) {
917  for (char32_t symbol : other.getAlphabet()) {
918  defineTransition(other.getLabelOf(q), other.getLabelOf(other.delta(q, symbol)), symbol);
919  }
920  setAccepting(other.getLabelOf(q), other.isAccepting(q));
921  }
922  }
923  return *this;
924 }
builder & setAccepting(std::string const &state, bool accept)
Sets whether or not a state will be accepting within the prospective DFA.
Definition: dfa.cpp:674
size_t index_of(C const &container, T const &element)
Basically Java&#39;s List interface&#39;s indexOf, but as a non-member function and returning the container&#39;s...
Definition: dfa.h:120
builder & defineTransition(std::string const &from, std::string const &to, char32_t symbol)
(Re-)Defines a transition for the prospective DFA.
Definition: dfa.cpp:708
unordered_map< string, unordered_map< char32_t, string > > Dtransitionmap
Shorthand for the map from state name and transition symbol to target state.
Definition: dfa.cpp:490
builder & addSymbol(char32_t symbol)
Adds a symbol to the prospective DFA's alphabet.
Definition: dfa.cpp:658

The documentation for this class was generated from the following files: