reglibcpp  1.5.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 70 of file dfa.h.

Constructor & Destructor Documentation

◆ builder() [1/5]

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

Constructs a blank builder object.

Definition at line 585 of file dfa.cpp.

585 : 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 588 of file dfa.cpp.

588  {
589  auto initial = dfa.getLabelOf(0);
590  auto alphabet = unordered_set<char32_t>(dfa.getAlphabet().begin(), dfa.getAlphabet().end());
591  auto labels = unordered_set<string>(dfa.getNumberOfStates());
592  auto transitions = Dtransitionmap(dfa.getNumberOfStates());
593  p = make_unique<pImpl>(initial, alphabet, labels, transitions);
594  for (size_t q = 0; q < dfa.getNumberOfStates(); ++q) {
595  for (char32_t symbol : dfa.getAlphabet()) {
596  defineTransition(dfa.getLabelOf(q), dfa.getLabelOf(dfa.delta(q, symbol)), symbol);
597  }
598  setAccepting(dfa.getLabelOf(q), dfa.isAccepting(q));
599  }
600 }
builder & setAccepting(std::string const &state, bool accept)
Sets whether or not a state will be accepting within the prospective DFA.
Definition: dfa.cpp:688
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:722
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:504

◆ 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 603 of file dfa.cpp.

603  {
605  forward_list<valarray<bool>> stack(1, nfa.epsilonClosure(0));
606  size_t stackSize(1);
607  auto initial = nfa.getLabelOf(stack.front());
608  auto alphabet = nfa.getAlphabet();
609  alphabet.erase(alphabet.begin());
610  unordered_set<char32_t> alphabetS(alphabet.begin(), alphabet.end());
611  unordered_set<string> acceptingStates;
612  Dtransitionmap transitions;
613  transitions[initial];
614  p = make_unique<pImpl>(initial, alphabetS, acceptingStates, transitions);
615  while (stackSize != 0) {
616  valarray<bool> current(move(stack.front()));
617  stack.pop_front();
618  stackSize--;
619  for (char32_t symbol : p->alphabet) {
620  valarray<bool> next(nfa.deltaHat(current, u32string(1, symbol)));
621  defineTransition(nfa.getLabelOf(current), nfa.getLabelOf(next), symbol);
622  auto equalToNext = [&](valarray<bool> const& ref)->bool{return (next == ref).min() == true;};
623  if (!equalToNext(current) &&
624  none_of(stack.begin(), stack.end(), equalToNext) &&
625  none_of(done.begin(), done.end(), equalToNext)) {
626  stack.push_front(next);
627  stackSize++;
628  }
629  }
630  for (size_t qi(0); qi < current.size(); qi++) {
631  if (current[qi] && nfa.isAccepting(qi)) {
632  setAccepting(nfa.getLabelOf(current), true);
633  break;
634  }
635  }
636  done.insert(current);
637  }
638 }
builder & setAccepting(std::string const &state, bool accept)
Sets whether or not a state will be accepting within the prospective DFA.
Definition: dfa.cpp:688
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:722
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:504

◆ 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 641 of file dfa.cpp.

641 : 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 645 of file dfa.cpp.

645 : 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 672 of file dfa.cpp.

672  {
673  p->alphabet.insert(symbol);
674  return *this;
675 }

◆ 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 678 of file dfa.cpp.

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

◆ 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 1049 of file dfa.cpp.

