reglibcpp  1.7.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...
 
 operator dfa ()
 Simply calls this builder's build() method. 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 67 of file dfa.h.

Constructor & Destructor Documentation

◆ builder() [1/5]

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

Constructs a blank builder object.

Definition at line 583 of file dfa.cpp.

583 : 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 586 of file dfa.cpp.

586  {
587  auto initial = dfa.getLabelOf(0);
588  auto alphabet = unordered_set<char32_t>(dfa.getAlphabet().begin(), dfa.getAlphabet().end());
589  auto labels = unordered_set<string>(dfa.getNumberOfStates());
590  auto transitions = Dtransitionmap(dfa.getNumberOfStates());
591  p = make_unique<pImpl>(initial, alphabet, labels, transitions);
592  for (size_t q = 0; q < dfa.getNumberOfStates(); ++q) {
593  for (char32_t symbol : dfa.getAlphabet()) {
594  defineTransition(dfa.getLabelOf(q), dfa.getLabelOf(dfa.delta(q, symbol)), symbol);
595  }
596  setAccepting(dfa.getLabelOf(q), dfa.isAccepting(q));
597  }
598 }
builder & setAccepting(std::string const &state, bool accept)
Sets whether or not a state will be accepting within the prospective DFA.
Definition: dfa.cpp:691
dfa()
Constructs a DFA accepting the empty language ∅.
Definition: dfa.cpp:127
builder & defineTransition(std::string const &from, std::string const &to, char32_t symbol)
(Re-)Defines a transition for the prospective DFA.
Definition: dfa.cpp:725
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:502

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

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

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

639 : 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 643 of file dfa.cpp.

643 : 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 675 of file dfa.cpp.

675  {
676  p->alphabet.insert(symbol);
677  return *this;
678 }

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

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

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

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

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

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

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

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

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

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

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

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

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

709  {
710  p->initial = state;
711  p->transitions[state];
712  return *this;
713 }

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

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

◆ minimize()

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

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

Definition at line 861 of file dfa.cpp.

861  {
862  return purge().merge();
863 }
builder & purge()
Purges the prospective DFA of unreachable and non-producing states, allowing for minimization.
Definition: dfa.cpp:802
builder & merge()
Merges the prospective DFA's indistinguishable states, allowing for minimization. ...
Definition: dfa.cpp:750

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

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

◆ operator dfa()

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

Simply calls this builder's build() method.

Definition at line 666 of file dfa.cpp.

666  {
667  return build();
668 }
dfa build()
Builds the DFA, as defined by previous operations, including completion.
Definition: dfa.cpp:1052

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

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

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

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

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

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

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

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

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

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