reglibcpp  1.3.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::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...
 

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

116  {
117  unordered_map<string,unordered_map<string,expression::exptr>> transitions(n.getNumberOfStates()+2);
118  forward_list<reference_wrapper<string const>> acceptingStates;
119  for (size_t qi(0); qi < n.getNumberOfStates(); qi++) {
120  auto const& qLabel = n.getLabelOf(qi);
121  auto& entry = transitions[qLabel];
122  if (n.isAccepting(qi)) {
123  acceptingStates.push_front(qLabel);
124  }
125  for (auto const& symbol : n.getAlphabet()) {
126  auto& pSet = n.delta(qi, symbol);
127  for (size_t pi(0); pi < pSet.size(); pi++) {
128  if (pSet[pi]) {
129  auto& dest = entry[n.getLabelOf(pi)];
130  if (!dest) {
131  dest = expression::spawnSymbol(symbol);
132  } else {
134  }
135  }
136  }
137  }
138  }
139  p = std::make_unique<pImpl>(transitions, n.getLabelOf(0), acceptingStates);
140 }
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:106
static exptr const & spawnSymbol(char32_t symbol)
Gives an RE representing the given UTF-32-encoded symbol.
Definition: expression.cpp:52

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

148  : p(new pImpl) {
149  p->transitions[p->initial][p->accepting] = r;
150 }

◆ gnfa() [3/4]

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

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

Definition at line 364 of file gnfa.cpp.

364 : 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 368 of file gnfa.cpp.

368 : 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 308 of file gnfa.cpp.

308  {
309  auto const& re = p->getTransition(qLabel, pLabel);
310  if (re == expression::spawnEmptySet()) {
311  return;
312  }
313  auto const& selfRe = p->getTransition(qLabel, qLabel);
314  for (auto const& from : p->transitions) {
315  if (from.first != qLabel) {
316  auto to = from.second.find(qLabel);
317  if (to != from.second.end() && to->second) {
318  p->addTransition(
319  from.first,
320  pLabel,
322  to->second,
324  expression::spawnKleene(selfRe),
325  re
326  )
327  )
328  );
329  }
330  }
331  }
332  p->transitions[qLabel].erase(pLabel);
333 }
static exptr const & spawnEmptySet()
Gives an RE representing the empty set ∅.
Definition: expression.cpp:33
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:140
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:71

◆ getAcceptingState()

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

Reveals the name of this GNFA's accept state.

Definition at line 178 of file gnfa.cpp.

178  {
179  return p->accepting;
180 }

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

183  {
184  vector<reference_wrapper<string const>> active;
185  for (auto const& entry : p->transitions) {
186  if (entry.first != p->initial && entry.first != p->accepting) {
187  active.push_back(std::cref(entry.first));
188  }
189  }
190  return active;
191 }

◆ getInitialState()

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

Reveals the name of this GNFA's initial state.

Definition at line 173 of file gnfa.cpp.

173  {
174  return p->initial;
175 }

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

202  {
203  vector<pair<reference_wrapper<string const>, reference_wrapper<string const>>> splittable;
204  splittable.reserve(p->transitions.size()*p->transitions.size());
205  for (pair<string const, unordered_map<string, expression::exptr>> const& from : p->transitions) {
206  for (pair<string const, expression::exptr> const& to : from.second) {
207  if (to.second && to.second->getOperation() > expression::operation::symbol) {
208  splittable.push_back(std::make_pair(std::ref(from.first), std::ref(to.first)));
209  }
210  }
211  }
212  splittable.shrink_to_fit();
213  return splittable;
214 }

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

194  {
195  return p->getTransition(qLabel, pLabel);
196 }

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

371  {
372  if (this != &n) {
373  p.reset(new pImpl(*(n.p)));
374  }
375  return *this;
376 }

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

380  {
381  if (this != &n) {
382  p.reset(new pImpl);
383  p.swap(n.p);
384  }
385  return *this;
386 }

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

356  {
357  for (auto const& rippable : getActiveStates()) {
358  ripState(rippable);
359  }
361 }
void ripState(std::string const &qLabel)
Removes a state, bypassing all its outgoing transitions.
Definition: gnfa.cpp:336
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:183
expression::exptr getTransition(std::string const &qLabel, std::string const &pLabel) const
Extracts the RE labelling the transition between two states.
Definition: gnfa.cpp:194
std::string const & getAcceptingState() const
Reveals the name of this GNFA's accept state.
Definition: gnfa.cpp:178
std::string const & getInitialState() const
Reveals the name of this GNFA's initial state.
Definition: gnfa.cpp:173

◆ ripState()

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

Removes a state, bypassing all its outgoing transitions.

Definition at line 336 of file gnfa.cpp.

336  {
337  forward_list<reference_wrapper<string const>> right;
338  for (auto const& to : p->transitions[qLabel]) {
339  right.push_front(to.first);
340  }
341  for (auto const& to : right) {
342  if (to.get() != qLabel) {
343  bypassTransition(qLabel, to);
344  }
345  }
346  for (auto& from : p->transitions) {
347  from.second.erase(qLabel);
348  }
349  p->transitions.erase(qLabel);
350 }
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:308

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

287  {
288  for (auto splittable = getSplittableTransitions(); !splittable.empty(); splittable = getSplittableTransitions()) {
289  for (auto const& nodes : splittable) {
290  splitTransition(nodes.first, nodes.second);
291  }
292  }
293  nfa::builder b;
294  auto const& empty = expression::spawnEmptySet();
295  for (auto const& from : p->transitions) {
296  for (auto const& to : from.second) {
297  if (to.second != empty) {
298  b.addTransition(from.first, to.first, to.second->extractSymbol());
299  }
300  }
301  }
302  b.makeInitial(p->initial);
303  b.setAccepting(p->accepting, true);
304  return b.build();
305 }
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:202
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:224
static exptr const & spawnEmptySet()
Gives an RE representing the empty set ∅.
Definition: expression.cpp:33

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

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

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