1049  {
1050  vector<char32_t> alphabetV(p->alphabet.begin(), p->alphabet.end());
1051  std::sort(alphabetV.begin(), alphabetV.end());
1052  p->complete();
1053  vector<string> labelV;
1054  labelV.reserve(p->transitions.size());
1055  labelV.push_back(p->initial);
1056  for (auto const& tr : p->transitions) {
1057  if (tr.first == p->initial) {
1058  continue;
1059  }
1060  labelV.push_back(tr.first);
1061  }
1062  valarray<bool> acceptingV(false, labelV.size());
1063  vector<vector<size_t>> transitionV(labelV.size(), vector<size_t>(alphabetV.size()));
1064  for (size_t q(0); q < labelV.size(); q++) {
1065  string const& qLabel = labelV[q];
1066  acceptingV[q] = (p->acceptingStates.find(qLabel) != p->acceptingStates.end());
1067  for (size_t s(0); s < alphabetV.size(); s++) {
1068  transitionV[q][s] = index_of(labelV, p->transitions[qLabel][alphabetV[s]]);
1069  }
1070  }
1071  return {alphabetV, transitionV, labelV, acceptingV};
1072 }
size_t index_of(vector< T > const &vec, 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.cpp:1080

◆ 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 1004 of file dfa.cpp.

1004  {
1005  p->complete();
1006  for (auto const& fromVia : p->transitions) {
1007  if (!p->acceptingStates.erase(fromVia.first)) {
1008  p->acceptingStates.insert(fromVia.first);
1009  }
1010  }
1011  return *this;
1012 }

◆ 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 722 of file dfa.cpp.

722  {
723  if (p->transitions.empty()) {
724  p->initial = from;
725  }
726  p->transitions[to];
727  p->transitions[from][symbol] = to;
728  addSymbol(symbol);
729  return *this;
730 }
builder & addSymbol(char32_t symbol)
Adds a symbol to the prospective DFA's alphabet.
Definition: dfa.cpp:672

◆ 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 733 of file dfa.cpp.

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

◆ 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 947 of file dfa.cpp.

947  {
948  if (!p->transitions.empty()) {
949  vector<string> stateNames;
950  stateNames.reserve(p->transitions.size());
951  stateNames.push_back(p->initial);
952  for (auto const& fromTo : p->transitions) {
953  if (fromTo.first != p->initial) {
954  stateNames.push_back(fromTo.first);
955  }
956  }
957  auto const& oAlph = other.getAlphabet();
958  size_t commonSymbols = 0;
959  for (char32_t symbol : p->alphabet) {
960  if (index_of(oAlph, symbol) < oAlph.size()) {
961  commonSymbols++;
962  } else {
963  for (auto & fromVia : p->transitions) {
964  fromVia.second.erase(symbol);
965  }
966  }
967  }
968  p->alphabet.insert(oAlph.begin(), oAlph.end());
969  Dtransitionmap newTr(stateNames.size() * other.getNumberOfStates());
970  unordered_set<string> newAcc(stateNames.size() * other.getNumberOfStates());
971  unordered_map<size_t, unordered_map<size_t, string const*>> pairToName(stateNames.size() * other.getNumberOfStates());
972  for (size_t q = 0; q < stateNames.size(); q++) {
973  for (size_t qq = 0; qq < other.getNumberOfStates(); qq++) {
974  string potentialName = stateNames[q] + other.getLabelOf(qq);
975  for (auto nameIt = newTr.find(potentialName); nameIt != newTr.end(); nameIt = newTr.find(potentialName)) {
976  potentialName.append("_");
977  }
978  auto nameIt = newTr.emplace(potentialName, commonSymbols);
979  pairToName.emplace(q, 1).first->second.emplace(qq, &(nameIt.first->first));
980  if (p->acceptingStates.find(stateNames[q]) != p->acceptingStates.end() && other.isAccepting(qq)) {
981  newAcc.insert(potentialName);
982  }
983  }
984  }
985  for (size_t q = 0; q < stateNames.size(); q++) {
986  auto const& qLabel = stateNames[q];
987  auto const& viaTos = p->transitions[qLabel];
988  for (auto const& viaTo : viaTos) {
989  size_t p = index_of(stateNames, viaTo.second);
990  for (size_t qq = 0; qq < other.getNumberOfStates(); qq++) {
991  size_t pp = other.delta(qq, viaTo.first);
992  newTr[*(pairToName[q][qq])][viaTo.first] = *(pairToName[p][pp]);
993  }
994  }
995  }
996  p->transitions = newTr;
997  p->acceptingStates = newAcc;
998  p->initial = *(pairToName[0][0]);
999  }
1000  return *this;
1001 }
size_t index_of(vector< T > const &vec, 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.cpp:1080
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:504

◆ 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 706 of file dfa.cpp.

706  {
707  p->initial = state;
708  p->transitions[state];
709  return *this;
710 }

◆ 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 747 of file dfa.cpp.

747  {
748  p->complete();
749  vector<vector<size_t>> tTable(p->transitions.size());
750  valarray<bool> accepting(false, p->transitions.size());
751  vector<char32_t> sortedAlphabet(p->alphabet.begin(), p->alphabet.end());
752  std::sort(sortedAlphabet.begin(), sortedAlphabet.end());
753  vector<string> orderedStates;
754  orderedStates.reserve(p->transitions.size());
755  orderedStates.push_back(p->initial);
756  for (auto const& entry : p->transitions) {
757  if (entry.first != p->initial) {
758  orderedStates.push_back(entry.first);
759  }
760  }
761  for (size_t q(0); q < orderedStates.size(); q++) {
762  string const& qLabel(orderedStates[q]);
763  if (p->acceptingStates.find(qLabel) != p->acceptingStates.end()) {
764  accepting[q] = true;
765  }
766  for (size_t s(0); s < sortedAlphabet.size(); s++) {
767  tTable[q].push_back(index_of(orderedStates, p->transitions[qLabel][sortedAlphabet[s]]));
768  }
769  }
770  vector<valarray<bool>> equivalences(dfa::pImpl::indistinguishableStates(tTable, accepting));
771  for (size_t q(0); q < orderedStates.size(); q++) {
772  for (size_t first(0); first < equivalences[q].size(); first++) {
773  if (equivalences[q][first] && q > first) {
774  string const& superfluous(orderedStates[q]);
775  string const& remaining(orderedStates[first]);
776  p->acceptingStates.erase(superfluous);
777  p->transitions.erase(superfluous);
778  for (auto& from : p->transitions) {
779  for (auto& via : from.second) {
780  if (via.second == superfluous) {
781  via.second = remaining;
782  }
783  }
784  }
785  break;
786  }
787  }
788  }
789  return *this;
790 }
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(vector< T > const &vec, 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.cpp:1080

◆ minimize()

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

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

Definition at line 858 of file dfa.cpp.

858  {
859  return purge().merge();
860 }
builder & purge()
Purges the prospective DFA of unreachable and non-producing states, allowing for minimization.
Definition: dfa.cpp:799
builder & merge()
Merges the prospective DFA's indistinguishable states, allowing for minimization. ...
Definition: dfa.cpp:747

◆ 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 1015 of file dfa.cpp.

1015  {
1016  if (!p->transitions.empty()) {
1017  vector<string> stateNames;
1018  stateNames.reserve(p->transitions.size());
1019  stateNames.push_back(p->initial);
1020  for (auto const& fromTo : p->transitions) {
1021  if (fromTo.first != p->initial) {
1022  stateNames.push_back(fromTo.first);
1023  }
1024  }
1025  Dtransitionmap newTr(p->transitions.size());
1026  unordered_set<string> newAcc(p->acceptingStates.size());
1027  for (size_t q = 0; q < stateNames.size(); q++) {
1028  auto const& vias = p->transitions[stateNames[q]];
1029  unordered_map<char32_t,string> newVias(vias.size());
1030  for (auto const& viaTo : vias) {
1031  newVias.insert(make_pair(viaTo.first, prefix + to_string(index_of(stateNames, viaTo.second))));
1032  }
1033  newTr.insert(make_pair(prefix + to_string(q), newVias));
1034  if (p->acceptingStates.find(stateNames[q]) != p->acceptingStates.end()) {
1035  newAcc.insert(prefix + to_string(q));
1036  }
1037  }
1038  p->initial = prefix + "0";
1039  p->transitions = newTr;
1040  p->acceptingStates = newAcc;
1041  }
1042  return *this;
1043 }
T to_string(T... args)
size_t index_of(vector< T > const &vec, 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.cpp:1080
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:504

◆ 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 648 of file dfa.cpp.

648  {
649  if (this != &b) {
650  p.reset(new pImpl(*(b.p)));
651  }
652  return *this;
653 }

◆ 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 657 of file dfa.cpp.

657  {
658  if (this != &b) {
659  p.reset(new pImpl);
660  p.swap(b.p);
661  }
662  return *this;
663 }

◆ 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 799 of file dfa.cpp.

799  {
800  unordered_set<string> reachable(&(p->initial), &(p->initial)+1);
801  unordered_set<string> newReachable(reachable);
802  while (newReachable.size() > 0) {
803  unordered_set<string> oldReachable(move(newReachable));
804  newReachable.clear();
805  for (string const& reachableState : oldReachable) {
806  for (auto const& reachedState : p->transitions[reachableState]) {
807  if (reachable.insert(reachedState.second).second) {
808  newReachable.insert(reachedState.second);
809  }
810  }
811  }
812  }
813  for (auto it = p->transitions.begin(); it != p->transitions.end(); ) {
814  if (reachable.find(it->first) == reachable.end()) {
815  p->acceptingStates.erase(it->first);
816  it = p->transitions.erase(it);
817  } else {
818  it++;
819  }
820  }
821  unordered_set<string> producing(p->acceptingStates);
822  unordered_set<string> newProducing(producing);
823  while (newProducing.size() > 0) {
824  unordered_set<string> oldProducing(move(newProducing));
825  newProducing.clear();
826  for (auto const& from : p->transitions) {
827  for (auto const& via : from.second) {
828  if (producing.find(via.second) != producing.end()) {
829  if (producing.insert(from.first).second) {
830  newProducing.insert(from.first);
831  }
832  break;
833  }
834  }
835  }
836  }
837  for (auto it = p->transitions.begin(); it != p->transitions.end(); ) {
838  if (producing.find(it->first) == producing.end() && it->first != p->initial) {
839  p->acceptingStates.erase(it->first);
840  for (auto& via : p->transitions) {
841  for (auto itv = via.second.begin(); itv != via.second.end(); ) {
842  if (itv->second == it->first) {
843  itv = via.second.erase(itv);
844  } else {
845  itv++;
846  }
847  }
848  }
849  it = p->transitions.erase(it);
850  } else {
851  it++;
852  }
853  }
854  return *this;
855 }
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 688 of file dfa.cpp.

688  {
689  if (p->transitions.empty()) {
690  p->initial = state;
691  }
692  p->transitions[state];
693  if (accept) {
694  p->acceptingStates.insert(state);
695  } else {
696  p->acceptingStates.erase(state);
697  }
698  return *this;
699 }

◆ 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 869 of file dfa.cpp.

869  {
870  if (!p->transitions.empty()) {
871  auto const& oAlph = other.getAlphabet();
872  for (char32_t symbol : oAlph) {
873  addSymbol(symbol);
874  }
875  size_t trash = other.getNumberOfStates() * !!(p->alphabet.size() - oAlph.size());
876  p->complete();
877  vector<string> stateNames;
878  stateNames.reserve(p->transitions.size());
879  stateNames.push_back(p->initial);
880  for (auto const& fromVia : p->transitions) {
881  if (fromVia.first != p->initial) {
882  stateNames.push_back(fromVia.first);
883  }
884  }
885  Dtransitionmap newTr(stateNames.size() * other.getNumberOfStates());
886  unordered_set<string> newAcc(stateNames.size() * other.getNumberOfStates());
887  unordered_map<size_t, unordered_map<size_t, string const*>> pairToName(stateNames.size() * other.getNumberOfStates());
888  for (size_t q = 0; q < stateNames.size(); q++) {
889  for (size_t qq = 0; qq < other.getNumberOfStates() + !!trash; qq++) {
890  string potentialName = stateNames[q];
891  try {
892  potentialName.append(other.getLabelOf(qq));
893  } catch (std::out_of_range e) {
894  // We hit the trash state.
895  }
896  for (auto nameIt = newTr.find(potentialName); nameIt != newTr.end(); nameIt = newTr.find(potentialName)) {
897  potentialName.append("_");
898  }
899  auto nameIt = newTr.emplace(potentialName, p->alphabet.size());
900  pairToName.emplace(q, 1).first->second.emplace(qq, &(nameIt.first->first));
901  try {
902  if (p->acceptingStates.find(stateNames[q]) != p->acceptingStates.end() || other.isAccepting(qq)) {
903  newAcc.insert(potentialName);
904  }
905  } catch (std::out_of_range e) {
906  // We hit the trash state AND q is not accepting.
907  }
908  }
909  }
910  for (size_t q = 0; q < stateNames.size(); q++) {
911  auto const& qLabel = stateNames[q];
912  auto const& viaTos = p->transitions[qLabel];
913  for (auto const& viaTo : viaTos) {
914  size_t p = index_of(stateNames, viaTo.second);
915  for (size_t qq = 0; qq < other.getNumberOfStates() + !!trash; qq++) {
916  size_t pp;
917  try {
918  pp = other.delta(qq, viaTo.first);
919  } catch (std::logic_error e) {
920  pp = trash;
921  }
922  newTr[*(pairToName[q][qq])][viaTo.first] = *(pairToName[p][pp]);
923  }
924  }
925  }
926  p->transitions = newTr;
927  p->acceptingStates = newAcc;
928  p->initial = *(pairToName[0][0]);
929  } else {
930  for (size_t q = 0; q < other.getNumberOfStates(); ++q) {
931  for (char32_t symbol : other.getAlphabet()) {
932  defineTransition(other.getLabelOf(q), other.getLabelOf(other.delta(q, symbol)), symbol);
933  }
934  setAccepting(other.getLabelOf(q), other.isAccepting(q));
935  }
936  }
937  return *this;
938 }
builder & setAccepting(std::string const &state, bool accept)
Sets whether or not a state will be accepting within the prospective DFA.
Definition: dfa.cpp:688
size_t index_of(vector< T > const &vec, 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.cpp:1080
builder & defineTransition(std::string const &from, std::string const &to, char32_t symbol)
(Re-)Defines a transition for the prospective DFA.
Definition: dfa.cpp:722
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:504
builder & addSymbol(char32_t symbol)
Adds a symbol to the prospective DFA's alphabet.
Definition: dfa.cpp:672

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