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

Constructs NFAs step by step. More...

#include <nfa.h>

Classes

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

Public Member Functions

 builder ()
 Constructs a blank builder object. More...
 
 builder (nfa const &nfa)
 Constructs a builder object with exactly the same states, symbols, transitions, initial state and accept states as a given NFA. 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 (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= (builder const &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 NFA's alphabet. More...
 
builderaddSymbol (std::string const &utf8Symbol)
 Same as above for 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 NFA. More...
 
buildermakeInitial (std::string const &state)
 Resets the initial state for the prospective NFA. More...
 
builderaddTransition (std::string const &from, std::string const &to, char32_t symbol)
 Adds a transition for the prospective NFA. More...
 
builderaddTransition (std::string const &from, std::string const &to, std::string const &utf8Symbol)
 Same as above for a UTF-8-encoded symbol. More...
 
builderunite (nfa const &other)
 Makes the prospective NFA also accept every word of another NFA's language. More...
 
builderintersect (nfa const &other)
 Makes the prospective NFA accept only words accepted also by another NFA. More...
 
buildernormalizeStateNames (std::string const &prefix)
 Reduces the prospective NFA's state names to consecutive numbers, prefixed with a given string. More...
 
nfa build ()
 Builds the NFA, as defined by previous operations. More...
 

Detailed Description

Constructs NFAs 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 94 of file nfa.h.

Constructor & Destructor Documentation

◆ builder() [1/5]

reg::nfa::builder::builder ( )

Constructs a blank builder object.

Definition at line 683 of file nfa.cpp.

683 : p(new pImpl) {}

◆ builder() [2/5]

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

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

Definition at line 686 of file nfa.cpp.

686  : p(new pImpl) {
687  makeInitial(nfa.getLabelOf(0));
688  for (char32_t symbol : nfa.getAlphabet()) {
689  addSymbol(symbol);
690  }
691  for (size_t qi = 0; qi < nfa.p->labels.size(); ++qi) {
692  string const& qLabel = nfa.getLabelOf(qi);
693  for (char32_t symbol : p->alphabet) {
694  valarray<bool> ps = nfa.delta(qi, symbol);
695  size_t pi(0);
696  for (bool pb : ps) {
697  if (pb) {
698  addTransition(qLabel, nfa.getLabelOf(pi), symbol);
699  }
700  pi++;
701  }
702  }
703  if (nfa.isAccepting(qi)) {
704  setAccepting(qLabel, true);
705  }
706  }
707 }
builder & addSymbol(char32_t symbol)
Adds a symbol to the prospective NFA's alphabet.
Definition: nfa.cpp:758
builder & setAccepting(std::string const &state, bool accept)
Sets whether or not a state will be accepting within the prospective NFA.
Definition: nfa.cpp:774
builder & makeInitial(std::string const &state)
Resets the initial state for the prospective NFA.
Definition: nfa.cpp:792
nfa()
Constructs an NFA accepting the empty language ∅.
Definition: nfa.cpp:79
builder & addTransition(std::string const &from, std::string const &to, char32_t symbol)
Adds a transition for the prospective NFA.
Definition: nfa.cpp:805

◆ builder() [3/5]

reg::nfa::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.

Transition destinations will be converted to singleton sets of the respective reached states.

Definition at line 711 of file nfa.cpp.

711  {
712  string initial(dfa.getLabelOf(0));
713  unordered_set<string> acceptingStates;
714  unordered_set<char32_t> alphabet(dfa.getAlphabet().begin(), dfa.getAlphabet().end());
715  Ntransitionmap transitions;
716  transitions[initial];
717  for (size_t q(0); q < dfa.getNumberOfStates(); q++) {
718  for (char32_t symbol : alphabet) {
719  transitions[dfa.getLabelOf(q)][symbol].insert(dfa.getLabelOf(dfa.delta(q, symbol)));
720  }
721  if (dfa.isAccepting(q)) {
722  acceptingStates.insert(dfa.getLabelOf(q));
723  }
724  }
725  p = make_unique<pImpl>(initial, acceptingStates, alphabet, transitions);
726 }
unordered_map< string, unordered_map< char32_t, unordered_set< string > >> Ntransitionmap
Shorthand for the map from state name and transition symbol to set of target states.
Definition: nfa.cpp:655

◆ builder() [4/5]

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

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

Definition at line 729 of file nfa.cpp.

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

◆ builder() [5/5]

reg::nfa::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 733 of file nfa.cpp.

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

Member Function Documentation

◆ addSymbol() [1/2]

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

Adds a symbol to the prospective NFA's alphabet.

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

Definition at line 758 of file nfa.cpp.

758  {
759  p->alphabet.insert(symbol);
760  return *this;
761 }

◆ addSymbol() [2/2]

nfa::builder & reg::nfa::builder::addSymbol ( 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 764 of file nfa.cpp.

764  {
765  return addSymbol(converter.from_bytes(utf8Symbol)[0]);
766 }
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 NFA's alphabet.
Definition: nfa.cpp:758

◆ addTransition() [1/2]

nfa::builder & reg::nfa::builder::addTransition ( std::string const &  from,
std::string const &  to,
char32_t  symbol 
)

Adds a transition for the prospective NFA.

Parameters
fromthe starting state for the transition
tothe destination state for the transition
symbolthe symbol triggering the transition or \0 for an ε-transition
Returns
reference to this object, for chaining operations

Definition at line 805 of file nfa.cpp.

805  {
806  if (p->transitions.empty()) {
807  p->initial = from;
808  }
809  p->transitions[to];
810  p->transitions[from][symbol].insert(to);
811  addSymbol(symbol);
812  return *this;
813 }
builder & addSymbol(char32_t symbol)
Adds a symbol to the prospective NFA's alphabet.
Definition: nfa.cpp:758

◆ addTransition() [2/2]

nfa::builder & reg::nfa::builder::addTransition ( 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 816 of file nfa.cpp.

816  {
817  return addTransition(from, to, converter.from_bytes(utf8Symbol)[0]);
818 }
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 & addTransition(std::string const &from, std::string const &to, char32_t symbol)
Adds a transition for the prospective NFA.
Definition: nfa.cpp:805

◆ build()

nfa reg::nfa::builder::build ( )

Builds the NFA, as defined by previous operations.

Returns
an NFA object with exactly the states, alphabet and transitions that were defined

Definition at line 1000 of file nfa.cpp.

1000  {
1001  p->transitions[p->initial];
1002  p->alphabet.insert(U'\0');
1003  vector<char32_t> alphabetV(p->alphabet.begin(), p->alphabet.end());
1004  std::sort(alphabetV.begin(), alphabetV.end());
1005  vector<string> labelV(p->transitions.size());
1006  labelV[0] = p->initial;
1007  valarray<bool> acceptingV(p->transitions.size());
1008  acceptingV[0] = (p->acceptingStates.find(p->initial) != p->acceptingStates.end());
1009  size_t i(1);
1010  for (auto entry : p->transitions) {
1011  if (entry.first == p->initial) {
1012  continue;
1013  }
1014  labelV[i] = entry.first;
1015  acceptingV[i++] = (
1016  p->acceptingStates.find(entry.first) != p->acceptingStates.end()
1017  );
1018  }
1019  vector<vector<valarray<bool>>> transitionV(
1020  p->transitions.size(),
1022  p->alphabet.size()+1,
1023  valarray<bool>(labelV.size())
1024  )
1025  );
1026  unordered_set<string> emptySet;
1027  size_t qi(0);
1028  for (auto const& q : labelV) {
1029  unordered_map<char32_t,unordered_set<string>> const& fromQ = p->transitions[q];
1030  size_t si(0);
1031  for (char32_t symbol : alphabetV) {
1032  auto to = fromQ.find(symbol);
1033  unordered_set<string> const& viaSymbol(to != fromQ.end() ? to->second : emptySet);
1034  i = 0;
1035  for (auto const& p : labelV) {
1036  transitionV[qi][si][i++] = (viaSymbol.count(p) != 0);
1037  }
1038  si++;
1039  }
1040  qi++;
1041  }
1042  return {alphabetV, transitionV, labelV, acceptingV};
1043 }

◆ intersect()

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

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

Concatenates the names of states defined so far with the other NFA'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 923 of file nfa.cpp.

923  {
924  if (!p->transitions.empty()) {
925  vector<string> stateNames;
926  stateNames.reserve(p->transitions.size());
927  stateNames.push_back(p->initial);
928  for (auto const& fromTo : p->transitions) {
929  if (fromTo.first != p->initial) {
930  stateNames.push_back(fromTo.first);
931  }
932  }
933  auto const& oAlph = other.getAlphabet();
934  size_t commonSymbols = 0;
935  for (char32_t symbol : p->alphabet) {
936  if (index_of(oAlph, symbol) < oAlph.size()) {
937  commonSymbols++;
938  } else {
939  for (auto & fromVia : p->transitions) {
940  fromVia.second.erase(symbol);
941  }
942  }
943  }
944  p->alphabet.insert(oAlph.begin(), oAlph.end());
945  Ntransitionmap newTr(stateNames.size() * other.getNumberOfStates());
946  unordered_set<string> newAcc(stateNames.size() * other.getNumberOfStates());
947  unordered_map<size_t, unordered_map<size_t, string const*>> pairToName(stateNames.size() * other.getNumberOfStates());
948  for (size_t q = 0; q < stateNames.size(); q++) {
949  for (size_t qq = 0; qq < other.getNumberOfStates(); qq++) {
950  string potentialName = stateNames[q] + other.getLabelOf(qq);
951  for (auto nameIt = newTr.find(potentialName); nameIt != newTr.end(); nameIt = newTr.find(potentialName)) {
952  potentialName.append("_");
953  }
954  auto nameIt = newTr.emplace(potentialName, commonSymbols);
955  pairToName.emplace(q, 1).first->second.emplace(qq, &(nameIt.first->first));
956  if (p->acceptingStates.find(stateNames[q]) != p->acceptingStates.end() && other.isAccepting(qq)) {
957  newAcc.insert(potentialName);
958  }
959  }
960  p->transitions[stateNames[q]][U'\0'].insert(stateNames[q]);
961  // Needed due to the equivalence of standing still to “taking” an ε-transition.
962  }
963  for (size_t q = 0; q < stateNames.size(); q++) {
964  auto const& qLabel = stateNames[q];
965  auto const& viaTos = p->transitions[qLabel];
966  for (auto const& viaTo : viaTos) {
967  for (size_t qq = 0; qq < other.getNumberOfStates(); qq++) {
968  valarray<bool> const& reached = other.delta(qq, viaTo.first);
969  for (auto const& to : viaTo.second) {
970  size_t p = index_of(stateNames, to);
971  for (size_t pp = 0; pp < reached.size(); pp++) {
972  if (reached[pp] || (pp == qq && viaTo.first == U'\0')) {
973  // Needed due to the equivalence of standing still to “taking” an ε-transition.
974  newTr[*(pairToName[q][qq])][viaTo.first].insert(*(pairToName[p][pp]));
975  }
976  }
977  }
978  }
979  }
980  }
981  for (auto & fromVia : newTr) {
982  auto const& from = fromVia.first;
983  auto to = fromVia.second.find(U'\0');
984  to->second.erase(from);
985  if (to->second.empty()) {
986  fromVia.second.erase(to);
987  }
988  }
989  p->transitions = newTr;
990  p->acceptingStates = newAcc;
991  p->initial = *(pairToName[0][0]);
992  }
993  return *this;
994 }
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, unordered_set< string > >> Ntransitionmap
Shorthand for the map from state name and transition symbol to set of target states.
Definition: nfa.cpp:655

◆ makeInitial()

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

Resets the initial state for the prospective NFA.

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

Definition at line 792 of file nfa.cpp.

792  {
793  p->initial = state;
794  p->transitions[state];
795  return *this;
796 }

◆ normalizeStateNames()

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

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

Definition at line 821 of file nfa.cpp.

821  {
822  if (!p->transitions.empty()) {
823  vector<string> stateNames;
824  stateNames.reserve(p->transitions.size());
825  stateNames.push_back(p->initial);
826  for (auto const& fromTo : p->transitions) {
827  if (fromTo.first != p->initial) {
828  stateNames.push_back(fromTo.first);
829  }
830  }
831  Ntransitionmap newTr(p->transitions.size());
832  unordered_set<string> newAcc(p->acceptingStates.size());
833  for (size_t q = 0; q < stateNames.size(); q++) {
834  auto const& vias = p->transitions[stateNames[q]];
835  unordered_map<char32_t,unordered_set<string>> newVias(vias.size());
836  for (auto const& viaTo : vias) {
837  unordered_set<string> newTos(viaTo.second.size());
838  for (size_t p = 0; p < stateNames.size(); p++) {
839  if (viaTo.second.find(stateNames[p]) != viaTo.second.cend()) {
840  newTos.insert(prefix + std::to_string(p));
841  }
842  }
843  newVias.insert(make_pair(viaTo.first, newTos));
844  }
845  newTr.insert(make_pair(prefix + std::to_string(q), newVias));
846  if (p->acceptingStates.find(stateNames[q]) != p->acceptingStates.end()) {
847  newAcc.insert(prefix + std::to_string(q));
848  }
849  }
850  p->initial = string(string(prefix).append("0"));
851  p->transitions = newTr;
852  p->acceptingStates = newAcc;
853  }
854  return *this;
855 }
T make_pair(T... args)
unordered_map< string, unordered_map< char32_t, unordered_set< string > >> Ntransitionmap
Shorthand for the map from state name and transition symbol to set of target states.
Definition: nfa.cpp:655

◆ operator=() [1/2]

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

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

Definition at line 736 of file nfa.cpp.

736  {
737  if (this != &b) {
738  p.reset(new pImpl(*(b.p)));
739  }
740  return *this;
741 }

◆ operator=() [2/2]

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

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

The other builder will be blank afterwards.

Definition at line 745 of file nfa.cpp.

745  {
746  if (this != &b) {
747  p.reset(new pImpl);
748  p.swap(b.p);
749  }
750  return *this;
751 }

◆ setAccepting()

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

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

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 774 of file nfa.cpp.

774  {
775  if (p->transitions.empty()) {
776  p->initial = state;
777  }
778  p->transitions[state];
779  if (accept) {
780  p->acceptingStates.insert(state);
781  } else {
782  p->acceptingStates.erase(state);
783  }
784  return *this;
785 }

◆ unite()

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

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

Prepends the names of states defined so far with a single 1 and the other NFA's state names with a single 2 and adds a new initial state with an ε transition to each of the other initial states.

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

Definition at line 865 of file nfa.cpp.

865  {
866  string newInitial("q0");
867  if (!p->transitions.empty()) {
868  Ntransitionmap tempTr(p->transitions.size());
869  for (auto const& fromVia : p->transitions) {
870  unordered_map<char32_t,unordered_set<string>> tempVia(fromVia.second.size());
871  for (auto const& viaTo : fromVia.second) {
872  unordered_set<string> tempTo(viaTo.second.size());
873  for (auto const& to : viaTo.second) {
874  tempTo.insert(string(to.length() + 1, '1').replace(1, string::npos, to));
875  }
876  tempVia.insert(make_pair(viaTo.first, tempTo));
877  }
878  tempTr.insert(make_pair(string(fromVia.first.length() + 1, '1').replace(1, string::npos, fromVia.first), tempVia));
879  }
880  p->transitions = tempTr;
881  unordered_set<string> tempAcc(p->acceptingStates.size());
882  for (auto const& acc : p->acceptingStates) {
883  tempAcc.insert(string(acc.length() + 1, '1').replace(1, string::npos, acc));
884  }
885  p->acceptingStates = tempAcc;
886  p->initial = string(p->initial.length() + 1, '1').replace(1, string::npos, p->initial);
887  addTransition(newInitial, p->initial, U'\0');
888  }
889  makeInitial(newInitial);
890  auto & oAlphabet = other.getAlphabet();
891  p->alphabet.insert(oAlphabet.cbegin(), oAlphabet.cend());
892  for (size_t q = 0; q < other.getNumberOfStates(); q++) {
893  auto & qLabel = other.getLabelOf(q);
894  string newQLabel = string(qLabel.length() + 1, '2').replace(1, string::npos, qLabel);
895  unordered_map<char32_t,unordered_set<string>> tempVia(oAlphabet.size() + 1);
896  for (char32_t symbol : oAlphabet) {
897  valarray<bool> const& to = other.delta(q, symbol);
898  unordered_set<string> tempTo(other.getNumberOfStates());
899  for (size_t p = 0; p < other.getNumberOfStates(); p++) { if (to[p]) {
900  auto & pLabel = other.getLabelOf(p);
901  tempTo.insert(string(pLabel.length() + 1, '2').replace(1, string::npos, pLabel));
902  }}
903  tempVia.insert(make_pair(symbol, tempTo));
904  }
905  p->transitions.insert(make_pair(newQLabel, tempVia));
906  if (other.isAccepting(q)) {
907  p->acceptingStates.insert(newQLabel);
908  }
909  if (q == 0) {
910  addTransition(newInitial, newQLabel, U'\0');
911  }
912  }
913  return *this;
914 }
T replace(T... args)
T make_pair(T... args)
builder & makeInitial(std::string const &state)
Resets the initial state for the prospective NFA.
Definition: nfa.cpp:792
unordered_map< string, unordered_map< char32_t, unordered_set< string > >> Ntransitionmap
Shorthand for the map from state name and transition symbol to set of target states.
Definition: nfa.cpp:655
builder & addTransition(std::string const &from, std::string const &to, char32_t symbol)
Adds a transition for the prospective NFA.
Definition: nfa.cpp:805

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