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

Represents generalized nondeterministic finite automata. More...

#include <gnfa.h>

Classes

struct  pImpl
 Private implementation details of GNFAs. More...
 

Public Member Functions

 gnfa (dfa const &d)
 Constructs a GNFA with the same states and transitions as a given DFA. More...
 
 gnfa (nfa const &n)
 Constructs a GNFA with the same states and transitions as a given NFA. More...
 
 gnfa (expression::exptr r)
 Constructs a GNFA with only one transition. More...
 
 gnfa (gnfa const &n)
 Copy-constructs a GNFA by copying another one's private implementation object. More...
 
 gnfa (gnfa &&n)
 Move-constructs a GNFA by stealing another one's private implementation object. More...
 
gnfaoperator= (gnfa const &n)
 Copy-assigns this GNFA by copying another one's private implementation object. More...
 
gnfaoperator= (gnfa &&n)
 Move-assigns this GNFA by stealing another one's private implementation object. More...
 
 operator nfa const & () const
 Returns an NFA accepting the same language as this GNFA. More...
 
bool operator== (nfa const &n) const
 Checks whether this RE describes the same regular language as another object. More...
 
bool operator!= (nfa const &n) const
 Checks whether this RE describes a different regular language than another object. More...
 
std::string const & getInitialState () const
 Reveals the name of this GNFA's initial state. More...
 
std::string const & getAcceptingState () const
 Reveals the name of this GNFA's accept state. More...
 
std::vector< std::reference_wrapper< std::string const > > getActiveStates () const
 Reveals the names of this GNFA's non-initial, non-accepting states. More...
 
expression::exptr getTransition (std::string const &qLabel, std::string const &pLabel) const
 Extracts the RE labelling the transition between two states. More...
 
std::vector< std::pair< std::reference_wrapper< std::string const >, std::reference_wrapper< std::string const > > > getSplittableTransitions () const
 Reveals this GNFA's splittable transitions. More...
 
std::vector< std::reference_wrapper< std::string const > > splitTransition (std::string const &qLabel, std::string const &pLabel)
 Splits a transition between two states, adding new states if needed. More...
 
nfa splitAllTransitions ()
 Splits all transitions until only ∅, ε, and symbol REs remain and builds the resulting NFA. More...
 
void bypassTransition (std::string const &qLabel, std::string const &pLabel)
 Removes a transition between two states and replaces it with equivalent ones, bypassing its beginning state. More...
 
void ripState (std::string const &qLabel)
 Removes a state, bypassing all its outgoing transitions. More...
 
expression::exptr ripAllStates ()
 Removes all active states, constructing an RE semantically equivalent to this GNFA. More...
 

Detailed Description

Represents generalized nondeterministic finite automata.

Definition at line 17 of file gnfa.h.

Constructor & Destructor Documentation

◆ gnfa() [1/5]

reg::gnfa::gnfa ( dfa const &  d)

Constructs a GNFA with the same states and transitions as a given DFA.

The following changes are applied upon conversion:

  • Add a new and uniquely named initial state and connect it via an ε-transition to the DFA's start state.
  • Add a new and uniquely named accept state and connect the DFA's accept states to it via ε-transitions.
  • Disregard any information about initial or accept states of the DFA.
  • Replace any transition with a corresponding symbol expression.
  • Replace transitions with more than one label with alternations of these labels.
    Parameters
    dthe DFA to base the GNFA on

Definition at line 120 of file gnfa.cpp.

120  {
121  unordered_map<string,unordered_map<string,expression::exptr>> transitions(d.getNumberOfStates()+2);
123  for (size_t qi(0); qi < d.getNumberOfStates(); qi++) {
124  auto const& qLabel = d.getLabelOf(qi);
125  auto& entry = transitions[qLabel];
126  if (d.isAccepting(qi)) {
127  acceptingStates.push_front(qLabel);
128  }
129  for (size_t si(0); si < d.getNumberOfSymbols(); si++) {
130  char32_t symbol = d.getAlphabet()[si];
131  size_t pi = d.delta(qi, si);
132  auto& dest = entry[d.getStates()[pi]];
133  if (!dest) {
134  dest = expression::spawnSymbol(symbol);
135  } else {
137  }
138  }
139  }
140  p = std::make_unique<pImpl>(transitions, d.getLabelOf(0), acceptingStates, new nfa(d));
141 }
static exptr spawnAlternation(exptr const &l, exptr const &r, bool optimized=true, bool aggressive=false)
Gives an RE representing the alternation of two given REs.
Definition: expression.cpp:123
static exptr const & spawnSymbol(char32_t symbol)
Gives an RE representing the given UTF-32-encoded symbol.
Definition: expression.cpp:69

◆ gnfa() [2/5]

reg::gnfa::gnfa ( nfa const &  n)

