@@ -210,6 +210,7 @@ class FiniteStateMachine {
210210 [[nodiscard]] virtual const SetOfStateRefs &getInitialStates () const = 0;
211211 [[nodiscard]] virtual const SetOfStateRefs &getFinalStates () const = 0;
212212 [[nodiscard]] virtual const SetOfStates &getStates () const = 0;
213+ [[nodiscard]] virtual SetOfStateRefs getStateRefs () const = 0;
213214 [[nodiscard]] virtual const SetOfEdges &getEdges () const = 0;
214215};
215216
@@ -266,19 +267,29 @@ class DepthFirstSearch {
266267
267268 virtual void onSimpleCycle (DfsStack &stack){};
268269
269- explicit DepthFirstSearch (const FiniteStateMachine &targetFsm) : fsm(targetFsm){};
270+ const FiniteStateMachine& getFSM (){
271+ return this ->fsm ;
272+ }
273+
274+ explicit DepthFirstSearch (const FiniteStateMachine &targetFsm) :
275+ fsm(targetFsm)
276+ {};
270277
271278 // Execute the depth first search
272- void DoDepthFirstSearch (const StateRef &startingState , bool fullDFS = false ) {
279+ void DoDepthFirstSearch (const SetOfStateRefs &startingStates , bool fullDFS = false ) {
273280 // store visited states
274281 SetOfStateRefs visitedStates;
275282 SetOfStateRefs statesOnStack;
276283
284+ this ->_abort = false ;
285+
277286 // put initial state on the stack
278- dfsStack.emplace_back (startingState);
279- this ->onEnterState (startingState);
287+ for (const auto & s: startingStates) {
288+ dfsStack.emplace_back (s);
289+ this ->onEnterState (s);
290+ }
280291
281- while (!(dfsStack.empty ())) {
292+ while (!this -> _abort && ! (dfsStack.empty ())) {
282293 DFSStackItem &si = dfsStack.back ();
283294
284295 // current item complete?
@@ -313,21 +324,34 @@ class DepthFirstSearch {
313324 }
314325 }
315326
327+ void DoDepthFirstSearch (const StateRef &startingState, bool fullDFS = false ){
328+ SetOfStateRefs stateSet;
329+ stateSet.insert (startingState);
330+ return this ->DoDepthFirstSearch (stateSet, fullDFS);
331+ }
332+
316333 // Execute the depth first search
317334 void DoDepthFirstSearch (bool fullDFS = false ) {
318- this ->DoDepthFirstSearch (this ->fsm .getInitialState (), fullDFS);
335+ this ->DoDepthFirstSearch (this ->fsm .getInitialStates (), fullDFS);
319336 }
320337
321- protected:
338+ void abortDFS () {
339+ this ->_abort = true ;
340+ }
341+
342+ private:
322343 const FiniteStateMachine &fsm;
344+ bool _abort{};
345+
323346};
324347
325348// Check for cycles
326349class DetectCycle : public DepthFirstSearch {
327350public:
328351 bool hasCycle = false ;
329352
330- explicit DetectCycle (const FiniteStateMachine &targetFsm) : DepthFirstSearch(targetFsm){};
353+ explicit DetectCycle (const FiniteStateMachine &targetFsm) : DepthFirstSearch(targetFsm){
354+ };
331355
332356 ~DetectCycle () override = default ;
333357
@@ -339,30 +363,15 @@ class DetectCycle : public DepthFirstSearch {
339363 bool checkForCycles () { return this ->checkForCycles (nullptr ); }
340364
341365 bool checkForCycles (ListOfStateRefs *cycle) {
342- this ->visitedStates .clear ();
343366 this ->cycle = cycle;
344- const SetOfStates &states = this ->fsm .getStates ();
345- auto nextStartingState = states.begin ();
346- while (nextStartingState != states.end ()) {
347- this ->DoDepthFirstSearch ((*nextStartingState).second ->getReference ());
348- if (this ->hasCycle ) {
349- return true ;
350- }
351- while (nextStartingState != states.end ()
352- && this ->visitedStates .includesState (
353- (*nextStartingState).second ->getReference ())) {
354- nextStartingState++;
355- }
356- }
357- return false ;
367+ const SetOfStateRefs states = this ->getFSM ().getStateRefs ();
368+ this ->DoDepthFirstSearch (states);
369+ return this ->hasCycle ;
358370 }
359371
360372private:
361- SetOfStateRefs visitedStates;
362373 ListOfStateRefs *cycle = nullptr ;
363374
364- void onEnterState (StateRef s) override { this ->visitedStates .insert (s); }
365-
366375 void onSimpleCycle (DfsStack &stack) override {
367376 if (!this ->hasCycle ) {
368377 if (this ->cycle != nullptr ) {
@@ -371,6 +380,7 @@ class DetectCycle : public DepthFirstSearch {
371380 }
372381 }
373382 this ->hasCycle = true ;
383+ this ->abortDFS ();
374384 }
375385 }
376386};
@@ -657,6 +667,14 @@ class FiniteStateMachine : public Abstract::FiniteStateMachine {
657667 return this ->states ;
658668 };
659669
670+ [[nodiscard]] FSM::Abstract::SetOfStateRefs getStateRefs () const override {
671+ FSM::Abstract::SetOfStateRefs result;
672+ for (const auto & s: this ->states ) {
673+ result.insert (s.second ->getReference ());
674+ }
675+ return result;
676+ };
677+
660678 [[nodiscard]] const SetOfEdges<StateLabelType, EdgeLabelType> &getEdges () const override {
661679 return this ->edges ;
662680 };
0 commit comments