reglibcpp  1.0.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 &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...
 
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 49 of file dfa.h.

Constructor & Destructor Documentation

◆ builder() [1/5]

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

Constructs a blank builder object.

Definition at line 437 of file dfa.cpp.

437 : 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 440 of file dfa.cpp.

440  {
441  auto initial = dfa.getLabelOf(0);
442  auto alphabet = unordered_set<char32_t>(dfa.getAlphabet().begin(), dfa.getAlphabet().end());
443  auto labels = unordered_set<string>(dfa.getNumberOfStates());
444  auto transitions = unordered_map<string,unordered_map<char32_t,string>>(dfa.getNumberOfStates());
445  p = unique_ptr<pImpl>(new pImpl(
446  initial,
447  alphabet,
448  labels,
449  transitions
450  ));
451  for (size_t q = 0; q < dfa.getNumberOfStates(); ++q) {
452  for (char32_t symbol : dfa.getAlphabet()) {
453  defineTransition(dfa.getLabelOf(q), dfa.getLabelOf(dfa.delta(q, symbol)), symbol);
454  }
455  setAccepting(dfa.getLabelOf(q), dfa.isAccepting(q));
456  }
457 }
builder & setAccepting(std::string const &state, bool accept)
Sets whether or not a state will be accepting within the prospective DFA.
Definition: dfa.cpp:552
dfa()
Constructs a DFA accepting the empty language ∅.
Definition: dfa.cpp:107
builder & defineTransition(std::string const &from, std::string const &to, char32_t symbol)
(Re-)Defines a transition for the prospective DFA.
Definition: dfa.cpp:587

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

460  {
461  unordered_set<valarray<bool>, pImpl::ValarrayBoolHasher, pImpl::ValarrayBoolEqual> done;
462  forward_list<valarray<bool>> stack(1, nfa.epsilonClosure(0));
463  size_t stackSize(1);
464  auto initial = nfa.getLabelOf(stack.front());
465  auto alphabet = nfa.getAlphabet();
466  alphabet.erase(alphabet.begin());
467  unordered_set<char32_t> alphabetS(alphabet.begin(), alphabet.end());
468  unordered_set<string> acceptingStates;
469  unordered_map<string,unordered_map<char32_t,string>> transitions;
470  transitions[initial];
471  p = unique_ptr<pImpl>(new pImpl(
472  initial,
473  alphabetS,
474  acceptingStates,
475  transitions
476  ));
477  while (stackSize != 0) {
478  valarray<bool> current(move(stack.front()));
479  stack.pop_front();
480  stackSize--;
481  for (char32_t symbol : p->alphabet) {
482  valarray<bool> next(nfa.deltaHat(current, u32string(1, symbol)));
483  defineTransition(nfa.getLabelOf(current), nfa.getLabelOf(next), symbol);
484  pImpl::ValarrayBoolEqualTo equalToNext(next);
485  if (!equalToNext(current) &&
486  none_of(stack.begin(), stack.end(), equalToNext) &&
487  none_of(done.begin(), done.end(), equalToNext)) {
488  stack.push_front(next);
489  stackSize++;
490  }
491  }
492  for (size_t qi(0); qi < current.size(); qi++) {
493  if (current[qi] && nfa.isAccepting(qi)) {
494  setAccepting(nfa.getLabelOf(current), true);
495  break;
496  }
497  }
498  done.insert(current);
499  }
500 }
builder & setAccepting(std::string const &state, bool accept)
Sets whether or not a state will be accepting within the prospective DFA.
Definition: dfa.cpp:552
builder & defineTransition(std::string const &from, std::string const &to, char32_t symbol)
(Re-)Defines a transition for the prospective DFA.
Definition: dfa.cpp:587

◆ builder() [4/5]

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

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

Definition at line 503 of file dfa.cpp.

503 : 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 507 of file dfa.cpp.

507 : 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 535 of file dfa.cpp.

535  {
536  p->alphabet.insert(symbol);
537  return *this;
538 }

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

541  {
542  return addSymbol(expression::converter->from_bytes(utf8Symbol)[0]);
543 }
static std::unique_ptr< std::wstring_convert< std::codecvt_utf8< char32_t >, char32_t > > const converter
Converts between UTF-8-encoded and UTF-32-encoded strings.
Definition: expression.h:97
builder & addSymbol(char32_t symbol)
Adds a symbol to the prospective DFA&#39;s alphabet.
Definition: dfa.cpp:535

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

726  {
727  vector<char32_t> alphabetV(p->alphabet.begin(), p->alphabet.end());
728  sort(alphabetV.begin(), alphabetV.end());
729  p->complete();
730  vector<string> labelV;
731  labelV.reserve(p->transitions.size());
732  labelV.push_back(p->initial);
733  valarray<bool> acceptingV(labelV.size(), false);
734  for (auto const& tr : p->transitions) {
735  if (tr.first == p->initial) {
736  continue;
737  }
738  labelV.push_back(tr.first);
739  }
740  vector<vector<size_t>> transitionV(labelV.size(), vector<size_t>(alphabetV.size()));
741  for (size_t q(0); q < labelV.size(); q++) {
742  string const& qLabel = labelV[q];
743  acceptingV[q] = (p->acceptingStates.find(qLabel) != p->acceptingStates.end());
744  for (size_t s(0); s < alphabetV.size(); s++) {
745  transitionV[q][s] = distance(
746  labelV.begin(),
747  find(labelV.begin(), labelV.end(), p->transitions[qLabel][alphabetV[s]])
748  );
749  }
750  }
751  return {alphabetV, transitionV, labelV, acceptingV};
752 }

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