Constructs a GNFA with the same states and transitions as a given NFA.

The following changes are applied upon conversion:

  • Add a new and uniquely named initial state and connect it via an ε-transition to the NFA's start state.
  • Add a new and uniquely named accept state and connect the NFA's accept states to it via ε-transitions.
  • Disregard any information about initial or accept states of the NFA.
  • Replace any transition with a corresponding symbol expression.
  • Replace transitions with more than one label with alternations of these labels.
    Parameters
    nthe NFA to base the GNFA on

Definition at line 153 of file gnfa.cpp.

153  {
154  unordered_map<string,unordered_map<string,expression::exptr>> transitions(n.getNumberOfStates()+2);
156  for (size_t qi(0); qi < n.getNumberOfStates(); qi++) {
157  auto const& qLabel = n.getLabelOf(qi);
158  auto& entry = transitions[qLabel];
159  if (n.isAccepting(qi)) {
160  acceptingStates.push_front(qLabel);
161  }
162  for (auto const& symbol : n.getAlphabet()) {
163  auto& pSet = n.delta(qi, symbol);
164  for (size_t pi(0); pi < pSet.size(); pi++) {
165  if (pSet[pi]) {
166  auto& dest = entry[n.getLabelOf(pi)];
167  if (!dest) {
168  dest = expression::spawnSymbol(symbol);
169  } else {
171  }
172  }
173  }
174  }
175  }
176  p = std::make_unique<pImpl>(transitions, n.getLabelOf(0), acceptingStates, new nfa(n));
177 }
static exptr spawnAlternation(exptr const &l, exptr const &r, bool optimized=true, bool aggressive=false)
Gives an RE representing the alternation of two given REs.
Definition: expression.cpp:123
static exptr const & spawnSymbol(char32_t symbol)
Gives an RE representing the given UTF-32-encoded symbol.
Definition: expression.cpp:69

◆ gnfa() [3/5]

reg::gnfa::gnfa ( expression::exptr  r)

Constructs a GNFA with only one transition.

The GNFA will have only two states: the initial and the accept state and a transition with the given label leading from the former to the latter.

Parameters
rthe transition's RE

Definition at line 185 of file gnfa.cpp.

185  : p(new pImpl) {
186  p->transitions[p->initial][p->accepting] = r;
187 }

◆ gnfa() [4/5]

reg::gnfa::gnfa ( gnfa const &  n)

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

Definition at line 401 of file gnfa.cpp.

401 : p(new pImpl(*(n.p))) {}

◆ gnfa() [5/5]

reg::gnfa::gnfa ( gnfa &&  n)

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

The other GNFA will be semantically equivalent to the ∅ RE afterwards.

Definition at line 405 of file gnfa.cpp.

405 : p(new pImpl) {p.swap(n.p);}

Member Function Documentation

◆ bypassTransition()

void reg::gnfa::bypassTransition ( std::string const &  qLabel,
std::string const &  pLabel 
)

Removes a transition between two states and replaces it with equivalent ones, bypassing its beginning state.

Definition at line 345 of file gnfa.cpp.

345  {
346  auto const& re = p->getTransition(qLabel, pLabel);
347  if (re == expression::spawnEmptySet()) {
348  return;
349  }
350  auto const& selfRe = p->getTransition(qLabel, qLabel);
351  for (auto const& from : p->transitions) {
352  if (from.first != qLabel) {
353  auto to = from.second.find(qLabel);
354  if (to != from.second.end() && to->second) {
355  p->addTransition(
356  from.first,
357  pLabel,
359  to->second,
361  expression::spawnKleene(selfRe),
362  re
363  )
364  )
365  );
366  }
367  }
368  }
369  p->transitions[qLabel].erase(pLabel);
370 }
static exptr const & spawnEmptySet()
Gives an RE representing the empty set ∅.
Definition: expression.cpp:50
static exptr spawnKleene(exptr const &b, bool optimized=true, bool aggressive=false)
Gives an RE representing the Kleene closure of a given RE.
Definition: expression.cpp:164
static exptr spawnConcatenation(exptr const &l, exptr const &r, bool optimized=true, bool aggressive=false)
Gives an RE representing the concatenation of two given REs.
Definition: expression.cpp:88

◆ getAcceptingState()

string const & reg::gnfa::getAcceptingState ( ) const

Reveals the name of this GNFA's accept state.

Definition at line 215 of file gnfa.cpp.

215  {
216  return p->accepting;
217 }

◆ getActiveStates()

vector< reference_wrapper< string const > > reg::gnfa::getActiveStates ( ) const

Reveals the names of this GNFA's non-initial, non-accepting states.

Definition at line 220 of file gnfa.cpp.

220  {
222  for (auto const& entry : p->transitions) {
223  if (entry.first != p->initial && entry.first != p->accepting) {
224  active.push_back(std::cref(entry.first));
225  }
226  }
227  return active;
228 }

