reglibcpp  1.0.0
(Naïve) C++ implementation of models for regular languages
Classes | Public Member Functions | Friends | 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 (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...
 
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::string const &, 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...
 

Friends

class expression
 

Detailed Description

Represents generalized nondeterministic finite automata.

Definition at line 18 of file gnfa.h.

Constructor & Destructor Documentation

◆ gnfa() [1/4]

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 125 of file gnfa.cpp.

125  {
126  unordered_map<string,unordered_map<string,expression::exptr>> transitions(n.getNumberOfStates()+2);
127  forward_list<reference_wrapper<string const>> acceptingStates;
128  for (size_t qi(0); qi < n.getNumberOfStates(); qi++) {
129  auto const& qLabel = n.getLabelOf(qi);
130  auto& entry = transitions[qLabel];
131  if (n.isAccepting(qi)) {
132  acceptingStates.push_front(qLabel);
133  }
134  for (auto const& symbol : n.getAlphabet()) {
135  auto& pSet = n.delta(qi, symbol);
136  for (size_t pi(0); pi < pSet.size(); pi++) {
137  if (pSet[pi]) {
138  auto& dest = entry[n.getLabelOf(pi)];
139  if (!dest) {
140  dest = expression::spawnSymbol(symbol);
141  } else {
143  }
144  }
145  }
146  }
147  }
148  p = unique_ptr<pImpl>(new pImpl(transitions, n.getLabelOf(0), acceptingStates));
149 }
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:117
static exptr const & spawnSymbol(char32_t symbol)
Gives an RE representing the given UTF-32-encoded symbol.
Definition: expression.cpp:61

◆ gnfa() [2/4]

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 158 of file gnfa.cpp.

158  : p(new pImpl) {
159  p->transitions[p->initial][p->accepting] = r;
160 }

◆ gnfa() [3/4]

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

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

Definition at line 378 of file gnfa.cpp.

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

◆ gnfa() [4/4]

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 382 of file gnfa.cpp.

382 : 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 321 of file gnfa.cpp.

321  {
322  auto const& re = p->getTransition(qLabel, pLabel);
323  if (re == expression::spawnEmptySet()) {
324  return;
325  }
326  auto const& selfRe = p->getTransition(qLabel, qLabel);
327  for (auto const& from : p->transitions) {
328  if (from.first != qLabel) {
329  auto to = from.second.find(qLabel);
330  if (to != from.second.end() && to->second) {
331  p->addTransition(
332  from.first,
333  pLabel,
335  to->second,
337  expression::spawnKleene(selfRe),
338  re
339  )
340  )
341  );
342  }
343  }
344  }
345  p->transitions[qLabel].erase(pLabel);
346 }
static exptr const & spawnEmptySet()
Gives an RE representing the empty set ∅.
Definition: expression.cpp:40
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:152
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:81

◆ getAcceptingState()

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

Reveals the name of this GNFA's accept state.

Definition at line 188 of file gnfa.cpp.

188  {
189  return p->accepting;
190 }

◆ 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 193 of file gnfa.cpp.

193  {
194  vector<reference_wrapper<string const>> active;
195  for (auto const& entry : p->transitions) {
196  if (entry.first != p->initial && entry.first != p->accepting) {
197  active.push_back(entry.first);
198  }
199  }
200  return active;
201 }

◆ getInitialState()

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

Reveals the name of this GNFA's initial state.

Definition at line 183 of file gnfa.cpp.

183  {
184  return p->initial;
185 }

◆ getSplittableTransitions()

vector< pair< string const &, 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 213 of file gnfa.cpp.

213  {
214  vector<pair<string const&, string const&>> splittable;
215  splittable.reserve(p->transitions.size()*p->transitions.size());
216  for (pair<string const, unordered_map<string, expression::exptr>> const& from : p->transitions) {
217  for (pair<string const, expression::exptr> const& to : from.second) {
218  if (to.second && to.second->getOperation() > expression::operation::symbol) {
219  splittable.push_back(std::make_pair(std::ref(from.first), std::ref(to.first)));
220  }
221  }
222  }
223  splittable.shrink_to_fit();
224  return splittable;
225 }

◆ 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 204 of file gnfa.cpp.

204  {
205  return p->getTransition(qLabel, pLabel);
206 }

◆ 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 385 of file gnfa.cpp.

385  {
386  if (this != &n) {
387  p.reset(new pImpl(*(n.p)));
388  }
389  return *this;
390 }

◆ 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 394 of file gnfa.cpp.

394  {
395  if (this != &n) {
396  p.reset(new pImpl);
397  p.swap(n.p);
398  }
399  return *this;
400 }

◆ 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 370 of file gnfa.cpp.

