4444#include " maxplus/base/basic_types.h"
4545#include " maxplus/base/exception/exception.h"
4646#include " maxplus/base/string/cstring.h"
47+ #include < functional>
4748#include < list>
4849#include < map>
4950#include < memory>
5051#include < set>
52+ #include < utility>
5153
5254namespace FSM {
5355
@@ -251,8 +253,9 @@ class DepthFirstSearch {
251253 SetOfEdgeRefs::CIter iter;
252254 };
253255
254- protected:
255256 using DfsStack = std::list<DFSStackItem>;
257+
258+ protected:
256259 DfsStack dfsStack;
257260
258261public:
@@ -267,13 +270,9 @@ class DepthFirstSearch {
267270
268271 virtual void onSimpleCycle (DfsStack &stack){};
269272
270- const FiniteStateMachine& getFSM (){
271- return this ->fsm ;
272- }
273+ const FiniteStateMachine &getFSM () { return this ->fsm ; }
273274
274- explicit DepthFirstSearch (const FiniteStateMachine &targetFsm) :
275- fsm(targetFsm)
276- {};
275+ explicit DepthFirstSearch (const FiniteStateMachine &targetFsm) : fsm(targetFsm){};
277276
278277 // Execute the depth first search
279278 void DoDepthFirstSearch (const SetOfStateRefs &startingStates, bool fullDFS = false ) {
@@ -283,48 +282,69 @@ class DepthFirstSearch {
283282
284283 this ->_abort = false ;
285284
286- // put initial state on the stack
287- for (const auto & s: startingStates) {
285+ // for each of the starting states
286+ auto nextStartingState = startingStates.begin ();
287+ while (nextStartingState != startingStates.end ()) {
288+
289+ // skip states we have already visited
290+ while (nextStartingState != startingStates.end ()
291+ && visitedStates.includesState (*nextStartingState)) {
292+ nextStartingState++;
293+ }
294+ // if we did not find any state anymore
295+ if (nextStartingState == startingStates.end ()) {
296+ break ;
297+ }
298+
299+ statesOnStack.clear ();
300+ StateRef s = *nextStartingState;
288301 dfsStack.emplace_back (s);
302+ statesOnStack.insert (s);
303+ visitedStates.insert (s);
289304 this ->onEnterState (s);
290- }
291305
292- while (!this ->_abort && !(dfsStack.empty ())) {
293- DFSStackItem &si = dfsStack.back ();
294-
295- // current item complete?
296- if (si.atEnd ()) {
297- // pop it from stack
298- this ->onLeaveState (si.getState ());
299- const auto *const s = si.getState ();
300- statesOnStack.erase (s);
301- if (fullDFS) {
302- assert (visitedStates.includesState (s));
303- visitedStates.erase (s);
306+ while (!this ->_abort && !(dfsStack.empty ())) {
307+ DFSStackItem &si = dfsStack.back ();
308+ if (!visitedStates.includesState (si.getState ())) {
309+ this ->onEnterState (si.getState ());
310+ visitedStates.insert (si.getState ());
304311 }
305- dfsStack.pop_back ();
306- } else {
307- // goto next edge
308- const auto *e = *(si.getIter ());
309- si.advance ();
310- StateRef dest = e->getDestination ();
311- bool revisit = statesOnStack.includesState (dest);
312- if (revisit) {
313- // cycle found
314- this ->onSimpleCycle (dfsStack);
312+ // current item complete?
313+ if (si.atEnd ()) {
314+ // pop it from stack
315+ this ->onLeaveState (si.getState ());
316+ const auto *const s = si.getState ();
317+ statesOnStack.erase (s);
318+ if (fullDFS) {
319+ assert (visitedStates.includesState (s));
320+ visitedStates.erase (s);
321+ }
322+ dfsStack.pop_back ();
315323 } else {
316- // if target state not visited before
317- dfsStack.emplace_back (dest);
318- this ->onTransition (*e);
319- this ->onEnterState (dest);
320- visitedStates.insert (dest);
321- statesOnStack.insert (dest);
324+ // goto next edge
325+ const auto *e = *(si.getIter ());
326+ si.advance ();
327+ StateRef dest = e->getDestination ();
328+ bool revisit = statesOnStack.includesState (dest);
329+ if (revisit) {
330+ // cycle found
331+ this ->onSimpleCycle (dfsStack);
332+ } else {
333+ if (!visitedStates.includesState (dest)) {
334+ // if target state not visited before
335+ dfsStack.emplace_back (dest);
336+ this ->onTransition (*e);
337+ this ->onEnterState (dest);
338+ visitedStates.insert (dest);
339+ statesOnStack.insert (dest);
340+ }
341+ }
322342 }
323343 }
324344 }
325345 }
326346
327- void DoDepthFirstSearch (const StateRef &startingState, bool fullDFS = false ){
347+ void DoDepthFirstSearch (const StateRef &startingState, bool fullDFS = false ) {
328348 SetOfStateRefs stateSet;
329349 stateSet.insert (startingState);
330350 return this ->DoDepthFirstSearch (stateSet, fullDFS);
@@ -335,23 +355,70 @@ class DepthFirstSearch {
335355 this ->DoDepthFirstSearch (this ->fsm .getInitialStates (), fullDFS);
336356 }
337357
338- void abortDFS () {
339- this ->_abort = true ;
340- }
358+ void abortDFS () { this ->_abort = true ; }
341359
342360private:
343361 const FiniteStateMachine &fsm;
344362 bool _abort{};
363+ };
364+
365+ class DepthFirstSearchLambda : public DepthFirstSearch {
366+
367+ public:
368+ DepthFirstSearchLambda (const DepthFirstSearchLambda &) = delete ;
369+ DepthFirstSearchLambda &operator =(const DepthFirstSearchLambda &other) = delete ;
370+ DepthFirstSearchLambda (DepthFirstSearch &&) = delete ;
371+ DepthFirstSearchLambda &operator =(DepthFirstSearchLambda &&) = delete ;
372+
373+ private:
374+ using TOnEnterLambda = std::function<void (StateRef s)>;
375+ TOnEnterLambda _onEnterStateLambda;
376+ using TOnLeaveLambda = std::function<void (StateRef s)>;
377+ TOnLeaveLambda _onLeaveStateLambda;
378+ using TOnTransitionLambda = std::function<void (const Edge &e)>;
379+ TOnTransitionLambda _onTransitionLambda;
380+ using TOnSimpleCycleLambda = std::function<void (const DepthFirstSearch::DfsStack &stack)>;
381+ TOnSimpleCycleLambda _onSimpleCycleLambda;
382+
383+ public:
384+ ~DepthFirstSearchLambda () override = default ;
345385
386+ void onEnterState (StateRef s) override { this ->_onEnterStateLambda (s); };
387+
388+ void onLeaveState (StateRef s) override { this ->_onLeaveStateLambda (s); };
389+
390+ void onTransition (const Edge &e) override { this ->_onTransitionLambda (e); };
391+
392+ void onSimpleCycle (DepthFirstSearch::DfsStack &stack) override {
393+ this ->_onSimpleCycleLambda (stack);
394+ };
395+
396+ explicit DepthFirstSearchLambda (const FiniteStateMachine &targetFsm) :
397+ _onEnterStateLambda([](StateRef) {}),
398+ _onLeaveStateLambda ([](StateRef) {}),
399+ _onTransitionLambda ([](const Edge &) {}),
400+ _onSimpleCycleLambda ([](const DepthFirstSearch::DfsStack &) {}),
401+ DepthFirstSearch (targetFsm){};
402+
403+ void setOnEnterLambda (TOnEnterLambda lambda) { this ->_onEnterStateLambda = std::move (lambda); }
404+
405+ void setOnLeaveLambda (TOnLeaveLambda lambda) { this ->_onLeaveStateLambda = std::move (lambda); }
406+
407+ void setOnTransitionLambda (TOnTransitionLambda lambda) {
408+ this ->_onTransitionLambda = std::move (lambda);
409+ }
410+
411+ void setOnSimpleCycleLambda (TOnSimpleCycleLambda lambda) {
412+ this ->_onSimpleCycleLambda = std::move (lambda);
413+ }
346414};
347415
348416// Check for cycles
349417class DetectCycle : public DepthFirstSearch {
350418public:
351419 bool hasCycle = false ;
352420
353- explicit DetectCycle (const FiniteStateMachine &targetFsm) : DepthFirstSearch(targetFsm){
354- };
421+ explicit DetectCycle (const FiniteStateMachine &targetFsm) : DepthFirstSearch(targetFsm){};
355422
356423 ~DetectCycle () override = default ;
357424
@@ -669,7 +736,7 @@ class FiniteStateMachine : public Abstract::FiniteStateMachine {
669736
670737 [[nodiscard]] FSM::Abstract::SetOfStateRefs getStateRefs () const override {
671738 FSM::Abstract::SetOfStateRefs result;
672- for (const auto & s : this ->states ) {
739+ for (const auto &s : this ->states ) {
673740 result.insert (s.second ->getReference ());
674741 }
675742 return result;
0 commit comments