◆ getInitialState()

string const & reg::gnfa::getInitialState ( ) const

Reveals the name of this GNFA's initial state.

Definition at line 210 of file gnfa.cpp.

210  {
211  return p->initial;
212 }

◆ getSplittableTransitions()

vector< pair< reference_wrapper< string const >, reference_wrapper< string const > > > reg::gnfa::getSplittableTransitions ( ) const

Reveals this GNFA's splittable transitions.

Returns
a vector of edges with transition labels with expression::size > 1

Definition at line 239 of file gnfa.cpp.

239  {
241  splittable.reserve(p->transitions.size()*p->transitions.size());
242  for (pair<string const, unordered_map<string, expression::exptr>> const& from : p->transitions) {
243  for (pair<string const, expression::exptr> const& to : from.second) {
244  if (to.second && to.second->getOperation() > expression::operation::symbol) {
245  splittable.push_back(std::make_pair(std::ref(from.first), std::ref(to.first)));
246  }
247  }
248  }
249  splittable.shrink_to_fit();
250  return splittable;
251 }

◆ getTransition()

expression::exptr reg::gnfa::getTransition ( std::string const &  qLabel,
std::string const &  pLabel 
) const

Extracts the RE labelling the transition between two states.

Definition at line 231 of file gnfa.cpp.

231  {
232  return p->getTransition(qLabel, pLabel);
233 }

◆ operator nfa const &()

reg::gnfa::operator nfa const & ( ) const

Returns an NFA accepting the same language as this GNFA.

◆ operator!=()

bool reg::gnfa::operator!= ( nfa const &  other) const

Checks whether this RE describes a different regular language than another object.

Returns
false if this RE's language is exactly the same as the other object's, true else

Definition at line 428 of file gnfa.cpp.

428  {
429  return !operator==(other);
430 }
bool operator==(nfa const &n) const
Checks whether this RE describes the same regular language as another object.
Definition: gnfa.cpp:420

◆ operator=() [1/2]

gnfa & reg::gnfa::operator= ( gnfa const &  n)

Copy-assigns this GNFA by copying another one's private implementation object.

Definition at line 433 of file gnfa.cpp.

433  {
434  if (this != &n) {
435  p.reset(new pImpl(*(n.p)));
436  }
437  return *this;
438 }

◆ operator=() [2/2]

gnfa & reg::gnfa::operator= ( gnfa &&  n)

Move-assigns this GNFA by stealing another one's private implementation object.

The other GNFA will be semantically equivalent to the ∅ RE afterwards.

Definition at line 442 of file gnfa.cpp.

442  {
443  if (this != &n) {
444  p.reset(new pImpl);
445  p.swap(n.p);
446  }
447  return *this;
448 }

◆ operator==()

bool reg::gnfa::operator== ( nfa const &  other) const

Checks whether this RE describes the same regular language as another object.

Returns
true if this RE's language is exactly the same as the other object's, false else

Definition at line 420 of file gnfa.cpp.

420  {
421  return other.operator==(*this);
422 }

◆ ripAllStates()

expression::exptr reg::gnfa::ripAllStates ( )

Removes all active states, constructing an RE semantically equivalent to this GNFA.

Returns
exptr to the RE labelling the remaining transition between initial state and accept state

Definition at line 393 of file gnfa.cpp.

393  {
394  for (auto const& rippable : getActiveStates()) {
395  ripState(rippable);
396  }
398 }
void ripState(std::string const &qLabel)
Removes a state, bypassing all its outgoing transitions.
Definition: gnfa.cpp:373
std::vector< std::reference_wrapper< std::string const > > getActiveStates() const
Reveals the names of this GNFA's non-initial, non-accepting states.
Definition: gnfa.cpp:220
expression::exptr getTransition(std::string const &qLabel, std::string const &pLabel) const
Extracts the RE labelling the transition between two states.
Definition: gnfa.cpp:231
std::string const & getAcceptingState() const
Reveals the name of this GNFA's accept state.
Definition: gnfa.cpp:215
std::string const & getInitialState() const
Reveals the name of this GNFA's initial state.
Definition: gnfa.cpp:210

◆ ripState()

void reg::gnfa::ripState ( std::string const &  qLabel)

Removes a state, bypassing all its outgoing transitions.

Definition at line 373 of file gnfa.cpp.

373  {
375  for (auto const& to : p->transitions[qLabel]) {
376  right.push_front(to.first);
377  }
378  for (auto const& to : right) {
379  if (to.get() != qLabel) {
380  bypassTransition(qLabel, to);
381  }
382  }
383  for (auto& from : p->transitions) {
384  from.second.erase(qLabel);
385  }
386  p->transitions.erase(qLabel);
387 }
T right(T... args)
void bypassTransition(std::string const &qLabel, std::string const &pLabel)
Removes a transition between two states and replaces it with equivalent ones, bypassing its beginning...
Definition: gnfa.cpp:345