587  {
588  if (p->transitions.empty()) {
589  p->initial = from;
590  }
591  p->transitions[to];
592  p->transitions[from][symbol] = to;
593  addSymbol(symbol);
594  return *this;
595 }
builder & addSymbol(char32_t symbol)
Adds a symbol to the prospective DFA&#39;s alphabet.
Definition: dfa.cpp:535

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

598  {
599  return defineTransition(from, to, expression::converter->from_bytes(utf8Symbol)[0]);
600 }
static std::unique_ptr< std::wstring_convert< std::codecvt_utf8< char32_t >, char32_t > > const converter
Converts between UTF-8-encoded and UTF-32-encoded strings.
Definition: expression.h:97
builder & defineTransition(std::string const &from, std::string const &to, char32_t symbol)
(Re-)Defines a transition for the prospective DFA.
Definition: dfa.cpp:587

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

571  {
572  p->initial = state;
573  p->transitions[state];
574  return *this;
575 }

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

611  {
612  p->complete();
613  vector<vector<size_t>> tTable(p->transitions.size());
614  valarray<bool> accepting(false, p->transitions.size());
615  vector<char32_t> sortedAlphabet(p->alphabet.begin(), p->alphabet.end());
616  sort(sortedAlphabet.begin(), sortedAlphabet.end());
617  vector<string> orderedStates;
618  orderedStates.reserve(p->transitions.size());
619  orderedStates.push_back(p->initial);
620  for (auto const& entry : p->transitions) {
621  if (entry.first != p->initial) {
622  orderedStates.push_back(entry.first);
623  }
624  }
625  for (size_t q(0); q < orderedStates.size(); q++) {
626  string const& qLabel(orderedStates[q]);
627  if (p->acceptingStates.find(qLabel) != p->acceptingStates.end()) {
628  accepting[q] = true;
629  }
630  for (size_t s(0); s < sortedAlphabet.size(); s++) {
631  tTable[q].push_back(distance(orderedStates.begin(), find(orderedStates.begin(), orderedStates.end(), p->transitions[qLabel][sortedAlphabet[s]])));
632  }
633  }
634  vector<valarray<bool>> equivalences(dfa::pImpl::indistinguishableStates(tTable, accepting));
635  for (size_t q(0); q < orderedStates.size(); q++) {
636  for (size_t first(0); first < equivalences[q].size(); first++) {
637  if (equivalences[q][first] && q > first) {
638  string const& superfluous(orderedStates[q]);
639  string const& remaining(orderedStates[first]);
640  p->acceptingStates.erase(superfluous);
641  p->transitions.erase(superfluous);
642  for (auto& from : p->transitions) {
643  for (auto& via : from.second) {
644  if (via.second == superfluous) {
645  via.second = remaining;
646  }
647  }
648  }
649  break;
650  }
651  }
652  }
653  return *this;
654 }
static vector< valarray< bool > > indistinguishableStates(vector< vector< size_t >> const &transitions, valarray< bool > const &accepting)
Builds the table of indistinguishable states w.r.t. a transition function.
Definition: dfa.cpp:64

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

510  {
511  if (this != &b) {
512  p.reset(new pImpl(*(b.p)));
513  }
514  return *this;
515 }

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

519  {
520  if (this != &b) {
521  p.reset(new pImpl);
522  p.swap(b.p);
523  }
524  return *this;
525 }

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

663  {
664  unordered_set<string> reachable(&(p->initial), &(p->initial)+1);
665  unordered_set<string> newReachable(reachable);
666  while (newReachable.size() > 0) {
667  unordered_set<string> oldReachable(move(newReachable));
668  newReachable.clear();
669  for (string const& reachableState : oldReachable) {
670  for (auto const& reachedState : p->transitions[reachableState]) {
671  if (reachable.insert(reachedState.second).second) {
672  newReachable.insert(reachedState.second);
673  }
674  }
675  }
676  }
677  for (auto it = p->transitions.begin(); it != p->transitions.end(); ) {
678  if (reachable.find(it->first) == reachable.end()) {
679  p->acceptingStates.erase(it->first);
680  it = p->transitions.erase(it);
681  } else {
682  it++;
683  }
684  }
685  unordered_set<string> producing(p->acceptingStates);
686  unordered_set<string> newProducing(producing);
687  while (newProducing.size() > 0) {
688  unordered_set<string> oldProducing(move(newProducing));
689  newProducing.clear();
690  for (auto const& from : p->transitions) {
691  for (auto const& via : from.second) {
692  if (producing.find(via.second) != producing.end()) {
693  if (producing.insert(from.first).second) {
694  newProducing.insert(from.first);
695  }
696  break;
697  }
698  }
699  }
700  }
701  for (auto it = p->transitions.begin(); it != p->transitions.end(); ) {
702  if (producing.find(it->first) == producing.end() && it->first != p->initial) {
703  p->acceptingStates.erase(it->first);
704  for (auto& via : p->transitions) {
705  for (auto itv = via.second.begin(); itv != via.second.end(); ) {
706  if (itv->second == it->first) {
707  itv = via.second.erase(itv);
708  } else {
709  itv++;
710  }
711  }
712  }
713  it = p->transitions.erase(it);
714  } else {
715  it++;
716  }
717  }
718  return *this;
719 }

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

552  {
553  if (p->transitions.empty()) {
554  p->initial = state;
555  }
556  p->transitions[state];
557  if (accept) {
558  p->acceptingStates.insert(state);
559  } else {
560  p->acceptingStates.erase(state);
561  }
562  return *this;
563 }

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