370  {
371  for (auto const& rippable : getActiveStates()) {
372  ripState(rippable);
373  }
375 }
void ripState(std::string const &qLabel)
Removes a state, bypassing all its outgoing transitions.
Definition: gnfa.cpp:349
std::vector< std::reference_wrapper< std::string const > > getActiveStates() const
Reveals the names of this GNFA&#39;s non-initial, non-accepting states.
Definition: gnfa.cpp:193
expression::exptr getTransition(std::string const &qLabel, std::string const &pLabel) const
Extracts the RE labelling the transition between two states.
Definition: gnfa.cpp:204
std::string const & getAcceptingState() const
Reveals the name of this GNFA&#39;s accept state.
Definition: gnfa.cpp:188
std::string const & getInitialState() const
Reveals the name of this GNFA&#39;s initial state.
Definition: gnfa.cpp:183

◆ ripState()

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

Removes a state, bypassing all its outgoing transitions.

Definition at line 349 of file gnfa.cpp.

349  {
350  forward_list<reference_wrapper<string const>> right;
351  for (auto const& to : p->transitions[qLabel]) {
352  right.push_front(to.first);
353  }
354  for (auto const& to : right) {
355  if (to.get() != qLabel) {
356  bypassTransition(qLabel, to);
357  }
358  }
359  for (auto& from : p->transitions) {
360  from.second.erase(qLabel);
361  }
362  p->transitions.erase(qLabel);
363 }
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:321

◆ 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 300 of file gnfa.cpp.

300  {
301  for (auto splittable = getSplittableTransitions(); !splittable.empty(); splittable = getSplittableTransitions()) {
302  for (auto const& nodes : splittable) {
303  splitTransition(nodes.first, nodes.second);
304  }
305  }
306  nfa::builder b;
307  auto const& empty = expression::spawnEmptySet();
308  for (auto const& from : p->transitions) {
309  for (auto const& to : from.second) {
310  if (to.second != empty) {
311  b.addTransition(from.first, to.first, to.second->extractSymbol());
312  }
313  }
314  }
315  b.makeInitial(p->initial);
316  b.setAccepting(p->accepting, true);
317  return b.build();
318 }
std::vector< std::pair< std::string const &, std::string const & > > getSplittableTransitions() const
Reveals this GNFA&#39;s splittable transitions.
Definition: gnfa.cpp:213
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:236
static exptr const & spawnEmptySet()
Gives an RE representing the empty set ∅.
Definition: expression.cpp:40

◆ 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 236 of file gnfa.cpp.

236  {
237  vector<reference_wrapper<string const>> newStates;
238  auto const& re = p->getTransition(qLabel, pLabel);
239  switch (re->getOperation()) {
240  case expression::operation::alternation : {
241  auto sub1 = *(re->begin());
242  auto sub2 = *(re->begin()+1);
243  p->transitions[qLabel][pLabel] = expression::spawnEmptySet();
244  newStates.reserve(4);
245  for (size_t i(0); i < 4; i++) {
246  newStates.push_back(p->generateState());
247  }
248  auto const& epsilon = expression::spawnEmptyString();
249  p->transitions[qLabel][newStates[0]] = epsilon;
250  p->transitions[newStates[0]][newStates[1]] = sub1;
251  p->transitions[newStates[1]][pLabel] = epsilon;
252  p->transitions[qLabel][newStates[2]] = epsilon;
253  p->transitions[newStates[2]][newStates[3]] = sub2;
254  p->transitions[newStates[3]][pLabel] = epsilon;
255  break;
256  }
257  case expression::operation::concatenation : {
258  auto sub1 = *(re->begin());
259  auto sub2 = *(re->begin()+1);
260  p->transitions[qLabel][pLabel] = expression::spawnEmptySet();
261  newStates.reserve(2);
262  for (size_t i(0); i < 2; i++) {
263  newStates.push_back(p->generateState());
264  }
265  p->transitions[qLabel][newStates[0]] = sub1;
266  p->transitions[newStates[0]][newStates[1]] = expression::spawnEmptyString();
267  p->transitions[newStates[1]][pLabel] = sub2;
268  break;
269  }
270  case expression::operation::kleene : {
271  auto sub = *(re->begin());
272  auto const& epsilon = expression::spawnEmptyString();
273  p->transitions[qLabel][pLabel] = epsilon;
274  newStates.reserve(2);
275  for (size_t i(0); i < 2; i++) {
276  newStates.push_back(p->generateState());
277  }
278  p->transitions[qLabel][newStates[0]] = epsilon;
279  p->transitions[newStates[1]][pLabel] = epsilon;
280  p->transitions[newStates[1]][newStates[0]] = epsilon;
281  p->transitions[newStates[0]][newStates[1]] = sub;
282  break;
283  }
284  case expression::operation::symbol :
285  case expression::operation::empty :
286  ;
287  }
288  return newStates;
289 }
static exptr const & spawnEmptyString()
Gives an RE representing the empty string ε.
Definition: expression.cpp:50
static exptr const & spawnEmptySet()
Gives an RE representing the empty set ∅.
Definition: expression.cpp:40

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