◆ splitAllTransitions()

nfa reg::gnfa::splitAllTransitions ( )

Splits all transitions until only ∅, ε, and symbol REs remain and builds the resulting NFA.

When building the NFA, transitions with symbol and ε REs are replaced with corresponding symbol transitions and transitions with ∅ REs will be ignored.

Returns
the NFA with equivalent states and transitions to the GNFA's after splitting

Definition at line 324 of file gnfa.cpp.

324  {
325  for (auto splittable = getSplittableTransitions(); !splittable.empty(); splittable = getSplittableTransitions()) {
326  for (auto const& nodes : splittable) {
327  splitTransition(nodes.first, nodes.second);
328  }
329  }
330  nfa::builder b;
331  auto const& empty = expression::spawnEmptySet();
332  for (auto const& from : p->transitions) {
333  for (auto const& to : from.second) {
334  if (to.second != empty) {
335  b.addTransition(from.first, to.first, to.second->extractSymbol());
336  }
337  }
338  }
339  b.makeInitial(p->initial);
340  b.setAccepting(p->accepting, true);
341  return b.build();
342 }
std::vector< std::pair< std::reference_wrapper< std::string const >, std::reference_wrapper< std::string const > > > getSplittableTransitions() const
Reveals this GNFA's splittable transitions.
Definition: gnfa.cpp:239
std::vector< std::reference_wrapper< std::string const > > splitTransition(std::string const &qLabel, std::string const &pLabel)
Splits a transition between two states, adding new states if needed.
Definition: gnfa.cpp:261
static exptr const & spawnEmptySet()
Gives an RE representing the empty set ∅.
Definition: expression.cpp:50

◆ splitTransition()

vector< reference_wrapper< string const > > reg::gnfa::splitTransition ( std::string const &  qLabel,
std::string const &  pLabel 
)

Splits a transition between two states, adding new states if needed.

The transition will be broken up into pieces, according to the semantics of its label.

Parameters
qLabelthe beginning state of the transition
pLabelthe end state of the transition
Returns
a vector of states that were newly added while splitting the transition

Definition at line 261 of file gnfa.cpp.

261  {
263  auto const& re = p->getTransition(qLabel, pLabel);
264  switch (re->getOperation()) {
265  case expression::operation::alternation : {
266  auto sub1 = *(re->begin());
267  auto sub2 = *(re->begin()+1);
268  p->transitions[qLabel][pLabel] = expression::spawnEmptySet();
269  newStates.reserve(4);
270  for (size_t i(0); i < 4; i++) {
271  newStates.push_back(p->generateState());
272  }
273  auto const& epsilon = expression::spawnEmptyString();
274  p->transitions[qLabel][newStates[0]] = epsilon;
275  p->transitions[newStates[0]][newStates[1]] = sub1;
276  p->transitions[newStates[1]][pLabel] = epsilon;
277  p->transitions[qLabel][newStates[2]] = epsilon;
278  p->transitions[newStates[2]][newStates[3]] = sub2;
279  p->transitions[newStates[3]][pLabel] = epsilon;
280  break;
281  }
282  case expression::operation::concatenation : {
283  auto sub1 = *(re->begin());
284  auto sub2 = *(re->begin()+1);
285  p->transitions[qLabel][pLabel] = expression::spawnEmptySet();
286  newStates.reserve(2);
287  for (size_t i(0); i < 2; i++) {
288  newStates.push_back(p->generateState());
289  }
290  p->transitions[qLabel][newStates[0]] = sub1;
291  p->transitions[newStates[0]][newStates[1]] = expression::spawnEmptyString();
292  p->transitions[newStates[1]][pLabel] = sub2;
293  break;
294  }
295  case expression::operation::kleene : {
296  auto sub = *(re->begin());
297  auto const& epsilon = expression::spawnEmptyString();
298  p->transitions[qLabel][pLabel] = epsilon;
299  newStates.reserve(2);
300  for (size_t i(0); i < 2; i++) {
301  newStates.push_back(p->generateState());
302  }
303  p->transitions[qLabel][newStates[0]] = epsilon;
304  p->transitions[newStates[1]][pLabel] = epsilon;
305  p->transitions[newStates[1]][newStates[0]] = epsilon;
306  p->transitions[newStates[0]][newStates[1]] = sub;
307  break;
308  }
309  case expression::operation::symbol :
310  case expression::operation::empty :
311  ;
312  }
313  return newStates;
314 }
static exptr const & spawnEmptyString()
Gives an RE representing the empty string ε.
Definition: expression.cpp:59
static exptr const & spawnEmptySet()
Gives an RE representing the empty set ∅.
Definition: expression.cpp:50

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