diff --git a/benchmarks/model_checking/C++/CAN_BUS_tlc.cpp b/benchmarks/model_checking/C++/CAN_BUS_tlc.cpp
index 12f680f388a39e4a9193033bcb0b566a842f182a..69e4a03203b9c371fad9855883d64ec74dcb70d5 100644
--- a/benchmarks/model_checking/C++/CAN_BUS_tlc.cpp
+++ b/benchmarks/model_checking/C++/CAN_BUS_tlc.cpp
@@ -11,6 +11,7 @@
 #include <boost/asio/post.hpp>
 #include <boost/asio/thread_pool.hpp>
 #include <boost/any.hpp>
+#include <boost/optional.hpp>
 #include <btypes_primitives/BUtils.hpp>
 #include <btypes_primitives/StateNotReachableError.hpp>
 #include <btypes_primitives/PreconditionOrAssertionViolation.hpp>
@@ -32,7 +33,6 @@ class CAN_BUS_tlc {
 
         enum Type { BFS, DFS, MIXED };
 
-
         class T1state : public BObject {
             public:
 
@@ -269,6 +269,7 @@ class CAN_BUS_tlc {
                 }
         };
 
+
         struct Hash {
             public:
                 size_t operator()(const CAN_BUS_tlc& obj) const {
@@ -315,9 +316,32 @@ class CAN_BUS_tlc {
         BInteger T3_readvalue;
         T3state T3_state;
 
+        mutable boost::optional<bool> _tr_cache_T1Evaluate;
+        mutable boost::optional<BSet<BInteger>> _tr_cache_T1Calculate;
+        mutable boost::optional<BSet<BTuple<BInteger, BInteger >>> _tr_cache_T1SendResult;
+        mutable boost::optional<BSet<BInteger>> _tr_cache_T1Wait;
+        mutable boost::optional<bool> _tr_cache_T2Evaluate;
+        mutable boost::optional<BSet<BTuple<BInteger, BInteger >>> _tr_cache_T2ReadBus;
+        mutable boost::optional<bool> _tr_cache_T2Reset;
+        mutable boost::optional<bool> _tr_cache_T2Complete;
+        mutable boost::optional<BSet<BInteger>> _tr_cache_T2ReleaseBus;
+        mutable boost::optional<bool> _tr_cache_T2Calculate;
+        mutable boost::optional<BSet<BTuple<BInteger, BInteger >>> _tr_cache_T2WriteBus;
+        mutable boost::optional<BSet<BInteger>> _tr_cache_T2Wait;
+        mutable boost::optional<bool> _tr_cache_T3Initiate;
+        mutable boost::optional<bool> _tr_cache_T3Evaluate;
+        mutable boost::optional<BSet<BTuple<BInteger, BInteger >>> _tr_cache_T3writebus;
+        mutable boost::optional<BSet<BTuple<BInteger, BInteger >>> _tr_cache_T3Read;
+        mutable boost::optional<bool> _tr_cache_T3Poll;
+        mutable boost::optional<BSet<BInteger>> _tr_cache_T3ReleaseBus;
+        mutable boost::optional<bool> _tr_cache_T3Wait;
+        mutable boost::optional<bool> _tr_cache_T3ReEnableWait;
+        mutable boost::optional<BSet<BInteger>> _tr_cache_Update;
 
     public:
 
+        std::string stateAccessedVia;
+
         CAN_BUS_tlc() {
             NATSET = (BSet<BInteger>::interval((BInteger(0)),(BInteger(5))));
             T2v = (BInteger(0));
@@ -595,190 +619,284 @@ class CAN_BUS_tlc {
         }
 
 
-        bool _tr_T1Evaluate() const {
-            return ((BBoolean(T1_timer.equal((BInteger(0))).booleanValue() && T1_state.equal((T1state(T1state::T1_EN))).booleanValue()))).booleanValue();
+        bool _tr_T1Evaluate(bool isCaching) const {
+            if (this->_tr_cache_T1Evaluate == boost::none){
+                bool __tmp_result = ((BBoolean(T1_timer.equal((BInteger(0))).booleanValue() && T1_state.equal((T1state(T1state::T1_EN))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_T1Evaluate = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_T1Evaluate.get();
         }
 
-        BSet<BInteger> _tr_T1Calculate() const {
-            BSet<BInteger> _ic_set_1 = BSet<BInteger>();
-            for(BInteger _ic_p_1 : (BSet<BInteger>::interval((BInteger(1)).negative(),(BInteger(3))))) {
-                if((T1_state.equal((T1state(T1state::T1_CALC)))).booleanValue()) {
-                    _ic_set_1 = _ic_set_1._union(BSet<BInteger>(_ic_p_1));
-                }
+        BSet<BInteger> _tr_T1Calculate(bool isCaching) const {
+            if (this->_tr_cache_T1Calculate == boost::none){
+                BSet<BInteger> _ic_set_1 = BSet<BInteger>();
+                for(const BInteger& _ic_p_1 : (BSet<BInteger>::interval((BInteger(1)).negative(),(BInteger(3))))) {
+                    if((T1_state.equal((T1state(T1state::T1_CALC)))).booleanValue()) {
+                        _ic_set_1 = _ic_set_1._union(BSet<BInteger>(_ic_p_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_T1Calculate = _ic_set_1;
+                else return _ic_set_1;
             }
-            return _ic_set_1;
+            return this->_tr_cache_T1Calculate.get();
         }
 
-        BSet<BTuple<BInteger, BInteger >> _tr_T1SendResult() const {
-            BSet<BTuple<BInteger, BInteger >> _ic_set_2 = BSet<BTuple<BInteger, BInteger >>();
-            for(BInteger _ic_ppriority_1 : {(BInteger(3))}) {
-                for(BInteger _ic_pv_1 : {T1_writevalue}) {
-                    if((T1_state.equal((T1state(T1state::T1_SEND)))).booleanValue()) {
-                        _ic_set_2 = _ic_set_2._union(BSet<BTuple<BInteger, BInteger >>((BTuple<BInteger, BInteger >(_ic_ppriority_1, _ic_pv_1))));
+        BSet<BTuple<BInteger, BInteger >> _tr_T1SendResult(bool isCaching) const {
+            if (this->_tr_cache_T1SendResult == boost::none){
+                BSet<BTuple<BInteger, BInteger >> _ic_set_2 = BSet<BTuple<BInteger, BInteger >>();
+                for(const BInteger& _ic_ppriority_1 : {(BInteger(3))}) {
+                    for(const BInteger& _ic_pv_1 : {T1_writevalue}) {
+                        if((T1_state.equal((T1state(T1state::T1_SEND)))).booleanValue()) {
+                            _ic_set_2 = _ic_set_2._union(BSet<BTuple<BInteger, BInteger >>((BTuple<BInteger, BInteger >(_ic_ppriority_1, _ic_pv_1))));
+                        }
+
                     }
 
                 }
 
+                if (isCaching) this->_tr_cache_T1SendResult = _ic_set_2;
+                else return _ic_set_2;
             }
-
-            return _ic_set_2;
+            return this->_tr_cache_T1SendResult.get();
         }
 
-        BSet<BInteger> _tr_T1Wait() const {
-            BSet<BInteger> _ic_set_3 = BSet<BInteger>();
-            for(BInteger _ic_pt_1 : {(BInteger(2))}) {
-                if((T1_state.equal((T1state(T1state::T1_WAIT)))).booleanValue()) {
-                    _ic_set_3 = _ic_set_3._union(BSet<BInteger>(_ic_pt_1));
+        BSet<BInteger> _tr_T1Wait(bool isCaching) const {
+            if (this->_tr_cache_T1Wait == boost::none){
+                BSet<BInteger> _ic_set_3 = BSet<BInteger>();
+                for(const BInteger& _ic_pt_1 : {(BInteger(2))}) {
+                    if((T1_state.equal((T1state(T1state::T1_WAIT)))).booleanValue()) {
+                        _ic_set_3 = _ic_set_3._union(BSet<BInteger>(_ic_pt_1));
+                    }
+
                 }
 
+                if (isCaching) this->_tr_cache_T1Wait = _ic_set_3;
+                else return _ic_set_3;
             }
-
-            return _ic_set_3;
+            return this->_tr_cache_T1Wait.get();
         }
 
-        bool _tr_T2Evaluate() const {
-            return ((BBoolean(T2_timer.equal((BInteger(0))).booleanValue() && T2_state.equal((T2state(T2state::T2_EN))).booleanValue()))).booleanValue();
+        bool _tr_T2Evaluate(bool isCaching) const {
+            if (this->_tr_cache_T2Evaluate == boost::none){
+                bool __tmp_result = ((BBoolean(T2_timer.equal((BInteger(0))).booleanValue() && T2_state.equal((T2state(T2state::T2_EN))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_T2Evaluate = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_T2Evaluate.get();
         }
 
-        BSet<BTuple<BInteger, BInteger >> _tr_T2ReadBus() const {
-            BSet<BTuple<BInteger, BInteger >> _ic_set_5 = BSet<BTuple<BInteger, BInteger >>();
-            for(BInteger _ic_ppriority_1 : {BUSpriority}) {
-                for(BInteger _ic_pv_1 : {BUSvalue}) {
-                    if((T2_state.equal((T2state(T2state::T2_RCV)))).booleanValue()) {
-                        _ic_set_5 = _ic_set_5._union(BSet<BTuple<BInteger, BInteger >>((BTuple<BInteger, BInteger >(_ic_ppriority_1, _ic_pv_1))));
+        BSet<BTuple<BInteger, BInteger >> _tr_T2ReadBus(bool isCaching) const {
+            if (this->_tr_cache_T2ReadBus == boost::none){
+                BSet<BTuple<BInteger, BInteger >> _ic_set_5 = BSet<BTuple<BInteger, BInteger >>();
+                for(const BInteger& _ic_ppriority_1 : {BUSpriority}) {
+                    for(const BInteger& _ic_pv_1 : {BUSvalue}) {
+                        if((T2_state.equal((T2state(T2state::T2_RCV)))).booleanValue()) {
+                            _ic_set_5 = _ic_set_5._union(BSet<BTuple<BInteger, BInteger >>((BTuple<BInteger, BInteger >(_ic_ppriority_1, _ic_pv_1))));
+                        }
+
                     }
 
                 }
 
+                if (isCaching) this->_tr_cache_T2ReadBus = _ic_set_5;
+                else return _ic_set_5;
             }
-
-            return _ic_set_5;
+            return this->_tr_cache_T2ReadBus.get();
         }
 
-        bool _tr_T2Reset() const {
-            return ((BBoolean(T2_readpriority.equal((BInteger(4))).booleanValue() && T2_state.equal((T2state(T2state::T2_PROC))).booleanValue()))).booleanValue();
+        bool _tr_T2Reset(bool isCaching) const {
+            if (this->_tr_cache_T2Reset == boost::none){
+                bool __tmp_result = ((BBoolean(T2_readpriority.equal((BInteger(4))).booleanValue() && T2_state.equal((T2state(T2state::T2_PROC))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_T2Reset = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_T2Reset.get();
         }
 
-        bool _tr_T2Complete() const {
-            return ((BBoolean((BBoolean(T2_state.equal((T2state(T2state::T2_PROC))).booleanValue() && T2_readpriority.equal((BInteger(5))).booleanValue())).booleanValue() && T2_mode.equal((T2mode(T2mode::T2MODE_TRANSMIT))).booleanValue()))).booleanValue();
+        bool _tr_T2Complete(bool isCaching) const {
+            if (this->_tr_cache_T2Complete == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean(T2_state.equal((T2state(T2state::T2_PROC))).booleanValue() && T2_readpriority.equal((BInteger(5))).booleanValue())).booleanValue() && T2_mode.equal((T2mode(T2mode::T2MODE_TRANSMIT))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_T2Complete = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_T2Complete.get();
         }
 
-        BSet<BInteger> _tr_T2ReleaseBus() const {
-            BSet<BInteger> _ic_set_8 = BSet<BInteger>();
-            for(BInteger _ic_ppriority_1 : {T2_readpriority}) {
-                if(((BBoolean(BUSwrite.domain().elementOf(_ic_ppriority_1).booleanValue() && T2_state.equal((T2state(T2state::T2_RELEASE))).booleanValue()))).booleanValue()) {
-                    _ic_set_8 = _ic_set_8._union(BSet<BInteger>(_ic_ppriority_1));
+        BSet<BInteger> _tr_T2ReleaseBus(bool isCaching) const {
+            if (this->_tr_cache_T2ReleaseBus == boost::none){
+                BSet<BInteger> _ic_set_8 = BSet<BInteger>();
+                for(const BInteger& _ic_ppriority_1 : {T2_readpriority}) {
+                    if(((BBoolean(BUSwrite.domain().elementOf(_ic_ppriority_1).booleanValue() && T2_state.equal((T2state(T2state::T2_RELEASE))).booleanValue()))).booleanValue()) {
+                        _ic_set_8 = _ic_set_8._union(BSet<BInteger>(_ic_ppriority_1));
+                    }
+
                 }
 
+                if (isCaching) this->_tr_cache_T2ReleaseBus = _ic_set_8;
+                else return _ic_set_8;
             }
-
-            return _ic_set_8;
+            return this->_tr_cache_T2ReleaseBus.get();
         }
 
-        bool _tr_T2Calculate() const {
-            return ((BBoolean(T2_readpriority.equal((BInteger(3))).booleanValue() && T2_state.equal((T2state(T2state::T2_PROC))).booleanValue()))).booleanValue();
+        bool _tr_T2Calculate(bool isCaching) const {
+            if (this->_tr_cache_T2Calculate == boost::none){
+                bool __tmp_result = ((BBoolean(T2_readpriority.equal((BInteger(3))).booleanValue() && T2_state.equal((T2state(T2state::T2_PROC))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_T2Calculate = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_T2Calculate.get();
         }
 
-        BSet<BTuple<BInteger, BInteger >> _tr_T2WriteBus() const {
-            BSet<BTuple<BInteger, BInteger >> _ic_set_10 = BSet<BTuple<BInteger, BInteger >>();
-            for(BInteger _ic_ppriority_1 : {(BInteger(5))}) {
-                for(BInteger _ic_pv_1 : {T2_writevalue}) {
-                    if((T2_state.equal((T2state(T2state::T2_SEND)))).booleanValue()) {
-                        _ic_set_10 = _ic_set_10._union(BSet<BTuple<BInteger, BInteger >>((BTuple<BInteger, BInteger >(_ic_ppriority_1, _ic_pv_1))));
+        BSet<BTuple<BInteger, BInteger >> _tr_T2WriteBus(bool isCaching) const {
+            if (this->_tr_cache_T2WriteBus == boost::none){
+                BSet<BTuple<BInteger, BInteger >> _ic_set_10 = BSet<BTuple<BInteger, BInteger >>();
+                for(const BInteger& _ic_ppriority_1 : {(BInteger(5))}) {
+                    for(const BInteger& _ic_pv_1 : {T2_writevalue}) {
+                        if((T2_state.equal((T2state(T2state::T2_SEND)))).booleanValue()) {
+                            _ic_set_10 = _ic_set_10._union(BSet<BTuple<BInteger, BInteger >>((BTuple<BInteger, BInteger >(_ic_ppriority_1, _ic_pv_1))));
+                        }
+
                     }
 
                 }
 
+                if (isCaching) this->_tr_cache_T2WriteBus = _ic_set_10;
+                else return _ic_set_10;
             }
-
-            return _ic_set_10;
+            return this->_tr_cache_T2WriteBus.get();
         }
 
-        BSet<BInteger> _tr_T2Wait() const {
-            BSet<BInteger> _ic_set_11 = BSet<BInteger>();
-            for(BInteger _ic_pt_1 : {(BInteger(3))}) {
-                if((T2_state.equal((T2state(T2state::T2_WAIT)))).booleanValue()) {
-                    _ic_set_11 = _ic_set_11._union(BSet<BInteger>(_ic_pt_1));
+        BSet<BInteger> _tr_T2Wait(bool isCaching) const {
+            if (this->_tr_cache_T2Wait == boost::none){
+                BSet<BInteger> _ic_set_11 = BSet<BInteger>();
+                for(const BInteger& _ic_pt_1 : {(BInteger(3))}) {
+                    if((T2_state.equal((T2state(T2state::T2_WAIT)))).booleanValue()) {
+                        _ic_set_11 = _ic_set_11._union(BSet<BInteger>(_ic_pt_1));
+                    }
+
                 }
 
+                if (isCaching) this->_tr_cache_T2Wait = _ic_set_11;
+                else return _ic_set_11;
             }
-
-            return _ic_set_11;
+            return this->_tr_cache_T2Wait.get();
         }
 
-        bool _tr_T3Initiate() const {
-            return ((BBoolean((BBoolean(T3_state.equal((T3state(T3state::T3_READY))).booleanValue() && T3_evaluated.equal((BBoolean(false))).booleanValue())).booleanValue() && T3_enabled.equal((BBoolean(true))).booleanValue()))).booleanValue();
+        bool _tr_T3Initiate(bool isCaching) const {
+            if (this->_tr_cache_T3Initiate == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean(T3_state.equal((T3state(T3state::T3_READY))).booleanValue() && T3_evaluated.equal((BBoolean(false))).booleanValue())).booleanValue() && T3_enabled.equal((BBoolean(true))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_T3Initiate = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_T3Initiate.get();
         }
 
-        bool _tr_T3Evaluate() const {
-            return ((BBoolean((BBoolean(T3_state.equal((T3state(T3state::T3_READY))).booleanValue() && T3_evaluated.equal((BBoolean(false))).booleanValue())).booleanValue() && T3_enabled.equal((BBoolean(false))).booleanValue()))).booleanValue();
+        bool _tr_T3Evaluate(bool isCaching) const {
+            if (this->_tr_cache_T3Evaluate == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean(T3_state.equal((T3state(T3state::T3_READY))).booleanValue() && T3_evaluated.equal((BBoolean(false))).booleanValue())).booleanValue() && T3_enabled.equal((BBoolean(false))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_T3Evaluate = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_T3Evaluate.get();
         }
 
-        BSet<BTuple<BInteger, BInteger >> _tr_T3writebus() const {
-            BSet<BTuple<BInteger, BInteger >> _ic_set_14 = BSet<BTuple<BInteger, BInteger >>();
-            for(BInteger _ic_ppriority_1 : {(BInteger(4))}) {
-                for(BInteger _ic_pv_1 : {(BInteger(0))}) {
-                    if((T3_state.equal((T3state(T3state::T3_WRITE)))).booleanValue()) {
-                        _ic_set_14 = _ic_set_14._union(BSet<BTuple<BInteger, BInteger >>((BTuple<BInteger, BInteger >(_ic_ppriority_1, _ic_pv_1))));
+        BSet<BTuple<BInteger, BInteger >> _tr_T3writebus(bool isCaching) const {
+            if (this->_tr_cache_T3writebus == boost::none){
+                BSet<BTuple<BInteger, BInteger >> _ic_set_14 = BSet<BTuple<BInteger, BInteger >>();
+                for(const BInteger& _ic_ppriority_1 : {(BInteger(4))}) {
+                    for(const BInteger& _ic_pv_1 : {(BInteger(0))}) {
+                        if((T3_state.equal((T3state(T3state::T3_WRITE)))).booleanValue()) {
+                            _ic_set_14 = _ic_set_14._union(BSet<BTuple<BInteger, BInteger >>((BTuple<BInteger, BInteger >(_ic_ppriority_1, _ic_pv_1))));
+                        }
+
                     }
 
                 }
 
+                if (isCaching) this->_tr_cache_T3writebus = _ic_set_14;
+                else return _ic_set_14;
             }
-
-            return _ic_set_14;
+            return this->_tr_cache_T3writebus.get();
         }
 
-        BSet<BTuple<BInteger, BInteger >> _tr_T3Read() const {
-            BSet<BTuple<BInteger, BInteger >> _ic_set_15 = BSet<BTuple<BInteger, BInteger >>();
-            for(BInteger _ic_ppriority_1 : {BUSpriority}) {
-                for(BInteger _ic_pv_1 : {BUSvalue}) {
-                    if((T3_state.equal((T3state(T3state::T3_READ)))).booleanValue()) {
-                        _ic_set_15 = _ic_set_15._union(BSet<BTuple<BInteger, BInteger >>((BTuple<BInteger, BInteger >(_ic_ppriority_1, _ic_pv_1))));
+        BSet<BTuple<BInteger, BInteger >> _tr_T3Read(bool isCaching) const {
+            if (this->_tr_cache_T3Read == boost::none){
+                BSet<BTuple<BInteger, BInteger >> _ic_set_15 = BSet<BTuple<BInteger, BInteger >>();
+                for(const BInteger& _ic_ppriority_1 : {BUSpriority}) {
+                    for(const BInteger& _ic_pv_1 : {BUSvalue}) {
+                        if((T3_state.equal((T3state(T3state::T3_READ)))).booleanValue()) {
+                            _ic_set_15 = _ic_set_15._union(BSet<BTuple<BInteger, BInteger >>((BTuple<BInteger, BInteger >(_ic_ppriority_1, _ic_pv_1))));
+                        }
+
                     }
 
                 }
 
+                if (isCaching) this->_tr_cache_T3Read = _ic_set_15;
+                else return _ic_set_15;
             }
-
-            return _ic_set_15;
+            return this->_tr_cache_T3Read.get();
         }
 
-        bool _tr_T3Poll() const {
-            return ((BBoolean(T3_readpriority.less((BInteger(5))).booleanValue() && T3_state.equal((T3state(T3state::T3_PROC))).booleanValue()))).booleanValue();
+        bool _tr_T3Poll(bool isCaching) const {
+            if (this->_tr_cache_T3Poll == boost::none){
+                bool __tmp_result = ((BBoolean(T3_readpriority.less((BInteger(5))).booleanValue() && T3_state.equal((T3state(T3state::T3_PROC))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_T3Poll = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_T3Poll.get();
         }
 
-        BSet<BInteger> _tr_T3ReleaseBus() const {
-            BSet<BInteger> _ic_set_17 = BSet<BInteger>();
-            for(BInteger _ic_ppriority_1 : {(BInteger(4))}) {
-                if(((BBoolean(T3_readpriority.equal((BInteger(5))).booleanValue() && T3_state.equal((T3state(T3state::T3_PROC))).booleanValue()))).booleanValue()) {
-                    _ic_set_17 = _ic_set_17._union(BSet<BInteger>(_ic_ppriority_1));
+        BSet<BInteger> _tr_T3ReleaseBus(bool isCaching) const {
+            if (this->_tr_cache_T3ReleaseBus == boost::none){
+                BSet<BInteger> _ic_set_17 = BSet<BInteger>();
+                for(const BInteger& _ic_ppriority_1 : {(BInteger(4))}) {
+                    if(((BBoolean(T3_readpriority.equal((BInteger(5))).booleanValue() && T3_state.equal((T3state(T3state::T3_PROC))).booleanValue()))).booleanValue()) {
+                        _ic_set_17 = _ic_set_17._union(BSet<BInteger>(_ic_ppriority_1));
+                    }
+
                 }
 
+                if (isCaching) this->_tr_cache_T3ReleaseBus = _ic_set_17;
+                else return _ic_set_17;
             }
-
-            return _ic_set_17;
+            return this->_tr_cache_T3ReleaseBus.get();
         }
 
-        bool _tr_T3Wait() const {
-            return (T3_state.equal((T3state(T3state::T3_WAIT)))).booleanValue();
+        bool _tr_T3Wait(bool isCaching) const {
+            if (this->_tr_cache_T3Wait == boost::none){
+                bool __tmp_result = (T3_state.equal((T3state(T3state::T3_WAIT)))).booleanValue();
+                if (isCaching) this->_tr_cache_T3Wait = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_T3Wait.get();
         }
 
-        bool _tr_T3ReEnableWait() const {
-            return (T3_state.equal((T3state(T3state::T3_RELEASE)))).booleanValue();
+        bool _tr_T3ReEnableWait(bool isCaching) const {
+            if (this->_tr_cache_T3ReEnableWait == boost::none){
+                bool __tmp_result = (T3_state.equal((T3state(T3state::T3_RELEASE)))).booleanValue();
+                if (isCaching) this->_tr_cache_T3ReEnableWait = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_T3ReEnableWait.get();
         }
 
-        BSet<BInteger> _tr_Update() const {
-            BSet<BInteger> _ic_set_20 = BSet<BInteger>();
-            for(BInteger _ic_pmax_1 : {BUSwrite.domain().max()}) {
-                if(((BBoolean((BBoolean(T1_timer.greater((BInteger(0))).booleanValue() && T2_timer.greater((BInteger(0))).booleanValue())).booleanValue() && (BBoolean(T3_enabled.equal((BBoolean(true))).booleanValue() || T3_evaluated.equal((BBoolean(true))).booleanValue())).booleanValue()))).booleanValue()) {
-                    _ic_set_20 = _ic_set_20._union(BSet<BInteger>(_ic_pmax_1));
+        BSet<BInteger> _tr_Update(bool isCaching) const {
+            if (this->_tr_cache_Update == boost::none){
+                BSet<BInteger> _ic_set_20 = BSet<BInteger>();
+                for(const BInteger& _ic_pmax_1 : {BUSwrite.domain().max()}) {
+                    if(((BBoolean((BBoolean(T1_timer.greater((BInteger(0))).booleanValue() && T2_timer.greater((BInteger(0))).booleanValue())).booleanValue() && (BBoolean(T3_enabled.equal((BBoolean(true))).booleanValue() || T3_evaluated.equal((BBoolean(true))).booleanValue())).booleanValue()))).booleanValue()) {
+                        _ic_set_20 = _ic_set_20._union(BSet<BInteger>(_ic_pmax_1));
+                    }
+
                 }
 
+                if (isCaching) this->_tr_cache_Update = _ic_set_20;
+                else return _ic_set_20;
             }
-
-            return _ic_set_20;
+            return this->_tr_cache_Update.get();
         }
 
         bool _check_inv_1() const {
@@ -861,8 +979,44 @@ class CAN_BUS_tlc {
             return (BUSwrite.domain().elementOf((BInteger(0)))).booleanValue();
         }
 
-        CAN_BUS_tlc _copy() const {
-            return CAN_BUS_tlc(NATSET, BUSpriority, BUSvalue, BUSwrite, T1_state, T1_timer, T1_writevalue, T2_mode, T2_readpriority, T2_readvalue, T2_state, T2_timer, T2_writevalue, T2v, T3_enabled, T3_evaluated, T3_readpriority, T3_readvalue, T3_state);
+        static constexpr unsigned int strHash(const char *s, int off = 0) {
+            return !s[off] ? 5381 : (strHash(s, off+1)*33) ^ s[off];
+        }
+
+        CAN_BUS_tlc _copy(unordered_set<string> toInvalidate) const {
+            static const char* allTransitions[] = {"_tr_T1Evaluate", "_tr_T1Calculate", "_tr_T1SendResult", "_tr_T1Wait", "_tr_T2Evaluate", "_tr_T2ReadBus", "_tr_T2Reset", "_tr_T2Complete", "_tr_T2ReleaseBus", "_tr_T2Calculate", "_tr_T2WriteBus", "_tr_T2Wait", "_tr_T3Initiate", "_tr_T3Evaluate", "_tr_T3writebus", "_tr_T3Read", "_tr_T3Poll", "_tr_T3ReleaseBus", "_tr_T3Wait", "_tr_T3ReEnableWait", "_tr_Update"};
+
+            CAN_BUS_tlc result = CAN_BUS_tlc(NATSET, BUSpriority, BUSvalue, BUSwrite, T1_state, T1_timer, T1_writevalue, T2_mode, T2_readpriority, T2_readvalue, T2_state, T2_timer, T2_writevalue, T2v, T3_enabled, T3_evaluated, T3_readpriority, T3_readvalue, T3_state);
+
+            for (const auto &item : allTransitions) {
+                if(toInvalidate.find(item) == toInvalidate.end()) {
+                    switch(strHash(item)) {
+                        case strHash("_tr_T1Evaluate"): result._tr_cache_T1Evaluate = this->_tr_cache_T1Evaluate; break;
+                        case strHash("_tr_T1Calculate"): result._tr_cache_T1Calculate = this->_tr_cache_T1Calculate; break;
+                        case strHash("_tr_T1SendResult"): result._tr_cache_T1SendResult = this->_tr_cache_T1SendResult; break;
+                        case strHash("_tr_T1Wait"): result._tr_cache_T1Wait = this->_tr_cache_T1Wait; break;
+                        case strHash("_tr_T2Evaluate"): result._tr_cache_T2Evaluate = this->_tr_cache_T2Evaluate; break;
+                        case strHash("_tr_T2ReadBus"): result._tr_cache_T2ReadBus = this->_tr_cache_T2ReadBus; break;
+                        case strHash("_tr_T2Reset"): result._tr_cache_T2Reset = this->_tr_cache_T2Reset; break;
+                        case strHash("_tr_T2Complete"): result._tr_cache_T2Complete = this->_tr_cache_T2Complete; break;
+                        case strHash("_tr_T2ReleaseBus"): result._tr_cache_T2ReleaseBus = this->_tr_cache_T2ReleaseBus; break;
+                        case strHash("_tr_T2Calculate"): result._tr_cache_T2Calculate = this->_tr_cache_T2Calculate; break;
+                        case strHash("_tr_T2WriteBus"): result._tr_cache_T2WriteBus = this->_tr_cache_T2WriteBus; break;
+                        case strHash("_tr_T2Wait"): result._tr_cache_T2Wait = this->_tr_cache_T2Wait; break;
+                        case strHash("_tr_T3Initiate"): result._tr_cache_T3Initiate = this->_tr_cache_T3Initiate; break;
+                        case strHash("_tr_T3Evaluate"): result._tr_cache_T3Evaluate = this->_tr_cache_T3Evaluate; break;
+                        case strHash("_tr_T3writebus"): result._tr_cache_T3writebus = this->_tr_cache_T3writebus; break;
+                        case strHash("_tr_T3Read"): result._tr_cache_T3Read = this->_tr_cache_T3Read; break;
+                        case strHash("_tr_T3Poll"): result._tr_cache_T3Poll = this->_tr_cache_T3Poll; break;
+                        case strHash("_tr_T3ReleaseBus"): result._tr_cache_T3ReleaseBus = this->_tr_cache_T3ReleaseBus; break;
+                        case strHash("_tr_T3Wait"): result._tr_cache_T3Wait = this->_tr_cache_T3Wait; break;
+                        case strHash("_tr_T3ReEnableWait"): result._tr_cache_T3ReEnableWait = this->_tr_cache_T3ReEnableWait; break;
+                        case strHash("_tr_Update"): result._tr_cache_Update = this->_tr_cache_Update; break;
+                        default: cout << "Transition " << item << " not found!";
+                    }
+                }
+            }
+            return result;
         }
 
         friend bool operator ==(const CAN_BUS_tlc& o1, const CAN_BUS_tlc& o2) {
@@ -949,1525 +1103,565 @@ class CAN_BUS_tlc {
 };
 
 
-static std::unordered_set<CAN_BUS_tlc, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> generateNextStates(std::mutex& guardMutex, const CAN_BUS_tlc& state, bool isCaching, std::unordered_map<string, std::unordered_set<string>>& invariantDependency, std::unordered_map<CAN_BUS_tlc, std::unordered_set<string>, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual>& dependentInvariant, std::unordered_map<string, std::unordered_set<string>>& guardDependency, std::unordered_map<CAN_BUS_tlc, std::unordered_set<string>, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual>& dependentGuard, std::unordered_map<CAN_BUS_tlc, immer::map<string, boost::any>, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual>& guardCache, std::unordered_map<CAN_BUS_tlc, CAN_BUS_tlc, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual>& parents, std::unordered_map<CAN_BUS_tlc, string, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual>& stateAccessedVia, std::atomic<int>& transitions) {
-    std::unordered_set<CAN_BUS_tlc, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> result = std::unordered_set<CAN_BUS_tlc, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual>();
-    if(isCaching) {
-        immer::map<string, boost::any> parentsGuard;
-        std::unordered_set<string> dependentGuardsOfState;
-        bool parentsExist = false;
-        bool dependentGuardsExist = false;
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            parentsExist = (parents.find(state) != parents.end());
-            dependentGuardsExist = (dependentGuard.find(state) != dependentGuard.end());
-            if(parentsExist) {
-                parentsGuard = guardCache[parents[state]];
-            }
-            if(dependentGuardsExist) {
-                dependentGuardsOfState = dependentGuard[state];
-            }
-        }
-        immer::map<string, boost::any> newCache = parentsGuard;
-        boost::any cachedValue;
-        bool dependentGuardsBoolean = true;
-        bool _trid_1;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_T1Evaluate"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_T1Evaluate") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_1 = state._tr_T1Evaluate();
-        } else {
-            _trid_1 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_T1Evaluate", _trid_1);
-        if(_trid_1) {
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T1Evaluate();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["T1Evaluate"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["T1Evaluate"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T1Evaluate"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BInteger> _trid_2;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_T1Calculate"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_T1Calculate") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_2 = state._tr_T1Calculate();
-        } else {
-            _trid_2 = boost::any_cast<BSet<BInteger>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_T1Calculate", _trid_2);
-        for(const BInteger& param : _trid_2) {
-            BInteger _tmp_1 = param;
+class ModelChecker {
+    private:
+        CAN_BUS_tlc::Type type;
+        int threads;
+        bool isCaching;
+        bool isDebug;
+
+        std::list<CAN_BUS_tlc> unvisitedStates;
+        std::unordered_set<CAN_BUS_tlc, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> states;
+        std::atomic<int> transitions;
+        std::mutex mutex;
+        std::mutex waitMutex;
+        std::mutex guardMutex;
+        std::condition_variable waitCV;
+
+        std::atomic<bool> invariantViolatedBool;
+        std::atomic<bool> deadlockDetected;
+        CAN_BUS_tlc counterExampleState;
+
+        std::unordered_map<string, std::unordered_set<string>> invariantDependency;
+        std::unordered_map<string, std::unordered_set<string>> guardDependency;
+        std::unordered_map<CAN_BUS_tlc, CAN_BUS_tlc, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> parents;
 
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T1Calculate(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["T1Calculate"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["T1Calculate"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T1Calculate"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BInteger, BInteger >> _trid_3;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_T1SendResult"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_T1SendResult") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_3 = state._tr_T1SendResult();
-        } else {
-            _trid_3 = boost::any_cast<BSet<BTuple<BInteger, BInteger >>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_T1SendResult", _trid_3);
-        for(const BTuple<BInteger, BInteger >& param : _trid_3) {
-            BInteger _tmp_1 = param.projection2();
-            BInteger _tmp_2 = param.projection1();
+    public:
+        ModelChecker() {}
 
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T1SendResult(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["T1SendResult"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["T1SendResult"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T1SendResult"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
+        ModelChecker(CAN_BUS_tlc::Type type, int threads, bool isCaching, bool isDebug) {
+            this->type = type;
+            this->threads = threads;
+            this->isCaching = isCaching;
+            this->isDebug = isDebug;
+            this->invariantViolatedBool = false;
+            this->deadlockDetected = false;
+            this->transitions = 0;
         }
-        BSet<BInteger> _trid_4;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_T1Wait"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_T1Wait") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_4 = state._tr_T1Wait();
-        } else {
-            _trid_4 = boost::any_cast<BSet<BInteger>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_T1Wait", _trid_4);
-        for(const BInteger& param : _trid_4) {
-            BInteger _tmp_1 = param;
 
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T1Wait(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["T1Wait"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["T1Wait"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T1Wait"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_5;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_T2Evaluate"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_T2Evaluate") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_5 = state._tr_T2Evaluate();
-        } else {
-            _trid_5 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_T2Evaluate", _trid_5);
-        if(_trid_5) {
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T2Evaluate();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["T2Evaluate"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["T2Evaluate"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T2Evaluate"});
-                }
+        void modelCheck() {
+            if (isDebug) {
+                cout << "Starting Modelchecking, STRATEGY=" << type << ", THREADS=" << threads << ", CACHING=" << isCaching << "\n";
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BInteger, BInteger >> _trid_6;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_T2ReadBus"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_T2ReadBus") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_6 = state._tr_T2ReadBus();
-        } else {
-            _trid_6 = boost::any_cast<BSet<BTuple<BInteger, BInteger >>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_T2ReadBus", _trid_6);
-        for(const BTuple<BInteger, BInteger >& param : _trid_6) {
-            BInteger _tmp_1 = param.projection2();
-            BInteger _tmp_2 = param.projection1();
 
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T2ReadBus(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["T2ReadBus"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["T2ReadBus"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T2ReadBus"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_7;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_T2Reset"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_T2Reset") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_7 = state._tr_T2Reset();
-        } else {
-            _trid_7 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_T2Reset", _trid_7);
-        if(_trid_7) {
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T2Reset();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["T2Reset"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["T2Reset"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T2Reset"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_8;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_T2Complete"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_T2Complete") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_8 = state._tr_T2Complete();
-        } else {
-            _trid_8 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_T2Complete", _trid_8);
-        if(_trid_8) {
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T2Complete();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["T2Complete"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["T2Complete"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T2Complete"});
-                }
+            if (threads <= 1) {
+                modelCheckSingleThreaded();
+            } else {
+                boost::asio::thread_pool workers(threads); // threads indicates the number of workers (without the coordinator)
+                modelCheckMultiThreaded(workers);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BInteger> _trid_9;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_T2ReleaseBus"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_T2ReleaseBus") != dependentGuardsOfState.end());
         }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_9 = state._tr_T2ReleaseBus();
-        } else {
-            _trid_9 = boost::any_cast<BSet<BInteger>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_T2ReleaseBus", _trid_9);
-        for(const BInteger& param : _trid_9) {
-            BInteger _tmp_1 = param;
 
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T2ReleaseBus(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["T2ReleaseBus"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["T2ReleaseBus"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T2ReleaseBus"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_10;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_T2Calculate"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_T2Calculate") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_10 = state._tr_T2Calculate();
-        } else {
-            _trid_10 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_T2Calculate", _trid_10);
-        if(_trid_10) {
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T2Calculate();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["T2Calculate"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["T2Calculate"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T2Calculate"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BInteger, BInteger >> _trid_11;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_T2WriteBus"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_T2WriteBus") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_11 = state._tr_T2WriteBus();
-        } else {
-            _trid_11 = boost::any_cast<BSet<BTuple<BInteger, BInteger >>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_T2WriteBus", _trid_11);
-        for(const BTuple<BInteger, BInteger >& param : _trid_11) {
-            BInteger _tmp_1 = param.projection2();
-            BInteger _tmp_2 = param.projection1();
+        void modelCheckSingleThreaded() {
+            CAN_BUS_tlc machine = CAN_BUS_tlc();
+            states.insert(machine);
+            unvisitedStates.push_back(machine);
 
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T2WriteBus(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["T2WriteBus"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["T2WriteBus"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T2WriteBus"});
-                }
+            if (isCaching) {
+                initCache(machine);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BInteger> _trid_12;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_T2Wait"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_T2Wait") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_12 = state._tr_T2Wait();
-        } else {
-            _trid_12 = boost::any_cast<BSet<BInteger>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_T2Wait", _trid_12);
-        for(const BInteger& param : _trid_12) {
-            BInteger _tmp_1 = param;
 
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T2Wait(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["T2Wait"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["T2Wait"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T2Wait"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_13;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_T3Initiate"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_T3Initiate") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_13 = state._tr_T3Initiate();
-        } else {
-            _trid_13 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_T3Initiate", _trid_13);
-        if(_trid_13) {
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T3Initiate();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["T3Initiate"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["T3Initiate"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T3Initiate"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_14;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_T3Evaluate"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_T3Evaluate") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_14 = state._tr_T3Evaluate();
-        } else {
-            _trid_14 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_T3Evaluate", _trid_14);
-        if(_trid_14) {
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T3Evaluate();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["T3Evaluate"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["T3Evaluate"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T3Evaluate"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BInteger, BInteger >> _trid_15;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_T3writebus"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_T3writebus") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_15 = state._tr_T3writebus();
-        } else {
-            _trid_15 = boost::any_cast<BSet<BTuple<BInteger, BInteger >>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_T3writebus", _trid_15);
-        for(const BTuple<BInteger, BInteger >& param : _trid_15) {
-            BInteger _tmp_1 = param.projection2();
-            BInteger _tmp_2 = param.projection1();
+            while(!unvisitedStates.empty()) {
+                CAN_BUS_tlc state = next();
 
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T3writebus(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["T3writebus"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["T3writebus"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T3writebus"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BInteger, BInteger >> _trid_16;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_T3Read"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_T3Read") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_16 = state._tr_T3Read();
-        } else {
-            _trid_16 = boost::any_cast<BSet<BTuple<BInteger, BInteger >>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_T3Read", _trid_16);
-        for(const BTuple<BInteger, BInteger >& param : _trid_16) {
-            BInteger _tmp_1 = param.projection2();
-            BInteger _tmp_2 = param.projection1();
+                std::unordered_set<CAN_BUS_tlc, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> nextStates = generateNextStates(state);
+                transitions += nextStates.size();
 
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T3Read(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["T3Read"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["T3Read"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T3Read"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_17;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_T3Poll"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_T3Poll") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_17 = state._tr_T3Poll();
-        } else {
-            _trid_17 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_T3Poll", _trid_17);
-        if(_trid_17) {
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T3Poll();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["T3Poll"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["T3Poll"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T3Poll"});
+                for(auto& nextState : nextStates) {
+                    if(states.find(nextState) == states.end()) {
+                        states.insert(nextState);
+                        parents.insert({nextState, state});
+                        unvisitedStates.push_back(nextState);
+                        if(states.size() % 50000 == 0) {
+                            cout << "VISITED STATES: " << states.size() << "\n";
+                            cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
+                            cout << "-------------------" << "\n";
+                        }
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BInteger> _trid_18;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_T3ReleaseBus"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_T3ReleaseBus") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_18 = state._tr_T3ReleaseBus();
-        } else {
-            _trid_18 = boost::any_cast<BSet<BInteger>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_T3ReleaseBus", _trid_18);
-        for(const BInteger& param : _trid_18) {
-            BInteger _tmp_1 = param;
 
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T3ReleaseBus(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["T3ReleaseBus"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["T3ReleaseBus"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T3ReleaseBus"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_19;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_T3Wait"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_T3Wait") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_19 = state._tr_T3Wait();
-        } else {
-            _trid_19 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_T3Wait", _trid_19);
-        if(_trid_19) {
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T3Wait();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["T3Wait"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["T3Wait"]});
+                if(invariantViolated(state)) {
+                    invariantViolatedBool = true;
+                    counterExampleState = state;
+                    break;
                 }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T3Wait"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_20;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_T3ReEnableWait"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_T3ReEnableWait") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_20 = state._tr_T3ReEnableWait();
-        } else {
-            _trid_20 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_T3ReEnableWait", _trid_20);
-        if(_trid_20) {
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T3ReEnableWait();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["T3ReEnableWait"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["T3ReEnableWait"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T3ReEnableWait"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BInteger> _trid_21;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_Update"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_Update") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_21 = state._tr_Update();
-        } else {
-            _trid_21 = boost::any_cast<BSet<BInteger>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_Update", _trid_21);
-        for(const BInteger& param : _trid_21) {
-            BInteger _tmp_1 = param;
 
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.Update(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["Update"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["Update"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "Update"});
+                if(nextStates.empty()) {
+                    deadlockDetected = true;
+                    counterExampleState = state;
+                    break;
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
 
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            guardCache.insert({state, newCache});
-        }
-    } else {
-        if(state._tr_T1Evaluate()) {
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T1Evaluate();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T1Evaluate"});
-                }
             }
-            result.insert(copiedState);
-            transitions += 1;
+            printResult();
         }
-        BSet<BInteger> _trid_2 = state._tr_T1Calculate();
-        for(const BInteger& param : _trid_2) {
-            BInteger _tmp_1 = param;
 
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T1Calculate(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T1Calculate"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BInteger, BInteger >> _trid_3 = state._tr_T1SendResult();
-        for(const BTuple<BInteger, BInteger >& param : _trid_3) {
-            BInteger _tmp_1 = param.projection2();
-            BInteger _tmp_2 = param.projection1();
+        void modelCheckMultiThreaded(boost::asio::thread_pool& workers) {
+            CAN_BUS_tlc machine = CAN_BUS_tlc();
+            states.insert(machine);
+            unvisitedStates.push_back(machine);
 
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T1SendResult(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T1SendResult"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BInteger> _trid_4 = state._tr_T1Wait();
-        for(const BInteger& param : _trid_4) {
-            BInteger _tmp_1 = param;
+            std::atomic<bool> stopThreads;
+            stopThreads = false;
+            std::atomic<int> possibleQueueChanges;
+            possibleQueueChanges = 0;
 
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T1Wait(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T1Wait"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_T2Evaluate()) {
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T2Evaluate();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T2Evaluate"});
-                }
+            if(isCaching) {
+                initCache(machine);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BInteger, BInteger >> _trid_6 = state._tr_T2ReadBus();
-        for(const BTuple<BInteger, BInteger >& param : _trid_6) {
-            BInteger _tmp_1 = param.projection2();
-            BInteger _tmp_2 = param.projection1();
 
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T2ReadBus(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T2ReadBus"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_T2Reset()) {
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T2Reset();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T2Reset"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_T2Complete()) {
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T2Complete();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T2Complete"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BInteger> _trid_9 = state._tr_T2ReleaseBus();
-        for(const BInteger& param : _trid_9) {
-            BInteger _tmp_1 = param;
+            std::atomic<bool> waitFlag;
+            waitFlag = true;
 
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T2ReleaseBus(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T2ReleaseBus"});
+            while(!unvisitedStates.empty() && !stopThreads) {
+                possibleQueueChanges += 1;
+                CAN_BUS_tlc state = next();
+                std::packaged_task<void()> task([&, state] {
+                    std::unordered_set<CAN_BUS_tlc, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> nextStates = generateNextStates(state);
+                    transitions += nextStates.size();
+
+                    for(auto& nextState : nextStates) {
+                        {
+                            std::unique_lock<std::mutex> lock(mutex);
+                            if(states.find(nextState) == states.end()) {
+                                states.insert(nextState);
+                                parents.insert({nextState, state});
+                                unvisitedStates.push_back(nextState); // TODO: sync ?
+                                if(isDebug && states.size() % 50000 == 0) {
+                                    cout << "VISITED STATES: " << states.size() << "\n";
+                                    cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
+                                    cout << "-------------------" << "\n";
+                                }
+                            }
+                        }
+                    }
+
+                    {
+                        std::unique_lock<std::mutex> lock(mutex);
+                        possibleQueueChanges -= 1;
+                        int running = possibleQueueChanges;
+                        if (!unvisitedStates.empty() || running == 0) {
+                            {
+                                std::unique_lock<std::mutex> lock(waitMutex);
+                                waitFlag = false;
+                                waitCV.notify_one();
+                            }
+                        }
+                    }
+
+                    if(invariantViolated(state)) {
+                        invariantViolatedBool = true;
+                        counterExampleState = state;
+                        stopThreads = true;
+                    }
+
+                    if(nextStates.empty()) {
+                        deadlockDetected = true;
+                        counterExampleState = state;
+                        stopThreads = true;
+                    }
+
+                });
+
+                waitFlag = true;
+                boost::asio::post(workers, std::move(task));
+
+                {
+                    std::unique_lock<std::mutex> lock(waitMutex);
+                    while (unvisitedStates.empty() && possibleQueueChanges > 0) {
+                        waitCV.wait(lock, [&] {
+                            return waitFlag == false;
+                        });
+                    }
                 }
             }
-            result.insert(copiedState);
-            transitions += 1;
+            workers.join();
+            printResult();
+        }
+
+        void initCache(CAN_BUS_tlc& machine) {
+            invariantDependency.insert({"T1Wait", {"_check_inv_10", "_check_inv_4"}});
+            invariantDependency.insert({"T1Calculate", {"_check_inv_7", "_check_inv_4"}});
+            invariantDependency.insert({"T1SendResult", {"_check_inv_18", "_check_inv_19", "_check_inv_20", "_check_inv_4"}});
+            invariantDependency.insert({"T2ReadBus", {"_check_inv_17", "_check_inv_5", "_check_inv_9"}});
+            invariantDependency.insert({"T2Reset", {"_check_inv_1", "_check_inv_5", "_check_inv_8", "_check_inv_12"}});
+            invariantDependency.insert({"T2Complete", {"_check_inv_5", "_check_inv_12"}});
+            invariantDependency.insert({"T2Evaluate", {"_check_inv_5", "_check_inv_11"}});
+            invariantDependency.insert({"T3Evaluate", {"_check_inv_6"}});
+            invariantDependency.insert({"T3ReleaseBus", {"_check_inv_18", "_check_inv_19", "_check_inv_6", "_check_inv_20"}});
+            invariantDependency.insert({"T1Evaluate", {"_check_inv_10", "_check_inv_4"}});
+            invariantDependency.insert({"T3Initiate", {"_check_inv_3", "_check_inv_6"}});
+            invariantDependency.insert({"T3ReEnableWait", {"_check_inv_2", "_check_inv_3", "_check_inv_6"}});
+            invariantDependency.insert({"T3writebus", {"_check_inv_18", "_check_inv_19", "_check_inv_6", "_check_inv_20"}});
+            invariantDependency.insert({"Update", {"_check_inv_2", "_check_inv_10", "_check_inv_14", "_check_inv_13", "_check_inv_11"}});
+            invariantDependency.insert({"T2ReleaseBus", {"_check_inv_18", "_check_inv_19", "_check_inv_20", "_check_inv_5"}});
+            invariantDependency.insert({"T2Wait", {"_check_inv_5", "_check_inv_11"}});
+            invariantDependency.insert({"T3Poll", {"_check_inv_6"}});
+            invariantDependency.insert({"T2Calculate", {"_check_inv_1", "_check_inv_5"}});
+            invariantDependency.insert({"T3Read", {"_check_inv_16", "_check_inv_15", "_check_inv_6"}});
+            invariantDependency.insert({"T3Wait", {"_check_inv_2", "_check_inv_6"}});
+            invariantDependency.insert({"T2WriteBus", {"_check_inv_18", "_check_inv_19", "_check_inv_20", "_check_inv_5"}});
+            invariantDependency.insert({"", {}});
+            guardDependency.insert({"T1Wait", {"_tr_T1Evaluate", "_tr_Update", "_tr_T1SendResult", "_tr_T1Calculate", "_tr_T1Wait"}});
+            guardDependency.insert({"T1Calculate", {"_tr_T1Evaluate", "_tr_T1SendResult", "_tr_T1Calculate", "_tr_T1Wait"}});
+            guardDependency.insert({"T1SendResult", {"_tr_T1Evaluate", "_tr_T2ReleaseBus", "_tr_Update", "_tr_T1SendResult", "_tr_T1Calculate", "_tr_T1Wait"}});
+            guardDependency.insert({"T2ReadBus", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
+            guardDependency.insert({"T2Reset", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
+            guardDependency.insert({"T2Complete", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
+            guardDependency.insert({"T2Evaluate", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_Update", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
+            guardDependency.insert({"T3Evaluate", {"_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
+            guardDependency.insert({"T3ReleaseBus", {"_tr_T2ReleaseBus", "_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_Update", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
+            guardDependency.insert({"T1Evaluate", {"_tr_T1Evaluate", "_tr_Update", "_tr_T1SendResult", "_tr_T1Calculate", "_tr_T1Wait"}});
+            guardDependency.insert({"T3Initiate", {"_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_Update", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
+            guardDependency.insert({"T3ReEnableWait", {"_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_Update", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
+            guardDependency.insert({"T3writebus", {"_tr_T2ReleaseBus", "_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_Update", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
+            guardDependency.insert({"Update", {"_tr_T1Evaluate", "_tr_T3Read", "_tr_T2Evaluate", "_tr_Update", "_tr_T2ReadBus", "_tr_T3Evaluate", "_tr_T3Initiate"}});
+            guardDependency.insert({"T2ReleaseBus", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_Update", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
+            guardDependency.insert({"T2Wait", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_Update", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
+            guardDependency.insert({"T3Poll", {"_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
+            guardDependency.insert({"T2Calculate", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
+            guardDependency.insert({"T3Read", {"_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
+            guardDependency.insert({"T3Wait", {"_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_Update", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
+            guardDependency.insert({"T2WriteBus", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_Update", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
         }
-        if(state._tr_T2Calculate()) {
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T2Calculate();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T2Calculate"});
+
+
+    private:
+        CAN_BUS_tlc next() {
+            std::unique_lock<std::mutex> lock(mutex);
+            switch(type) {
+                case CAN_BUS_tlc::BFS: {
+                    CAN_BUS_tlc state = unvisitedStates.front();
+                    unvisitedStates.pop_front();
+                    return state;
+                }
+                case CAN_BUS_tlc::DFS: {
+                    CAN_BUS_tlc state = unvisitedStates.back();
+                    unvisitedStates.pop_back();
+                    return state;
+                }
+                case CAN_BUS_tlc::MIXED: {
+                    if(unvisitedStates.size() % 2 == 0) {
+                        CAN_BUS_tlc state = unvisitedStates.front();
+                        unvisitedStates.pop_front();
+                        return state;
+                    } else {
+                        CAN_BUS_tlc state = unvisitedStates.back();
+                        unvisitedStates.pop_back();
+                        return state;
+                    }
                 }
             }
-            result.insert(copiedState);
-            transitions += 1;
         }
-        BSet<BTuple<BInteger, BInteger >> _trid_11 = state._tr_T2WriteBus();
-        for(const BTuple<BInteger, BInteger >& param : _trid_11) {
-            BInteger _tmp_1 = param.projection2();
-            BInteger _tmp_2 = param.projection1();
 
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T2WriteBus(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T2WriteBus"});
-                }
+        std::unordered_set<CAN_BUS_tlc, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> generateNextStates(const CAN_BUS_tlc& state) {
+            std::unordered_set<CAN_BUS_tlc, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> result = std::unordered_set<CAN_BUS_tlc, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual>();
+            if(state._tr_T1Evaluate(isCaching)) {
+                CAN_BUS_tlc copiedState = state._copy(guardDependency["T1Evaluate"]);
+                copiedState.T1Evaluate();
+                copiedState.stateAccessedVia = "T1Evaluate";
+                result.insert(copiedState);
+            }
+            BSet<BInteger> _trid_2 = state._tr_T1Calculate(isCaching);
+            for(const BInteger& param : _trid_2) {
+                BInteger _tmp_1 = param;
+
+                CAN_BUS_tlc copiedState = state._copy(guardDependency["T1Calculate"]);
+                copiedState.T1Calculate(_tmp_1);
+                copiedState.stateAccessedVia = "T1Calculate";
+                result.insert(copiedState);
+            }
+            BSet<BTuple<BInteger, BInteger >> _trid_3 = state._tr_T1SendResult(isCaching);
+            for(const BTuple<BInteger, BInteger >& param : _trid_3) {
+                BInteger _tmp_1 = param.projection2();
+                BInteger _tmp_2 = param.projection1();
+
+                CAN_BUS_tlc copiedState = state._copy(guardDependency["T1SendResult"]);
+                copiedState.T1SendResult(_tmp_2, _tmp_1);
+                copiedState.stateAccessedVia = "T1SendResult";
+                result.insert(copiedState);
+            }
+            BSet<BInteger> _trid_4 = state._tr_T1Wait(isCaching);
+            for(const BInteger& param : _trid_4) {
+                BInteger _tmp_1 = param;
+
+                CAN_BUS_tlc copiedState = state._copy(guardDependency["T1Wait"]);
+                copiedState.T1Wait(_tmp_1);
+                copiedState.stateAccessedVia = "T1Wait";
+                result.insert(copiedState);
+            }
+            if(state._tr_T2Evaluate(isCaching)) {
+                CAN_BUS_tlc copiedState = state._copy(guardDependency["T2Evaluate"]);
+                copiedState.T2Evaluate();
+                copiedState.stateAccessedVia = "T2Evaluate";
+                result.insert(copiedState);
+            }
+            BSet<BTuple<BInteger, BInteger >> _trid_6 = state._tr_T2ReadBus(isCaching);
+            for(const BTuple<BInteger, BInteger >& param : _trid_6) {
+                BInteger _tmp_1 = param.projection2();
+                BInteger _tmp_2 = param.projection1();
+
+                CAN_BUS_tlc copiedState = state._copy(guardDependency["T2ReadBus"]);
+                copiedState.T2ReadBus(_tmp_2, _tmp_1);
+                copiedState.stateAccessedVia = "T2ReadBus";
+                result.insert(copiedState);
+            }
+            if(state._tr_T2Reset(isCaching)) {
+                CAN_BUS_tlc copiedState = state._copy(guardDependency["T2Reset"]);
+                copiedState.T2Reset();
+                copiedState.stateAccessedVia = "T2Reset";
+                result.insert(copiedState);
+            }
+            if(state._tr_T2Complete(isCaching)) {
+                CAN_BUS_tlc copiedState = state._copy(guardDependency["T2Complete"]);
+                copiedState.T2Complete();
+                copiedState.stateAccessedVia = "T2Complete";
+                result.insert(copiedState);
+            }
+            BSet<BInteger> _trid_9 = state._tr_T2ReleaseBus(isCaching);
+            for(const BInteger& param : _trid_9) {
+                BInteger _tmp_1 = param;
+
+                CAN_BUS_tlc copiedState = state._copy(guardDependency["T2ReleaseBus"]);
+                copiedState.T2ReleaseBus(_tmp_1);
+                copiedState.stateAccessedVia = "T2ReleaseBus";
+                result.insert(copiedState);
+            }
+            if(state._tr_T2Calculate(isCaching)) {
+                CAN_BUS_tlc copiedState = state._copy(guardDependency["T2Calculate"]);
+                copiedState.T2Calculate();
+                copiedState.stateAccessedVia = "T2Calculate";
+                result.insert(copiedState);
+            }
+            BSet<BTuple<BInteger, BInteger >> _trid_11 = state._tr_T2WriteBus(isCaching);
+            for(const BTuple<BInteger, BInteger >& param : _trid_11) {
+                BInteger _tmp_1 = param.projection2();
+                BInteger _tmp_2 = param.projection1();
+
+                CAN_BUS_tlc copiedState = state._copy(guardDependency["T2WriteBus"]);
+                copiedState.T2WriteBus(_tmp_2, _tmp_1);
+                copiedState.stateAccessedVia = "T2WriteBus";
+                result.insert(copiedState);
+            }
+            BSet<BInteger> _trid_12 = state._tr_T2Wait(isCaching);
+            for(const BInteger& param : _trid_12) {
+                BInteger _tmp_1 = param;
+
+                CAN_BUS_tlc copiedState = state._copy(guardDependency["T2Wait"]);
+                copiedState.T2Wait(_tmp_1);
+                copiedState.stateAccessedVia = "T2Wait";
+                result.insert(copiedState);
+            }
+            if(state._tr_T3Initiate(isCaching)) {
+                CAN_BUS_tlc copiedState = state._copy(guardDependency["T3Initiate"]);
+                copiedState.T3Initiate();
+                copiedState.stateAccessedVia = "T3Initiate";
+                result.insert(copiedState);
+            }
+            if(state._tr_T3Evaluate(isCaching)) {
+                CAN_BUS_tlc copiedState = state._copy(guardDependency["T3Evaluate"]);
+                copiedState.T3Evaluate();
+                copiedState.stateAccessedVia = "T3Evaluate";
+                result.insert(copiedState);
+            }
+            BSet<BTuple<BInteger, BInteger >> _trid_15 = state._tr_T3writebus(isCaching);
+            for(const BTuple<BInteger, BInteger >& param : _trid_15) {
+                BInteger _tmp_1 = param.projection2();
+                BInteger _tmp_2 = param.projection1();
+
+                CAN_BUS_tlc copiedState = state._copy(guardDependency["T3writebus"]);
+                copiedState.T3writebus(_tmp_2, _tmp_1);
+                copiedState.stateAccessedVia = "T3writebus";
+                result.insert(copiedState);
+            }
+            BSet<BTuple<BInteger, BInteger >> _trid_16 = state._tr_T3Read(isCaching);
+            for(const BTuple<BInteger, BInteger >& param : _trid_16) {
+                BInteger _tmp_1 = param.projection2();
+                BInteger _tmp_2 = param.projection1();
+
+                CAN_BUS_tlc copiedState = state._copy(guardDependency["T3Read"]);
+                copiedState.T3Read(_tmp_2, _tmp_1);
+                copiedState.stateAccessedVia = "T3Read";
+                result.insert(copiedState);
+            }
+            if(state._tr_T3Poll(isCaching)) {
+                CAN_BUS_tlc copiedState = state._copy(guardDependency["T3Poll"]);
+                copiedState.T3Poll();
+                copiedState.stateAccessedVia = "T3Poll";
+                result.insert(copiedState);
+            }
+            BSet<BInteger> _trid_18 = state._tr_T3ReleaseBus(isCaching);
+            for(const BInteger& param : _trid_18) {
+                BInteger _tmp_1 = param;
+
+                CAN_BUS_tlc copiedState = state._copy(guardDependency["T3ReleaseBus"]);
+                copiedState.T3ReleaseBus(_tmp_1);
+                copiedState.stateAccessedVia = "T3ReleaseBus";
+                result.insert(copiedState);
+            }
+            if(state._tr_T3Wait(isCaching)) {
+                CAN_BUS_tlc copiedState = state._copy(guardDependency["T3Wait"]);
+                copiedState.T3Wait();
+                copiedState.stateAccessedVia = "T3Wait";
+                result.insert(copiedState);
+            }
+            if(state._tr_T3ReEnableWait(isCaching)) {
+                CAN_BUS_tlc copiedState = state._copy(guardDependency["T3ReEnableWait"]);
+                copiedState.T3ReEnableWait();
+                copiedState.stateAccessedVia = "T3ReEnableWait";
+                result.insert(copiedState);
+            }
+            BSet<BInteger> _trid_21 = state._tr_Update(isCaching);
+            for(const BInteger& param : _trid_21) {
+                BInteger _tmp_1 = param;
+
+                CAN_BUS_tlc copiedState = state._copy(guardDependency["Update"]);
+                copiedState.Update(_tmp_1);
+                copiedState.stateAccessedVia = "Update";
+                result.insert(copiedState);
             }
-            result.insert(copiedState);
-            transitions += 1;
+
+            return result;
         }
-        BSet<BInteger> _trid_12 = state._tr_T2Wait();
-        for(const BInteger& param : _trid_12) {
-            BInteger _tmp_1 = param;
 
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T2Wait(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+        bool invariantViolated(const CAN_BUS_tlc& state) {
+            if(isCaching) {
+                std::unordered_set<string> dependentInvariantsOfState = invariantDependency[state.stateAccessedVia];
+                if(dependentInvariantsOfState.find("_check_inv_1") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_1()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T2Wait"});
+                if(dependentInvariantsOfState.find("_check_inv_2") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_2()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_T3Initiate()) {
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T3Initiate();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_3") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_3()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T3Initiate"});
+                if(dependentInvariantsOfState.find("_check_inv_4") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_4()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_T3Evaluate()) {
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T3Evaluate();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_5") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_5()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T3Evaluate"});
+                if(dependentInvariantsOfState.find("_check_inv_6") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_6()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BInteger, BInteger >> _trid_15 = state._tr_T3writebus();
-        for(const BTuple<BInteger, BInteger >& param : _trid_15) {
-            BInteger _tmp_1 = param.projection2();
-            BInteger _tmp_2 = param.projection1();
-
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T3writebus(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_7") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_7()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T3writebus"});
+                if(dependentInvariantsOfState.find("_check_inv_8") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_8()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BInteger, BInteger >> _trid_16 = state._tr_T3Read();
-        for(const BTuple<BInteger, BInteger >& param : _trid_16) {
-            BInteger _tmp_1 = param.projection2();
-            BInteger _tmp_2 = param.projection1();
-
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T3Read(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_9") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_9()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T3Read"});
+                if(dependentInvariantsOfState.find("_check_inv_10") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_10()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_T3Poll()) {
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T3Poll();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_11") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_11()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T3Poll"});
+                if(dependentInvariantsOfState.find("_check_inv_12") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_12()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BInteger> _trid_18 = state._tr_T3ReleaseBus();
-        for(const BInteger& param : _trid_18) {
-            BInteger _tmp_1 = param;
-
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T3ReleaseBus(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_13") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_13()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T3ReleaseBus"});
+                if(dependentInvariantsOfState.find("_check_inv_14") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_14()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_T3Wait()) {
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T3Wait();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_15") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_15()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T3Wait"});
+                if(dependentInvariantsOfState.find("_check_inv_16") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_16()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_T3ReEnableWait()) {
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.T3ReEnableWait();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_17") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_17()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "T3ReEnableWait"});
+                if(dependentInvariantsOfState.find("_check_inv_18") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_18()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BInteger> _trid_21 = state._tr_Update();
-        for(const BInteger& param : _trid_21) {
-            BInteger _tmp_1 = param;
-
-            CAN_BUS_tlc copiedState = state._copy();
-            copiedState.Update(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_19") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_19()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "Update"});
+                if(dependentInvariantsOfState.find("_check_inv_20") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_20()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-
-    }
-    return result;
-}
-
-static void printResult(int states, int transitions, bool deadlockDetected, bool invariantViolated, CAN_BUS_tlc& counterExampleState, std::unordered_map<CAN_BUS_tlc, CAN_BUS_tlc, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual>& parents, std::unordered_map<CAN_BUS_tlc, string, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual>& stateAccessedVia) {
-    if(deadlockDetected || invariantViolated) {
-        if(deadlockDetected) {
-            cout << "DEADLOCK DETECTED" << "\n";
-        }
-        if(invariantViolated) {
-            cout << "INVARIANT VIOLATED" << "\n";
-        }
-        cout << "COUNTER EXAMPLE TRACE: " << "\n";
-
-        CAN_BUS_tlc currentState = counterExampleState;
-        std::string trace = "";
-        while(parents.find(currentState) != parents.end()) {
-            std::stringstream stringStream;
-            stringStream << currentState;
-            trace.insert(0, stringStream.str());
-            trace.insert(0, "\n");
-            trace.insert(0, stateAccessedVia[currentState]);
-            trace.insert(0, "\n\n");
-            currentState = parents[currentState];
-        }
-        cout << trace;
-    }
-
-    if(!deadlockDetected && !invariantViolated) {
-        cout << "MODEL CHECKING SUCCESSFUL" << "\n";
-    }
-    cout << "Number of States: " << states << "\n";
-    cout << "Number of Transitions: " << transitions << "\n";
-}
-
-static bool checkInvariants(std::mutex& guardMutex, const CAN_BUS_tlc& state, bool isCaching, std::unordered_map<CAN_BUS_tlc, std::unordered_set<string>, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual>& dependentInvariant) {
-    if(isCaching) {
-        std::unordered_set<string> dependentInvariantsOfState;
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            dependentInvariantsOfState = dependentInvariant[state];
-        }
-        if(dependentInvariantsOfState.find("_check_inv_1") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_1()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_2") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_2()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_3") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_3()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_4") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_4()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_5") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_5()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_6") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_6()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_7") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_7()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_8") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_8()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_9") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_9()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_10") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_10()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_11") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_11()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_12") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_12()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_13") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_13()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_14") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_14()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_15") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_15()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_16") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_16()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_17") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_17()) {
                 return false;
             }
+            return !(state._check_inv_1() && state._check_inv_2() && state._check_inv_3() && state._check_inv_4() && state._check_inv_5() && state._check_inv_6() && state._check_inv_7() && state._check_inv_8() && state._check_inv_9() && state._check_inv_10() && state._check_inv_11() && state._check_inv_12() && state._check_inv_13() && state._check_inv_14() && state._check_inv_15() && state._check_inv_16() && state._check_inv_17() && state._check_inv_18() && state._check_inv_19() && state._check_inv_20());
         }
-        if(dependentInvariantsOfState.find("_check_inv_18") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_18()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_19") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_19()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_20") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_20()) {
-                return false;
-            }
-        }
-        return true;
-    }
-    return !(!state._check_inv_1() || !state._check_inv_2() || !state._check_inv_3() || !state._check_inv_4() || !state._check_inv_5() || !state._check_inv_6() || !state._check_inv_7() || !state._check_inv_8() || !state._check_inv_9() || !state._check_inv_10() || !state._check_inv_11() || !state._check_inv_12() || !state._check_inv_13() || !state._check_inv_14() || !state._check_inv_15() || !state._check_inv_16() || !state._check_inv_17() || !state._check_inv_18() || !state._check_inv_19() || !state._check_inv_20());
-}
 
-static CAN_BUS_tlc next(std::list<CAN_BUS_tlc>& collection, std::mutex& mutex, CAN_BUS_tlc::Type type) {
-    std::unique_lock<std::mutex> lock(mutex);
-    switch(type) {
-        case CAN_BUS_tlc::BFS: {
-            CAN_BUS_tlc state = collection.front();
-            collection.pop_front();
-            return state;
-        }
-        case CAN_BUS_tlc::DFS: {
-            CAN_BUS_tlc state = collection.back();
-            collection.pop_back();
-            return state;
-        }
-        case CAN_BUS_tlc::MIXED: {
-            if(collection.size() % 2 == 0) {
-                CAN_BUS_tlc state = collection.front();
-                collection.pop_front();
-                return state;
-            } else {
-                CAN_BUS_tlc state = collection.back();
-                collection.pop_back();
-                return state;
-            }
-        }
-    };
-}
 
-static void modelCheckSingleThreaded(CAN_BUS_tlc::Type type, bool isCaching) {
-    std::mutex mutex;
-    std::mutex guardMutex;
-
-    CAN_BUS_tlc machine = CAN_BUS_tlc();
-
-    std::atomic<bool> invariantViolated;
-    invariantViolated = false;
-    std::atomic<bool> deadlockDetected;
-    deadlockDetected = false;
-    std::atomic<bool> stopThreads;
-    stopThreads = false;
-
-    std::unordered_set<CAN_BUS_tlc, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> states = std::unordered_set<CAN_BUS_tlc, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual>();
-    states.insert(machine);
-    std::atomic<int> numberStates;
-    numberStates = 1;
-
-    std::list<CAN_BUS_tlc> collection = std::list<CAN_BUS_tlc>();
-    collection.push_back(machine);
-
-    std::atomic<int> transitions;
-    transitions = 0;
-
-    std::unordered_map<string, std::unordered_set<string>> invariantDependency;
-    std::unordered_map<string, std::unordered_set<string>> guardDependency;
-    std::unordered_map<CAN_BUS_tlc, std::unordered_set<string>, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> dependentInvariant;
-    std::unordered_map<CAN_BUS_tlc, std::unordered_set<string>, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> dependentGuard;
-    std::unordered_map<CAN_BUS_tlc, immer::map<string, boost::any>, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> guardCache;
-    std::unordered_map<CAN_BUS_tlc, CAN_BUS_tlc, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> parents;
-    std::unordered_map<CAN_BUS_tlc, string, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> stateAccessedVia;
-    if(isCaching) {
-        invariantDependency.insert({"T1Wait", {"_check_inv_10", "_check_inv_4"}});
-        invariantDependency.insert({"T1Calculate", {"_check_inv_7", "_check_inv_4"}});
-        invariantDependency.insert({"T1SendResult", {"_check_inv_18", "_check_inv_19", "_check_inv_20", "_check_inv_4"}});
-        invariantDependency.insert({"T2ReadBus", {"_check_inv_17", "_check_inv_5", "_check_inv_9"}});
-        invariantDependency.insert({"T2Reset", {"_check_inv_1", "_check_inv_5", "_check_inv_8", "_check_inv_12"}});
-        invariantDependency.insert({"T2Complete", {"_check_inv_5", "_check_inv_12"}});
-        invariantDependency.insert({"T2Evaluate", {"_check_inv_5", "_check_inv_11"}});
-        invariantDependency.insert({"T3Evaluate", {"_check_inv_6"}});
-        invariantDependency.insert({"T3ReleaseBus", {"_check_inv_18", "_check_inv_19", "_check_inv_6", "_check_inv_20"}});
-        invariantDependency.insert({"T1Evaluate", {"_check_inv_10", "_check_inv_4"}});
-        invariantDependency.insert({"T3Initiate", {"_check_inv_3", "_check_inv_6"}});
-        invariantDependency.insert({"T3ReEnableWait", {"_check_inv_2", "_check_inv_3", "_check_inv_6"}});
-        invariantDependency.insert({"T3writebus", {"_check_inv_18", "_check_inv_19", "_check_inv_6", "_check_inv_20"}});
-        invariantDependency.insert({"Update", {"_check_inv_2", "_check_inv_10", "_check_inv_14", "_check_inv_13", "_check_inv_11"}});
-        invariantDependency.insert({"T2ReleaseBus", {"_check_inv_18", "_check_inv_19", "_check_inv_20", "_check_inv_5"}});
-        invariantDependency.insert({"T2Wait", {"_check_inv_5", "_check_inv_11"}});
-        invariantDependency.insert({"T3Poll", {"_check_inv_6"}});
-        invariantDependency.insert({"T2Calculate", {"_check_inv_1", "_check_inv_5"}});
-        invariantDependency.insert({"T3Read", {"_check_inv_16", "_check_inv_15", "_check_inv_6"}});
-        invariantDependency.insert({"T3Wait", {"_check_inv_2", "_check_inv_6"}});
-        invariantDependency.insert({"T2WriteBus", {"_check_inv_18", "_check_inv_19", "_check_inv_20", "_check_inv_5"}});
-        guardDependency.insert({"T1Wait", {"_tr_T1Evaluate", "_tr_Update", "_tr_T1SendResult", "_tr_T1Calculate", "_tr_T1Wait"}});
-        guardDependency.insert({"T1Calculate", {"_tr_T1Evaluate", "_tr_T1SendResult", "_tr_T1Calculate", "_tr_T1Wait"}});
-        guardDependency.insert({"T1SendResult", {"_tr_T1Evaluate", "_tr_T2ReleaseBus", "_tr_Update", "_tr_T1SendResult", "_tr_T1Calculate", "_tr_T1Wait"}});
-        guardDependency.insert({"T2ReadBus", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
-        guardDependency.insert({"T2Reset", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
-        guardDependency.insert({"T2Complete", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
-        guardDependency.insert({"T2Evaluate", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_Update", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
-        guardDependency.insert({"T3Evaluate", {"_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
-        guardDependency.insert({"T3ReleaseBus", {"_tr_T2ReleaseBus", "_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_Update", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
-        guardDependency.insert({"T1Evaluate", {"_tr_T1Evaluate", "_tr_Update", "_tr_T1SendResult", "_tr_T1Calculate", "_tr_T1Wait"}});
-        guardDependency.insert({"T3Initiate", {"_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_Update", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
-        guardDependency.insert({"T3ReEnableWait", {"_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_Update", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
-        guardDependency.insert({"T3writebus", {"_tr_T2ReleaseBus", "_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_Update", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
-        guardDependency.insert({"Update", {"_tr_T1Evaluate", "_tr_T3Read", "_tr_T2Evaluate", "_tr_Update", "_tr_T2ReadBus", "_tr_T3Evaluate", "_tr_T3Initiate"}});
-        guardDependency.insert({"T2ReleaseBus", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_Update", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
-        guardDependency.insert({"T2Wait", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_Update", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
-        guardDependency.insert({"T3Poll", {"_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
-        guardDependency.insert({"T2Calculate", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
-        guardDependency.insert({"T3Read", {"_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
-        guardDependency.insert({"T3Wait", {"_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_Update", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
-        guardDependency.insert({"T2WriteBus", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_Update", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
-        dependentInvariant.insert({machine, std::unordered_set<string>()});
-    }
-    CAN_BUS_tlc counterExampleState;
-
-    while(!collection.empty() && !stopThreads) {
-        CAN_BUS_tlc state = next(collection, mutex, type);
-
-        std::unordered_set<CAN_BUS_tlc, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> nextStates = generateNextStates(guardMutex, state, isCaching, invariantDependency, dependentInvariant, guardDependency, dependentGuard, guardCache, parents, stateAccessedVia, transitions);
-        for(auto nextState : nextStates) {
-            if(states.find(nextState) == states.end()) {
-                numberStates += 1;
-                states.insert(nextState);
-                collection.push_back(nextState);
-                if(numberStates % 50000 == 0) {
-                    cout << "VISITED STATES: " << numberStates << "\n";
-                    cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
-                    cout << "-------------------" << "\n";
+        void printResult() {
+            if(deadlockDetected || invariantViolatedBool) {
+                if(deadlockDetected) {
+                    cout << "DEADLOCK DETECTED" << "\n";
+                } else {
+                    cout << "INVARIANT VIOLATED" << "\n";
                 }
-            }
-        }
-
-        if(!checkInvariants(guardMutex, state, isCaching, dependentInvariant)) {
-            invariantViolated = true;
-            stopThreads = true;
-            counterExampleState = state;
-        }
-
-        if(nextStates.empty()) {
-            deadlockDetected = true;
-            stopThreads = true;
-            counterExampleState = state;
-        }
-
-    }
-    printResult(numberStates, transitions, deadlockDetected, invariantViolated, counterExampleState, parents, stateAccessedVia);
-}
-
-static void modelCheckMultiThreaded(CAN_BUS_tlc::Type type, int threads, bool isCaching) {
-    std::mutex mutex;
-    std::mutex waitMutex;
-    std::mutex guardMutex;
-    std::condition_variable waitCV;
-
-    CAN_BUS_tlc machine = CAN_BUS_tlc();
-
-
-    std::atomic<bool> invariantViolated;
-    invariantViolated = false;
-    std::atomic<bool> deadlockDetected;
-    deadlockDetected = false;
-    std::atomic<bool> stopThreads;
-    stopThreads = false;
-
-    std::unordered_set<CAN_BUS_tlc, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> states = std::unordered_set<CAN_BUS_tlc, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual>();
-    states.insert(machine);
-    std::atomic<int> numberStates;
-    numberStates = 1;
-
-    std::list<CAN_BUS_tlc> collection = std::list<CAN_BUS_tlc>();
-    collection.push_back(machine);
-
-    std::atomic<int> transitions;
-    transitions = 0;
-
-    std::atomic<int> possibleQueueChanges;
-    possibleQueueChanges = 0;
-
-    std::atomic<bool> waitFlag;
-    waitFlag = true;
-
-    std::unordered_map<string, std::unordered_set<string>> invariantDependency;
-    std::unordered_map<string, std::unordered_set<string>> guardDependency;
-    std::unordered_map<CAN_BUS_tlc, std::unordered_set<string>, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> dependentInvariant;
-    std::unordered_map<CAN_BUS_tlc, std::unordered_set<string>, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> dependentGuard;
-    std::unordered_map<CAN_BUS_tlc, immer::map<string, boost::any>, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> guardCache;
-    std::unordered_map<CAN_BUS_tlc, CAN_BUS_tlc, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> parents;
-    std::unordered_map<CAN_BUS_tlc, string, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> stateAccessedVia;
-    if(isCaching) {
-        invariantDependency.insert({"T1Wait", {"_check_inv_10", "_check_inv_4"}});
-        invariantDependency.insert({"T1Calculate", {"_check_inv_7", "_check_inv_4"}});
-        invariantDependency.insert({"T1SendResult", {"_check_inv_18", "_check_inv_19", "_check_inv_20", "_check_inv_4"}});
-        invariantDependency.insert({"T2ReadBus", {"_check_inv_17", "_check_inv_5", "_check_inv_9"}});
-        invariantDependency.insert({"T2Reset", {"_check_inv_1", "_check_inv_5", "_check_inv_8", "_check_inv_12"}});
-        invariantDependency.insert({"T2Complete", {"_check_inv_5", "_check_inv_12"}});
-        invariantDependency.insert({"T2Evaluate", {"_check_inv_5", "_check_inv_11"}});
-        invariantDependency.insert({"T3Evaluate", {"_check_inv_6"}});
-        invariantDependency.insert({"T3ReleaseBus", {"_check_inv_18", "_check_inv_19", "_check_inv_6", "_check_inv_20"}});
-        invariantDependency.insert({"T1Evaluate", {"_check_inv_10", "_check_inv_4"}});
-        invariantDependency.insert({"T3Initiate", {"_check_inv_3", "_check_inv_6"}});
-        invariantDependency.insert({"T3ReEnableWait", {"_check_inv_2", "_check_inv_3", "_check_inv_6"}});
-        invariantDependency.insert({"T3writebus", {"_check_inv_18", "_check_inv_19", "_check_inv_6", "_check_inv_20"}});
-        invariantDependency.insert({"Update", {"_check_inv_2", "_check_inv_10", "_check_inv_14", "_check_inv_13", "_check_inv_11"}});
-        invariantDependency.insert({"T2ReleaseBus", {"_check_inv_18", "_check_inv_19", "_check_inv_20", "_check_inv_5"}});
-        invariantDependency.insert({"T2Wait", {"_check_inv_5", "_check_inv_11"}});
-        invariantDependency.insert({"T3Poll", {"_check_inv_6"}});
-        invariantDependency.insert({"T2Calculate", {"_check_inv_1", "_check_inv_5"}});
-        invariantDependency.insert({"T3Read", {"_check_inv_16", "_check_inv_15", "_check_inv_6"}});
-        invariantDependency.insert({"T3Wait", {"_check_inv_2", "_check_inv_6"}});
-        invariantDependency.insert({"T2WriteBus", {"_check_inv_18", "_check_inv_19", "_check_inv_20", "_check_inv_5"}});
-        guardDependency.insert({"T1Wait", {"_tr_T1Evaluate", "_tr_Update", "_tr_T1SendResult", "_tr_T1Calculate", "_tr_T1Wait"}});
-        guardDependency.insert({"T1Calculate", {"_tr_T1Evaluate", "_tr_T1SendResult", "_tr_T1Calculate", "_tr_T1Wait"}});
-        guardDependency.insert({"T1SendResult", {"_tr_T1Evaluate", "_tr_T2ReleaseBus", "_tr_Update", "_tr_T1SendResult", "_tr_T1Calculate", "_tr_T1Wait"}});
-        guardDependency.insert({"T2ReadBus", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
-        guardDependency.insert({"T2Reset", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
-        guardDependency.insert({"T2Complete", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
-        guardDependency.insert({"T2Evaluate", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_Update", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
-        guardDependency.insert({"T3Evaluate", {"_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
-        guardDependency.insert({"T3ReleaseBus", {"_tr_T2ReleaseBus", "_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_Update", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
-        guardDependency.insert({"T1Evaluate", {"_tr_T1Evaluate", "_tr_Update", "_tr_T1SendResult", "_tr_T1Calculate", "_tr_T1Wait"}});
-        guardDependency.insert({"T3Initiate", {"_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_Update", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
-        guardDependency.insert({"T3ReEnableWait", {"_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_Update", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
-        guardDependency.insert({"T3writebus", {"_tr_T2ReleaseBus", "_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_Update", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
-        guardDependency.insert({"Update", {"_tr_T1Evaluate", "_tr_T3Read", "_tr_T2Evaluate", "_tr_Update", "_tr_T2ReadBus", "_tr_T3Evaluate", "_tr_T3Initiate"}});
-        guardDependency.insert({"T2ReleaseBus", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_Update", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
-        guardDependency.insert({"T2Wait", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_Update", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
-        guardDependency.insert({"T3Poll", {"_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
-        guardDependency.insert({"T2Calculate", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
-        guardDependency.insert({"T3Read", {"_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
-        guardDependency.insert({"T3Wait", {"_tr_T3writebus", "_tr_T3Read", "_tr_T3ReleaseBus", "_tr_T3Poll", "_tr_Update", "_tr_T3ReEnableWait", "_tr_T3Evaluate", "_tr_T3Wait", "_tr_T3Initiate"}});
-        guardDependency.insert({"T2WriteBus", {"_tr_T2Reset", "_tr_T2ReleaseBus", "_tr_T2Complete", "_tr_T2Calculate", "_tr_T2Evaluate", "_tr_Update", "_tr_T2ReadBus", "_tr_T2WriteBus", "_tr_T2Wait"}});
-        dependentInvariant.insert({machine, std::unordered_set<string>()});
-    }
-    CAN_BUS_tlc counterExampleState;
-
-    boost::asio::thread_pool workers(threads);
-
-    while(!collection.empty() && !stopThreads) {
-        possibleQueueChanges += 1;
-        CAN_BUS_tlc state = next(collection, mutex, type);
-        std::packaged_task<void()> task([&, state] {
-            std::unordered_set<CAN_BUS_tlc, CAN_BUS_tlc::Hash, CAN_BUS_tlc::HashEqual> nextStates = generateNextStates(guardMutex, state, isCaching, invariantDependency, dependentInvariant, guardDependency, dependentGuard, guardCache, parents, stateAccessedVia, transitions);
 
+                cout << "COUNTER EXAMPLE TRACE: " << "\n";
 
-            for(auto nextState : nextStates) {
-                {
-                    std::unique_lock<std::mutex> lock(mutex);
-                    if(states.find(nextState) == states.end()) {
-                        numberStates += 1;
-                        states.insert(nextState);
-                        collection.push_back(nextState);
-                        if(numberStates % 50000 == 0) {
-                            cout << "VISITED STATES: " << numberStates << "\n";
-                            cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
-                            cout << "-------------------" << "\n";
-                        }
-                    }
+                std::string trace = "";
+                while(parents.find(counterExampleState) != parents.end()) {
+                    std::stringstream stringStream;
+                    stringStream << counterExampleState;
+                    trace.insert(0, stringStream.str());
+                    trace.insert(0, "\n");
+                    trace.insert(0, counterExampleState.stateAccessedVia);
+                    trace.insert(0, "\n\n");
+                    counterExampleState = parents[counterExampleState];
                 }
+                cout << trace;
+            } else {
+                cout << "MODEL CHECKING SUCCESSFUL" << "\n";
             }
 
-            {
-                std::unique_lock<std::mutex> lock(mutex);
-                possibleQueueChanges -= 1;
-                int running = possibleQueueChanges;
-                if (!collection.empty() || running == 0) {
-                    {
-                        std::unique_lock<std::mutex> lock(waitMutex);
-                        waitFlag = false;
-                        waitCV.notify_one();
-                    }
-                }
-            }
-
-            if(nextStates.empty()) {
-                deadlockDetected = true;
-                stopThreads = true;
-                counterExampleState = state;
-            }
-
-            if(!checkInvariants(guardMutex, state, isCaching, dependentInvariant)) {
-                invariantViolated = true;
-                stopThreads = true;
-                counterExampleState = state;
-            }
-
-
-        });
-        waitFlag = true;
-        boost::asio::post(workers, std::move(task));
-
-        {
-            std::unique_lock<std::mutex> lock(waitMutex);
-            if (collection.empty() && possibleQueueChanges > 0) {
-                waitCV.wait(lock, [&] {
-                    return waitFlag == false;
-                });
-            }
+            cout << "Number of States: " << states.size() << "\n";
+            cout << "Number of Transitions: " << transitions << "\n";
         }
-    }
-    workers.join();
-    printResult(numberStates, transitions, deadlockDetected, invariantViolated, counterExampleState, parents, stateAccessedVia);
-}
+};
 
 int main(int argc, char *argv[]) {
     if(argc != 4) {
@@ -2516,11 +1710,12 @@ int main(int argc, char *argv[]) {
         return - 1;
     }
 
-    if(threads == 1) {
-        modelCheckSingleThreaded(type, isCaching);
-    } else {
-        modelCheckMultiThreaded(type, threads, isCaching);
-    }
+    bool isDebug = true;
+    // TODO
+
+    ModelChecker modelchecker(type, threads, isCaching, isDebug);
+    modelchecker.modelCheck();
+
     return 0;
 }
 
diff --git a/benchmarks/model_checking/C++/Cruise_finite1_deterministic_MC.cpp b/benchmarks/model_checking/C++/Cruise_finite1_deterministic_MC.cpp
index fd5f99ab6dd6a712d06dc9b4e6a09194989af772..02d0fd98d4757d710cb62eaad6bd8edb7f19de7c 100644
--- a/benchmarks/model_checking/C++/Cruise_finite1_deterministic_MC.cpp
+++ b/benchmarks/model_checking/C++/Cruise_finite1_deterministic_MC.cpp
@@ -11,6 +11,7 @@
 #include <boost/asio/post.hpp>
 #include <boost/asio/thread_pool.hpp>
 #include <boost/any.hpp>
+#include <boost/optional.hpp>
 #include <btypes_primitives/BUtils.hpp>
 #include <btypes_primitives/StateNotReachableError.hpp>
 #include <btypes_primitives/PreconditionOrAssertionViolation.hpp>
@@ -31,7 +32,6 @@ class Cruise_finite1_deterministic_MC {
 
         enum Type { BFS, DFS, MIXED };
 
-
         class RSset : public BObject {
             public:
 
@@ -144,6 +144,7 @@ class Cruise_finite1_deterministic_MC {
                 }
         };
 
+
         struct Hash {
             public:
                 size_t operator()(const Cruise_finite1_deterministic_MC& obj) const {
@@ -184,9 +185,37 @@ class Cruise_finite1_deterministic_MC {
         BBoolean CruiseSpeedChangeInProgress;
         BInteger NumberOfSetCruise;
 
+        mutable boost::optional<bool> _tr_cache_CruiseBecomesNotAllowed;
+        mutable boost::optional<bool> _tr_cache_CruiseBecomesAllowed;
+        mutable boost::optional<BSet<BTuple<BBoolean, BBoolean >>> _tr_cache_SetCruiseSpeed;
+        mutable boost::optional<BSet<BTuple<BBoolean, BBoolean >>> _tr_cache_CCInitialisationFinished;
+        mutable boost::optional<bool> _tr_cache_CCInitialisationDelayFinished;
+        mutable boost::optional<BSet<BTuple<BBoolean, BBoolean >>> _tr_cache_CruiseSpeedChangeFinished;
+        mutable boost::optional<bool> _tr_cache_CruiseSpeedChangeDelayFinished;
+        mutable boost::optional<bool> _tr_cache_CruiseOff;
+        mutable boost::optional<bool> _tr_cache_ExternalForcesBecomesExtreme;
+        mutable boost::optional<bool> _tr_cache_ExternalForcesBecomesNormal;
+        mutable boost::optional<bool> _tr_cache_VehicleLeavesCruiseSpeed;
+        mutable boost::optional<bool> _tr_cache_VehicleReachesCruiseSpeed;
+        mutable boost::optional<bool> _tr_cache_VehicleExceedsMaxCruiseSpeed;
+        mutable boost::optional<bool> _tr_cache_VehicleFallsBelowMaxCruiseSpeed;
+        mutable boost::optional<bool> _tr_cache_ObstacleDistanceBecomesVeryClose;
+        mutable boost::optional<bool> _tr_cache_ObstacleDistanceBecomesClose;
+        mutable boost::optional<bool> _tr_cache_ObstacleDistanceBecomesBig;
+        mutable boost::optional<bool> _tr_cache_ObstacleStartsTravelFaster;
+        mutable boost::optional<bool> _tr_cache_ObstacleStopsTravelFaster;
+        mutable boost::optional<bool> _tr_cache_ObstacleStartsTravelSlower;
+        mutable boost::optional<bool> _tr_cache_ObstacleStopsTravelSlower;
+        mutable boost::optional<BSet<BTuple<RSset, ODset >>> _tr_cache_ObstacleAppearsWhenCruiseActive;
+        mutable boost::optional<BSet<RSset>> _tr_cache_ObstacleAppearsWhenCruiseInactive;
+        mutable boost::optional<bool> _tr_cache_ObstacleDisappears;
+        mutable boost::optional<BSet<BTuple<BBoolean, BBoolean >>> _tr_cache_VehicleManageObstacle;
+        mutable boost::optional<bool> _tr_cache_ObstacleBecomesOld;
 
     public:
 
+        std::string stateAccessedVia;
+
         Cruise_finite1_deterministic_MC() {
             CruiseAllowed = (BBoolean(true));
             CruiseActive = (BBoolean(false));
@@ -501,160 +530,284 @@ class Cruise_finite1_deterministic_MC {
         }
 
 
-        bool _tr_CruiseBecomesNotAllowed() const {
-            return (CruiseAllowed.equal((BBoolean(true)))).booleanValue();
+        bool _tr_CruiseBecomesNotAllowed(bool isCaching) const {
+            if (this->_tr_cache_CruiseBecomesNotAllowed == boost::none){
+                bool __tmp_result = (CruiseAllowed.equal((BBoolean(true)))).booleanValue();
+                if (isCaching) this->_tr_cache_CruiseBecomesNotAllowed = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_CruiseBecomesNotAllowed.get();
         }
 
-        bool _tr_CruiseBecomesAllowed() const {
-            return (CruiseAllowed.equal((BBoolean(false)))).booleanValue();
+        bool _tr_CruiseBecomesAllowed(bool isCaching) const {
+            if (this->_tr_cache_CruiseBecomesAllowed == boost::none){
+                bool __tmp_result = (CruiseAllowed.equal((BBoolean(false)))).booleanValue();
+                if (isCaching) this->_tr_cache_CruiseBecomesAllowed = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_CruiseBecomesAllowed.get();
         }
 
-        BSet<BTuple<BBoolean, BBoolean >> _tr_SetCruiseSpeed() const {
-            BSet<BTuple<BBoolean, BBoolean >> _ic_set_2 = BSet<BTuple<BBoolean, BBoolean >>();
-            for(BBoolean _ic_vcks_1 : (BOOL)) {
-                for(BBoolean _ic_csam_1 : (BOOL)) {
-                    if((CruiseAllowed.equal((BBoolean(true)))).booleanValue()) {
-                        _ic_set_2 = _ic_set_2._union(BSet<BTuple<BBoolean, BBoolean >>((BTuple<BBoolean, BBoolean >(_ic_vcks_1, _ic_csam_1))));
-                    }
+        BSet<BTuple<BBoolean, BBoolean >> _tr_SetCruiseSpeed(bool isCaching) const {
+            if (this->_tr_cache_SetCruiseSpeed == boost::none){
+                BSet<BTuple<BBoolean, BBoolean >> _ic_set_2 = BSet<BTuple<BBoolean, BBoolean >>();
+                for(const BBoolean& _ic_vcks_1 : (BOOL)) {
+                    for(const BBoolean& _ic_csam_1 : (BOOL)) {
+                        if((CruiseAllowed.equal((BBoolean(true)))).booleanValue()) {
+                            _ic_set_2 = _ic_set_2._union(BSet<BTuple<BBoolean, BBoolean >>((BTuple<BBoolean, BBoolean >(_ic_vcks_1, _ic_csam_1))));
+                        }
 
+                    }
                 }
+                if (isCaching) this->_tr_cache_SetCruiseSpeed = _ic_set_2;
+                else return _ic_set_2;
             }
-            return _ic_set_2;
+            return this->_tr_cache_SetCruiseSpeed.get();
         }
 
-        BSet<BTuple<BBoolean, BBoolean >> _tr_CCInitialisationFinished() const {
-            BSet<BTuple<BBoolean, BBoolean >> _ic_set_3 = BSet<BTuple<BBoolean, BBoolean >>();
-            for(BBoolean _ic_vtks_1 : (BOOL)) {
-                for(BBoolean _ic_vtktg_1 : (BOOL)) {
-                    if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(_ic_vtks_1.equal((BBoolean(true))).booleanValue() || _ic_vtktg_1.equal((BBoolean(true))).booleanValue())).booleanValue() || ObstacleStatusJustChanged.equal((BBoolean(true))).booleanValue())).booleanValue() || CruiseSpeedChangeInProgress.equal((BBoolean(true))).booleanValue())).booleanValue() && (BBoolean(!ObstaclePresent.equal((BBoolean(false))).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue() || _ic_vtks_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODclose))).booleanValue() && ObstacleRelativeSpeed.unequal((RSset(RSset::RSpos))).booleanValue())).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODveryclose))).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue() && ObstacleDistance.unequal((ODset(ODset::ODveryclose))).booleanValue())).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || _ic_vtks_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSequal))).booleanValue() && ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSneg))).booleanValue() && ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue() && ObstacleDistance.unequal((ODset(ODset::ODveryclose))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(true))).booleanValue()))).booleanValue()) {
-                        _ic_set_3 = _ic_set_3._union(BSet<BTuple<BBoolean, BBoolean >>((BTuple<BBoolean, BBoolean >(_ic_vtks_1, _ic_vtktg_1))));
-                    }
+        BSet<BTuple<BBoolean, BBoolean >> _tr_CCInitialisationFinished(bool isCaching) const {
+            if (this->_tr_cache_CCInitialisationFinished == boost::none){
+                BSet<BTuple<BBoolean, BBoolean >> _ic_set_3 = BSet<BTuple<BBoolean, BBoolean >>();
+                for(const BBoolean& _ic_vtks_1 : (BOOL)) {
+                    for(const BBoolean& _ic_vtktg_1 : (BOOL)) {
+                        if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(_ic_vtks_1.equal((BBoolean(true))).booleanValue() || _ic_vtktg_1.equal((BBoolean(true))).booleanValue())).booleanValue() || ObstacleStatusJustChanged.equal((BBoolean(true))).booleanValue())).booleanValue() || CruiseSpeedChangeInProgress.equal((BBoolean(true))).booleanValue())).booleanValue() && (BBoolean(!ObstaclePresent.equal((BBoolean(false))).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue() || _ic_vtks_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODclose))).booleanValue() && ObstacleRelativeSpeed.unequal((RSset(RSset::RSpos))).booleanValue())).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODveryclose))).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue() && ObstacleDistance.unequal((ODset(ODset::ODveryclose))).booleanValue())).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || _ic_vtks_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSequal))).booleanValue() && ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSneg))).booleanValue() && ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue() && ObstacleDistance.unequal((ODset(ODset::ODveryclose))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(true))).booleanValue()))).booleanValue()) {
+                            _ic_set_3 = _ic_set_3._union(BSet<BTuple<BBoolean, BBoolean >>((BTuple<BBoolean, BBoolean >(_ic_vtks_1, _ic_vtktg_1))));
+                        }
 
+                    }
                 }
+                if (isCaching) this->_tr_cache_CCInitialisationFinished = _ic_set_3;
+                else return _ic_set_3;
             }
-            return _ic_set_3;
+            return this->_tr_cache_CCInitialisationFinished.get();
         }
 
-        bool _tr_CCInitialisationDelayFinished() const {
-            return ((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(CCInitialisationInProgress.equal((BBoolean(true))).booleanValue() && (BBoolean((BBoolean((BBoolean(VehicleTryKeepSpeed.equal((BBoolean(true))).booleanValue() || VehicleTryKeepTimeGap.equal((BBoolean(true))).booleanValue())).booleanValue() || ObstacleStatusJustChanged.equal((BBoolean(true))).booleanValue())).booleanValue() || CruiseSpeedChangeInProgress.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue() || VehicleTryKeepSpeed.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODclose))).booleanValue() && ObstacleRelativeSpeed.unequal((RSset(RSset::RSpos))).booleanValue())).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || VehicleTryKeepTimeGap.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODveryclose))).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || VehicleTryKeepTimeGap.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue() && ObstacleDistance.unequal((ODset(ODset::ODveryclose))).booleanValue())).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || VehicleTryKeepSpeed.equal((BBoolean(true))).booleanValue())).booleanValue()))).booleanValue();
+        bool _tr_CCInitialisationDelayFinished(bool isCaching) const {
+            if (this->_tr_cache_CCInitialisationDelayFinished == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(CCInitialisationInProgress.equal((BBoolean(true))).booleanValue() && (BBoolean((BBoolean((BBoolean(VehicleTryKeepSpeed.equal((BBoolean(true))).booleanValue() || VehicleTryKeepTimeGap.equal((BBoolean(true))).booleanValue())).booleanValue() || ObstacleStatusJustChanged.equal((BBoolean(true))).booleanValue())).booleanValue() || CruiseSpeedChangeInProgress.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue() || VehicleTryKeepSpeed.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODclose))).booleanValue() && ObstacleRelativeSpeed.unequal((RSset(RSset::RSpos))).booleanValue())).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || VehicleTryKeepTimeGap.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODveryclose))).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || VehicleTryKeepTimeGap.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue() && ObstacleDistance.unequal((ODset(ODset::ODveryclose))).booleanValue())).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || VehicleTryKeepSpeed.equal((BBoolean(true))).booleanValue())).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_CCInitialisationDelayFinished = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_CCInitialisationDelayFinished.get();
         }
 
-        BSet<BTuple<BBoolean, BBoolean >> _tr_CruiseSpeedChangeFinished() const {
-            BSet<BTuple<BBoolean, BBoolean >> _ic_set_5 = BSet<BTuple<BBoolean, BBoolean >>();
-            for(BBoolean _ic_vtks_1 : (BOOL)) {
-                for(BBoolean _ic_vtktg_1 : (BOOL)) {
-                    if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(_ic_vtks_1.equal((BBoolean(true))).booleanValue() || _ic_vtktg_1.equal((BBoolean(true))).booleanValue())).booleanValue() || ObstacleStatusJustChanged.equal((BBoolean(true))).booleanValue())).booleanValue() || CCInitialisationInProgress.equal((BBoolean(true))).booleanValue())).booleanValue() && (BBoolean(!ObstaclePresent.equal((BBoolean(false))).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue() || _ic_vtks_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODclose))).booleanValue() && ObstacleRelativeSpeed.unequal((RSset(RSset::RSpos))).booleanValue())).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODveryclose))).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue() && ObstacleDistance.unequal((ODset(ODset::ODveryclose))).booleanValue())).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || _ic_vtks_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSequal))).booleanValue() && ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSneg))).booleanValue() && ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue() && ObstacleDistance.unequal((ODset(ODset::ODveryclose))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(true))).booleanValue()))).booleanValue()) {
-                        _ic_set_5 = _ic_set_5._union(BSet<BTuple<BBoolean, BBoolean >>((BTuple<BBoolean, BBoolean >(_ic_vtks_1, _ic_vtktg_1))));
-                    }
+        BSet<BTuple<BBoolean, BBoolean >> _tr_CruiseSpeedChangeFinished(bool isCaching) const {
+            if (this->_tr_cache_CruiseSpeedChangeFinished == boost::none){
+                BSet<BTuple<BBoolean, BBoolean >> _ic_set_5 = BSet<BTuple<BBoolean, BBoolean >>();
+                for(const BBoolean& _ic_vtks_1 : (BOOL)) {
+                    for(const BBoolean& _ic_vtktg_1 : (BOOL)) {
+                        if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(_ic_vtks_1.equal((BBoolean(true))).booleanValue() || _ic_vtktg_1.equal((BBoolean(true))).booleanValue())).booleanValue() || ObstacleStatusJustChanged.equal((BBoolean(true))).booleanValue())).booleanValue() || CCInitialisationInProgress.equal((BBoolean(true))).booleanValue())).booleanValue() && (BBoolean(!ObstaclePresent.equal((BBoolean(false))).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue() || _ic_vtks_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODclose))).booleanValue() && ObstacleRelativeSpeed.unequal((RSset(RSset::RSpos))).booleanValue())).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODveryclose))).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue() && ObstacleDistance.unequal((ODset(ODset::ODveryclose))).booleanValue())).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || _ic_vtks_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSequal))).booleanValue() && ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSneg))).booleanValue() && ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue() && ObstacleDistance.unequal((ODset(ODset::ODveryclose))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(true))).booleanValue()))).booleanValue()) {
+                            _ic_set_5 = _ic_set_5._union(BSet<BTuple<BBoolean, BBoolean >>((BTuple<BBoolean, BBoolean >(_ic_vtks_1, _ic_vtktg_1))));
+                        }
 
+                    }
                 }
+                if (isCaching) this->_tr_cache_CruiseSpeedChangeFinished = _ic_set_5;
+                else return _ic_set_5;
             }
-            return _ic_set_5;
+            return this->_tr_cache_CruiseSpeedChangeFinished.get();
         }
 
-        bool _tr_CruiseSpeedChangeDelayFinished() const {
-            return ((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(CruiseSpeedChangeInProgress.equal((BBoolean(true))).booleanValue() && (BBoolean((BBoolean((BBoolean(VehicleTryKeepSpeed.equal((BBoolean(true))).booleanValue() || VehicleTryKeepTimeGap.equal((BBoolean(true))).booleanValue())).booleanValue() || ObstacleStatusJustChanged.equal((BBoolean(true))).booleanValue())).booleanValue() || CCInitialisationInProgress.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue() || VehicleTryKeepSpeed.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODclose))).booleanValue() && ObstacleRelativeSpeed.unequal((RSset(RSset::RSpos))).booleanValue())).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || VehicleTryKeepTimeGap.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODveryclose))).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || VehicleTryKeepTimeGap.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue() && ObstacleDistance.unequal((ODset(ODset::ODveryclose))).booleanValue())).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || VehicleTryKeepSpeed.equal((BBoolean(true))).booleanValue())).booleanValue()))).booleanValue();
+        bool _tr_CruiseSpeedChangeDelayFinished(bool isCaching) const {
+            if (this->_tr_cache_CruiseSpeedChangeDelayFinished == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(CruiseSpeedChangeInProgress.equal((BBoolean(true))).booleanValue() && (BBoolean((BBoolean((BBoolean(VehicleTryKeepSpeed.equal((BBoolean(true))).booleanValue() || VehicleTryKeepTimeGap.equal((BBoolean(true))).booleanValue())).booleanValue() || ObstacleStatusJustChanged.equal((BBoolean(true))).booleanValue())).booleanValue() || CCInitialisationInProgress.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue() || VehicleTryKeepSpeed.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODclose))).booleanValue() && ObstacleRelativeSpeed.unequal((RSset(RSset::RSpos))).booleanValue())).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || VehicleTryKeepTimeGap.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODveryclose))).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || VehicleTryKeepTimeGap.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue() && ObstacleDistance.unequal((ODset(ODset::ODveryclose))).booleanValue())).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || VehicleTryKeepSpeed.equal((BBoolean(true))).booleanValue())).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_CruiseSpeedChangeDelayFinished = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_CruiseSpeedChangeDelayFinished.get();
         }
 
-        bool _tr_CruiseOff() const {
-            return (CruiseActive.equal((BBoolean(true)))).booleanValue();
+        bool _tr_CruiseOff(bool isCaching) const {
+            if (this->_tr_cache_CruiseOff == boost::none){
+                bool __tmp_result = (CruiseActive.equal((BBoolean(true)))).booleanValue();
+                if (isCaching) this->_tr_cache_CruiseOff = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_CruiseOff.get();
         }
 
-        bool _tr_ExternalForcesBecomesExtreme() const {
-            return (VehicleCanKeepSpeed.equal((BBoolean(true)))).booleanValue();
+        bool _tr_ExternalForcesBecomesExtreme(bool isCaching) const {
+            if (this->_tr_cache_ExternalForcesBecomesExtreme == boost::none){
+                bool __tmp_result = (VehicleCanKeepSpeed.equal((BBoolean(true)))).booleanValue();
+                if (isCaching) this->_tr_cache_ExternalForcesBecomesExtreme = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_ExternalForcesBecomesExtreme.get();
         }
 
-        bool _tr_ExternalForcesBecomesNormal() const {
-            return ((BBoolean(CruiseActive.equal((BBoolean(true))).booleanValue() && VehicleCanKeepSpeed.equal((BBoolean(false))).booleanValue()))).booleanValue();
+        bool _tr_ExternalForcesBecomesNormal(bool isCaching) const {
+            if (this->_tr_cache_ExternalForcesBecomesNormal == boost::none){
+                bool __tmp_result = ((BBoolean(CruiseActive.equal((BBoolean(true))).booleanValue() && VehicleCanKeepSpeed.equal((BBoolean(false))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_ExternalForcesBecomesNormal = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_ExternalForcesBecomesNormal.get();
         }
 
-        bool _tr_VehicleLeavesCruiseSpeed() const {
-            return ((BBoolean((BBoolean(VehicleAtCruiseSpeed.equal((BBoolean(true))).booleanValue() && (BBoolean(VehicleCanKeepSpeed.equal((BBoolean(false))).booleanValue() && VehicleTryKeepSpeed.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() || VehicleTryKeepSpeed.equal((BBoolean(false))).booleanValue()))).booleanValue();
+        bool _tr_VehicleLeavesCruiseSpeed(bool isCaching) const {
+            if (this->_tr_cache_VehicleLeavesCruiseSpeed == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean(VehicleAtCruiseSpeed.equal((BBoolean(true))).booleanValue() && (BBoolean(VehicleCanKeepSpeed.equal((BBoolean(false))).booleanValue() && VehicleTryKeepSpeed.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() || VehicleTryKeepSpeed.equal((BBoolean(false))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_VehicleLeavesCruiseSpeed = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_VehicleLeavesCruiseSpeed.get();
         }
 
-        bool _tr_VehicleReachesCruiseSpeed() const {
-            return ((BBoolean((BBoolean(CruiseActive.equal((BBoolean(true))).booleanValue() && VehicleAtCruiseSpeed.equal((BBoolean(false))).booleanValue())).booleanValue() && SpeedAboveMax.equal((BBoolean(false))).booleanValue()))).booleanValue();
+        bool _tr_VehicleReachesCruiseSpeed(bool isCaching) const {
+            if (this->_tr_cache_VehicleReachesCruiseSpeed == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean(CruiseActive.equal((BBoolean(true))).booleanValue() && VehicleAtCruiseSpeed.equal((BBoolean(false))).booleanValue())).booleanValue() && SpeedAboveMax.equal((BBoolean(false))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_VehicleReachesCruiseSpeed = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_VehicleReachesCruiseSpeed.get();
         }
 
-        bool _tr_VehicleExceedsMaxCruiseSpeed() const {
-            return ((BBoolean(SpeedAboveMax.equal((BBoolean(false))).booleanValue() && (BBoolean((BBoolean(CruiseActive.equal((BBoolean(false))).booleanValue() || VehicleCanKeepSpeed.equal((BBoolean(false))).booleanValue())).booleanValue() || (BBoolean((BBoolean(ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue()))).booleanValue();
+        bool _tr_VehicleExceedsMaxCruiseSpeed(bool isCaching) const {
+            if (this->_tr_cache_VehicleExceedsMaxCruiseSpeed == boost::none){
+                bool __tmp_result = ((BBoolean(SpeedAboveMax.equal((BBoolean(false))).booleanValue() && (BBoolean((BBoolean(CruiseActive.equal((BBoolean(false))).booleanValue() || VehicleCanKeepSpeed.equal((BBoolean(false))).booleanValue())).booleanValue() || (BBoolean((BBoolean(ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_VehicleExceedsMaxCruiseSpeed = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_VehicleExceedsMaxCruiseSpeed.get();
         }
 
-        bool _tr_VehicleFallsBelowMaxCruiseSpeed() const {
-            return (SpeedAboveMax.equal((BBoolean(true)))).booleanValue();
+        bool _tr_VehicleFallsBelowMaxCruiseSpeed(bool isCaching) const {
+            if (this->_tr_cache_VehicleFallsBelowMaxCruiseSpeed == boost::none){
+                bool __tmp_result = (SpeedAboveMax.equal((BBoolean(true)))).booleanValue();
+                if (isCaching) this->_tr_cache_VehicleFallsBelowMaxCruiseSpeed = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_VehicleFallsBelowMaxCruiseSpeed.get();
         }
 
-        bool _tr_ObstacleDistanceBecomesVeryClose() const {
-            return ((BBoolean(ObstacleDistance.equal((ODset(ODset::ODclose))).booleanValue() && ObstacleRelativeSpeed.equal((RSset(RSset::RSneg))).booleanValue()))).booleanValue();
+        bool _tr_ObstacleDistanceBecomesVeryClose(bool isCaching) const {
+            if (this->_tr_cache_ObstacleDistanceBecomesVeryClose == boost::none){
+                bool __tmp_result = ((BBoolean(ObstacleDistance.equal((ODset(ODset::ODclose))).booleanValue() && ObstacleRelativeSpeed.equal((RSset(RSset::RSneg))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_ObstacleDistanceBecomesVeryClose = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_ObstacleDistanceBecomesVeryClose.get();
         }
 
-        bool _tr_ObstacleDistanceBecomesClose() const {
-            return ((BBoolean((BBoolean(ObstaclePresent.equal((BBoolean(true))).booleanValue() && CruiseActive.equal((BBoolean(true))).booleanValue())).booleanValue() && (BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODveryclose))).booleanValue() && ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue())).booleanValue() || (BBoolean(ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue() && ObstacleRelativeSpeed.equal((RSset(RSset::RSneg))).booleanValue())).booleanValue())).booleanValue()))).booleanValue();
+        bool _tr_ObstacleDistanceBecomesClose(bool isCaching) const {
+            if (this->_tr_cache_ObstacleDistanceBecomesClose == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean(ObstaclePresent.equal((BBoolean(true))).booleanValue() && CruiseActive.equal((BBoolean(true))).booleanValue())).booleanValue() && (BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODveryclose))).booleanValue() && ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue())).booleanValue() || (BBoolean(ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue() && ObstacleRelativeSpeed.equal((RSset(RSset::RSneg))).booleanValue())).booleanValue())).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_ObstacleDistanceBecomesClose = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_ObstacleDistanceBecomesClose.get();
         }
 
-        bool _tr_ObstacleDistanceBecomesBig() const {
-            return ((BBoolean(ObstacleDistance.equal((ODset(ODset::ODclose))).booleanValue() && ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue()))).booleanValue();
+        bool _tr_ObstacleDistanceBecomesBig(bool isCaching) const {
+            if (this->_tr_cache_ObstacleDistanceBecomesBig == boost::none){
+                bool __tmp_result = ((BBoolean(ObstacleDistance.equal((ODset(ODset::ODclose))).booleanValue() && ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_ObstacleDistanceBecomesBig = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_ObstacleDistanceBecomesBig.get();
         }
 
-        bool _tr_ObstacleStartsTravelFaster() const {
-            return ((BBoolean(ObstaclePresent.equal((BBoolean(true))).booleanValue() && ObstacleRelativeSpeed.equal((RSset(RSset::RSequal))).booleanValue()))).booleanValue();
+        bool _tr_ObstacleStartsTravelFaster(bool isCaching) const {
+            if (this->_tr_cache_ObstacleStartsTravelFaster == boost::none){
+                bool __tmp_result = ((BBoolean(ObstaclePresent.equal((BBoolean(true))).booleanValue() && ObstacleRelativeSpeed.equal((RSset(RSset::RSequal))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_ObstacleStartsTravelFaster = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_ObstacleStartsTravelFaster.get();
         }
 
-        bool _tr_ObstacleStopsTravelFaster() const {
-            return (ObstacleRelativeSpeed.equal((RSset(RSset::RSpos)))).booleanValue();
+        bool _tr_ObstacleStopsTravelFaster(bool isCaching) const {
+            if (this->_tr_cache_ObstacleStopsTravelFaster == boost::none){
+                bool __tmp_result = (ObstacleRelativeSpeed.equal((RSset(RSset::RSpos)))).booleanValue();
+                if (isCaching) this->_tr_cache_ObstacleStopsTravelFaster = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_ObstacleStopsTravelFaster.get();
         }
 
-        bool _tr_ObstacleStartsTravelSlower() const {
-            return (ObstacleRelativeSpeed.equal((RSset(RSset::RSequal)))).booleanValue();
+        bool _tr_ObstacleStartsTravelSlower(bool isCaching) const {
+            if (this->_tr_cache_ObstacleStartsTravelSlower == boost::none){
+                bool __tmp_result = (ObstacleRelativeSpeed.equal((RSset(RSset::RSequal)))).booleanValue();
+                if (isCaching) this->_tr_cache_ObstacleStartsTravelSlower = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_ObstacleStartsTravelSlower.get();
         }
 
-        bool _tr_ObstacleStopsTravelSlower() const {
-            return (ObstacleRelativeSpeed.equal((RSset(RSset::RSneg)))).booleanValue();
+        bool _tr_ObstacleStopsTravelSlower(bool isCaching) const {
+            if (this->_tr_cache_ObstacleStopsTravelSlower == boost::none){
+                bool __tmp_result = (ObstacleRelativeSpeed.equal((RSset(RSset::RSneg)))).booleanValue();
+                if (isCaching) this->_tr_cache_ObstacleStopsTravelSlower = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_ObstacleStopsTravelSlower.get();
         }
 
-        BSet<BTuple<RSset, ODset >> _tr_ObstacleAppearsWhenCruiseActive() const {
-            BSet<BTuple<RSset, ODset >> _ic_set_21 = BSet<BTuple<RSset, ODset >>();
-            for(RSset _ic_ors_1 : _RSset.difference((BSet<RSset >((RSset(RSset::RSnone)))))) {
-                for(ODset _ic_od_1 : _ODset.difference((BSet<ODset >((ODset(ODset::ODnone)))))) {
-                    if(((BBoolean(ObstaclePresent.equal((BBoolean(false))).booleanValue() && CruiseActive.equal((BBoolean(true))).booleanValue()))).booleanValue()) {
-                        _ic_set_21 = _ic_set_21._union(BSet<BTuple<RSset, ODset >>((BTuple<RSset, ODset >(_ic_ors_1, _ic_od_1))));
-                    }
+        BSet<BTuple<RSset, ODset >> _tr_ObstacleAppearsWhenCruiseActive(bool isCaching) const {
+            if (this->_tr_cache_ObstacleAppearsWhenCruiseActive == boost::none){
+                BSet<BTuple<RSset, ODset >> _ic_set_21 = BSet<BTuple<RSset, ODset >>();
+                for(const RSset& _ic_ors_1 : _RSset.difference((BSet<RSset >((RSset(RSset::RSnone)))))) {
+                    for(const ODset& _ic_od_1 : _ODset.difference((BSet<ODset >((ODset(ODset::ODnone)))))) {
+                        if(((BBoolean(ObstaclePresent.equal((BBoolean(false))).booleanValue() && CruiseActive.equal((BBoolean(true))).booleanValue()))).booleanValue()) {
+                            _ic_set_21 = _ic_set_21._union(BSet<BTuple<RSset, ODset >>((BTuple<RSset, ODset >(_ic_ors_1, _ic_od_1))));
+                        }
 
+                    }
                 }
+                if (isCaching) this->_tr_cache_ObstacleAppearsWhenCruiseActive = _ic_set_21;
+                else return _ic_set_21;
             }
-            return _ic_set_21;
+            return this->_tr_cache_ObstacleAppearsWhenCruiseActive.get();
         }
 
-        BSet<RSset> _tr_ObstacleAppearsWhenCruiseInactive() const {
-            BSet<RSset> _ic_set_22 = BSet<RSset>();
-            for(RSset _ic_ors_1 : _RSset.difference((BSet<RSset >((RSset(RSset::RSnone)))))) {
-                if(((BBoolean(ObstaclePresent.equal((BBoolean(false))).booleanValue() && CruiseActive.equal((BBoolean(false))).booleanValue()))).booleanValue()) {
-                    _ic_set_22 = _ic_set_22._union(BSet<RSset>(_ic_ors_1));
-                }
+        BSet<RSset> _tr_ObstacleAppearsWhenCruiseInactive(bool isCaching) const {
+            if (this->_tr_cache_ObstacleAppearsWhenCruiseInactive == boost::none){
+                BSet<RSset> _ic_set_22 = BSet<RSset>();
+                for(const RSset& _ic_ors_1 : _RSset.difference((BSet<RSset >((RSset(RSset::RSnone)))))) {
+                    if(((BBoolean(ObstaclePresent.equal((BBoolean(false))).booleanValue() && CruiseActive.equal((BBoolean(false))).booleanValue()))).booleanValue()) {
+                        _ic_set_22 = _ic_set_22._union(BSet<RSset>(_ic_ors_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_ObstacleAppearsWhenCruiseInactive = _ic_set_22;
+                else return _ic_set_22;
             }
-            return _ic_set_22;
+            return this->_tr_cache_ObstacleAppearsWhenCruiseInactive.get();
         }
 
-        bool _tr_ObstacleDisappears() const {
-            return (ObstaclePresent.equal((BBoolean(true)))).booleanValue();
+        bool _tr_ObstacleDisappears(bool isCaching) const {
+            if (this->_tr_cache_ObstacleDisappears == boost::none){
+                bool __tmp_result = (ObstaclePresent.equal((BBoolean(true)))).booleanValue();
+                if (isCaching) this->_tr_cache_ObstacleDisappears = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_ObstacleDisappears.get();
         }
 
-        BSet<BTuple<BBoolean, BBoolean >> _tr_VehicleManageObstacle() const {
-            BSet<BTuple<BBoolean, BBoolean >> _ic_set_24 = BSet<BTuple<BBoolean, BBoolean >>();
-            for(BBoolean _ic_vtks_1 : (BOOL)) {
-                for(BBoolean _ic_vtktg_1 : (BOOL)) {
-                    if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(_ic_vtks_1.equal((BBoolean(true))).booleanValue() || _ic_vtktg_1.equal((BBoolean(true))).booleanValue())).booleanValue() || CCInitialisationInProgress.equal((BBoolean(true))).booleanValue())).booleanValue() || CruiseSpeedChangeInProgress.equal((BBoolean(true))).booleanValue())).booleanValue() && (BBoolean(!ObstaclePresent.equal((BBoolean(false))).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue() || _ic_vtks_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODclose))).booleanValue() && ObstacleRelativeSpeed.unequal((RSset(RSset::RSpos))).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODveryclose))).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue() && ObstacleDistance.unequal((ODset(ODset::ODveryclose))).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || _ic_vtks_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSequal))).booleanValue() && ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSneg))).booleanValue() && ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue() && ObstacleDistance.unequal((ODset(ODset::ODveryclose))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(true))).booleanValue()))).booleanValue()) {
-                        _ic_set_24 = _ic_set_24._union(BSet<BTuple<BBoolean, BBoolean >>((BTuple<BBoolean, BBoolean >(_ic_vtks_1, _ic_vtktg_1))));
-                    }
+        BSet<BTuple<BBoolean, BBoolean >> _tr_VehicleManageObstacle(bool isCaching) const {
+            if (this->_tr_cache_VehicleManageObstacle == boost::none){
+                BSet<BTuple<BBoolean, BBoolean >> _ic_set_24 = BSet<BTuple<BBoolean, BBoolean >>();
+                for(const BBoolean& _ic_vtks_1 : (BOOL)) {
+                    for(const BBoolean& _ic_vtktg_1 : (BOOL)) {
+                        if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(_ic_vtks_1.equal((BBoolean(true))).booleanValue() || _ic_vtktg_1.equal((BBoolean(true))).booleanValue())).booleanValue() || CCInitialisationInProgress.equal((BBoolean(true))).booleanValue())).booleanValue() || CruiseSpeedChangeInProgress.equal((BBoolean(true))).booleanValue())).booleanValue() && (BBoolean(!ObstaclePresent.equal((BBoolean(false))).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue() || _ic_vtks_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODclose))).booleanValue() && ObstacleRelativeSpeed.unequal((RSset(RSset::RSpos))).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODveryclose))).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue() && ObstacleDistance.unequal((ODset(ODset::ODveryclose))).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || _ic_vtks_1.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSequal))).booleanValue() && ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSneg))).booleanValue() && ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue() && ObstacleDistance.unequal((ODset(ODset::ODveryclose))).booleanValue())).booleanValue() || _ic_vtktg_1.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() && ObstacleStatusJustChanged.equal((BBoolean(true))).booleanValue()))).booleanValue()) {
+                            _ic_set_24 = _ic_set_24._union(BSet<BTuple<BBoolean, BBoolean >>((BTuple<BBoolean, BBoolean >(_ic_vtks_1, _ic_vtktg_1))));
+                        }
 
+                    }
                 }
+                if (isCaching) this->_tr_cache_VehicleManageObstacle = _ic_set_24;
+                else return _ic_set_24;
             }
-            return _ic_set_24;
+            return this->_tr_cache_VehicleManageObstacle.get();
         }
 
-        bool _tr_ObstacleBecomesOld() const {
-            return ((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(ObstacleStatusJustChanged.equal((BBoolean(true))).booleanValue() && (BBoolean((BBoolean((BBoolean(VehicleTryKeepSpeed.equal((BBoolean(true))).booleanValue() || VehicleTryKeepTimeGap.equal((BBoolean(true))).booleanValue())).booleanValue() || CCInitialisationInProgress.equal((BBoolean(true))).booleanValue())).booleanValue() || CruiseSpeedChangeInProgress.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue() || VehicleTryKeepSpeed.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODclose))).booleanValue() && ObstacleRelativeSpeed.unequal((RSset(RSset::RSpos))).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || VehicleTryKeepTimeGap.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODveryclose))).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || VehicleTryKeepTimeGap.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue() && ObstacleDistance.unequal((ODset(ODset::ODveryclose))).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || VehicleTryKeepSpeed.equal((BBoolean(true))).booleanValue())).booleanValue()))).booleanValue();
+        bool _tr_ObstacleBecomesOld(bool isCaching) const {
+            if (this->_tr_cache_ObstacleBecomesOld == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(ObstacleStatusJustChanged.equal((BBoolean(true))).booleanValue() && (BBoolean((BBoolean((BBoolean(VehicleTryKeepSpeed.equal((BBoolean(true))).booleanValue() || VehicleTryKeepTimeGap.equal((BBoolean(true))).booleanValue())).booleanValue() || CCInitialisationInProgress.equal((BBoolean(true))).booleanValue())).booleanValue() || CruiseSpeedChangeInProgress.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!ObstacleDistance.equal((ODset(ODset::ODnone))).booleanValue() || VehicleTryKeepSpeed.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODclose))).booleanValue() && ObstacleRelativeSpeed.unequal((RSset(RSset::RSpos))).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || VehicleTryKeepTimeGap.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean(ObstacleDistance.equal((ODset(ODset::ODveryclose))).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || VehicleTryKeepTimeGap.equal((BBoolean(true))).booleanValue())).booleanValue())).booleanValue() && (BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue() && ObstacleDistance.unequal((ODset(ODset::ODveryclose))).booleanValue())).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() || VehicleTryKeepSpeed.equal((BBoolean(true))).booleanValue())).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_ObstacleBecomesOld = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_ObstacleBecomesOld.get();
         }
 
         bool _check_inv_1() const {
@@ -813,8 +966,49 @@ class Cruise_finite1_deterministic_MC {
             return ((BBoolean(!(BBoolean((BBoolean((BBoolean(ObstacleRelativeSpeed.equal((RSset(RSset::RSpos))).booleanValue() && ObstacleDistance.unequal((ODset(ODset::ODveryclose))).booleanValue())).booleanValue() && CruiseActive.equal((BBoolean(true))).booleanValue())).booleanValue() && (BBoolean((BBoolean(ObstacleStatusJustChanged.equal((BBoolean(false))).booleanValue() && CCInitialisationInProgress.equal((BBoolean(false))).booleanValue())).booleanValue() && CruiseSpeedChangeInProgress.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() || VehicleTryKeepSpeed.equal((BBoolean(true))).booleanValue()))).booleanValue();
         }
 
-        Cruise_finite1_deterministic_MC _copy() const {
-            return Cruise_finite1_deterministic_MC(CruiseAllowed, CruiseActive, VehicleAtCruiseSpeed, VehicleCanKeepSpeed, VehicleTryKeepSpeed, SpeedAboveMax, VehicleTryKeepTimeGap, CruiseSpeedAtMax, ObstaclePresent, ObstacleDistance, ObstacleRelativeSpeed, ObstacleStatusJustChanged, CCInitialisationInProgress, CruiseSpeedChangeInProgress, NumberOfSetCruise);
+        static constexpr unsigned int strHash(const char *s, int off = 0) {
+            return !s[off] ? 5381 : (strHash(s, off+1)*33) ^ s[off];
+        }
+
+        Cruise_finite1_deterministic_MC _copy(unordered_set<string> toInvalidate) const {
+            static const char* allTransitions[] = {"_tr_CruiseBecomesNotAllowed", "_tr_CruiseBecomesAllowed", "_tr_SetCruiseSpeed", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_CruiseOff", "_tr_ExternalForcesBecomesExtreme", "_tr_ExternalForcesBecomesNormal", "_tr_VehicleLeavesCruiseSpeed", "_tr_VehicleReachesCruiseSpeed", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_VehicleFallsBelowMaxCruiseSpeed", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_ObstacleDistanceBecomesClose", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleStartsTravelFaster", "_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStopsTravelSlower", "_tr_ObstacleAppearsWhenCruiseActive", "_tr_ObstacleAppearsWhenCruiseInactive", "_tr_ObstacleDisappears", "_tr_VehicleManageObstacle", "_tr_ObstacleBecomesOld"};
+
+            Cruise_finite1_deterministic_MC result = Cruise_finite1_deterministic_MC(CruiseAllowed, CruiseActive, VehicleAtCruiseSpeed, VehicleCanKeepSpeed, VehicleTryKeepSpeed, SpeedAboveMax, VehicleTryKeepTimeGap, CruiseSpeedAtMax, ObstaclePresent, ObstacleDistance, ObstacleRelativeSpeed, ObstacleStatusJustChanged, CCInitialisationInProgress, CruiseSpeedChangeInProgress, NumberOfSetCruise);
+
+            for (const auto &item : allTransitions) {
+                if(toInvalidate.find(item) == toInvalidate.end()) {
+                    switch(strHash(item)) {
+                        case strHash("_tr_CruiseBecomesNotAllowed"): result._tr_cache_CruiseBecomesNotAllowed = this->_tr_cache_CruiseBecomesNotAllowed; break;
+                        case strHash("_tr_CruiseBecomesAllowed"): result._tr_cache_CruiseBecomesAllowed = this->_tr_cache_CruiseBecomesAllowed; break;
+                        case strHash("_tr_SetCruiseSpeed"): result._tr_cache_SetCruiseSpeed = this->_tr_cache_SetCruiseSpeed; break;
+                        case strHash("_tr_CCInitialisationFinished"): result._tr_cache_CCInitialisationFinished = this->_tr_cache_CCInitialisationFinished; break;
+                        case strHash("_tr_CCInitialisationDelayFinished"): result._tr_cache_CCInitialisationDelayFinished = this->_tr_cache_CCInitialisationDelayFinished; break;
+                        case strHash("_tr_CruiseSpeedChangeFinished"): result._tr_cache_CruiseSpeedChangeFinished = this->_tr_cache_CruiseSpeedChangeFinished; break;
+                        case strHash("_tr_CruiseSpeedChangeDelayFinished"): result._tr_cache_CruiseSpeedChangeDelayFinished = this->_tr_cache_CruiseSpeedChangeDelayFinished; break;
+                        case strHash("_tr_CruiseOff"): result._tr_cache_CruiseOff = this->_tr_cache_CruiseOff; break;
+                        case strHash("_tr_ExternalForcesBecomesExtreme"): result._tr_cache_ExternalForcesBecomesExtreme = this->_tr_cache_ExternalForcesBecomesExtreme; break;
+                        case strHash("_tr_ExternalForcesBecomesNormal"): result._tr_cache_ExternalForcesBecomesNormal = this->_tr_cache_ExternalForcesBecomesNormal; break;
+                        case strHash("_tr_VehicleLeavesCruiseSpeed"): result._tr_cache_VehicleLeavesCruiseSpeed = this->_tr_cache_VehicleLeavesCruiseSpeed; break;
+                        case strHash("_tr_VehicleReachesCruiseSpeed"): result._tr_cache_VehicleReachesCruiseSpeed = this->_tr_cache_VehicleReachesCruiseSpeed; break;
+                        case strHash("_tr_VehicleExceedsMaxCruiseSpeed"): result._tr_cache_VehicleExceedsMaxCruiseSpeed = this->_tr_cache_VehicleExceedsMaxCruiseSpeed; break;
+                        case strHash("_tr_VehicleFallsBelowMaxCruiseSpeed"): result._tr_cache_VehicleFallsBelowMaxCruiseSpeed = this->_tr_cache_VehicleFallsBelowMaxCruiseSpeed; break;
+                        case strHash("_tr_ObstacleDistanceBecomesVeryClose"): result._tr_cache_ObstacleDistanceBecomesVeryClose = this->_tr_cache_ObstacleDistanceBecomesVeryClose; break;
+                        case strHash("_tr_ObstacleDistanceBecomesClose"): result._tr_cache_ObstacleDistanceBecomesClose = this->_tr_cache_ObstacleDistanceBecomesClose; break;
+                        case strHash("_tr_ObstacleDistanceBecomesBig"): result._tr_cache_ObstacleDistanceBecomesBig = this->_tr_cache_ObstacleDistanceBecomesBig; break;
+                        case strHash("_tr_ObstacleStartsTravelFaster"): result._tr_cache_ObstacleStartsTravelFaster = this->_tr_cache_ObstacleStartsTravelFaster; break;
+                        case strHash("_tr_ObstacleStopsTravelFaster"): result._tr_cache_ObstacleStopsTravelFaster = this->_tr_cache_ObstacleStopsTravelFaster; break;
+                        case strHash("_tr_ObstacleStartsTravelSlower"): result._tr_cache_ObstacleStartsTravelSlower = this->_tr_cache_ObstacleStartsTravelSlower; break;
+                        case strHash("_tr_ObstacleStopsTravelSlower"): result._tr_cache_ObstacleStopsTravelSlower = this->_tr_cache_ObstacleStopsTravelSlower; break;
+                        case strHash("_tr_ObstacleAppearsWhenCruiseActive"): result._tr_cache_ObstacleAppearsWhenCruiseActive = this->_tr_cache_ObstacleAppearsWhenCruiseActive; break;
+                        case strHash("_tr_ObstacleAppearsWhenCruiseInactive"): result._tr_cache_ObstacleAppearsWhenCruiseInactive = this->_tr_cache_ObstacleAppearsWhenCruiseInactive; break;
+                        case strHash("_tr_ObstacleDisappears"): result._tr_cache_ObstacleDisappears = this->_tr_cache_ObstacleDisappears; break;
+                        case strHash("_tr_VehicleManageObstacle"): result._tr_cache_VehicleManageObstacle = this->_tr_cache_VehicleManageObstacle; break;
+                        case strHash("_tr_ObstacleBecomesOld"): result._tr_cache_ObstacleBecomesOld = this->_tr_cache_ObstacleBecomesOld; break;
+                        default: cout << "Transition " << item << " not found!";
+                    }
+                }
+            }
+            return result;
         }
 
         friend bool operator ==(const Cruise_finite1_deterministic_MC& o1, const Cruise_finite1_deterministic_MC& o2) {
@@ -892,1850 +1086,685 @@ class Cruise_finite1_deterministic_MC {
 };
 
 
-static std::unordered_set<Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> generateNextStates(std::mutex& guardMutex, const Cruise_finite1_deterministic_MC& state, bool isCaching, std::unordered_map<string, std::unordered_set<string>>& invariantDependency, std::unordered_map<Cruise_finite1_deterministic_MC, std::unordered_set<string>, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual>& dependentInvariant, std::unordered_map<string, std::unordered_set<string>>& guardDependency, std::unordered_map<Cruise_finite1_deterministic_MC, std::unordered_set<string>, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual>& dependentGuard, std::unordered_map<Cruise_finite1_deterministic_MC, immer::map<string, boost::any>, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual>& guardCache, std::unordered_map<Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual>& parents, std::unordered_map<Cruise_finite1_deterministic_MC, string, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual>& stateAccessedVia, std::atomic<int>& transitions) {
-    std::unordered_set<Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> result = std::unordered_set<Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual>();
-    if(isCaching) {
-        immer::map<string, boost::any> parentsGuard;
-        std::unordered_set<string> dependentGuardsOfState;
-        bool parentsExist = false;
-        bool dependentGuardsExist = false;
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            parentsExist = (parents.find(state) != parents.end());
-            dependentGuardsExist = (dependentGuard.find(state) != dependentGuard.end());
-            if(parentsExist) {
-                parentsGuard = guardCache[parents[state]];
-            }
-            if(dependentGuardsExist) {
-                dependentGuardsOfState = dependentGuard[state];
-            }
-        }
-        immer::map<string, boost::any> newCache = parentsGuard;
-        boost::any cachedValue;
-        bool dependentGuardsBoolean = true;
-        bool _trid_1;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_CruiseBecomesNotAllowed"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_CruiseBecomesNotAllowed") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_1 = state._tr_CruiseBecomesNotAllowed();
-        } else {
-            _trid_1 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_CruiseBecomesNotAllowed", _trid_1);
-        if(_trid_1) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.CruiseBecomesNotAllowed();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["CruiseBecomesNotAllowed"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["CruiseBecomesNotAllowed"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "CruiseBecomesNotAllowed"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_2;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_CruiseBecomesAllowed"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_CruiseBecomesAllowed") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_2 = state._tr_CruiseBecomesAllowed();
-        } else {
-            _trid_2 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_CruiseBecomesAllowed", _trid_2);
-        if(_trid_2) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.CruiseBecomesAllowed();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["CruiseBecomesAllowed"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["CruiseBecomesAllowed"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "CruiseBecomesAllowed"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BBoolean, BBoolean >> _trid_3;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_SetCruiseSpeed"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_SetCruiseSpeed") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_3 = state._tr_SetCruiseSpeed();
-        } else {
-            _trid_3 = boost::any_cast<BSet<BTuple<BBoolean, BBoolean >>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_SetCruiseSpeed", _trid_3);
-        for(const BTuple<BBoolean, BBoolean >& param : _trid_3) {
-            BBoolean _tmp_1 = param.projection2();
-            BBoolean _tmp_2 = param.projection1();
-
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.SetCruiseSpeed(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["SetCruiseSpeed"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["SetCruiseSpeed"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "SetCruiseSpeed"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BBoolean, BBoolean >> _trid_4;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_CCInitialisationFinished"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_CCInitialisationFinished") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_4 = state._tr_CCInitialisationFinished();
-        } else {
-            _trid_4 = boost::any_cast<BSet<BTuple<BBoolean, BBoolean >>>(cachedValue);
+class ModelChecker {
+    private:
+        Cruise_finite1_deterministic_MC::Type type;
+        int threads;
+        bool isCaching;
+        bool isDebug;
+
+        std::list<Cruise_finite1_deterministic_MC> unvisitedStates;
+        std::unordered_set<Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> states;
+        std::atomic<int> transitions;
+        std::mutex mutex;
+        std::mutex waitMutex;
+        std::mutex guardMutex;
+        std::condition_variable waitCV;
+
+        std::atomic<bool> invariantViolatedBool;
+        std::atomic<bool> deadlockDetected;
+        Cruise_finite1_deterministic_MC counterExampleState;
+
+        std::unordered_map<string, std::unordered_set<string>> invariantDependency;
+        std::unordered_map<string, std::unordered_set<string>> guardDependency;
+        std::unordered_map<Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> parents;
+
+    public:
+        ModelChecker() {}
+
+        ModelChecker(Cruise_finite1_deterministic_MC::Type type, int threads, bool isCaching, bool isDebug) {
+            this->type = type;
+            this->threads = threads;
+            this->isCaching = isCaching;
+            this->isDebug = isDebug;
+            this->invariantViolatedBool = false;
+            this->deadlockDetected = false;
+            this->transitions = 0;
         }
-        newCache = newCache.set("_tr_CCInitialisationFinished", _trid_4);
-        for(const BTuple<BBoolean, BBoolean >& param : _trid_4) {
-            BBoolean _tmp_1 = param.projection2();
-            BBoolean _tmp_2 = param.projection1();
 
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.CCInitialisationFinished(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["CCInitialisationFinished"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["CCInitialisationFinished"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "CCInitialisationFinished"});
-                }
+        void modelCheck() {
+            if (isDebug) {
+                cout << "Starting Modelchecking, STRATEGY=" << type << ", THREADS=" << threads << ", CACHING=" << isCaching << "\n";
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_5;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_CCInitialisationDelayFinished"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_CCInitialisationDelayFinished") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_5 = state._tr_CCInitialisationDelayFinished();
-        } else {
-            _trid_5 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_CCInitialisationDelayFinished", _trid_5);
-        if(_trid_5) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.CCInitialisationDelayFinished();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["CCInitialisationDelayFinished"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["CCInitialisationDelayFinished"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "CCInitialisationDelayFinished"});
-                }
+
+            if (threads <= 1) {
+                modelCheckSingleThreaded();
+            } else {
+                boost::asio::thread_pool workers(threads); // threads indicates the number of workers (without the coordinator)
+                modelCheckMultiThreaded(workers);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BBoolean, BBoolean >> _trid_6;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_CruiseSpeedChangeFinished"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_CruiseSpeedChangeFinished") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_6 = state._tr_CruiseSpeedChangeFinished();
-        } else {
-            _trid_6 = boost::any_cast<BSet<BTuple<BBoolean, BBoolean >>>(cachedValue);
         }
-        newCache = newCache.set("_tr_CruiseSpeedChangeFinished", _trid_6);
-        for(const BTuple<BBoolean, BBoolean >& param : _trid_6) {
-            BBoolean _tmp_1 = param.projection2();
-            BBoolean _tmp_2 = param.projection1();
 
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.CruiseSpeedChangeFinished(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["CruiseSpeedChangeFinished"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["CruiseSpeedChangeFinished"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "CruiseSpeedChangeFinished"});
-                }
+        void modelCheckSingleThreaded() {
+            Cruise_finite1_deterministic_MC machine = Cruise_finite1_deterministic_MC();
+            states.insert(machine);
+            unvisitedStates.push_back(machine);
+
+            if (isCaching) {
+                initCache(machine);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_7;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_CruiseSpeedChangeDelayFinished"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_CruiseSpeedChangeDelayFinished") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_7 = state._tr_CruiseSpeedChangeDelayFinished();
-        } else {
-            _trid_7 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_CruiseSpeedChangeDelayFinished", _trid_7);
-        if(_trid_7) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.CruiseSpeedChangeDelayFinished();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["CruiseSpeedChangeDelayFinished"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["CruiseSpeedChangeDelayFinished"]});
+
+            while(!unvisitedStates.empty()) {
+                Cruise_finite1_deterministic_MC state = next();
+
+                std::unordered_set<Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> nextStates = generateNextStates(state);
+                transitions += nextStates.size();
+
+                for(auto& nextState : nextStates) {
+                    if(states.find(nextState) == states.end()) {
+                        states.insert(nextState);
+                        parents.insert({nextState, state});
+                        unvisitedStates.push_back(nextState);
+                        if(states.size() % 50000 == 0) {
+                            cout << "VISITED STATES: " << states.size() << "\n";
+                            cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
+                            cout << "-------------------" << "\n";
+                        }
+                    }
                 }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+
+                if(invariantViolated(state)) {
+                    invariantViolatedBool = true;
+                    counterExampleState = state;
+                    break;
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "CruiseSpeedChangeDelayFinished"});
+
+                if(nextStates.empty()) {
+                    deadlockDetected = true;
+                    counterExampleState = state;
+                    break;
                 }
+
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_8;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_CruiseOff"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_CruiseOff") != dependentGuardsOfState.end());
+            printResult();
         }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_8 = state._tr_CruiseOff();
-        } else {
-            _trid_8 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_CruiseOff", _trid_8);
-        if(_trid_8) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.CruiseOff();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["CruiseOff"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["CruiseOff"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "CruiseOff"});
-                }
+
+        void modelCheckMultiThreaded(boost::asio::thread_pool& workers) {
+            Cruise_finite1_deterministic_MC machine = Cruise_finite1_deterministic_MC();
+            states.insert(machine);
+            unvisitedStates.push_back(machine);
+
+            std::atomic<bool> stopThreads;
+            stopThreads = false;
+            std::atomic<int> possibleQueueChanges;
+            possibleQueueChanges = 0;
+
+            if(isCaching) {
+                initCache(machine);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_9;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_ExternalForcesBecomesExtreme"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_ExternalForcesBecomesExtreme") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_9 = state._tr_ExternalForcesBecomesExtreme();
-        } else {
-            _trid_9 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_ExternalForcesBecomesExtreme", _trid_9);
-        if(_trid_9) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ExternalForcesBecomesExtreme();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["ExternalForcesBecomesExtreme"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["ExternalForcesBecomesExtreme"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ExternalForcesBecomesExtreme"});
+
+            std::atomic<bool> waitFlag;
+            waitFlag = true;
+
+            while(!unvisitedStates.empty() && !stopThreads) {
+                possibleQueueChanges += 1;
+                Cruise_finite1_deterministic_MC state = next();
+                std::packaged_task<void()> task([&, state] {
+                    std::unordered_set<Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> nextStates = generateNextStates(state);
+                    transitions += nextStates.size();
+
+                    for(auto& nextState : nextStates) {
+                        {
+                            std::unique_lock<std::mutex> lock(mutex);
+                            if(states.find(nextState) == states.end()) {
+                                states.insert(nextState);
+                                parents.insert({nextState, state});
+                                unvisitedStates.push_back(nextState); // TODO: sync ?
+                                if(isDebug && states.size() % 50000 == 0) {
+                                    cout << "VISITED STATES: " << states.size() << "\n";
+                                    cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
+                                    cout << "-------------------" << "\n";
+                                }
+                            }
+                        }
+                    }
+
+                    {
+                        std::unique_lock<std::mutex> lock(mutex);
+                        possibleQueueChanges -= 1;
+                        int running = possibleQueueChanges;
+                        if (!unvisitedStates.empty() || running == 0) {
+                            {
+                                std::unique_lock<std::mutex> lock(waitMutex);
+                                waitFlag = false;
+                                waitCV.notify_one();
+                            }
+                        }
+                    }
+
+                    if(invariantViolated(state)) {
+                        invariantViolatedBool = true;
+                        counterExampleState = state;
+                        stopThreads = true;
+                    }
+
+                    if(nextStates.empty()) {
+                        deadlockDetected = true;
+                        counterExampleState = state;
+                        stopThreads = true;
+                    }
+
+                });
+
+                waitFlag = true;
+                boost::asio::post(workers, std::move(task));
+
+                {
+                    std::unique_lock<std::mutex> lock(waitMutex);
+                    while (unvisitedStates.empty() && possibleQueueChanges > 0) {
+                        waitCV.wait(lock, [&] {
+                            return waitFlag == false;
+                        });
+                    }
                 }
             }
-            result.insert(copiedState);
-            transitions += 1;
+            workers.join();
+            printResult();
+        }
+
+        void initCache(Cruise_finite1_deterministic_MC& machine) {
+            invariantDependency.insert({"ObstacleStopsTravelSlower", {"_check_inv_29", "_check_inv_39", "_check_inv_38", "_check_inv_37", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_13", "_check_inv_35", "_check_inv_24"}});
+            invariantDependency.insert({"SetCruiseSpeed", {"_check_inv_18", "_check_inv_17", "_check_inv_39", "_check_inv_16", "_check_inv_38", "_check_inv_15", "_check_inv_37", "_check_inv_19", "_check_inv_10", "_check_inv_14", "_check_inv_36", "_check_inv_35", "_check_inv_34", "_check_inv_33", "_check_inv_26", "_check_inv_21", "_check_inv_20", "_check_inv_4", "_check_inv_25", "_check_inv_24", "_check_inv_8", "_check_inv_23", "_check_inv_9", "_check_inv_22", "_check_inv_2", "_check_inv_3"}});
+            invariantDependency.insert({"VehicleLeavesCruiseSpeed", {"_check_inv_17", "_check_inv_3", "_check_inv_34"}});
+            invariantDependency.insert({"VehicleFallsBelowMaxCruiseSpeed", {"_check_inv_17", "_check_inv_3", "_check_inv_6", "_check_inv_34"}});
+            invariantDependency.insert({"CCInitialisationFinished", {"_check_inv_39", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_19", "_check_inv_32", "_check_inv_21", "_check_inv_31", "_check_inv_7", "_check_inv_30", "_check_inv_5", "_check_inv_36", "_check_inv_35"}});
+            invariantDependency.insert({"VehicleReachesCruiseSpeed", {"_check_inv_17", "_check_inv_3", "_check_inv_34"}});
+            invariantDependency.insert({"ObstacleAppearsWhenCruiseActive", {"_check_inv_29", "_check_inv_39", "_check_inv_28", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_13", "_check_inv_35", "_check_inv_24", "_check_inv_12", "_check_inv_23", "_check_inv_11"}});
+            invariantDependency.insert({"ObstacleStartsTravelSlower", {"_check_inv_29", "_check_inv_39", "_check_inv_38", "_check_inv_37", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_13", "_check_inv_35", "_check_inv_24"}});
+            invariantDependency.insert({"CruiseBecomesNotAllowed", {"_check_inv_18", "_check_inv_17", "_check_inv_39", "_check_inv_16", "_check_inv_38", "_check_inv_15", "_check_inv_37", "_check_inv_19", "_check_inv_10", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_35", "_check_inv_12", "_check_inv_34", "_check_inv_33", "_check_inv_28", "_check_inv_27", "_check_inv_26", "_check_inv_21", "_check_inv_7", "_check_inv_20", "_check_inv_4", "_check_inv_5", "_check_inv_25", "_check_inv_24", "_check_inv_8", "_check_inv_23", "_check_inv_9", "_check_inv_22", "_check_inv_2", "_check_inv_3", "_check_inv_1"}});
+            invariantDependency.insert({"ObstacleAppearsWhenCruiseInactive", {"_check_inv_29", "_check_inv_39", "_check_inv_28", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_36", "_check_inv_13", "_check_inv_12", "_check_inv_23", "_check_inv_11"}});
+            invariantDependency.insert({"CCInitialisationDelayFinished", {"_check_inv_39", "_check_inv_38", "_check_inv_15", "_check_inv_37", "_check_inv_36", "_check_inv_25", "_check_inv_35"}});
+            invariantDependency.insert({"ObstacleDistanceBecomesClose", {"_check_inv_39", "_check_inv_28", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_32", "_check_inv_21", "_check_inv_31", "_check_inv_7", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_35", "_check_inv_24", "_check_inv_12", "_check_inv_23"}});
+            invariantDependency.insert({"ObstacleStartsTravelFaster", {"_check_inv_29", "_check_inv_39", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_32", "_check_inv_21", "_check_inv_31", "_check_inv_7", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_13", "_check_inv_35", "_check_inv_24"}});
+            invariantDependency.insert({"ExternalForcesBecomesExtreme", {"_check_inv_18", "_check_inv_4"}});
+            invariantDependency.insert({"CruiseOff", {"_check_inv_18", "_check_inv_17", "_check_inv_39", "_check_inv_16", "_check_inv_38", "_check_inv_15", "_check_inv_37", "_check_inv_19", "_check_inv_10", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_35", "_check_inv_12", "_check_inv_34", "_check_inv_33", "_check_inv_28", "_check_inv_27", "_check_inv_26", "_check_inv_21", "_check_inv_7", "_check_inv_20", "_check_inv_4", "_check_inv_5", "_check_inv_25", "_check_inv_24", "_check_inv_8", "_check_inv_23", "_check_inv_9", "_check_inv_22", "_check_inv_2", "_check_inv_3"}});
+            invariantDependency.insert({"CruiseSpeedChangeDelayFinished", {"_check_inv_39", "_check_inv_16", "_check_inv_38", "_check_inv_37", "_check_inv_26", "_check_inv_36", "_check_inv_35"}});
+            invariantDependency.insert({"ObstacleStopsTravelFaster", {"_check_inv_29", "_check_inv_39", "_check_inv_38", "_check_inv_37", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_13", "_check_inv_35", "_check_inv_24"}});
+            invariantDependency.insert({"ObstacleDistanceBecomesVeryClose", {"_check_inv_39", "_check_inv_28", "_check_inv_38", "_check_inv_37", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_35", "_check_inv_24", "_check_inv_12", "_check_inv_23"}});
+            invariantDependency.insert({"VehicleManageObstacle", {"_check_inv_39", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_19", "_check_inv_32", "_check_inv_21", "_check_inv_31", "_check_inv_7", "_check_inv_30", "_check_inv_5", "_check_inv_36", "_check_inv_35"}});
+            invariantDependency.insert({"CruiseBecomesAllowed", {"_check_inv_1", "_check_inv_33"}});
+            invariantDependency.insert({"VehicleExceedsMaxCruiseSpeed", {"_check_inv_17", "_check_inv_3", "_check_inv_6", "_check_inv_34"}});
+            invariantDependency.insert({"CruiseSpeedChangeFinished", {"_check_inv_39", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_19", "_check_inv_32", "_check_inv_21", "_check_inv_31", "_check_inv_7", "_check_inv_30", "_check_inv_5", "_check_inv_36", "_check_inv_35"}});
+            invariantDependency.insert({"ObstacleDisappears", {"_check_inv_29", "_check_inv_39", "_check_inv_28", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_32", "_check_inv_21", "_check_inv_31", "_check_inv_7", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_13", "_check_inv_35", "_check_inv_24", "_check_inv_12", "_check_inv_23", "_check_inv_11"}});
+            invariantDependency.insert({"ExternalForcesBecomesNormal", {"_check_inv_18", "_check_inv_4"}});
+            invariantDependency.insert({"ObstacleBecomesOld", {"_check_inv_39", "_check_inv_38", "_check_inv_37", "_check_inv_14", "_check_inv_36", "_check_inv_35", "_check_inv_24"}});
+            invariantDependency.insert({"ObstacleDistanceBecomesBig", {"_check_inv_39", "_check_inv_28", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_32", "_check_inv_21", "_check_inv_31", "_check_inv_7", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_35", "_check_inv_24", "_check_inv_12", "_check_inv_23"}});
+            invariantDependency.insert({"", {}});
+            guardDependency.insert({"ObstacleStopsTravelSlower", {"_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStopsTravelSlower", "_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseSpeedChangeFinished", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStartsTravelFaster", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose"}});
+            guardDependency.insert({"SetCruiseSpeed", {"_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesClose", "_tr_ExternalForcesBecomesNormal", "_tr_CruiseSpeedChangeFinished", "_tr_ExternalForcesBecomesExtreme", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_VehicleLeavesCruiseSpeed", "_tr_ObstacleAppearsWhenCruiseActive", "_tr_VehicleReachesCruiseSpeed", "_tr_CruiseOff", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleAppearsWhenCruiseInactive"}});
+            guardDependency.insert({"VehicleLeavesCruiseSpeed", {"_tr_VehicleReachesCruiseSpeed", "_tr_VehicleLeavesCruiseSpeed"}});
+            guardDependency.insert({"VehicleFallsBelowMaxCruiseSpeed", {"_tr_VehicleReachesCruiseSpeed", "_tr_VehicleFallsBelowMaxCruiseSpeed", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_VehicleLeavesCruiseSpeed"}});
+            guardDependency.insert({"CCInitialisationFinished", {"_tr_ObstacleBecomesOld", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_VehicleLeavesCruiseSpeed"}});
+            guardDependency.insert({"VehicleReachesCruiseSpeed", {"_tr_VehicleReachesCruiseSpeed", "_tr_VehicleLeavesCruiseSpeed"}});
+            guardDependency.insert({"ObstacleAppearsWhenCruiseActive", {"_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStopsTravelSlower", "_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleDisappears", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStartsTravelFaster", "_tr_ObstacleAppearsWhenCruiseActive", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_ObstacleAppearsWhenCruiseInactive"}});
+            guardDependency.insert({"ObstacleStartsTravelSlower", {"_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStopsTravelSlower", "_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseSpeedChangeFinished", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStartsTravelFaster", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose"}});
+            guardDependency.insert({"CruiseBecomesNotAllowed", {"_tr_SetCruiseSpeed", "_tr_VehicleManageObstacle", "_tr_CruiseBecomesAllowed", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseBecomesNotAllowed", "_tr_ExternalForcesBecomesNormal", "_tr_CruiseSpeedChangeFinished", "_tr_ExternalForcesBecomesExtreme", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_VehicleLeavesCruiseSpeed", "_tr_ObstacleAppearsWhenCruiseActive", "_tr_VehicleReachesCruiseSpeed", "_tr_CruiseOff", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_ObstacleAppearsWhenCruiseInactive"}});
+            guardDependency.insert({"ObstacleAppearsWhenCruiseInactive", {"_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStopsTravelSlower", "_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleDisappears", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStartsTravelFaster", "_tr_ObstacleAppearsWhenCruiseActive", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_ObstacleAppearsWhenCruiseInactive"}});
+            guardDependency.insert({"CCInitialisationDelayFinished", {"_tr_VehicleManageObstacle", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleBecomesOld", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished"}});
+            guardDependency.insert({"ObstacleDistanceBecomesClose", {"_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished"}});
+            guardDependency.insert({"ObstacleStartsTravelFaster", {"_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStopsTravelSlower", "_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseSpeedChangeFinished", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStartsTravelFaster", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose"}});
+            guardDependency.insert({"ExternalForcesBecomesExtreme", {"_tr_ExternalForcesBecomesNormal", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ExternalForcesBecomesExtreme", "_tr_VehicleLeavesCruiseSpeed"}});
+            guardDependency.insert({"CruiseOff", {"_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_ExternalForcesBecomesNormal", "_tr_CruiseSpeedChangeFinished", "_tr_ExternalForcesBecomesExtreme", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_VehicleLeavesCruiseSpeed", "_tr_ObstacleAppearsWhenCruiseActive", "_tr_VehicleReachesCruiseSpeed", "_tr_CruiseOff", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_ObstacleAppearsWhenCruiseInactive"}});
+            guardDependency.insert({"CruiseSpeedChangeDelayFinished", {"_tr_VehicleManageObstacle", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleBecomesOld", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished"}});
+            guardDependency.insert({"ObstacleStopsTravelFaster", {"_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStopsTravelSlower", "_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseSpeedChangeFinished", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStartsTravelFaster", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose"}});
+            guardDependency.insert({"ObstacleDistanceBecomesVeryClose", {"_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished"}});
+            guardDependency.insert({"VehicleManageObstacle", {"_tr_ObstacleBecomesOld", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_VehicleLeavesCruiseSpeed"}});
+            guardDependency.insert({"CruiseBecomesAllowed", {"_tr_SetCruiseSpeed", "_tr_CruiseBecomesAllowed", "_tr_CruiseBecomesNotAllowed"}});
+            guardDependency.insert({"VehicleExceedsMaxCruiseSpeed", {"_tr_VehicleReachesCruiseSpeed", "_tr_VehicleFallsBelowMaxCruiseSpeed", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_VehicleLeavesCruiseSpeed"}});
+            guardDependency.insert({"CruiseSpeedChangeFinished", {"_tr_ObstacleBecomesOld", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_VehicleLeavesCruiseSpeed"}});
+            guardDependency.insert({"ObstacleDisappears", {"_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStopsTravelSlower", "_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleDisappears", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStartsTravelFaster", "_tr_ObstacleAppearsWhenCruiseActive", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_ObstacleAppearsWhenCruiseInactive"}});
+            guardDependency.insert({"ExternalForcesBecomesNormal", {"_tr_ExternalForcesBecomesNormal", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ExternalForcesBecomesExtreme", "_tr_VehicleLeavesCruiseSpeed"}});
+            guardDependency.insert({"ObstacleBecomesOld", {"_tr_VehicleManageObstacle", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleBecomesOld", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished"}});
+            guardDependency.insert({"ObstacleDistanceBecomesBig", {"_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished"}});
         }
-        bool _trid_10;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_ExternalForcesBecomesNormal"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_ExternalForcesBecomesNormal") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_10 = state._tr_ExternalForcesBecomesNormal();
-        } else {
-            _trid_10 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_ExternalForcesBecomesNormal", _trid_10);
-        if(_trid_10) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ExternalForcesBecomesNormal();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["ExternalForcesBecomesNormal"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["ExternalForcesBecomesNormal"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ExternalForcesBecomesNormal"});
+
+
+    private:
+        Cruise_finite1_deterministic_MC next() {
+            std::unique_lock<std::mutex> lock(mutex);
+            switch(type) {
+                case Cruise_finite1_deterministic_MC::BFS: {
+                    Cruise_finite1_deterministic_MC state = unvisitedStates.front();
+                    unvisitedStates.pop_front();
+                    return state;
+                }
+                case Cruise_finite1_deterministic_MC::DFS: {
+                    Cruise_finite1_deterministic_MC state = unvisitedStates.back();
+                    unvisitedStates.pop_back();
+                    return state;
+                }
+                case Cruise_finite1_deterministic_MC::MIXED: {
+                    if(unvisitedStates.size() % 2 == 0) {
+                        Cruise_finite1_deterministic_MC state = unvisitedStates.front();
+                        unvisitedStates.pop_front();
+                        return state;
+                    } else {
+                        Cruise_finite1_deterministic_MC state = unvisitedStates.back();
+                        unvisitedStates.pop_back();
+                        return state;
+                    }
                 }
             }
-            result.insert(copiedState);
-            transitions += 1;
         }
-        bool _trid_11;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_VehicleLeavesCruiseSpeed"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_VehicleLeavesCruiseSpeed") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_11 = state._tr_VehicleLeavesCruiseSpeed();
-        } else {
-            _trid_11 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_VehicleLeavesCruiseSpeed", _trid_11);
-        if(_trid_11) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.VehicleLeavesCruiseSpeed();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["VehicleLeavesCruiseSpeed"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["VehicleLeavesCruiseSpeed"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "VehicleLeavesCruiseSpeed"});
-                }
+
+        std::unordered_set<Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> generateNextStates(const Cruise_finite1_deterministic_MC& state) {
+            std::unordered_set<Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> result = std::unordered_set<Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual>();
+            if(state._tr_CruiseBecomesNotAllowed(isCaching)) {
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["CruiseBecomesNotAllowed"]);
+                copiedState.CruiseBecomesNotAllowed();
+                copiedState.stateAccessedVia = "CruiseBecomesNotAllowed";
+                result.insert(copiedState);
+            }
+            if(state._tr_CruiseBecomesAllowed(isCaching)) {
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["CruiseBecomesAllowed"]);
+                copiedState.CruiseBecomesAllowed();
+                copiedState.stateAccessedVia = "CruiseBecomesAllowed";
+                result.insert(copiedState);
+            }
+            BSet<BTuple<BBoolean, BBoolean >> _trid_3 = state._tr_SetCruiseSpeed(isCaching);
+            for(const BTuple<BBoolean, BBoolean >& param : _trid_3) {
+                BBoolean _tmp_1 = param.projection2();
+                BBoolean _tmp_2 = param.projection1();
+
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["SetCruiseSpeed"]);
+                copiedState.SetCruiseSpeed(_tmp_2, _tmp_1);
+                copiedState.stateAccessedVia = "SetCruiseSpeed";
+                result.insert(copiedState);
+            }
+            BSet<BTuple<BBoolean, BBoolean >> _trid_4 = state._tr_CCInitialisationFinished(isCaching);
+            for(const BTuple<BBoolean, BBoolean >& param : _trid_4) {
+                BBoolean _tmp_1 = param.projection2();
+                BBoolean _tmp_2 = param.projection1();
+
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["CCInitialisationFinished"]);
+                copiedState.CCInitialisationFinished(_tmp_2, _tmp_1);
+                copiedState.stateAccessedVia = "CCInitialisationFinished";
+                result.insert(copiedState);
+            }
+            if(state._tr_CCInitialisationDelayFinished(isCaching)) {
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["CCInitialisationDelayFinished"]);
+                copiedState.CCInitialisationDelayFinished();
+                copiedState.stateAccessedVia = "CCInitialisationDelayFinished";
+                result.insert(copiedState);
+            }
+            BSet<BTuple<BBoolean, BBoolean >> _trid_6 = state._tr_CruiseSpeedChangeFinished(isCaching);
+            for(const BTuple<BBoolean, BBoolean >& param : _trid_6) {
+                BBoolean _tmp_1 = param.projection2();
+                BBoolean _tmp_2 = param.projection1();
+
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["CruiseSpeedChangeFinished"]);
+                copiedState.CruiseSpeedChangeFinished(_tmp_2, _tmp_1);
+                copiedState.stateAccessedVia = "CruiseSpeedChangeFinished";
+                result.insert(copiedState);
+            }
+            if(state._tr_CruiseSpeedChangeDelayFinished(isCaching)) {
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["CruiseSpeedChangeDelayFinished"]);
+                copiedState.CruiseSpeedChangeDelayFinished();
+                copiedState.stateAccessedVia = "CruiseSpeedChangeDelayFinished";
+                result.insert(copiedState);
+            }
+            if(state._tr_CruiseOff(isCaching)) {
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["CruiseOff"]);
+                copiedState.CruiseOff();
+                copiedState.stateAccessedVia = "CruiseOff";
+                result.insert(copiedState);
+            }
+            if(state._tr_ExternalForcesBecomesExtreme(isCaching)) {
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["ExternalForcesBecomesExtreme"]);
+                copiedState.ExternalForcesBecomesExtreme();
+                copiedState.stateAccessedVia = "ExternalForcesBecomesExtreme";
+                result.insert(copiedState);
+            }
+            if(state._tr_ExternalForcesBecomesNormal(isCaching)) {
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["ExternalForcesBecomesNormal"]);
+                copiedState.ExternalForcesBecomesNormal();
+                copiedState.stateAccessedVia = "ExternalForcesBecomesNormal";
+                result.insert(copiedState);
+            }
+            if(state._tr_VehicleLeavesCruiseSpeed(isCaching)) {
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["VehicleLeavesCruiseSpeed"]);
+                copiedState.VehicleLeavesCruiseSpeed();
+                copiedState.stateAccessedVia = "VehicleLeavesCruiseSpeed";
+                result.insert(copiedState);
+            }
+            if(state._tr_VehicleReachesCruiseSpeed(isCaching)) {
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["VehicleReachesCruiseSpeed"]);
+                copiedState.VehicleReachesCruiseSpeed();
+                copiedState.stateAccessedVia = "VehicleReachesCruiseSpeed";
+                result.insert(copiedState);
+            }
+            if(state._tr_VehicleExceedsMaxCruiseSpeed(isCaching)) {
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["VehicleExceedsMaxCruiseSpeed"]);
+                copiedState.VehicleExceedsMaxCruiseSpeed();
+                copiedState.stateAccessedVia = "VehicleExceedsMaxCruiseSpeed";
+                result.insert(copiedState);
+            }
+            if(state._tr_VehicleFallsBelowMaxCruiseSpeed(isCaching)) {
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["VehicleFallsBelowMaxCruiseSpeed"]);
+                copiedState.VehicleFallsBelowMaxCruiseSpeed();
+                copiedState.stateAccessedVia = "VehicleFallsBelowMaxCruiseSpeed";
+                result.insert(copiedState);
+            }
+            if(state._tr_ObstacleDistanceBecomesVeryClose(isCaching)) {
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["ObstacleDistanceBecomesVeryClose"]);
+                copiedState.ObstacleDistanceBecomesVeryClose();
+                copiedState.stateAccessedVia = "ObstacleDistanceBecomesVeryClose";
+                result.insert(copiedState);
+            }
+            if(state._tr_ObstacleDistanceBecomesClose(isCaching)) {
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["ObstacleDistanceBecomesClose"]);
+                copiedState.ObstacleDistanceBecomesClose();
+                copiedState.stateAccessedVia = "ObstacleDistanceBecomesClose";
+                result.insert(copiedState);
+            }
+            if(state._tr_ObstacleDistanceBecomesBig(isCaching)) {
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["ObstacleDistanceBecomesBig"]);
+                copiedState.ObstacleDistanceBecomesBig();
+                copiedState.stateAccessedVia = "ObstacleDistanceBecomesBig";
+                result.insert(copiedState);
+            }
+            if(state._tr_ObstacleStartsTravelFaster(isCaching)) {
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["ObstacleStartsTravelFaster"]);
+                copiedState.ObstacleStartsTravelFaster();
+                copiedState.stateAccessedVia = "ObstacleStartsTravelFaster";
+                result.insert(copiedState);
+            }
+            if(state._tr_ObstacleStopsTravelFaster(isCaching)) {
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["ObstacleStopsTravelFaster"]);
+                copiedState.ObstacleStopsTravelFaster();
+                copiedState.stateAccessedVia = "ObstacleStopsTravelFaster";
+                result.insert(copiedState);
+            }
+            if(state._tr_ObstacleStartsTravelSlower(isCaching)) {
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["ObstacleStartsTravelSlower"]);
+                copiedState.ObstacleStartsTravelSlower();
+                copiedState.stateAccessedVia = "ObstacleStartsTravelSlower";
+                result.insert(copiedState);
+            }
+            if(state._tr_ObstacleStopsTravelSlower(isCaching)) {
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["ObstacleStopsTravelSlower"]);
+                copiedState.ObstacleStopsTravelSlower();
+                copiedState.stateAccessedVia = "ObstacleStopsTravelSlower";
+                result.insert(copiedState);
+            }
+            BSet<BTuple<Cruise_finite1_deterministic_MC::RSset, Cruise_finite1_deterministic_MC::ODset >> _trid_22 = state._tr_ObstacleAppearsWhenCruiseActive(isCaching);
+            for(const BTuple<Cruise_finite1_deterministic_MC::RSset, Cruise_finite1_deterministic_MC::ODset >& param : _trid_22) {
+                Cruise_finite1_deterministic_MC::ODset _tmp_1 = param.projection2();
+                Cruise_finite1_deterministic_MC::RSset _tmp_2 = param.projection1();
+
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["ObstacleAppearsWhenCruiseActive"]);
+                copiedState.ObstacleAppearsWhenCruiseActive(_tmp_2, _tmp_1);
+                copiedState.stateAccessedVia = "ObstacleAppearsWhenCruiseActive";
+                result.insert(copiedState);
+            }
+            BSet<Cruise_finite1_deterministic_MC::RSset> _trid_23 = state._tr_ObstacleAppearsWhenCruiseInactive(isCaching);
+            for(const Cruise_finite1_deterministic_MC::RSset& param : _trid_23) {
+                Cruise_finite1_deterministic_MC::RSset _tmp_1 = param;
+
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["ObstacleAppearsWhenCruiseInactive"]);
+                copiedState.ObstacleAppearsWhenCruiseInactive(_tmp_1);
+                copiedState.stateAccessedVia = "ObstacleAppearsWhenCruiseInactive";
+                result.insert(copiedState);
+            }
+            if(state._tr_ObstacleDisappears(isCaching)) {
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["ObstacleDisappears"]);
+                copiedState.ObstacleDisappears();
+                copiedState.stateAccessedVia = "ObstacleDisappears";
+                result.insert(copiedState);
+            }
+            BSet<BTuple<BBoolean, BBoolean >> _trid_25 = state._tr_VehicleManageObstacle(isCaching);
+            for(const BTuple<BBoolean, BBoolean >& param : _trid_25) {
+                BBoolean _tmp_1 = param.projection2();
+                BBoolean _tmp_2 = param.projection1();
+
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["VehicleManageObstacle"]);
+                copiedState.VehicleManageObstacle(_tmp_2, _tmp_1);
+                copiedState.stateAccessedVia = "VehicleManageObstacle";
+                result.insert(copiedState);
+            }
+            if(state._tr_ObstacleBecomesOld(isCaching)) {
+                Cruise_finite1_deterministic_MC copiedState = state._copy(guardDependency["ObstacleBecomesOld"]);
+                copiedState.ObstacleBecomesOld();
+                copiedState.stateAccessedVia = "ObstacleBecomesOld";
+                result.insert(copiedState);
             }
-            result.insert(copiedState);
-            transitions += 1;
+
+            return result;
         }
-        bool _trid_12;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_VehicleReachesCruiseSpeed"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_VehicleReachesCruiseSpeed") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_12 = state._tr_VehicleReachesCruiseSpeed();
-        } else {
-            _trid_12 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_VehicleReachesCruiseSpeed", _trid_12);
-        if(_trid_12) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.VehicleReachesCruiseSpeed();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["VehicleReachesCruiseSpeed"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["VehicleReachesCruiseSpeed"]});
+
+        bool invariantViolated(const Cruise_finite1_deterministic_MC& state) {
+            if(isCaching) {
+                std::unordered_set<string> dependentInvariantsOfState = invariantDependency[state.stateAccessedVia];
+                if(dependentInvariantsOfState.find("_check_inv_1") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_1()) {
+                        return false;
+                    }
                 }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_2") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_2()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "VehicleReachesCruiseSpeed"});
+                if(dependentInvariantsOfState.find("_check_inv_3") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_3()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_13;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_VehicleExceedsMaxCruiseSpeed"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_VehicleExceedsMaxCruiseSpeed") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_13 = state._tr_VehicleExceedsMaxCruiseSpeed();
-        } else {
-            _trid_13 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_VehicleExceedsMaxCruiseSpeed", _trid_13);
-        if(_trid_13) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.VehicleExceedsMaxCruiseSpeed();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["VehicleExceedsMaxCruiseSpeed"]});
+                if(dependentInvariantsOfState.find("_check_inv_4") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_4()) {
+                        return false;
+                    }
                 }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["VehicleExceedsMaxCruiseSpeed"]});
+                if(dependentInvariantsOfState.find("_check_inv_5") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_5()) {
+                        return false;
+                    }
                 }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_6") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_6()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "VehicleExceedsMaxCruiseSpeed"});
+                if(dependentInvariantsOfState.find("_check_inv_7") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_7()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_14;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_VehicleFallsBelowMaxCruiseSpeed"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_VehicleFallsBelowMaxCruiseSpeed") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_14 = state._tr_VehicleFallsBelowMaxCruiseSpeed();
-        } else {
-            _trid_14 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_VehicleFallsBelowMaxCruiseSpeed", _trid_14);
-        if(_trid_14) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.VehicleFallsBelowMaxCruiseSpeed();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["VehicleFallsBelowMaxCruiseSpeed"]});
+                if(dependentInvariantsOfState.find("_check_inv_8") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_8()) {
+                        return false;
+                    }
                 }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["VehicleFallsBelowMaxCruiseSpeed"]});
+                if(dependentInvariantsOfState.find("_check_inv_9") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_9()) {
+                        return false;
+                    }
                 }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_10") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_10()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "VehicleFallsBelowMaxCruiseSpeed"});
+                if(dependentInvariantsOfState.find("_check_inv_11") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_11()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_15;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_ObstacleDistanceBecomesVeryClose"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_ObstacleDistanceBecomesVeryClose") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_15 = state._tr_ObstacleDistanceBecomesVeryClose();
-        } else {
-            _trid_15 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_ObstacleDistanceBecomesVeryClose", _trid_15);
-        if(_trid_15) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleDistanceBecomesVeryClose();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["ObstacleDistanceBecomesVeryClose"]});
+                if(dependentInvariantsOfState.find("_check_inv_12") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_12()) {
+                        return false;
+                    }
                 }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["ObstacleDistanceBecomesVeryClose"]});
+                if(dependentInvariantsOfState.find("_check_inv_13") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_13()) {
+                        return false;
+                    }
                 }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_14") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_14()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleDistanceBecomesVeryClose"});
+                if(dependentInvariantsOfState.find("_check_inv_15") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_15()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_16;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_ObstacleDistanceBecomesClose"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_ObstacleDistanceBecomesClose") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_16 = state._tr_ObstacleDistanceBecomesClose();
-        } else {
-            _trid_16 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_ObstacleDistanceBecomesClose", _trid_16);
-        if(_trid_16) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleDistanceBecomesClose();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["ObstacleDistanceBecomesClose"]});
+                if(dependentInvariantsOfState.find("_check_inv_16") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_16()) {
+                        return false;
+                    }
                 }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["ObstacleDistanceBecomesClose"]});
+                if(dependentInvariantsOfState.find("_check_inv_17") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_17()) {
+                        return false;
+                    }
                 }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_18") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_18()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleDistanceBecomesClose"});
+                if(dependentInvariantsOfState.find("_check_inv_19") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_19()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_17;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_ObstacleDistanceBecomesBig"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_ObstacleDistanceBecomesBig") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_17 = state._tr_ObstacleDistanceBecomesBig();
-        } else {
-            _trid_17 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_ObstacleDistanceBecomesBig", _trid_17);
-        if(_trid_17) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleDistanceBecomesBig();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["ObstacleDistanceBecomesBig"]});
+                if(dependentInvariantsOfState.find("_check_inv_20") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_20()) {
+                        return false;
+                    }
                 }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["ObstacleDistanceBecomesBig"]});
+                if(dependentInvariantsOfState.find("_check_inv_21") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_21()) {
+                        return false;
+                    }
                 }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_22") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_22()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleDistanceBecomesBig"});
+                if(dependentInvariantsOfState.find("_check_inv_23") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_23()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_18;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_ObstacleStartsTravelFaster"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_ObstacleStartsTravelFaster") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_18 = state._tr_ObstacleStartsTravelFaster();
-        } else {
-            _trid_18 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_ObstacleStartsTravelFaster", _trid_18);
-        if(_trid_18) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleStartsTravelFaster();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["ObstacleStartsTravelFaster"]});
+                if(dependentInvariantsOfState.find("_check_inv_24") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_24()) {
+                        return false;
+                    }
                 }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["ObstacleStartsTravelFaster"]});
+                if(dependentInvariantsOfState.find("_check_inv_25") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_25()) {
+                        return false;
+                    }
                 }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_26") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_26()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleStartsTravelFaster"});
+                if(dependentInvariantsOfState.find("_check_inv_27") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_27()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_19;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_ObstacleStopsTravelFaster"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_ObstacleStopsTravelFaster") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_19 = state._tr_ObstacleStopsTravelFaster();
-        } else {
-            _trid_19 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_ObstacleStopsTravelFaster", _trid_19);
-        if(_trid_19) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleStopsTravelFaster();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["ObstacleStopsTravelFaster"]});
+                if(dependentInvariantsOfState.find("_check_inv_28") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_28()) {
+                        return false;
+                    }
                 }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["ObstacleStopsTravelFaster"]});
+                if(dependentInvariantsOfState.find("_check_inv_29") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_29()) {
+                        return false;
+                    }
                 }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_30") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_30()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleStopsTravelFaster"});
+                if(dependentInvariantsOfState.find("_check_inv_31") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_31()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_20;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_ObstacleStartsTravelSlower"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_ObstacleStartsTravelSlower") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_20 = state._tr_ObstacleStartsTravelSlower();
-        } else {
-            _trid_20 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_ObstacleStartsTravelSlower", _trid_20);
-        if(_trid_20) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleStartsTravelSlower();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["ObstacleStartsTravelSlower"]});
+                if(dependentInvariantsOfState.find("_check_inv_32") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_32()) {
+                        return false;
+                    }
                 }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["ObstacleStartsTravelSlower"]});
+                if(dependentInvariantsOfState.find("_check_inv_33") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_33()) {
+                        return false;
+                    }
                 }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_34") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_34()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleStartsTravelSlower"});
+                if(dependentInvariantsOfState.find("_check_inv_35") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_35()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_21;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_ObstacleStopsTravelSlower"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_ObstacleStopsTravelSlower") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_21 = state._tr_ObstacleStopsTravelSlower();
-        } else {
-            _trid_21 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_ObstacleStopsTravelSlower", _trid_21);
-        if(_trid_21) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleStopsTravelSlower();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["ObstacleStopsTravelSlower"]});
+                if(dependentInvariantsOfState.find("_check_inv_36") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_36()) {
+                        return false;
+                    }
                 }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["ObstacleStopsTravelSlower"]});
+                if(dependentInvariantsOfState.find("_check_inv_37") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_37()) {
+                        return false;
+                    }
                 }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_38") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_38()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleStopsTravelSlower"});
+                if(dependentInvariantsOfState.find("_check_inv_39") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_39()) {
+                        return false;
+                    }
                 }
+                return false;
             }
-            result.insert(copiedState);
-            transitions += 1;
+            return !(state._check_inv_1() && state._check_inv_2() && state._check_inv_3() && state._check_inv_4() && state._check_inv_5() && state._check_inv_6() && state._check_inv_7() && state._check_inv_8() && state._check_inv_9() && state._check_inv_10() && state._check_inv_11() && state._check_inv_12() && state._check_inv_13() && state._check_inv_14() && state._check_inv_15() && state._check_inv_16() && state._check_inv_17() && state._check_inv_18() && state._check_inv_19() && state._check_inv_20() && state._check_inv_21() && state._check_inv_22() && state._check_inv_23() && state._check_inv_24() && state._check_inv_25() && state._check_inv_26() && state._check_inv_27() && state._check_inv_28() && state._check_inv_29() && state._check_inv_30() && state._check_inv_31() && state._check_inv_32() && state._check_inv_33() && state._check_inv_34() && state._check_inv_35() && state._check_inv_36() && state._check_inv_37() && state._check_inv_38() && state._check_inv_39());
         }
-        BSet<BTuple<Cruise_finite1_deterministic_MC::RSset, Cruise_finite1_deterministic_MC::ODset >> _trid_22;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_ObstacleAppearsWhenCruiseActive"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_ObstacleAppearsWhenCruiseActive") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_22 = state._tr_ObstacleAppearsWhenCruiseActive();
-        } else {
-            _trid_22 = boost::any_cast<BSet<BTuple<Cruise_finite1_deterministic_MC::RSset, Cruise_finite1_deterministic_MC::ODset >>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_ObstacleAppearsWhenCruiseActive", _trid_22);
-        for(const BTuple<Cruise_finite1_deterministic_MC::RSset, Cruise_finite1_deterministic_MC::ODset >& param : _trid_22) {
-            Cruise_finite1_deterministic_MC::ODset _tmp_1 = param.projection2();
-            Cruise_finite1_deterministic_MC::RSset _tmp_2 = param.projection1();
 
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleAppearsWhenCruiseActive(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["ObstacleAppearsWhenCruiseActive"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["ObstacleAppearsWhenCruiseActive"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+
+        void printResult() {
+            if(deadlockDetected || invariantViolatedBool) {
+                if(deadlockDetected) {
+                    cout << "DEADLOCK DETECTED" << "\n";
+                } else {
+                    cout << "INVARIANT VIOLATED" << "\n";
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleAppearsWhenCruiseActive"});
+
+                cout << "COUNTER EXAMPLE TRACE: " << "\n";
+
+                std::string trace = "";
+                while(parents.find(counterExampleState) != parents.end()) {
+                    std::stringstream stringStream;
+                    stringStream << counterExampleState;
+                    trace.insert(0, stringStream.str());
+                    trace.insert(0, "\n");
+                    trace.insert(0, counterExampleState.stateAccessedVia);
+                    trace.insert(0, "\n\n");
+                    counterExampleState = parents[counterExampleState];
                 }
+                cout << trace;
+            } else {
+                cout << "MODEL CHECKING SUCCESSFUL" << "\n";
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Cruise_finite1_deterministic_MC::RSset> _trid_23;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_ObstacleAppearsWhenCruiseInactive"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_ObstacleAppearsWhenCruiseInactive") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_23 = state._tr_ObstacleAppearsWhenCruiseInactive();
-        } else {
-            _trid_23 = boost::any_cast<BSet<Cruise_finite1_deterministic_MC::RSset>>(cachedValue);
+
+            cout << "Number of States: " << states.size() << "\n";
+            cout << "Number of Transitions: " << transitions << "\n";
         }
-        newCache = newCache.set("_tr_ObstacleAppearsWhenCruiseInactive", _trid_23);
-        for(const Cruise_finite1_deterministic_MC::RSset& param : _trid_23) {
-            Cruise_finite1_deterministic_MC::RSset _tmp_1 = param;
-
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleAppearsWhenCruiseInactive(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["ObstacleAppearsWhenCruiseInactive"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["ObstacleAppearsWhenCruiseInactive"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleAppearsWhenCruiseInactive"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_24;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_ObstacleDisappears"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_ObstacleDisappears") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_24 = state._tr_ObstacleDisappears();
-        } else {
-            _trid_24 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_ObstacleDisappears", _trid_24);
-        if(_trid_24) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleDisappears();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["ObstacleDisappears"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["ObstacleDisappears"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleDisappears"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BBoolean, BBoolean >> _trid_25;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_VehicleManageObstacle"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_VehicleManageObstacle") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_25 = state._tr_VehicleManageObstacle();
-        } else {
-            _trid_25 = boost::any_cast<BSet<BTuple<BBoolean, BBoolean >>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_VehicleManageObstacle", _trid_25);
-        for(const BTuple<BBoolean, BBoolean >& param : _trid_25) {
-            BBoolean _tmp_1 = param.projection2();
-            BBoolean _tmp_2 = param.projection1();
-
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.VehicleManageObstacle(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["VehicleManageObstacle"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["VehicleManageObstacle"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "VehicleManageObstacle"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_26;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_ObstacleBecomesOld"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_ObstacleBecomesOld") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_26 = state._tr_ObstacleBecomesOld();
-        } else {
-            _trid_26 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_ObstacleBecomesOld", _trid_26);
-        if(_trid_26) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleBecomesOld();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["ObstacleBecomesOld"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["ObstacleBecomesOld"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleBecomesOld"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            guardCache.insert({state, newCache});
-        }
-    } else {
-        if(state._tr_CruiseBecomesNotAllowed()) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.CruiseBecomesNotAllowed();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "CruiseBecomesNotAllowed"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_CruiseBecomesAllowed()) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.CruiseBecomesAllowed();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "CruiseBecomesAllowed"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BBoolean, BBoolean >> _trid_3 = state._tr_SetCruiseSpeed();
-        for(const BTuple<BBoolean, BBoolean >& param : _trid_3) {
-            BBoolean _tmp_1 = param.projection2();
-            BBoolean _tmp_2 = param.projection1();
-
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.SetCruiseSpeed(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "SetCruiseSpeed"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BBoolean, BBoolean >> _trid_4 = state._tr_CCInitialisationFinished();
-        for(const BTuple<BBoolean, BBoolean >& param : _trid_4) {
-            BBoolean _tmp_1 = param.projection2();
-            BBoolean _tmp_2 = param.projection1();
-
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.CCInitialisationFinished(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "CCInitialisationFinished"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_CCInitialisationDelayFinished()) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.CCInitialisationDelayFinished();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "CCInitialisationDelayFinished"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BBoolean, BBoolean >> _trid_6 = state._tr_CruiseSpeedChangeFinished();
-        for(const BTuple<BBoolean, BBoolean >& param : _trid_6) {
-            BBoolean _tmp_1 = param.projection2();
-            BBoolean _tmp_2 = param.projection1();
-
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.CruiseSpeedChangeFinished(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "CruiseSpeedChangeFinished"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_CruiseSpeedChangeDelayFinished()) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.CruiseSpeedChangeDelayFinished();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "CruiseSpeedChangeDelayFinished"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_CruiseOff()) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.CruiseOff();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "CruiseOff"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_ExternalForcesBecomesExtreme()) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ExternalForcesBecomesExtreme();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ExternalForcesBecomesExtreme"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_ExternalForcesBecomesNormal()) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ExternalForcesBecomesNormal();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ExternalForcesBecomesNormal"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_VehicleLeavesCruiseSpeed()) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.VehicleLeavesCruiseSpeed();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "VehicleLeavesCruiseSpeed"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_VehicleReachesCruiseSpeed()) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.VehicleReachesCruiseSpeed();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "VehicleReachesCruiseSpeed"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_VehicleExceedsMaxCruiseSpeed()) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.VehicleExceedsMaxCruiseSpeed();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "VehicleExceedsMaxCruiseSpeed"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_VehicleFallsBelowMaxCruiseSpeed()) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.VehicleFallsBelowMaxCruiseSpeed();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "VehicleFallsBelowMaxCruiseSpeed"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_ObstacleDistanceBecomesVeryClose()) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleDistanceBecomesVeryClose();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleDistanceBecomesVeryClose"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_ObstacleDistanceBecomesClose()) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleDistanceBecomesClose();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleDistanceBecomesClose"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_ObstacleDistanceBecomesBig()) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleDistanceBecomesBig();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleDistanceBecomesBig"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_ObstacleStartsTravelFaster()) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleStartsTravelFaster();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleStartsTravelFaster"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_ObstacleStopsTravelFaster()) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleStopsTravelFaster();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleStopsTravelFaster"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_ObstacleStartsTravelSlower()) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleStartsTravelSlower();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleStartsTravelSlower"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_ObstacleStopsTravelSlower()) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleStopsTravelSlower();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleStopsTravelSlower"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<Cruise_finite1_deterministic_MC::RSset, Cruise_finite1_deterministic_MC::ODset >> _trid_22 = state._tr_ObstacleAppearsWhenCruiseActive();
-        for(const BTuple<Cruise_finite1_deterministic_MC::RSset, Cruise_finite1_deterministic_MC::ODset >& param : _trid_22) {
-            Cruise_finite1_deterministic_MC::ODset _tmp_1 = param.projection2();
-            Cruise_finite1_deterministic_MC::RSset _tmp_2 = param.projection1();
-
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleAppearsWhenCruiseActive(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleAppearsWhenCruiseActive"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Cruise_finite1_deterministic_MC::RSset> _trid_23 = state._tr_ObstacleAppearsWhenCruiseInactive();
-        for(const Cruise_finite1_deterministic_MC::RSset& param : _trid_23) {
-            Cruise_finite1_deterministic_MC::RSset _tmp_1 = param;
-
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleAppearsWhenCruiseInactive(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleAppearsWhenCruiseInactive"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_ObstacleDisappears()) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleDisappears();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleDisappears"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BBoolean, BBoolean >> _trid_25 = state._tr_VehicleManageObstacle();
-        for(const BTuple<BBoolean, BBoolean >& param : _trid_25) {
-            BBoolean _tmp_1 = param.projection2();
-            BBoolean _tmp_2 = param.projection1();
-
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.VehicleManageObstacle(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "VehicleManageObstacle"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_ObstacleBecomesOld()) {
-            Cruise_finite1_deterministic_MC copiedState = state._copy();
-            copiedState.ObstacleBecomesOld();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "ObstacleBecomesOld"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-
-    }
-    return result;
-}
-
-static void printResult(int states, int transitions, bool deadlockDetected, bool invariantViolated, Cruise_finite1_deterministic_MC& counterExampleState, std::unordered_map<Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual>& parents, std::unordered_map<Cruise_finite1_deterministic_MC, string, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual>& stateAccessedVia) {
-    if(deadlockDetected || invariantViolated) {
-        if(deadlockDetected) {
-            cout << "DEADLOCK DETECTED" << "\n";
-        }
-        if(invariantViolated) {
-            cout << "INVARIANT VIOLATED" << "\n";
-        }
-        cout << "COUNTER EXAMPLE TRACE: " << "\n";
-
-        Cruise_finite1_deterministic_MC currentState = counterExampleState;
-        std::string trace = "";
-        while(parents.find(currentState) != parents.end()) {
-            std::stringstream stringStream;
-            stringStream << currentState;
-            trace.insert(0, stringStream.str());
-            trace.insert(0, "\n");
-            trace.insert(0, stateAccessedVia[currentState]);
-            trace.insert(0, "\n\n");
-            currentState = parents[currentState];
-        }
-        cout << trace;
-    }
-
-    if(!deadlockDetected && !invariantViolated) {
-        cout << "MODEL CHECKING SUCCESSFUL" << "\n";
-    }
-    cout << "Number of States: " << states << "\n";
-    cout << "Number of Transitions: " << transitions << "\n";
-}
-
-static bool checkInvariants(std::mutex& guardMutex, const Cruise_finite1_deterministic_MC& state, bool isCaching, std::unordered_map<Cruise_finite1_deterministic_MC, std::unordered_set<string>, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual>& dependentInvariant) {
-    if(isCaching) {
-        std::unordered_set<string> dependentInvariantsOfState;
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            dependentInvariantsOfState = dependentInvariant[state];
-        }
-        if(dependentInvariantsOfState.find("_check_inv_1") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_1()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_2") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_2()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_3") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_3()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_4") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_4()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_5") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_5()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_6") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_6()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_7") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_7()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_8") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_8()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_9") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_9()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_10") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_10()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_11") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_11()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_12") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_12()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_13") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_13()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_14") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_14()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_15") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_15()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_16") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_16()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_17") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_17()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_18") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_18()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_19") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_19()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_20") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_20()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_21") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_21()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_22") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_22()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_23") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_23()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_24") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_24()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_25") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_25()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_26") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_26()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_27") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_27()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_28") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_28()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_29") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_29()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_30") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_30()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_31") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_31()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_32") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_32()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_33") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_33()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_34") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_34()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_35") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_35()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_36") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_36()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_37") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_37()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_38") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_38()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_39") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_39()) {
-                return false;
-            }
-        }
-        return true;
-    }
-    return !(!state._check_inv_1() || !state._check_inv_2() || !state._check_inv_3() || !state._check_inv_4() || !state._check_inv_5() || !state._check_inv_6() || !state._check_inv_7() || !state._check_inv_8() || !state._check_inv_9() || !state._check_inv_10() || !state._check_inv_11() || !state._check_inv_12() || !state._check_inv_13() || !state._check_inv_14() || !state._check_inv_15() || !state._check_inv_16() || !state._check_inv_17() || !state._check_inv_18() || !state._check_inv_19() || !state._check_inv_20() || !state._check_inv_21() || !state._check_inv_22() || !state._check_inv_23() || !state._check_inv_24() || !state._check_inv_25() || !state._check_inv_26() || !state._check_inv_27() || !state._check_inv_28() || !state._check_inv_29() || !state._check_inv_30() || !state._check_inv_31() || !state._check_inv_32() || !state._check_inv_33() || !state._check_inv_34() || !state._check_inv_35() || !state._check_inv_36() || !state._check_inv_37() || !state._check_inv_38() || !state._check_inv_39());
-}
-
-static Cruise_finite1_deterministic_MC next(std::list<Cruise_finite1_deterministic_MC>& collection, std::mutex& mutex, Cruise_finite1_deterministic_MC::Type type) {
-    std::unique_lock<std::mutex> lock(mutex);
-    switch(type) {
-        case Cruise_finite1_deterministic_MC::BFS: {
-            Cruise_finite1_deterministic_MC state = collection.front();
-            collection.pop_front();
-            return state;
-        }
-        case Cruise_finite1_deterministic_MC::DFS: {
-            Cruise_finite1_deterministic_MC state = collection.back();
-            collection.pop_back();
-            return state;
-        }
-        case Cruise_finite1_deterministic_MC::MIXED: {
-            if(collection.size() % 2 == 0) {
-                Cruise_finite1_deterministic_MC state = collection.front();
-                collection.pop_front();
-                return state;
-            } else {
-                Cruise_finite1_deterministic_MC state = collection.back();
-                collection.pop_back();
-                return state;
-            }
-        }
-    };
-}
-
-static void modelCheckSingleThreaded(Cruise_finite1_deterministic_MC::Type type, bool isCaching) {
-    std::mutex mutex;
-    std::mutex guardMutex;
-
-    Cruise_finite1_deterministic_MC machine = Cruise_finite1_deterministic_MC();
-
-    std::atomic<bool> invariantViolated;
-    invariantViolated = false;
-    std::atomic<bool> deadlockDetected;
-    deadlockDetected = false;
-    std::atomic<bool> stopThreads;
-    stopThreads = false;
-
-    std::unordered_set<Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> states = std::unordered_set<Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual>();
-    states.insert(machine);
-    std::atomic<int> numberStates;
-    numberStates = 1;
-
-    std::list<Cruise_finite1_deterministic_MC> collection = std::list<Cruise_finite1_deterministic_MC>();
-    collection.push_back(machine);
-
-    std::atomic<int> transitions;
-    transitions = 0;
-
-    std::unordered_map<string, std::unordered_set<string>> invariantDependency;
-    std::unordered_map<string, std::unordered_set<string>> guardDependency;
-    std::unordered_map<Cruise_finite1_deterministic_MC, std::unordered_set<string>, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> dependentInvariant;
-    std::unordered_map<Cruise_finite1_deterministic_MC, std::unordered_set<string>, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> dependentGuard;
-    std::unordered_map<Cruise_finite1_deterministic_MC, immer::map<string, boost::any>, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> guardCache;
-    std::unordered_map<Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> parents;
-    std::unordered_map<Cruise_finite1_deterministic_MC, string, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> stateAccessedVia;
-    if(isCaching) {
-        invariantDependency.insert({"ObstacleStopsTravelSlower", {"_check_inv_29", "_check_inv_39", "_check_inv_38", "_check_inv_37", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_13", "_check_inv_35", "_check_inv_24"}});
-        invariantDependency.insert({"SetCruiseSpeed", {"_check_inv_18", "_check_inv_17", "_check_inv_39", "_check_inv_16", "_check_inv_38", "_check_inv_15", "_check_inv_37", "_check_inv_19", "_check_inv_10", "_check_inv_14", "_check_inv_36", "_check_inv_35", "_check_inv_34", "_check_inv_33", "_check_inv_26", "_check_inv_21", "_check_inv_20", "_check_inv_4", "_check_inv_25", "_check_inv_24", "_check_inv_8", "_check_inv_23", "_check_inv_9", "_check_inv_22", "_check_inv_2", "_check_inv_3"}});
-        invariantDependency.insert({"VehicleLeavesCruiseSpeed", {"_check_inv_17", "_check_inv_3", "_check_inv_34"}});
-        invariantDependency.insert({"VehicleFallsBelowMaxCruiseSpeed", {"_check_inv_17", "_check_inv_3", "_check_inv_6", "_check_inv_34"}});
-        invariantDependency.insert({"CCInitialisationFinished", {"_check_inv_39", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_19", "_check_inv_32", "_check_inv_21", "_check_inv_31", "_check_inv_7", "_check_inv_30", "_check_inv_5", "_check_inv_36", "_check_inv_35"}});
-        invariantDependency.insert({"VehicleReachesCruiseSpeed", {"_check_inv_17", "_check_inv_3", "_check_inv_34"}});
-        invariantDependency.insert({"ObstacleAppearsWhenCruiseActive", {"_check_inv_29", "_check_inv_39", "_check_inv_28", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_13", "_check_inv_35", "_check_inv_24", "_check_inv_12", "_check_inv_23", "_check_inv_11"}});
-        invariantDependency.insert({"ObstacleStartsTravelSlower", {"_check_inv_29", "_check_inv_39", "_check_inv_38", "_check_inv_37", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_13", "_check_inv_35", "_check_inv_24"}});
-        invariantDependency.insert({"CruiseBecomesNotAllowed", {"_check_inv_18", "_check_inv_17", "_check_inv_39", "_check_inv_16", "_check_inv_38", "_check_inv_15", "_check_inv_37", "_check_inv_19", "_check_inv_10", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_35", "_check_inv_12", "_check_inv_34", "_check_inv_33", "_check_inv_28", "_check_inv_27", "_check_inv_26", "_check_inv_21", "_check_inv_7", "_check_inv_20", "_check_inv_4", "_check_inv_5", "_check_inv_25", "_check_inv_24", "_check_inv_8", "_check_inv_23", "_check_inv_9", "_check_inv_22", "_check_inv_2", "_check_inv_3", "_check_inv_1"}});
-        invariantDependency.insert({"ObstacleAppearsWhenCruiseInactive", {"_check_inv_29", "_check_inv_39", "_check_inv_28", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_36", "_check_inv_13", "_check_inv_12", "_check_inv_23", "_check_inv_11"}});
-        invariantDependency.insert({"CCInitialisationDelayFinished", {"_check_inv_39", "_check_inv_38", "_check_inv_15", "_check_inv_37", "_check_inv_36", "_check_inv_25", "_check_inv_35"}});
-        invariantDependency.insert({"ObstacleDistanceBecomesClose", {"_check_inv_39", "_check_inv_28", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_32", "_check_inv_21", "_check_inv_31", "_check_inv_7", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_35", "_check_inv_24", "_check_inv_12", "_check_inv_23"}});
-        invariantDependency.insert({"ObstacleStartsTravelFaster", {"_check_inv_29", "_check_inv_39", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_32", "_check_inv_21", "_check_inv_31", "_check_inv_7", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_13", "_check_inv_35", "_check_inv_24"}});
-        invariantDependency.insert({"ExternalForcesBecomesExtreme", {"_check_inv_18", "_check_inv_4"}});
-        invariantDependency.insert({"CruiseOff", {"_check_inv_18", "_check_inv_17", "_check_inv_39", "_check_inv_16", "_check_inv_38", "_check_inv_15", "_check_inv_37", "_check_inv_19", "_check_inv_10", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_35", "_check_inv_12", "_check_inv_34", "_check_inv_33", "_check_inv_28", "_check_inv_27", "_check_inv_26", "_check_inv_21", "_check_inv_7", "_check_inv_20", "_check_inv_4", "_check_inv_5", "_check_inv_25", "_check_inv_24", "_check_inv_8", "_check_inv_23", "_check_inv_9", "_check_inv_22", "_check_inv_2", "_check_inv_3"}});
-        invariantDependency.insert({"CruiseSpeedChangeDelayFinished", {"_check_inv_39", "_check_inv_16", "_check_inv_38", "_check_inv_37", "_check_inv_26", "_check_inv_36", "_check_inv_35"}});
-        invariantDependency.insert({"ObstacleStopsTravelFaster", {"_check_inv_29", "_check_inv_39", "_check_inv_38", "_check_inv_37", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_13", "_check_inv_35", "_check_inv_24"}});
-        invariantDependency.insert({"ObstacleDistanceBecomesVeryClose", {"_check_inv_39", "_check_inv_28", "_check_inv_38", "_check_inv_37", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_35", "_check_inv_24", "_check_inv_12", "_check_inv_23"}});
-        invariantDependency.insert({"VehicleManageObstacle", {"_check_inv_39", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_19", "_check_inv_32", "_check_inv_21", "_check_inv_31", "_check_inv_7", "_check_inv_30", "_check_inv_5", "_check_inv_36", "_check_inv_35"}});
-        invariantDependency.insert({"CruiseBecomesAllowed", {"_check_inv_1", "_check_inv_33"}});
-        invariantDependency.insert({"VehicleExceedsMaxCruiseSpeed", {"_check_inv_17", "_check_inv_3", "_check_inv_6", "_check_inv_34"}});
-        invariantDependency.insert({"CruiseSpeedChangeFinished", {"_check_inv_39", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_19", "_check_inv_32", "_check_inv_21", "_check_inv_31", "_check_inv_7", "_check_inv_30", "_check_inv_5", "_check_inv_36", "_check_inv_35"}});
-        invariantDependency.insert({"ObstacleDisappears", {"_check_inv_29", "_check_inv_39", "_check_inv_28", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_32", "_check_inv_21", "_check_inv_31", "_check_inv_7", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_13", "_check_inv_35", "_check_inv_24", "_check_inv_12", "_check_inv_23", "_check_inv_11"}});
-        invariantDependency.insert({"ExternalForcesBecomesNormal", {"_check_inv_18", "_check_inv_4"}});
-        invariantDependency.insert({"ObstacleBecomesOld", {"_check_inv_39", "_check_inv_38", "_check_inv_37", "_check_inv_14", "_check_inv_36", "_check_inv_35", "_check_inv_24"}});
-        invariantDependency.insert({"ObstacleDistanceBecomesBig", {"_check_inv_39", "_check_inv_28", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_32", "_check_inv_21", "_check_inv_31", "_check_inv_7", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_35", "_check_inv_24", "_check_inv_12", "_check_inv_23"}});
-        guardDependency.insert({"ObstacleStopsTravelSlower", {"_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStopsTravelSlower", "_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseSpeedChangeFinished", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStartsTravelFaster", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose"}});
-        guardDependency.insert({"SetCruiseSpeed", {"_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesClose", "_tr_ExternalForcesBecomesNormal", "_tr_CruiseSpeedChangeFinished", "_tr_ExternalForcesBecomesExtreme", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_VehicleLeavesCruiseSpeed", "_tr_ObstacleAppearsWhenCruiseActive", "_tr_VehicleReachesCruiseSpeed", "_tr_CruiseOff", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleAppearsWhenCruiseInactive"}});
-        guardDependency.insert({"VehicleLeavesCruiseSpeed", {"_tr_VehicleReachesCruiseSpeed", "_tr_VehicleLeavesCruiseSpeed"}});
-        guardDependency.insert({"VehicleFallsBelowMaxCruiseSpeed", {"_tr_VehicleReachesCruiseSpeed", "_tr_VehicleFallsBelowMaxCruiseSpeed", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_VehicleLeavesCruiseSpeed"}});
-        guardDependency.insert({"CCInitialisationFinished", {"_tr_ObstacleBecomesOld", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_VehicleLeavesCruiseSpeed"}});
-        guardDependency.insert({"VehicleReachesCruiseSpeed", {"_tr_VehicleReachesCruiseSpeed", "_tr_VehicleLeavesCruiseSpeed"}});
-        guardDependency.insert({"ObstacleAppearsWhenCruiseActive", {"_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStopsTravelSlower", "_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleDisappears", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStartsTravelFaster", "_tr_ObstacleAppearsWhenCruiseActive", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_ObstacleAppearsWhenCruiseInactive"}});
-        guardDependency.insert({"ObstacleStartsTravelSlower", {"_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStopsTravelSlower", "_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseSpeedChangeFinished", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStartsTravelFaster", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose"}});
-        guardDependency.insert({"CruiseBecomesNotAllowed", {"_tr_SetCruiseSpeed", "_tr_VehicleManageObstacle", "_tr_CruiseBecomesAllowed", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseBecomesNotAllowed", "_tr_ExternalForcesBecomesNormal", "_tr_CruiseSpeedChangeFinished", "_tr_ExternalForcesBecomesExtreme", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_VehicleLeavesCruiseSpeed", "_tr_ObstacleAppearsWhenCruiseActive", "_tr_VehicleReachesCruiseSpeed", "_tr_CruiseOff", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_ObstacleAppearsWhenCruiseInactive"}});
-        guardDependency.insert({"ObstacleAppearsWhenCruiseInactive", {"_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStopsTravelSlower", "_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleDisappears", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStartsTravelFaster", "_tr_ObstacleAppearsWhenCruiseActive", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_ObstacleAppearsWhenCruiseInactive"}});
-        guardDependency.insert({"CCInitialisationDelayFinished", {"_tr_VehicleManageObstacle", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleBecomesOld", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished"}});
-        guardDependency.insert({"ObstacleDistanceBecomesClose", {"_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished"}});
-        guardDependency.insert({"ObstacleStartsTravelFaster", {"_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStopsTravelSlower", "_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseSpeedChangeFinished", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStartsTravelFaster", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose"}});
-        guardDependency.insert({"ExternalForcesBecomesExtreme", {"_tr_ExternalForcesBecomesNormal", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ExternalForcesBecomesExtreme", "_tr_VehicleLeavesCruiseSpeed"}});
-        guardDependency.insert({"CruiseOff", {"_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_ExternalForcesBecomesNormal", "_tr_CruiseSpeedChangeFinished", "_tr_ExternalForcesBecomesExtreme", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_VehicleLeavesCruiseSpeed", "_tr_ObstacleAppearsWhenCruiseActive", "_tr_VehicleReachesCruiseSpeed", "_tr_CruiseOff", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_ObstacleAppearsWhenCruiseInactive"}});
-        guardDependency.insert({"CruiseSpeedChangeDelayFinished", {"_tr_VehicleManageObstacle", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleBecomesOld", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished"}});
-        guardDependency.insert({"ObstacleStopsTravelFaster", {"_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStopsTravelSlower", "_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseSpeedChangeFinished", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStartsTravelFaster", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose"}});
-        guardDependency.insert({"ObstacleDistanceBecomesVeryClose", {"_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished"}});
-        guardDependency.insert({"VehicleManageObstacle", {"_tr_ObstacleBecomesOld", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_VehicleLeavesCruiseSpeed"}});
-        guardDependency.insert({"CruiseBecomesAllowed", {"_tr_SetCruiseSpeed", "_tr_CruiseBecomesAllowed", "_tr_CruiseBecomesNotAllowed"}});
-        guardDependency.insert({"VehicleExceedsMaxCruiseSpeed", {"_tr_VehicleReachesCruiseSpeed", "_tr_VehicleFallsBelowMaxCruiseSpeed", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_VehicleLeavesCruiseSpeed"}});
-        guardDependency.insert({"CruiseSpeedChangeFinished", {"_tr_ObstacleBecomesOld", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_VehicleLeavesCruiseSpeed"}});
-        guardDependency.insert({"ObstacleDisappears", {"_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStopsTravelSlower", "_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleDisappears", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStartsTravelFaster", "_tr_ObstacleAppearsWhenCruiseActive", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_ObstacleAppearsWhenCruiseInactive"}});
-        guardDependency.insert({"ExternalForcesBecomesNormal", {"_tr_ExternalForcesBecomesNormal", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ExternalForcesBecomesExtreme", "_tr_VehicleLeavesCruiseSpeed"}});
-        guardDependency.insert({"ObstacleBecomesOld", {"_tr_VehicleManageObstacle", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleBecomesOld", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished"}});
-        guardDependency.insert({"ObstacleDistanceBecomesBig", {"_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished"}});
-        dependentInvariant.insert({machine, std::unordered_set<string>()});
-    }
-    Cruise_finite1_deterministic_MC counterExampleState;
-
-    while(!collection.empty() && !stopThreads) {
-        Cruise_finite1_deterministic_MC state = next(collection, mutex, type);
-
-        std::unordered_set<Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> nextStates = generateNextStates(guardMutex, state, isCaching, invariantDependency, dependentInvariant, guardDependency, dependentGuard, guardCache, parents, stateAccessedVia, transitions);
-        for(auto nextState : nextStates) {
-            if(states.find(nextState) == states.end()) {
-                numberStates += 1;
-                states.insert(nextState);
-                collection.push_back(nextState);
-                if(numberStates % 50000 == 0) {
-                    cout << "VISITED STATES: " << numberStates << "\n";
-                    cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
-                    cout << "-------------------" << "\n";
-                }
-            }
-        }
-
-        if(!checkInvariants(guardMutex, state, isCaching, dependentInvariant)) {
-            invariantViolated = true;
-            stopThreads = true;
-            counterExampleState = state;
-        }
-
-        if(nextStates.empty()) {
-            deadlockDetected = true;
-            stopThreads = true;
-            counterExampleState = state;
-        }
-
-    }
-    printResult(numberStates, transitions, deadlockDetected, invariantViolated, counterExampleState, parents, stateAccessedVia);
-}
-
-static void modelCheckMultiThreaded(Cruise_finite1_deterministic_MC::Type type, int threads, bool isCaching) {
-    std::mutex mutex;
-    std::mutex waitMutex;
-    std::mutex guardMutex;
-    std::condition_variable waitCV;
-
-    Cruise_finite1_deterministic_MC machine = Cruise_finite1_deterministic_MC();
-
-
-    std::atomic<bool> invariantViolated;
-    invariantViolated = false;
-    std::atomic<bool> deadlockDetected;
-    deadlockDetected = false;
-    std::atomic<bool> stopThreads;
-    stopThreads = false;
-
-    std::unordered_set<Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> states = std::unordered_set<Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual>();
-    states.insert(machine);
-    std::atomic<int> numberStates;
-    numberStates = 1;
-
-    std::list<Cruise_finite1_deterministic_MC> collection = std::list<Cruise_finite1_deterministic_MC>();
-    collection.push_back(machine);
-
-    std::atomic<int> transitions;
-    transitions = 0;
-
-    std::atomic<int> possibleQueueChanges;
-    possibleQueueChanges = 0;
-
-    std::atomic<bool> waitFlag;
-    waitFlag = true;
-
-    std::unordered_map<string, std::unordered_set<string>> invariantDependency;
-    std::unordered_map<string, std::unordered_set<string>> guardDependency;
-    std::unordered_map<Cruise_finite1_deterministic_MC, std::unordered_set<string>, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> dependentInvariant;
-    std::unordered_map<Cruise_finite1_deterministic_MC, std::unordered_set<string>, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> dependentGuard;
-    std::unordered_map<Cruise_finite1_deterministic_MC, immer::map<string, boost::any>, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> guardCache;
-    std::unordered_map<Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> parents;
-    std::unordered_map<Cruise_finite1_deterministic_MC, string, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> stateAccessedVia;
-    if(isCaching) {
-        invariantDependency.insert({"ObstacleStopsTravelSlower", {"_check_inv_29", "_check_inv_39", "_check_inv_38", "_check_inv_37", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_13", "_check_inv_35", "_check_inv_24"}});
-        invariantDependency.insert({"SetCruiseSpeed", {"_check_inv_18", "_check_inv_17", "_check_inv_39", "_check_inv_16", "_check_inv_38", "_check_inv_15", "_check_inv_37", "_check_inv_19", "_check_inv_10", "_check_inv_14", "_check_inv_36", "_check_inv_35", "_check_inv_34", "_check_inv_33", "_check_inv_26", "_check_inv_21", "_check_inv_20", "_check_inv_4", "_check_inv_25", "_check_inv_24", "_check_inv_8", "_check_inv_23", "_check_inv_9", "_check_inv_22", "_check_inv_2", "_check_inv_3"}});
-        invariantDependency.insert({"VehicleLeavesCruiseSpeed", {"_check_inv_17", "_check_inv_3", "_check_inv_34"}});
-        invariantDependency.insert({"VehicleFallsBelowMaxCruiseSpeed", {"_check_inv_17", "_check_inv_3", "_check_inv_6", "_check_inv_34"}});
-        invariantDependency.insert({"CCInitialisationFinished", {"_check_inv_39", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_19", "_check_inv_32", "_check_inv_21", "_check_inv_31", "_check_inv_7", "_check_inv_30", "_check_inv_5", "_check_inv_36", "_check_inv_35"}});
-        invariantDependency.insert({"VehicleReachesCruiseSpeed", {"_check_inv_17", "_check_inv_3", "_check_inv_34"}});
-        invariantDependency.insert({"ObstacleAppearsWhenCruiseActive", {"_check_inv_29", "_check_inv_39", "_check_inv_28", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_13", "_check_inv_35", "_check_inv_24", "_check_inv_12", "_check_inv_23", "_check_inv_11"}});
-        invariantDependency.insert({"ObstacleStartsTravelSlower", {"_check_inv_29", "_check_inv_39", "_check_inv_38", "_check_inv_37", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_13", "_check_inv_35", "_check_inv_24"}});
-        invariantDependency.insert({"CruiseBecomesNotAllowed", {"_check_inv_18", "_check_inv_17", "_check_inv_39", "_check_inv_16", "_check_inv_38", "_check_inv_15", "_check_inv_37", "_check_inv_19", "_check_inv_10", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_35", "_check_inv_12", "_check_inv_34", "_check_inv_33", "_check_inv_28", "_check_inv_27", "_check_inv_26", "_check_inv_21", "_check_inv_7", "_check_inv_20", "_check_inv_4", "_check_inv_5", "_check_inv_25", "_check_inv_24", "_check_inv_8", "_check_inv_23", "_check_inv_9", "_check_inv_22", "_check_inv_2", "_check_inv_3", "_check_inv_1"}});
-        invariantDependency.insert({"ObstacleAppearsWhenCruiseInactive", {"_check_inv_29", "_check_inv_39", "_check_inv_28", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_36", "_check_inv_13", "_check_inv_12", "_check_inv_23", "_check_inv_11"}});
-        invariantDependency.insert({"CCInitialisationDelayFinished", {"_check_inv_39", "_check_inv_38", "_check_inv_15", "_check_inv_37", "_check_inv_36", "_check_inv_25", "_check_inv_35"}});
-        invariantDependency.insert({"ObstacleDistanceBecomesClose", {"_check_inv_39", "_check_inv_28", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_32", "_check_inv_21", "_check_inv_31", "_check_inv_7", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_35", "_check_inv_24", "_check_inv_12", "_check_inv_23"}});
-        invariantDependency.insert({"ObstacleStartsTravelFaster", {"_check_inv_29", "_check_inv_39", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_32", "_check_inv_21", "_check_inv_31", "_check_inv_7", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_13", "_check_inv_35", "_check_inv_24"}});
-        invariantDependency.insert({"ExternalForcesBecomesExtreme", {"_check_inv_18", "_check_inv_4"}});
-        invariantDependency.insert({"CruiseOff", {"_check_inv_18", "_check_inv_17", "_check_inv_39", "_check_inv_16", "_check_inv_38", "_check_inv_15", "_check_inv_37", "_check_inv_19", "_check_inv_10", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_35", "_check_inv_12", "_check_inv_34", "_check_inv_33", "_check_inv_28", "_check_inv_27", "_check_inv_26", "_check_inv_21", "_check_inv_7", "_check_inv_20", "_check_inv_4", "_check_inv_5", "_check_inv_25", "_check_inv_24", "_check_inv_8", "_check_inv_23", "_check_inv_9", "_check_inv_22", "_check_inv_2", "_check_inv_3"}});
-        invariantDependency.insert({"CruiseSpeedChangeDelayFinished", {"_check_inv_39", "_check_inv_16", "_check_inv_38", "_check_inv_37", "_check_inv_26", "_check_inv_36", "_check_inv_35"}});
-        invariantDependency.insert({"ObstacleStopsTravelFaster", {"_check_inv_29", "_check_inv_39", "_check_inv_38", "_check_inv_37", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_13", "_check_inv_35", "_check_inv_24"}});
-        invariantDependency.insert({"ObstacleDistanceBecomesVeryClose", {"_check_inv_39", "_check_inv_28", "_check_inv_38", "_check_inv_37", "_check_inv_32", "_check_inv_31", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_35", "_check_inv_24", "_check_inv_12", "_check_inv_23"}});
-        invariantDependency.insert({"VehicleManageObstacle", {"_check_inv_39", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_19", "_check_inv_32", "_check_inv_21", "_check_inv_31", "_check_inv_7", "_check_inv_30", "_check_inv_5", "_check_inv_36", "_check_inv_35"}});
-        invariantDependency.insert({"CruiseBecomesAllowed", {"_check_inv_1", "_check_inv_33"}});
-        invariantDependency.insert({"VehicleExceedsMaxCruiseSpeed", {"_check_inv_17", "_check_inv_3", "_check_inv_6", "_check_inv_34"}});
-        invariantDependency.insert({"CruiseSpeedChangeFinished", {"_check_inv_39", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_19", "_check_inv_32", "_check_inv_21", "_check_inv_31", "_check_inv_7", "_check_inv_30", "_check_inv_5", "_check_inv_36", "_check_inv_35"}});
-        invariantDependency.insert({"ObstacleDisappears", {"_check_inv_29", "_check_inv_39", "_check_inv_28", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_32", "_check_inv_21", "_check_inv_31", "_check_inv_7", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_13", "_check_inv_35", "_check_inv_24", "_check_inv_12", "_check_inv_23", "_check_inv_11"}});
-        invariantDependency.insert({"ExternalForcesBecomesNormal", {"_check_inv_18", "_check_inv_4"}});
-        invariantDependency.insert({"ObstacleBecomesOld", {"_check_inv_39", "_check_inv_38", "_check_inv_37", "_check_inv_14", "_check_inv_36", "_check_inv_35", "_check_inv_24"}});
-        invariantDependency.insert({"ObstacleDistanceBecomesBig", {"_check_inv_39", "_check_inv_28", "_check_inv_38", "_check_inv_27", "_check_inv_37", "_check_inv_32", "_check_inv_21", "_check_inv_31", "_check_inv_7", "_check_inv_30", "_check_inv_14", "_check_inv_36", "_check_inv_35", "_check_inv_24", "_check_inv_12", "_check_inv_23"}});
-        guardDependency.insert({"ObstacleStopsTravelSlower", {"_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStopsTravelSlower", "_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseSpeedChangeFinished", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStartsTravelFaster", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose"}});
-        guardDependency.insert({"SetCruiseSpeed", {"_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesClose", "_tr_ExternalForcesBecomesNormal", "_tr_CruiseSpeedChangeFinished", "_tr_ExternalForcesBecomesExtreme", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_VehicleLeavesCruiseSpeed", "_tr_ObstacleAppearsWhenCruiseActive", "_tr_VehicleReachesCruiseSpeed", "_tr_CruiseOff", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleAppearsWhenCruiseInactive"}});
-        guardDependency.insert({"VehicleLeavesCruiseSpeed", {"_tr_VehicleReachesCruiseSpeed", "_tr_VehicleLeavesCruiseSpeed"}});
-        guardDependency.insert({"VehicleFallsBelowMaxCruiseSpeed", {"_tr_VehicleReachesCruiseSpeed", "_tr_VehicleFallsBelowMaxCruiseSpeed", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_VehicleLeavesCruiseSpeed"}});
-        guardDependency.insert({"CCInitialisationFinished", {"_tr_ObstacleBecomesOld", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_VehicleLeavesCruiseSpeed"}});
-        guardDependency.insert({"VehicleReachesCruiseSpeed", {"_tr_VehicleReachesCruiseSpeed", "_tr_VehicleLeavesCruiseSpeed"}});
-        guardDependency.insert({"ObstacleAppearsWhenCruiseActive", {"_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStopsTravelSlower", "_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleDisappears", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStartsTravelFaster", "_tr_ObstacleAppearsWhenCruiseActive", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_ObstacleAppearsWhenCruiseInactive"}});
-        guardDependency.insert({"ObstacleStartsTravelSlower", {"_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStopsTravelSlower", "_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseSpeedChangeFinished", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStartsTravelFaster", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose"}});
-        guardDependency.insert({"CruiseBecomesNotAllowed", {"_tr_SetCruiseSpeed", "_tr_VehicleManageObstacle", "_tr_CruiseBecomesAllowed", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseBecomesNotAllowed", "_tr_ExternalForcesBecomesNormal", "_tr_CruiseSpeedChangeFinished", "_tr_ExternalForcesBecomesExtreme", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_VehicleLeavesCruiseSpeed", "_tr_ObstacleAppearsWhenCruiseActive", "_tr_VehicleReachesCruiseSpeed", "_tr_CruiseOff", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_ObstacleAppearsWhenCruiseInactive"}});
-        guardDependency.insert({"ObstacleAppearsWhenCruiseInactive", {"_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStopsTravelSlower", "_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleDisappears", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStartsTravelFaster", "_tr_ObstacleAppearsWhenCruiseActive", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_ObstacleAppearsWhenCruiseInactive"}});
-        guardDependency.insert({"CCInitialisationDelayFinished", {"_tr_VehicleManageObstacle", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleBecomesOld", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished"}});
-        guardDependency.insert({"ObstacleDistanceBecomesClose", {"_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished"}});
-        guardDependency.insert({"ObstacleStartsTravelFaster", {"_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStopsTravelSlower", "_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseSpeedChangeFinished", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStartsTravelFaster", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose"}});
-        guardDependency.insert({"ExternalForcesBecomesExtreme", {"_tr_ExternalForcesBecomesNormal", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ExternalForcesBecomesExtreme", "_tr_VehicleLeavesCruiseSpeed"}});
-        guardDependency.insert({"CruiseOff", {"_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_ExternalForcesBecomesNormal", "_tr_CruiseSpeedChangeFinished", "_tr_ExternalForcesBecomesExtreme", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_VehicleLeavesCruiseSpeed", "_tr_ObstacleAppearsWhenCruiseActive", "_tr_VehicleReachesCruiseSpeed", "_tr_CruiseOff", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_ObstacleAppearsWhenCruiseInactive"}});
-        guardDependency.insert({"CruiseSpeedChangeDelayFinished", {"_tr_VehicleManageObstacle", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleBecomesOld", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished"}});
-        guardDependency.insert({"ObstacleStopsTravelFaster", {"_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStopsTravelSlower", "_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseSpeedChangeFinished", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStartsTravelFaster", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose"}});
-        guardDependency.insert({"ObstacleDistanceBecomesVeryClose", {"_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished"}});
-        guardDependency.insert({"VehicleManageObstacle", {"_tr_ObstacleBecomesOld", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_VehicleLeavesCruiseSpeed"}});
-        guardDependency.insert({"CruiseBecomesAllowed", {"_tr_SetCruiseSpeed", "_tr_CruiseBecomesAllowed", "_tr_CruiseBecomesNotAllowed"}});
-        guardDependency.insert({"VehicleExceedsMaxCruiseSpeed", {"_tr_VehicleReachesCruiseSpeed", "_tr_VehicleFallsBelowMaxCruiseSpeed", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_VehicleLeavesCruiseSpeed"}});
-        guardDependency.insert({"CruiseSpeedChangeFinished", {"_tr_ObstacleBecomesOld", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_VehicleLeavesCruiseSpeed"}});
-        guardDependency.insert({"ObstacleDisappears", {"_tr_ObstacleStopsTravelFaster", "_tr_ObstacleStopsTravelSlower", "_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleDisappears", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished", "_tr_ObstacleStartsTravelSlower", "_tr_ObstacleStartsTravelFaster", "_tr_ObstacleAppearsWhenCruiseActive", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_ObstacleAppearsWhenCruiseInactive"}});
-        guardDependency.insert({"ExternalForcesBecomesNormal", {"_tr_ExternalForcesBecomesNormal", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_ExternalForcesBecomesExtreme", "_tr_VehicleLeavesCruiseSpeed"}});
-        guardDependency.insert({"ObstacleBecomesOld", {"_tr_VehicleManageObstacle", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleBecomesOld", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished"}});
-        guardDependency.insert({"ObstacleDistanceBecomesBig", {"_tr_VehicleManageObstacle", "_tr_ObstacleDistanceBecomesBig", "_tr_ObstacleDistanceBecomesClose", "_tr_VehicleExceedsMaxCruiseSpeed", "_tr_CruiseSpeedChangeFinished", "_tr_ObstacleBecomesOld", "_tr_ObstacleDistanceBecomesVeryClose", "_tr_CCInitialisationFinished", "_tr_CCInitialisationDelayFinished", "_tr_CruiseSpeedChangeDelayFinished"}});
-        dependentInvariant.insert({machine, std::unordered_set<string>()});
-    }
-    Cruise_finite1_deterministic_MC counterExampleState;
-
-    boost::asio::thread_pool workers(threads);
-
-    while(!collection.empty() && !stopThreads) {
-        possibleQueueChanges += 1;
-        Cruise_finite1_deterministic_MC state = next(collection, mutex, type);
-        std::packaged_task<void()> task([&, state] {
-            std::unordered_set<Cruise_finite1_deterministic_MC, Cruise_finite1_deterministic_MC::Hash, Cruise_finite1_deterministic_MC::HashEqual> nextStates = generateNextStates(guardMutex, state, isCaching, invariantDependency, dependentInvariant, guardDependency, dependentGuard, guardCache, parents, stateAccessedVia, transitions);
-
-
-            for(auto nextState : nextStates) {
-                {
-                    std::unique_lock<std::mutex> lock(mutex);
-                    if(states.find(nextState) == states.end()) {
-                        numberStates += 1;
-                        states.insert(nextState);
-                        collection.push_back(nextState);
-                        if(numberStates % 50000 == 0) {
-                            cout << "VISITED STATES: " << numberStates << "\n";
-                            cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
-                            cout << "-------------------" << "\n";
-                        }
-                    }
-                }
-            }
-
-            {
-                std::unique_lock<std::mutex> lock(mutex);
-                possibleQueueChanges -= 1;
-                int running = possibleQueueChanges;
-                if (!collection.empty() || running == 0) {
-                    {
-                        std::unique_lock<std::mutex> lock(waitMutex);
-                        waitFlag = false;
-                        waitCV.notify_one();
-                    }
-                }
-            }
-
-            if(nextStates.empty()) {
-                deadlockDetected = true;
-                stopThreads = true;
-                counterExampleState = state;
-            }
-
-            if(!checkInvariants(guardMutex, state, isCaching, dependentInvariant)) {
-                invariantViolated = true;
-                stopThreads = true;
-                counterExampleState = state;
-            }
-
-
-        });
-        waitFlag = true;
-        boost::asio::post(workers, std::move(task));
-
-        {
-            std::unique_lock<std::mutex> lock(waitMutex);
-            if (collection.empty() && possibleQueueChanges > 0) {
-                waitCV.wait(lock, [&] {
-                    return waitFlag == false;
-                });
-            }
-        }
-    }
-    workers.join();
-    printResult(numberStates, transitions, deadlockDetected, invariantViolated, counterExampleState, parents, stateAccessedVia);
-}
+};
 
 int main(int argc, char *argv[]) {
     if(argc != 4) {
@@ -2784,11 +1813,12 @@ int main(int argc, char *argv[]) {
         return - 1;
     }
 
-    if(threads == 1) {
-        modelCheckSingleThreaded(type, isCaching);
-    } else {
-        modelCheckMultiThreaded(type, threads, isCaching);
-    }
+    bool isDebug = true;
+    // TODO
+
+    ModelChecker modelchecker(type, threads, isCaching, isDebug);
+    modelchecker.modelCheck();
+
     return 0;
 }
 
diff --git a/benchmarks/model_checking/C++/LandingGear_R6.cpp b/benchmarks/model_checking/C++/LandingGear_R6.cpp
index 0881404a354a0a889133cd159cd42883c2f3bc1a..1550b6d6b28b9fb54fcd41571023da22355827fd 100644
--- a/benchmarks/model_checking/C++/LandingGear_R6.cpp
+++ b/benchmarks/model_checking/C++/LandingGear_R6.cpp
@@ -11,6 +11,7 @@
 #include <boost/asio/post.hpp>
 #include <boost/asio/thread_pool.hpp>
 #include <boost/any.hpp>
+#include <boost/optional.hpp>
 #include <btypes_primitives/BUtils.hpp>
 #include <btypes_primitives/StateNotReachableError.hpp>
 #include <btypes_primitives/PreconditionOrAssertionViolation.hpp>
@@ -31,7 +32,6 @@ class LandingGear_R6 {
 
         enum Type { BFS, DFS, MIXED };
 
-
         class DOOR_STATE : public BObject {
             public:
 
@@ -409,6 +409,7 @@ class LandingGear_R6 {
                 }
         };
 
+
         struct Hash {
             public:
                 size_t operator()(const LandingGear_R6& obj) const {
@@ -457,9 +458,49 @@ class LandingGear_R6 {
         DOOR_STATE door;
         GEAR_STATE gear;
 
+        mutable boost::optional<bool> _tr_cache_begin_flying;
+        mutable boost::optional<bool> _tr_cache_land_plane;
+        mutable boost::optional<bool> _tr_cache_open_valve_door_open;
+        mutable boost::optional<bool> _tr_cache_close_valve_door_open;
+        mutable boost::optional<bool> _tr_cache_open_valve_door_close;
+        mutable boost::optional<bool> _tr_cache_close_valve_door_close;
+        mutable boost::optional<bool> _tr_cache_open_valve_retract_gear;
+        mutable boost::optional<bool> _tr_cache_close_valve_retract_gear;
+        mutable boost::optional<bool> _tr_cache_open_valve_extend_gear;
+        mutable boost::optional<bool> _tr_cache_close_valve_extend_gear;
+        mutable boost::optional<bool> _tr_cache_con_stimulate_open_door_valve;
+        mutable boost::optional<bool> _tr_cache_con_stop_stimulate_open_door_valve;
+        mutable boost::optional<bool> _tr_cache_con_stimulate_close_door_valve;
+        mutable boost::optional<bool> _tr_cache_con_stop_stimulate_close_door_valve;
+        mutable boost::optional<bool> _tr_cache_con_stimulate_retract_gear_valve;
+        mutable boost::optional<bool> _tr_cache_con_stop_stimulate_retract_gear_valve;
+        mutable boost::optional<bool> _tr_cache_con_stimulate_extend_gear_valve;
+        mutable boost::optional<bool> _tr_cache_con_stop_stimulate_extend_gear_valve;
+        mutable boost::optional<BSet<POSITION>> _tr_cache_env_start_retracting_first;
+        mutable boost::optional<BSet<POSITION>> _tr_cache_env_retract_gear_skip;
+        mutable boost::optional<BSet<POSITION>> _tr_cache_env_retract_gear_last;
+        mutable boost::optional<BSet<POSITION>> _tr_cache_env_start_extending;
+        mutable boost::optional<BSet<POSITION>> _tr_cache_env_extend_gear_last;
+        mutable boost::optional<BSet<POSITION>> _tr_cache_env_extend_gear_skip;
+        mutable boost::optional<BSet<POSITION>> _tr_cache_env_start_open_door;
+        mutable boost::optional<BSet<POSITION>> _tr_cache_env_open_door_last;
+        mutable boost::optional<BSet<POSITION>> _tr_cache_env_open_door_skip;
+        mutable boost::optional<BSet<POSITION>> _tr_cache_env_start_close_door;
+        mutable boost::optional<BSet<POSITION>> _tr_cache_env_close_door;
+        mutable boost::optional<BSet<POSITION>> _tr_cache_env_close_door_skip;
+        mutable boost::optional<bool> _tr_cache_toggle_handle_up;
+        mutable boost::optional<bool> _tr_cache_toggle_handle_down;
+        mutable boost::optional<bool> _tr_cache_con_stimulate_general_valve;
+        mutable boost::optional<bool> _tr_cache_con_stop_stimulate_general_valve;
+        mutable boost::optional<bool> _tr_cache_evn_open_general_valve;
+        mutable boost::optional<bool> _tr_cache_evn_close_general_valve;
+        mutable boost::optional<bool> _tr_cache_env_close_analogical_switch;
+        mutable boost::optional<bool> _tr_cache_env_open_analogical_switch;
 
     public:
 
+        std::string stateAccessedVia;
+
         LandingGear_R6() {
             gears = (BRelation<POSITION, GEAR_STATE >::cartesianProduct(_POSITION, (BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))));
             doors = (BRelation<POSITION, DOOR_STATE >::cartesianProduct(_POSITION, (BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::closed))))));
@@ -812,240 +853,418 @@ class LandingGear_R6 {
         }
 
 
-        bool _tr_begin_flying() const {
-            return (shock_absorber.equal((PLANE_STATE(PLANE_STATE::ground)))).booleanValue();
+        bool _tr_begin_flying(bool isCaching) const {
+            if (this->_tr_cache_begin_flying == boost::none){
+                bool __tmp_result = (shock_absorber.equal((PLANE_STATE(PLANE_STATE::ground)))).booleanValue();
+                if (isCaching) this->_tr_cache_begin_flying = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_begin_flying.get();
         }
 
-        bool _tr_land_plane() const {
-            return (shock_absorber.equal((PLANE_STATE(PLANE_STATE::flight)))).booleanValue();
+        bool _tr_land_plane(bool isCaching) const {
+            if (this->_tr_cache_land_plane == boost::none){
+                bool __tmp_result = (shock_absorber.equal((PLANE_STATE(PLANE_STATE::flight)))).booleanValue();
+                if (isCaching) this->_tr_cache_land_plane = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_land_plane.get();
         }
 
-        bool _tr_open_valve_door_open() const {
-            return ((BBoolean(valve_open_door.equal((VALVE_STATE(VALVE_STATE::valve_closed))).booleanValue() && open_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+        bool _tr_open_valve_door_open(bool isCaching) const {
+            if (this->_tr_cache_open_valve_door_open == boost::none){
+                bool __tmp_result = ((BBoolean(valve_open_door.equal((VALVE_STATE(VALVE_STATE::valve_closed))).booleanValue() && open_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_open_valve_door_open = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_open_valve_door_open.get();
         }
 
-        bool _tr_close_valve_door_open() const {
-            return ((BBoolean(valve_open_door.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue() && open_EV.equal((BBoolean(false))).booleanValue()))).booleanValue();
+        bool _tr_close_valve_door_open(bool isCaching) const {
+            if (this->_tr_cache_close_valve_door_open == boost::none){
+                bool __tmp_result = ((BBoolean(valve_open_door.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue() && open_EV.equal((BBoolean(false))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_close_valve_door_open = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_close_valve_door_open.get();
         }
 
-        bool _tr_open_valve_door_close() const {
-            return ((BBoolean(valve_close_door.equal((VALVE_STATE(VALVE_STATE::valve_closed))).booleanValue() && close_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+        bool _tr_open_valve_door_close(bool isCaching) const {
+            if (this->_tr_cache_open_valve_door_close == boost::none){
+                bool __tmp_result = ((BBoolean(valve_close_door.equal((VALVE_STATE(VALVE_STATE::valve_closed))).booleanValue() && close_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_open_valve_door_close = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_open_valve_door_close.get();
         }
 
-        bool _tr_close_valve_door_close() const {
-            return ((BBoolean(valve_close_door.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue() && close_EV.equal((BBoolean(false))).booleanValue()))).booleanValue();
+        bool _tr_close_valve_door_close(bool isCaching) const {
+            if (this->_tr_cache_close_valve_door_close == boost::none){
+                bool __tmp_result = ((BBoolean(valve_close_door.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue() && close_EV.equal((BBoolean(false))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_close_valve_door_close = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_close_valve_door_close.get();
         }
 
-        bool _tr_open_valve_retract_gear() const {
-            return ((BBoolean(valve_retract_gear.equal((VALVE_STATE(VALVE_STATE::valve_closed))).booleanValue() && retract_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+        bool _tr_open_valve_retract_gear(bool isCaching) const {
+            if (this->_tr_cache_open_valve_retract_gear == boost::none){
+                bool __tmp_result = ((BBoolean(valve_retract_gear.equal((VALVE_STATE(VALVE_STATE::valve_closed))).booleanValue() && retract_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_open_valve_retract_gear = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_open_valve_retract_gear.get();
         }
 
-        bool _tr_close_valve_retract_gear() const {
-            return ((BBoolean(valve_retract_gear.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue() && retract_EV.equal((BBoolean(false))).booleanValue()))).booleanValue();
+        bool _tr_close_valve_retract_gear(bool isCaching) const {
+            if (this->_tr_cache_close_valve_retract_gear == boost::none){
+                bool __tmp_result = ((BBoolean(valve_retract_gear.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue() && retract_EV.equal((BBoolean(false))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_close_valve_retract_gear = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_close_valve_retract_gear.get();
         }
 
-        bool _tr_open_valve_extend_gear() const {
-            return ((BBoolean(valve_extend_gear.equal((VALVE_STATE(VALVE_STATE::valve_closed))).booleanValue() && extend_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+        bool _tr_open_valve_extend_gear(bool isCaching) const {
+            if (this->_tr_cache_open_valve_extend_gear == boost::none){
+                bool __tmp_result = ((BBoolean(valve_extend_gear.equal((VALVE_STATE(VALVE_STATE::valve_closed))).booleanValue() && extend_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_open_valve_extend_gear = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_open_valve_extend_gear.get();
         }
 
-        bool _tr_close_valve_extend_gear() const {
-            return ((BBoolean(valve_extend_gear.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue() && extend_EV.equal((BBoolean(false))).booleanValue()))).booleanValue();
+        bool _tr_close_valve_extend_gear(bool isCaching) const {
+            if (this->_tr_cache_close_valve_extend_gear == boost::none){
+                bool __tmp_result = ((BBoolean(valve_extend_gear.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue() && extend_EV.equal((BBoolean(false))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_close_valve_extend_gear = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_close_valve_extend_gear.get();
         }
 
-        bool _tr_con_stimulate_open_door_valve() const {
-            return ((BBoolean((BBoolean((BBoolean(open_EV.equal((BBoolean(false))).booleanValue() && close_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended)))))._not().booleanValue())).booleanValue() || (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted)))))._not().booleanValue())).booleanValue() && (BBoolean(doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue() && shock_absorber.equal((PLANE_STATE(PLANE_STATE::ground))).booleanValue()))._not().booleanValue())).booleanValue())).booleanValue())).booleanValue() && general_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+        bool _tr_con_stimulate_open_door_valve(bool isCaching) const {
+            if (this->_tr_cache_con_stimulate_open_door_valve == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean((BBoolean(open_EV.equal((BBoolean(false))).booleanValue() && close_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended)))))._not().booleanValue())).booleanValue() || (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted)))))._not().booleanValue())).booleanValue() && (BBoolean(doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue() && shock_absorber.equal((PLANE_STATE(PLANE_STATE::ground))).booleanValue()))._not().booleanValue())).booleanValue())).booleanValue())).booleanValue() && general_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_con_stimulate_open_door_valve = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_con_stimulate_open_door_valve.get();
         }
 
-        bool _tr_con_stop_stimulate_open_door_valve() const {
-            return ((BBoolean((BBoolean((BBoolean((BBoolean(open_EV.equal((BBoolean(true))).booleanValue() && extend_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && retract_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue() || (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && (BBoolean(gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue() || shock_absorber.equal((PLANE_STATE(PLANE_STATE::ground))).booleanValue())).booleanValue())).booleanValue() && doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue())).booleanValue())).booleanValue())).booleanValue() && general_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+        bool _tr_con_stop_stimulate_open_door_valve(bool isCaching) const {
+            if (this->_tr_cache_con_stop_stimulate_open_door_valve == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean((BBoolean((BBoolean(open_EV.equal((BBoolean(true))).booleanValue() && extend_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && retract_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue() || (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && (BBoolean(gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue() || shock_absorber.equal((PLANE_STATE(PLANE_STATE::ground))).booleanValue())).booleanValue())).booleanValue() && doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue())).booleanValue())).booleanValue())).booleanValue() && general_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_con_stop_stimulate_open_door_valve = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_con_stop_stimulate_open_door_valve.get();
         }
 
-        bool _tr_con_stimulate_close_door_valve() const {
-            return ((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(close_EV.equal((BBoolean(false))).booleanValue() && open_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && extend_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && retract_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && (BBoolean(gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue() || shock_absorber.equal((PLANE_STATE(PLANE_STATE::ground))).booleanValue())).booleanValue())).booleanValue())).booleanValue())).booleanValue() && doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::closed)))))._not().booleanValue())).booleanValue() && general_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+        bool _tr_con_stimulate_close_door_valve(bool isCaching) const {
+            if (this->_tr_cache_con_stimulate_close_door_valve == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(close_EV.equal((BBoolean(false))).booleanValue() && open_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && extend_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && retract_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && (BBoolean(gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue() || shock_absorber.equal((PLANE_STATE(PLANE_STATE::ground))).booleanValue())).booleanValue())).booleanValue())).booleanValue())).booleanValue() && doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::closed)))))._not().booleanValue())).booleanValue() && general_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_con_stimulate_close_door_valve = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_con_stimulate_close_door_valve.get();
         }
 
-        bool _tr_con_stop_stimulate_close_door_valve() const {
-            return ((BBoolean((BBoolean(close_EV.equal((BBoolean(true))).booleanValue() && (BBoolean((BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue() && doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::closed))))).booleanValue())).booleanValue() || (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && (BBoolean(gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue() || shock_absorber.equal((PLANE_STATE(PLANE_STATE::ground))).booleanValue())).booleanValue())).booleanValue() && doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::closed))))).booleanValue())).booleanValue())).booleanValue())).booleanValue() && general_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+        bool _tr_con_stop_stimulate_close_door_valve(bool isCaching) const {
+            if (this->_tr_cache_con_stop_stimulate_close_door_valve == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean(close_EV.equal((BBoolean(true))).booleanValue() && (BBoolean((BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue() && doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::closed))))).booleanValue())).booleanValue() || (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && (BBoolean(gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue() || shock_absorber.equal((PLANE_STATE(PLANE_STATE::ground))).booleanValue())).booleanValue())).booleanValue() && doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::closed))))).booleanValue())).booleanValue())).booleanValue())).booleanValue() && general_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_con_stop_stimulate_close_door_valve = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_con_stop_stimulate_close_door_valve.get();
         }
 
-        bool _tr_con_stimulate_retract_gear_valve() const {
-            return ((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(retract_EV.equal((BBoolean(false))).booleanValue() && extend_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && open_EV.equal((BBoolean(true))).booleanValue())).booleanValue() && handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue())).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted)))))._not().booleanValue())).booleanValue() && shock_absorber.equal((PLANE_STATE(PLANE_STATE::flight))).booleanValue())).booleanValue() && doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue())).booleanValue() && general_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+        bool _tr_con_stimulate_retract_gear_valve(bool isCaching) const {
+            if (this->_tr_cache_con_stimulate_retract_gear_valve == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(retract_EV.equal((BBoolean(false))).booleanValue() && extend_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && open_EV.equal((BBoolean(true))).booleanValue())).booleanValue() && handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue())).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted)))))._not().booleanValue())).booleanValue() && shock_absorber.equal((PLANE_STATE(PLANE_STATE::flight))).booleanValue())).booleanValue() && doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue())).booleanValue() && general_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_con_stimulate_retract_gear_valve = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_con_stimulate_retract_gear_valve.get();
         }
 
-        bool _tr_con_stop_stimulate_retract_gear_valve() const {
-            return ((BBoolean((BBoolean(retract_EV.equal((BBoolean(true))).booleanValue() && (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() || gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue())).booleanValue())).booleanValue() && general_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+        bool _tr_con_stop_stimulate_retract_gear_valve(bool isCaching) const {
+            if (this->_tr_cache_con_stop_stimulate_retract_gear_valve == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean(retract_EV.equal((BBoolean(true))).booleanValue() && (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() || gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue())).booleanValue())).booleanValue() && general_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_con_stop_stimulate_retract_gear_valve = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_con_stop_stimulate_retract_gear_valve.get();
         }
 
-        bool _tr_con_stimulate_extend_gear_valve() const {
-            return ((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(extend_EV.equal((BBoolean(false))).booleanValue() && retract_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && open_EV.equal((BBoolean(true))).booleanValue())).booleanValue() && handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue())).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended)))))._not().booleanValue())).booleanValue() && doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue())).booleanValue() && general_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+        bool _tr_con_stimulate_extend_gear_valve(bool isCaching) const {
+            if (this->_tr_cache_con_stimulate_extend_gear_valve == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(extend_EV.equal((BBoolean(false))).booleanValue() && retract_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && open_EV.equal((BBoolean(true))).booleanValue())).booleanValue() && handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue())).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended)))))._not().booleanValue())).booleanValue() && doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue())).booleanValue() && general_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_con_stimulate_extend_gear_valve = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_con_stimulate_extend_gear_valve.get();
         }
 
-        bool _tr_con_stop_stimulate_extend_gear_valve() const {
-            return ((BBoolean((BBoolean(extend_EV.equal((BBoolean(true))).booleanValue() && (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() || gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue())).booleanValue() && general_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+        bool _tr_con_stop_stimulate_extend_gear_valve(bool isCaching) const {
+            if (this->_tr_cache_con_stop_stimulate_extend_gear_valve == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean(extend_EV.equal((BBoolean(true))).booleanValue() && (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() || gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue())).booleanValue() && general_EV.equal((BBoolean(true))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_con_stop_stimulate_extend_gear_valve = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_con_stop_stimulate_extend_gear_valve.get();
         }
 
-        BSet<POSITION> _tr_env_start_retracting_first() const {
-            BSet<POSITION> _ic_set_18 = BSet<POSITION>();
-            for(POSITION _ic_gr_1 : gears.domain()) {
-                if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue() && handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue())).booleanValue() && gears.functionCall(_ic_gr_1).equal((GEAR_STATE(GEAR_STATE::extended))).booleanValue())).booleanValue() && valve_retract_gear.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && (BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended)), (GEAR_STATE(GEAR_STATE::gear_moving)))).elementOf(gear).booleanValue())).booleanValue() && door.equal((DOOR_STATE(DOOR_STATE::open))).booleanValue()))).booleanValue()) {
-                    _ic_set_18 = _ic_set_18._union(BSet<POSITION>(_ic_gr_1));
-                }
+        BSet<POSITION> _tr_env_start_retracting_first(bool isCaching) const {
+            if (this->_tr_cache_env_start_retracting_first == boost::none){
+                BSet<POSITION> _ic_set_18 = BSet<POSITION>();
+                for(const POSITION& _ic_gr_1 : gears.domain()) {
+                    if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue() && handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue())).booleanValue() && gears.functionCall(_ic_gr_1).equal((GEAR_STATE(GEAR_STATE::extended))).booleanValue())).booleanValue() && valve_retract_gear.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && (BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended)), (GEAR_STATE(GEAR_STATE::gear_moving)))).elementOf(gear).booleanValue())).booleanValue() && door.equal((DOOR_STATE(DOOR_STATE::open))).booleanValue()))).booleanValue()) {
+                        _ic_set_18 = _ic_set_18._union(BSet<POSITION>(_ic_gr_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_env_start_retracting_first = _ic_set_18;
+                else return _ic_set_18;
             }
-            return _ic_set_18;
+            return this->_tr_cache_env_start_retracting_first.get();
         }
 
-        BSet<POSITION> _tr_env_retract_gear_skip() const {
-            BSet<POSITION> _ic_set_19 = BSet<POSITION>();
-            for(POSITION _ic_gr_1 : gears.domain()) {
-                if(((BBoolean((BBoolean((BBoolean((BBoolean(doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue() && gears.relationImage(_POSITION.difference((BSet<POSITION >(_ic_gr_1)))).unequal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue())).booleanValue() && handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue())).booleanValue() && gears.functionCall(_ic_gr_1).equal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue()))).booleanValue()) {
-                    _ic_set_19 = _ic_set_19._union(BSet<POSITION>(_ic_gr_1));
-                }
+        BSet<POSITION> _tr_env_retract_gear_skip(bool isCaching) const {
+            if (this->_tr_cache_env_retract_gear_skip == boost::none){
+                BSet<POSITION> _ic_set_19 = BSet<POSITION>();
+                for(const POSITION& _ic_gr_1 : gears.domain()) {
+                    if(((BBoolean((BBoolean((BBoolean((BBoolean(doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue() && gears.relationImage(_POSITION.difference((BSet<POSITION >(_ic_gr_1)))).unequal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue())).booleanValue() && handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue())).booleanValue() && gears.functionCall(_ic_gr_1).equal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue()))).booleanValue()) {
+                        _ic_set_19 = _ic_set_19._union(BSet<POSITION>(_ic_gr_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_env_retract_gear_skip = _ic_set_19;
+                else return _ic_set_19;
             }
-            return _ic_set_19;
+            return this->_tr_cache_env_retract_gear_skip.get();
         }
 
-        BSet<POSITION> _tr_env_retract_gear_last() const {
-            BSet<POSITION> _ic_set_20 = BSet<POSITION>();
-            for(POSITION _ic_gr_1 : gears.domain()) {
-                if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue() && gears.relationImage(_POSITION.difference((BSet<POSITION >(_ic_gr_1)))).equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue())).booleanValue() && handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue())).booleanValue() && gears.functionCall(_ic_gr_1).equal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && gear.equal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && door.equal((DOOR_STATE(DOOR_STATE::open))).booleanValue()))).booleanValue()) {
-                    _ic_set_20 = _ic_set_20._union(BSet<POSITION>(_ic_gr_1));
-                }
+        BSet<POSITION> _tr_env_retract_gear_last(bool isCaching) const {
+            if (this->_tr_cache_env_retract_gear_last == boost::none){
+                BSet<POSITION> _ic_set_20 = BSet<POSITION>();
+                for(const POSITION& _ic_gr_1 : gears.domain()) {
+                    if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue() && gears.relationImage(_POSITION.difference((BSet<POSITION >(_ic_gr_1)))).equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue())).booleanValue() && handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue())).booleanValue() && gears.functionCall(_ic_gr_1).equal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && gear.equal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && door.equal((DOOR_STATE(DOOR_STATE::open))).booleanValue()))).booleanValue()) {
+                        _ic_set_20 = _ic_set_20._union(BSet<POSITION>(_ic_gr_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_env_retract_gear_last = _ic_set_20;
+                else return _ic_set_20;
             }
-            return _ic_set_20;
+            return this->_tr_cache_env_retract_gear_last.get();
         }
 
-        BSet<POSITION> _tr_env_start_extending() const {
-            BSet<POSITION> _ic_set_21 = BSet<POSITION>();
-            for(POSITION _ic_gr_1 : gears.domain()) {
-                if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue() && handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue())).booleanValue() && gears.functionCall(_ic_gr_1).equal((GEAR_STATE(GEAR_STATE::retracted))).booleanValue())).booleanValue() && valve_extend_gear.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && (BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::gear_moving)), (GEAR_STATE(GEAR_STATE::retracted)))).elementOf(gear).booleanValue())).booleanValue() && door.equal((DOOR_STATE(DOOR_STATE::open))).booleanValue()))).booleanValue()) {
-                    _ic_set_21 = _ic_set_21._union(BSet<POSITION>(_ic_gr_1));
-                }
+        BSet<POSITION> _tr_env_start_extending(bool isCaching) const {
+            if (this->_tr_cache_env_start_extending == boost::none){
+                BSet<POSITION> _ic_set_21 = BSet<POSITION>();
+                for(const POSITION& _ic_gr_1 : gears.domain()) {
+                    if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue() && handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue())).booleanValue() && gears.functionCall(_ic_gr_1).equal((GEAR_STATE(GEAR_STATE::retracted))).booleanValue())).booleanValue() && valve_extend_gear.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && (BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::gear_moving)), (GEAR_STATE(GEAR_STATE::retracted)))).elementOf(gear).booleanValue())).booleanValue() && door.equal((DOOR_STATE(DOOR_STATE::open))).booleanValue()))).booleanValue()) {
+                        _ic_set_21 = _ic_set_21._union(BSet<POSITION>(_ic_gr_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_env_start_extending = _ic_set_21;
+                else return _ic_set_21;
             }
-            return _ic_set_21;
+            return this->_tr_cache_env_start_extending.get();
         }
 
-        BSet<POSITION> _tr_env_extend_gear_last() const {
-            BSet<POSITION> _ic_set_22 = BSet<POSITION>();
-            for(POSITION _ic_gr_1 : gears.domain()) {
-                if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue() && handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue())).booleanValue() && gears.relationImage(_POSITION.difference((BSet<POSITION >(_ic_gr_1)))).equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue() && gears.functionCall(_ic_gr_1).equal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && gear.equal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && door.equal((DOOR_STATE(DOOR_STATE::open))).booleanValue()))).booleanValue()) {
-                    _ic_set_22 = _ic_set_22._union(BSet<POSITION>(_ic_gr_1));
-                }
+        BSet<POSITION> _tr_env_extend_gear_last(bool isCaching) const {
+            if (this->_tr_cache_env_extend_gear_last == boost::none){
+                BSet<POSITION> _ic_set_22 = BSet<POSITION>();
+                for(const POSITION& _ic_gr_1 : gears.domain()) {
+                    if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue() && handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue())).booleanValue() && gears.relationImage(_POSITION.difference((BSet<POSITION >(_ic_gr_1)))).equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue() && gears.functionCall(_ic_gr_1).equal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && gear.equal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && door.equal((DOOR_STATE(DOOR_STATE::open))).booleanValue()))).booleanValue()) {
+                        _ic_set_22 = _ic_set_22._union(BSet<POSITION>(_ic_gr_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_env_extend_gear_last = _ic_set_22;
+                else return _ic_set_22;
             }
-            return _ic_set_22;
+            return this->_tr_cache_env_extend_gear_last.get();
         }
 
-        BSet<POSITION> _tr_env_extend_gear_skip() const {
-            BSet<POSITION> _ic_set_23 = BSet<POSITION>();
-            for(POSITION _ic_gr_1 : gears.domain()) {
-                if(((BBoolean((BBoolean((BBoolean((BBoolean(doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue() && handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue())).booleanValue() && gears.relationImage(_POSITION.difference((BSet<POSITION >(_ic_gr_1)))).unequal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue() && gears.functionCall(_ic_gr_1).equal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue()))).booleanValue()) {
-                    _ic_set_23 = _ic_set_23._union(BSet<POSITION>(_ic_gr_1));
-                }
+        BSet<POSITION> _tr_env_extend_gear_skip(bool isCaching) const {
+            if (this->_tr_cache_env_extend_gear_skip == boost::none){
+                BSet<POSITION> _ic_set_23 = BSet<POSITION>();
+                for(const POSITION& _ic_gr_1 : gears.domain()) {
+                    if(((BBoolean((BBoolean((BBoolean((BBoolean(doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue() && handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue())).booleanValue() && gears.relationImage(_POSITION.difference((BSet<POSITION >(_ic_gr_1)))).unequal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue() && gears.functionCall(_ic_gr_1).equal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue()))).booleanValue()) {
+                        _ic_set_23 = _ic_set_23._union(BSet<POSITION>(_ic_gr_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_env_extend_gear_skip = _ic_set_23;
+                else return _ic_set_23;
             }
-            return _ic_set_23;
+            return this->_tr_cache_env_extend_gear_skip.get();
         }
 
-        BSet<POSITION> _tr_env_start_open_door() const {
-            BSet<POSITION> _ic_set_24 = BSet<POSITION>();
-            for(POSITION _ic_gr_1 : gears.domain()) {
-                if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(doors.functionCall(_ic_gr_1).equal((DOOR_STATE(DOOR_STATE::closed))).booleanValue() && gears.functionCall(_ic_gr_1).unequal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && gears.range().notElementOf((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue())).booleanValue())).booleanValue() && valve_open_door.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && (BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::closed)), (DOOR_STATE(DOOR_STATE::door_moving)))).elementOf(door).booleanValue())).booleanValue() && gear.unequal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gear.equal((GEAR_STATE(GEAR_STATE::retracted))).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && gear.equal((GEAR_STATE(GEAR_STATE::extended))).booleanValue())).booleanValue())).booleanValue()))).booleanValue()) {
-                    _ic_set_24 = _ic_set_24._union(BSet<POSITION>(_ic_gr_1));
-                }
+        BSet<POSITION> _tr_env_start_open_door(bool isCaching) const {
+            if (this->_tr_cache_env_start_open_door == boost::none){
+                BSet<POSITION> _ic_set_24 = BSet<POSITION>();
+                for(const POSITION& _ic_gr_1 : gears.domain()) {
+                    if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(doors.functionCall(_ic_gr_1).equal((DOOR_STATE(DOOR_STATE::closed))).booleanValue() && gears.functionCall(_ic_gr_1).unequal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && gears.range().notElementOf((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue())).booleanValue())).booleanValue() && valve_open_door.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && (BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::closed)), (DOOR_STATE(DOOR_STATE::door_moving)))).elementOf(door).booleanValue())).booleanValue() && gear.unequal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gear.equal((GEAR_STATE(GEAR_STATE::retracted))).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && gear.equal((GEAR_STATE(GEAR_STATE::extended))).booleanValue())).booleanValue())).booleanValue()))).booleanValue()) {
+                        _ic_set_24 = _ic_set_24._union(BSet<POSITION>(_ic_gr_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_env_start_open_door = _ic_set_24;
+                else return _ic_set_24;
             }
-            return _ic_set_24;
+            return this->_tr_cache_env_start_open_door.get();
         }
 
-        BSet<POSITION> _tr_env_open_door_last() const {
-            BSet<POSITION> _ic_set_25 = BSet<POSITION>();
-            for(POSITION _ic_gr_1 : gears.domain()) {
-                if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(doors.functionCall(_ic_gr_1).equal((DOOR_STATE(DOOR_STATE::door_moving))).booleanValue() && gears.functionCall(_ic_gr_1).unequal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && gears.range().notElementOf((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && doors.relationImage(_POSITION.difference((BSet<POSITION >(_ic_gr_1)))).equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue())).booleanValue())).booleanValue() && valve_open_door.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && door.equal((DOOR_STATE(DOOR_STATE::door_moving))).booleanValue())).booleanValue() && gear.unequal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gear.equal((GEAR_STATE(GEAR_STATE::retracted))).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && gear.equal((GEAR_STATE(GEAR_STATE::extended))).booleanValue())).booleanValue())).booleanValue()))).booleanValue()) {
-                    _ic_set_25 = _ic_set_25._union(BSet<POSITION>(_ic_gr_1));
-                }
+        BSet<POSITION> _tr_env_open_door_last(bool isCaching) const {
+            if (this->_tr_cache_env_open_door_last == boost::none){
+                BSet<POSITION> _ic_set_25 = BSet<POSITION>();
+                for(const POSITION& _ic_gr_1 : gears.domain()) {
+                    if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(doors.functionCall(_ic_gr_1).equal((DOOR_STATE(DOOR_STATE::door_moving))).booleanValue() && gears.functionCall(_ic_gr_1).unequal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && gears.range().notElementOf((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && doors.relationImage(_POSITION.difference((BSet<POSITION >(_ic_gr_1)))).equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue())).booleanValue())).booleanValue() && valve_open_door.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && door.equal((DOOR_STATE(DOOR_STATE::door_moving))).booleanValue())).booleanValue() && gear.unequal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gear.equal((GEAR_STATE(GEAR_STATE::retracted))).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && gear.equal((GEAR_STATE(GEAR_STATE::extended))).booleanValue())).booleanValue())).booleanValue()))).booleanValue()) {
+                        _ic_set_25 = _ic_set_25._union(BSet<POSITION>(_ic_gr_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_env_open_door_last = _ic_set_25;
+                else return _ic_set_25;
             }
-            return _ic_set_25;
+            return this->_tr_cache_env_open_door_last.get();
         }
 
-        BSet<POSITION> _tr_env_open_door_skip() const {
-            BSet<POSITION> _ic_set_26 = BSet<POSITION>();
-            for(POSITION _ic_gr_1 : gears.domain()) {
-                if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(doors.functionCall(_ic_gr_1).equal((DOOR_STATE(DOOR_STATE::door_moving))).booleanValue() && gears.functionCall(_ic_gr_1).unequal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && gears.range().notElementOf((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && doors.relationImage(_POSITION.difference((BSet<POSITION >(_ic_gr_1)))).unequal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue())).booleanValue())).booleanValue() && valve_open_door.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue()))).booleanValue()) {
-                    _ic_set_26 = _ic_set_26._union(BSet<POSITION>(_ic_gr_1));
-                }
+        BSet<POSITION> _tr_env_open_door_skip(bool isCaching) const {
+            if (this->_tr_cache_env_open_door_skip == boost::none){
+                BSet<POSITION> _ic_set_26 = BSet<POSITION>();
+                for(const POSITION& _ic_gr_1 : gears.domain()) {
+                    if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(doors.functionCall(_ic_gr_1).equal((DOOR_STATE(DOOR_STATE::door_moving))).booleanValue() && gears.functionCall(_ic_gr_1).unequal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && gears.range().notElementOf((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && doors.relationImage(_POSITION.difference((BSet<POSITION >(_ic_gr_1)))).unequal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::open))))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue())).booleanValue())).booleanValue() && valve_open_door.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue()))).booleanValue()) {
+                        _ic_set_26 = _ic_set_26._union(BSet<POSITION>(_ic_gr_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_env_open_door_skip = _ic_set_26;
+                else return _ic_set_26;
             }
-            return _ic_set_26;
+            return this->_tr_cache_env_open_door_skip.get();
         }
 
-        BSet<POSITION> _tr_env_start_close_door() const {
-            BSet<POSITION> _ic_set_27 = BSet<POSITION>();
-            for(POSITION _ic_gr_1 : gears.domain()) {
-                if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(doors.functionCall(_ic_gr_1).equal((DOOR_STATE(DOOR_STATE::open))).booleanValue() && gears.functionCall(_ic_gr_1).unequal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && (BBoolean(gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue() || gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue())).booleanValue())).booleanValue() && valve_close_door.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && (BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::door_moving)), (DOOR_STATE(DOOR_STATE::open)))).elementOf(door).booleanValue())).booleanValue() && gear.unequal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gear.equal((GEAR_STATE(GEAR_STATE::extended))).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && (BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended)), (GEAR_STATE(GEAR_STATE::retracted)))).elementOf(gear).booleanValue())).booleanValue())).booleanValue()))).booleanValue()) {
-                    _ic_set_27 = _ic_set_27._union(BSet<POSITION>(_ic_gr_1));
-                }
+        BSet<POSITION> _tr_env_start_close_door(bool isCaching) const {
+            if (this->_tr_cache_env_start_close_door == boost::none){
+                BSet<POSITION> _ic_set_27 = BSet<POSITION>();
+                for(const POSITION& _ic_gr_1 : gears.domain()) {
+                    if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(doors.functionCall(_ic_gr_1).equal((DOOR_STATE(DOOR_STATE::open))).booleanValue() && gears.functionCall(_ic_gr_1).unequal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && (BBoolean(gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue() || gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue())).booleanValue())).booleanValue() && valve_close_door.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && (BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::door_moving)), (DOOR_STATE(DOOR_STATE::open)))).elementOf(door).booleanValue())).booleanValue() && gear.unequal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gear.equal((GEAR_STATE(GEAR_STATE::extended))).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && (BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended)), (GEAR_STATE(GEAR_STATE::retracted)))).elementOf(gear).booleanValue())).booleanValue())).booleanValue()))).booleanValue()) {
+                        _ic_set_27 = _ic_set_27._union(BSet<POSITION>(_ic_gr_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_env_start_close_door = _ic_set_27;
+                else return _ic_set_27;
             }
-            return _ic_set_27;
+            return this->_tr_cache_env_start_close_door.get();
         }
 
-        BSet<POSITION> _tr_env_close_door() const {
-            BSet<POSITION> _ic_set_28 = BSet<POSITION>();
-            for(POSITION _ic_gr_1 : gears.domain()) {
-                if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(doors.functionCall(_ic_gr_1).equal((DOOR_STATE(DOOR_STATE::door_moving))).booleanValue() && gears.functionCall(_ic_gr_1).unequal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && gears.range().notElementOf((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && doors.relationImage(_POSITION.difference((BSet<POSITION >(_ic_gr_1)))).equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::closed))))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && (BBoolean(gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue() || gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue())).booleanValue())).booleanValue() && valve_close_door.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue() || shock_absorber.equal((PLANE_STATE(PLANE_STATE::ground))).booleanValue())).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && door.equal((DOOR_STATE(DOOR_STATE::door_moving))).booleanValue())).booleanValue() && gear.unequal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gear.equal((GEAR_STATE(GEAR_STATE::extended))).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && (BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended)), (GEAR_STATE(GEAR_STATE::retracted)))).elementOf(gear).booleanValue())).booleanValue())).booleanValue()))).booleanValue()) {
-                    _ic_set_28 = _ic_set_28._union(BSet<POSITION>(_ic_gr_1));
-                }
+        BSet<POSITION> _tr_env_close_door(bool isCaching) const {
+            if (this->_tr_cache_env_close_door == boost::none){
+                BSet<POSITION> _ic_set_28 = BSet<POSITION>();
+                for(const POSITION& _ic_gr_1 : gears.domain()) {
+                    if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(doors.functionCall(_ic_gr_1).equal((DOOR_STATE(DOOR_STATE::door_moving))).booleanValue() && gears.functionCall(_ic_gr_1).unequal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && gears.range().notElementOf((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && doors.relationImage(_POSITION.difference((BSet<POSITION >(_ic_gr_1)))).equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::closed))))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && (BBoolean(gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue() || gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue())).booleanValue())).booleanValue() && valve_close_door.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue() || shock_absorber.equal((PLANE_STATE(PLANE_STATE::ground))).booleanValue())).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && door.equal((DOOR_STATE(DOOR_STATE::door_moving))).booleanValue())).booleanValue() && gear.unequal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gear.equal((GEAR_STATE(GEAR_STATE::extended))).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && (BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended)), (GEAR_STATE(GEAR_STATE::retracted)))).elementOf(gear).booleanValue())).booleanValue())).booleanValue()))).booleanValue()) {
+                        _ic_set_28 = _ic_set_28._union(BSet<POSITION>(_ic_gr_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_env_close_door = _ic_set_28;
+                else return _ic_set_28;
             }
-            return _ic_set_28;
+            return this->_tr_cache_env_close_door.get();
         }
 
-        BSet<POSITION> _tr_env_close_door_skip() const {
-            BSet<POSITION> _ic_set_29 = BSet<POSITION>();
-            for(POSITION _ic_gr_1 : gears.domain()) {
-                if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(doors.functionCall(_ic_gr_1).equal((DOOR_STATE(DOOR_STATE::door_moving))).booleanValue() && gears.functionCall(_ic_gr_1).unequal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && gears.range().notElementOf((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && doors.relationImage(_POSITION.difference((BSet<POSITION >(_ic_gr_1)))).unequal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::closed))))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && (BBoolean(gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue() || gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue())).booleanValue())).booleanValue() && valve_close_door.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue() || shock_absorber.equal((PLANE_STATE(PLANE_STATE::ground))).booleanValue())).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue()))).booleanValue()) {
-                    _ic_set_29 = _ic_set_29._union(BSet<POSITION>(_ic_gr_1));
-                }
+        BSet<POSITION> _tr_env_close_door_skip(bool isCaching) const {
+            if (this->_tr_cache_env_close_door_skip == boost::none){
+                BSet<POSITION> _ic_set_29 = BSet<POSITION>();
+                for(const POSITION& _ic_gr_1 : gears.domain()) {
+                    if(((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(doors.functionCall(_ic_gr_1).equal((DOOR_STATE(DOOR_STATE::door_moving))).booleanValue() && gears.functionCall(_ic_gr_1).unequal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && gears.range().notElementOf((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue())).booleanValue() && doors.relationImage(_POSITION.difference((BSet<POSITION >(_ic_gr_1)))).unequal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::closed))))).booleanValue())).booleanValue() && (BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && (BBoolean(gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue() || gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue())).booleanValue() || (BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue())).booleanValue())).booleanValue() && valve_close_door.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue())).booleanValue() && (BBoolean(!(BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue() || shock_absorber.equal((PLANE_STATE(PLANE_STATE::ground))).booleanValue())).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue()))).booleanValue()) {
+                        _ic_set_29 = _ic_set_29._union(BSet<POSITION>(_ic_gr_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_env_close_door_skip = _ic_set_29;
+                else return _ic_set_29;
             }
-            return _ic_set_29;
+            return this->_tr_cache_env_close_door_skip.get();
         }
 
-        bool _tr_toggle_handle_up() const {
-            return (handle.equal((HANDLE_STATE(HANDLE_STATE::down)))).booleanValue();
+        bool _tr_toggle_handle_up(bool isCaching) const {
+            if (this->_tr_cache_toggle_handle_up == boost::none){
+                bool __tmp_result = (handle.equal((HANDLE_STATE(HANDLE_STATE::down)))).booleanValue();
+                if (isCaching) this->_tr_cache_toggle_handle_up = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_toggle_handle_up.get();
         }
 
-        bool _tr_toggle_handle_down() const {
-            return (handle.equal((HANDLE_STATE(HANDLE_STATE::up)))).booleanValue();
+        bool _tr_toggle_handle_down(bool isCaching) const {
+            if (this->_tr_cache_toggle_handle_down == boost::none){
+                bool __tmp_result = (handle.equal((HANDLE_STATE(HANDLE_STATE::up)))).booleanValue();
+                if (isCaching) this->_tr_cache_toggle_handle_down = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_toggle_handle_down.get();
         }
 
-        bool _tr_con_stimulate_general_valve() const {
-            return ((BBoolean(general_EV.equal((BBoolean(false))).booleanValue() && handle_move.equal((BBoolean(true))).booleanValue()))).booleanValue();
+        bool _tr_con_stimulate_general_valve(bool isCaching) const {
+            if (this->_tr_cache_con_stimulate_general_valve == boost::none){
+                bool __tmp_result = ((BBoolean(general_EV.equal((BBoolean(false))).booleanValue() && handle_move.equal((BBoolean(true))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_con_stimulate_general_valve = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_con_stimulate_general_valve.get();
         }
 
-        bool _tr_con_stop_stimulate_general_valve() const {
-            return ((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(general_EV.equal((BBoolean(true))).booleanValue() && open_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && close_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && retract_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && extend_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && close_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && (BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue())).booleanValue() && doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::closed))))).booleanValue())).booleanValue() && open_EV.equal((BBoolean(false))).booleanValue())).booleanValue() || (BBoolean((BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue() && doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::closed))))).booleanValue())).booleanValue() && open_EV.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() || (BBoolean((BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue() && doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::closed))))).booleanValue())).booleanValue() && open_EV.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue()))).booleanValue();
+        bool _tr_con_stop_stimulate_general_valve(bool isCaching) const {
+            if (this->_tr_cache_con_stop_stimulate_general_valve == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(general_EV.equal((BBoolean(true))).booleanValue() && open_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && close_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && retract_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && extend_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && close_EV.equal((BBoolean(false))).booleanValue())).booleanValue() && (BBoolean((BBoolean((BBoolean((BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::retracted))))).booleanValue())).booleanValue() && doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::closed))))).booleanValue())).booleanValue() && open_EV.equal((BBoolean(false))).booleanValue())).booleanValue() || (BBoolean((BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::down))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue() && doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::closed))))).booleanValue())).booleanValue() && open_EV.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue() || (BBoolean((BBoolean((BBoolean(handle.equal((HANDLE_STATE(HANDLE_STATE::up))).booleanValue() && gears.range().equal((BSet<GEAR_STATE >((GEAR_STATE(GEAR_STATE::extended))))).booleanValue())).booleanValue() && doors.range().equal((BSet<DOOR_STATE >((DOOR_STATE(DOOR_STATE::closed))))).booleanValue())).booleanValue() && open_EV.equal((BBoolean(false))).booleanValue())).booleanValue())).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_con_stop_stimulate_general_valve = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_con_stop_stimulate_general_valve.get();
         }
 
-        bool _tr_evn_open_general_valve() const {
-            return ((BBoolean((BBoolean(general_EV.equal((BBoolean(true))).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_closed))).booleanValue())).booleanValue() && analogical_switch.equal((SWITCH_STATE(SWITCH_STATE::switch_closed))).booleanValue()))).booleanValue();
+        bool _tr_evn_open_general_valve(bool isCaching) const {
+            if (this->_tr_cache_evn_open_general_valve == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean(general_EV.equal((BBoolean(true))).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_closed))).booleanValue())).booleanValue() && analogical_switch.equal((SWITCH_STATE(SWITCH_STATE::switch_closed))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_evn_open_general_valve = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_evn_open_general_valve.get();
         }
 
-        bool _tr_evn_close_general_valve() const {
-            return ((BBoolean((BBoolean(general_EV.equal((BBoolean(false))).booleanValue() || analogical_switch.equal((SWITCH_STATE(SWITCH_STATE::switch_open))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue()))).booleanValue();
+        bool _tr_evn_close_general_valve(bool isCaching) const {
+            if (this->_tr_cache_evn_close_general_valve == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean(general_EV.equal((BBoolean(false))).booleanValue() || analogical_switch.equal((SWITCH_STATE(SWITCH_STATE::switch_open))).booleanValue())).booleanValue() && general_valve.equal((VALVE_STATE(VALVE_STATE::valve_open))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_evn_close_general_valve = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_evn_close_general_valve.get();
         }
 
-        bool _tr_env_close_analogical_switch() const {
-            return ((BBoolean(analogical_switch.equal((SWITCH_STATE(SWITCH_STATE::switch_open))).booleanValue() && handle_move.equal((BBoolean(true))).booleanValue()))).booleanValue();
+        bool _tr_env_close_analogical_switch(bool isCaching) const {
+            if (this->_tr_cache_env_close_analogical_switch == boost::none){
+                bool __tmp_result = ((BBoolean(analogical_switch.equal((SWITCH_STATE(SWITCH_STATE::switch_open))).booleanValue() && handle_move.equal((BBoolean(true))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_env_close_analogical_switch = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_env_close_analogical_switch.get();
         }
 
-        bool _tr_env_open_analogical_switch() const {
-            return (analogical_switch.equal((SWITCH_STATE(SWITCH_STATE::switch_closed)))).booleanValue();
+        bool _tr_env_open_analogical_switch(bool isCaching) const {
+            if (this->_tr_cache_env_open_analogical_switch == boost::none){
+                bool __tmp_result = (analogical_switch.equal((SWITCH_STATE(SWITCH_STATE::switch_closed)))).booleanValue();
+                if (isCaching) this->_tr_cache_env_open_analogical_switch = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_env_open_analogical_switch.get();
         }
 
         bool _check_inv_1() const {
@@ -1148,8 +1367,61 @@ class LandingGear_R6 {
             return ((BBoolean(!gear.equal((GEAR_STATE(GEAR_STATE::gear_moving))).booleanValue() || door.equal((DOOR_STATE(DOOR_STATE::open))).booleanValue()))).booleanValue();
         }
 
-        LandingGear_R6 _copy() const {
-            return LandingGear_R6(analogical_switch, general_EV, general_valve, handle_move, close_EV, extend_EV, open_EV, retract_EV, shock_absorber, valve_close_door, valve_extend_gear, valve_open_door, valve_retract_gear, doors, gears, handle, door, gear);
+        static constexpr unsigned int strHash(const char *s, int off = 0) {
+            return !s[off] ? 5381 : (strHash(s, off+1)*33) ^ s[off];
+        }
+
+        LandingGear_R6 _copy(unordered_set<string> toInvalidate) const {
+            static const char* allTransitions[] = {"_tr_begin_flying", "_tr_land_plane", "_tr_open_valve_door_open", "_tr_close_valve_door_open", "_tr_open_valve_door_close", "_tr_close_valve_door_close", "_tr_open_valve_retract_gear", "_tr_close_valve_retract_gear", "_tr_open_valve_extend_gear", "_tr_close_valve_extend_gear", "_tr_con_stimulate_open_door_valve", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_con_stimulate_extend_gear_valve", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_env_retract_gear_skip", "_tr_env_retract_gear_last", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_extend_gear_skip", "_tr_env_start_open_door", "_tr_env_open_door_last", "_tr_env_open_door_skip", "_tr_env_start_close_door", "_tr_env_close_door", "_tr_env_close_door_skip", "_tr_toggle_handle_up", "_tr_toggle_handle_down", "_tr_con_stimulate_general_valve", "_tr_con_stop_stimulate_general_valve", "_tr_evn_open_general_valve", "_tr_evn_close_general_valve", "_tr_env_close_analogical_switch", "_tr_env_open_analogical_switch"};
+
+            LandingGear_R6 result = LandingGear_R6(analogical_switch, general_EV, general_valve, handle_move, close_EV, extend_EV, open_EV, retract_EV, shock_absorber, valve_close_door, valve_extend_gear, valve_open_door, valve_retract_gear, doors, gears, handle, door, gear);
+
+            for (const auto &item : allTransitions) {
+                if(toInvalidate.find(item) == toInvalidate.end()) {
+                    switch(strHash(item)) {
+                        case strHash("_tr_begin_flying"): result._tr_cache_begin_flying = this->_tr_cache_begin_flying; break;
+                        case strHash("_tr_land_plane"): result._tr_cache_land_plane = this->_tr_cache_land_plane; break;
+                        case strHash("_tr_open_valve_door_open"): result._tr_cache_open_valve_door_open = this->_tr_cache_open_valve_door_open; break;
+                        case strHash("_tr_close_valve_door_open"): result._tr_cache_close_valve_door_open = this->_tr_cache_close_valve_door_open; break;
+                        case strHash("_tr_open_valve_door_close"): result._tr_cache_open_valve_door_close = this->_tr_cache_open_valve_door_close; break;
+                        case strHash("_tr_close_valve_door_close"): result._tr_cache_close_valve_door_close = this->_tr_cache_close_valve_door_close; break;
+                        case strHash("_tr_open_valve_retract_gear"): result._tr_cache_open_valve_retract_gear = this->_tr_cache_open_valve_retract_gear; break;
+                        case strHash("_tr_close_valve_retract_gear"): result._tr_cache_close_valve_retract_gear = this->_tr_cache_close_valve_retract_gear; break;
+                        case strHash("_tr_open_valve_extend_gear"): result._tr_cache_open_valve_extend_gear = this->_tr_cache_open_valve_extend_gear; break;
+                        case strHash("_tr_close_valve_extend_gear"): result._tr_cache_close_valve_extend_gear = this->_tr_cache_close_valve_extend_gear; break;
+                        case strHash("_tr_con_stimulate_open_door_valve"): result._tr_cache_con_stimulate_open_door_valve = this->_tr_cache_con_stimulate_open_door_valve; break;
+                        case strHash("_tr_con_stop_stimulate_open_door_valve"): result._tr_cache_con_stop_stimulate_open_door_valve = this->_tr_cache_con_stop_stimulate_open_door_valve; break;
+                        case strHash("_tr_con_stimulate_close_door_valve"): result._tr_cache_con_stimulate_close_door_valve = this->_tr_cache_con_stimulate_close_door_valve; break;
+                        case strHash("_tr_con_stop_stimulate_close_door_valve"): result._tr_cache_con_stop_stimulate_close_door_valve = this->_tr_cache_con_stop_stimulate_close_door_valve; break;
+                        case strHash("_tr_con_stimulate_retract_gear_valve"): result._tr_cache_con_stimulate_retract_gear_valve = this->_tr_cache_con_stimulate_retract_gear_valve; break;
+                        case strHash("_tr_con_stop_stimulate_retract_gear_valve"): result._tr_cache_con_stop_stimulate_retract_gear_valve = this->_tr_cache_con_stop_stimulate_retract_gear_valve; break;
+                        case strHash("_tr_con_stimulate_extend_gear_valve"): result._tr_cache_con_stimulate_extend_gear_valve = this->_tr_cache_con_stimulate_extend_gear_valve; break;
+                        case strHash("_tr_con_stop_stimulate_extend_gear_valve"): result._tr_cache_con_stop_stimulate_extend_gear_valve = this->_tr_cache_con_stop_stimulate_extend_gear_valve; break;
+                        case strHash("_tr_env_start_retracting_first"): result._tr_cache_env_start_retracting_first = this->_tr_cache_env_start_retracting_first; break;
+                        case strHash("_tr_env_retract_gear_skip"): result._tr_cache_env_retract_gear_skip = this->_tr_cache_env_retract_gear_skip; break;
+                        case strHash("_tr_env_retract_gear_last"): result._tr_cache_env_retract_gear_last = this->_tr_cache_env_retract_gear_last; break;
+                        case strHash("_tr_env_start_extending"): result._tr_cache_env_start_extending = this->_tr_cache_env_start_extending; break;
+                        case strHash("_tr_env_extend_gear_last"): result._tr_cache_env_extend_gear_last = this->_tr_cache_env_extend_gear_last; break;
+                        case strHash("_tr_env_extend_gear_skip"): result._tr_cache_env_extend_gear_skip = this->_tr_cache_env_extend_gear_skip; break;
+                        case strHash("_tr_env_start_open_door"): result._tr_cache_env_start_open_door = this->_tr_cache_env_start_open_door; break;
+                        case strHash("_tr_env_open_door_last"): result._tr_cache_env_open_door_last = this->_tr_cache_env_open_door_last; break;
+                        case strHash("_tr_env_open_door_skip"): result._tr_cache_env_open_door_skip = this->_tr_cache_env_open_door_skip; break;
+                        case strHash("_tr_env_start_close_door"): result._tr_cache_env_start_close_door = this->_tr_cache_env_start_close_door; break;
+                        case strHash("_tr_env_close_door"): result._tr_cache_env_close_door = this->_tr_cache_env_close_door; break;
+                        case strHash("_tr_env_close_door_skip"): result._tr_cache_env_close_door_skip = this->_tr_cache_env_close_door_skip; break;
+                        case strHash("_tr_toggle_handle_up"): result._tr_cache_toggle_handle_up = this->_tr_cache_toggle_handle_up; break;
+                        case strHash("_tr_toggle_handle_down"): result._tr_cache_toggle_handle_down = this->_tr_cache_toggle_handle_down; break;
+                        case strHash("_tr_con_stimulate_general_valve"): result._tr_cache_con_stimulate_general_valve = this->_tr_cache_con_stimulate_general_valve; break;
+                        case strHash("_tr_con_stop_stimulate_general_valve"): result._tr_cache_con_stop_stimulate_general_valve = this->_tr_cache_con_stop_stimulate_general_valve; break;
+                        case strHash("_tr_evn_open_general_valve"): result._tr_cache_evn_open_general_valve = this->_tr_cache_evn_open_general_valve; break;
+                        case strHash("_tr_evn_close_general_valve"): result._tr_cache_evn_close_general_valve = this->_tr_cache_evn_close_general_valve; break;
+                        case strHash("_tr_env_close_analogical_switch"): result._tr_cache_env_close_analogical_switch = this->_tr_cache_env_close_analogical_switch; break;
+                        case strHash("_tr_env_open_analogical_switch"): result._tr_cache_env_open_analogical_switch = this->_tr_cache_env_open_analogical_switch; break;
+                        default: cout << "Transition " << item << " not found!";
+                    }
+                }
+            }
+            return result;
         }
 
         friend bool operator ==(const LandingGear_R6& o1, const LandingGear_R6& o2) {
@@ -1236,2412 +1508,724 @@ class LandingGear_R6 {
 };
 
 
-static std::unordered_set<LandingGear_R6, LandingGear_R6::Hash, LandingGear_R6::HashEqual> generateNextStates(std::mutex& guardMutex, const LandingGear_R6& state, bool isCaching, std::unordered_map<string, std::unordered_set<string>>& invariantDependency, std::unordered_map<LandingGear_R6, std::unordered_set<string>, LandingGear_R6::Hash, LandingGear_R6::HashEqual>& dependentInvariant, std::unordered_map<string, std::unordered_set<string>>& guardDependency, std::unordered_map<LandingGear_R6, std::unordered_set<string>, LandingGear_R6::Hash, LandingGear_R6::HashEqual>& dependentGuard, std::unordered_map<LandingGear_R6, immer::map<string, boost::any>, LandingGear_R6::Hash, LandingGear_R6::HashEqual>& guardCache, std::unordered_map<LandingGear_R6, LandingGear_R6, LandingGear_R6::Hash, LandingGear_R6::HashEqual>& parents, std::unordered_map<LandingGear_R6, string, LandingGear_R6::Hash, LandingGear_R6::HashEqual>& stateAccessedVia, std::atomic<int>& transitions) {
-    std::unordered_set<LandingGear_R6, LandingGear_R6::Hash, LandingGear_R6::HashEqual> result = std::unordered_set<LandingGear_R6, LandingGear_R6::Hash, LandingGear_R6::HashEqual>();
-    if(isCaching) {
-        immer::map<string, boost::any> parentsGuard;
-        std::unordered_set<string> dependentGuardsOfState;
-        bool parentsExist = false;
-        bool dependentGuardsExist = false;
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            parentsExist = (parents.find(state) != parents.end());
-            dependentGuardsExist = (dependentGuard.find(state) != dependentGuard.end());
-            if(parentsExist) {
-                parentsGuard = guardCache[parents[state]];
-            }
-            if(dependentGuardsExist) {
-                dependentGuardsOfState = dependentGuard[state];
-            }
-        }
-        immer::map<string, boost::any> newCache = parentsGuard;
-        boost::any cachedValue;
-        bool dependentGuardsBoolean = true;
-        bool _trid_1;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_begin_flying"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_begin_flying") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_1 = state._tr_begin_flying();
-        } else {
-            _trid_1 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_begin_flying", _trid_1);
-        if(_trid_1) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.begin_flying();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["begin_flying"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["begin_flying"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "begin_flying"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_2;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_land_plane"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_land_plane") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_2 = state._tr_land_plane();
-        } else {
-            _trid_2 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_land_plane", _trid_2);
-        if(_trid_2) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.land_plane();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["land_plane"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["land_plane"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "land_plane"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_3;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_open_valve_door_open"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_open_valve_door_open") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_3 = state._tr_open_valve_door_open();
-        } else {
-            _trid_3 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_open_valve_door_open", _trid_3);
-        if(_trid_3) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.open_valve_door_open();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["open_valve_door_open"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["open_valve_door_open"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "open_valve_door_open"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
+class ModelChecker {
+    private:
+        LandingGear_R6::Type type;
+        int threads;
+        bool isCaching;
+        bool isDebug;
+
+        std::list<LandingGear_R6> unvisitedStates;
+        std::unordered_set<LandingGear_R6, LandingGear_R6::Hash, LandingGear_R6::HashEqual> states;
+        std::atomic<int> transitions;
+        std::mutex mutex;
+        std::mutex waitMutex;
+        std::mutex guardMutex;
+        std::condition_variable waitCV;
+
+        std::atomic<bool> invariantViolatedBool;
+        std::atomic<bool> deadlockDetected;
+        LandingGear_R6 counterExampleState;
+
+        std::unordered_map<string, std::unordered_set<string>> invariantDependency;
+        std::unordered_map<string, std::unordered_set<string>> guardDependency;
+        std::unordered_map<LandingGear_R6, LandingGear_R6, LandingGear_R6::Hash, LandingGear_R6::HashEqual> parents;
+
+    public:
+        ModelChecker() {}
+
+        ModelChecker(LandingGear_R6::Type type, int threads, bool isCaching, bool isDebug) {
+            this->type = type;
+            this->threads = threads;
+            this->isCaching = isCaching;
+            this->isDebug = isDebug;
+            this->invariantViolatedBool = false;
+            this->deadlockDetected = false;
+            this->transitions = 0;
         }
-        bool _trid_4;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_close_valve_door_open"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_close_valve_door_open") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_4 = state._tr_close_valve_door_open();
-        } else {
-            _trid_4 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_close_valve_door_open", _trid_4);
-        if(_trid_4) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.close_valve_door_open();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["close_valve_door_open"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["close_valve_door_open"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "close_valve_door_open"});
-                }
+
+        void modelCheck() {
+            if (isDebug) {
+                cout << "Starting Modelchecking, STRATEGY=" << type << ", THREADS=" << threads << ", CACHING=" << isCaching << "\n";
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_5;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_open_valve_door_close"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_open_valve_door_close") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_5 = state._tr_open_valve_door_close();
-        } else {
-            _trid_5 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_open_valve_door_close", _trid_5);
-        if(_trid_5) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.open_valve_door_close();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["open_valve_door_close"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["open_valve_door_close"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "open_valve_door_close"});
-                }
+
+            if (threads <= 1) {
+                modelCheckSingleThreaded();
+            } else {
+                boost::asio::thread_pool workers(threads); // threads indicates the number of workers (without the coordinator)
+                modelCheckMultiThreaded(workers);
             }
-            result.insert(copiedState);
-            transitions += 1;
         }
-        bool _trid_6;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_close_valve_door_close"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_close_valve_door_close") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_6 = state._tr_close_valve_door_close();
-        } else {
-            _trid_6 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_close_valve_door_close", _trid_6);
-        if(_trid_6) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.close_valve_door_close();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["close_valve_door_close"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["close_valve_door_close"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "close_valve_door_close"});
-                }
+
+        void modelCheckSingleThreaded() {
+            LandingGear_R6 machine = LandingGear_R6();
+            states.insert(machine);
+            unvisitedStates.push_back(machine);
+
+            if (isCaching) {
+                initCache(machine);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_7;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_open_valve_retract_gear"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_open_valve_retract_gear") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_7 = state._tr_open_valve_retract_gear();
-        } else {
-            _trid_7 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_open_valve_retract_gear", _trid_7);
-        if(_trid_7) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.open_valve_retract_gear();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["open_valve_retract_gear"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["open_valve_retract_gear"]});
+
+            while(!unvisitedStates.empty()) {
+                LandingGear_R6 state = next();
+
+                std::unordered_set<LandingGear_R6, LandingGear_R6::Hash, LandingGear_R6::HashEqual> nextStates = generateNextStates(state);
+                transitions += nextStates.size();
+
+                for(auto& nextState : nextStates) {
+                    if(states.find(nextState) == states.end()) {
+                        states.insert(nextState);
+                        parents.insert({nextState, state});
+                        unvisitedStates.push_back(nextState);
+                        if(states.size() % 50000 == 0) {
+                            cout << "VISITED STATES: " << states.size() << "\n";
+                            cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
+                            cout << "-------------------" << "\n";
+                        }
+                    }
                 }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+
+                if(invariantViolated(state)) {
+                    invariantViolatedBool = true;
+                    counterExampleState = state;
+                    break;
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "open_valve_retract_gear"});
+
+                if(nextStates.empty()) {
+                    deadlockDetected = true;
+                    counterExampleState = state;
+                    break;
                 }
+
             }
-            result.insert(copiedState);
-            transitions += 1;
+            printResult();
         }
-        bool _trid_8;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_close_valve_retract_gear"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_close_valve_retract_gear") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_8 = state._tr_close_valve_retract_gear();
-        } else {
-            _trid_8 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_close_valve_retract_gear", _trid_8);
-        if(_trid_8) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.close_valve_retract_gear();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["close_valve_retract_gear"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["close_valve_retract_gear"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "close_valve_retract_gear"});
-                }
+
+        void modelCheckMultiThreaded(boost::asio::thread_pool& workers) {
+            LandingGear_R6 machine = LandingGear_R6();
+            states.insert(machine);
+            unvisitedStates.push_back(machine);
+
+            std::atomic<bool> stopThreads;
+            stopThreads = false;
+            std::atomic<int> possibleQueueChanges;
+            possibleQueueChanges = 0;
+
+            if(isCaching) {
+                initCache(machine);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_9;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_open_valve_extend_gear"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_open_valve_extend_gear") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_9 = state._tr_open_valve_extend_gear();
-        } else {
-            _trid_9 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_open_valve_extend_gear", _trid_9);
-        if(_trid_9) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.open_valve_extend_gear();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["open_valve_extend_gear"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["open_valve_extend_gear"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "open_valve_extend_gear"});
+
+            std::atomic<bool> waitFlag;
+            waitFlag = true;
+
+            while(!unvisitedStates.empty() && !stopThreads) {
+                possibleQueueChanges += 1;
+                LandingGear_R6 state = next();
+                std::packaged_task<void()> task([&, state] {
+                    std::unordered_set<LandingGear_R6, LandingGear_R6::Hash, LandingGear_R6::HashEqual> nextStates = generateNextStates(state);
+                    transitions += nextStates.size();
+
+                    for(auto& nextState : nextStates) {
+                        {
+                            std::unique_lock<std::mutex> lock(mutex);
+                            if(states.find(nextState) == states.end()) {
+                                states.insert(nextState);
+                                parents.insert({nextState, state});
+                                unvisitedStates.push_back(nextState); // TODO: sync ?
+                                if(isDebug && states.size() % 50000 == 0) {
+                                    cout << "VISITED STATES: " << states.size() << "\n";
+                                    cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
+                                    cout << "-------------------" << "\n";
+                                }
+                            }
+                        }
+                    }
+
+                    {
+                        std::unique_lock<std::mutex> lock(mutex);
+                        possibleQueueChanges -= 1;
+                        int running = possibleQueueChanges;
+                        if (!unvisitedStates.empty() || running == 0) {
+                            {
+                                std::unique_lock<std::mutex> lock(waitMutex);
+                                waitFlag = false;
+                                waitCV.notify_one();
+                            }
+                        }
+                    }
+
+                    if(invariantViolated(state)) {
+                        invariantViolatedBool = true;
+                        counterExampleState = state;
+                        stopThreads = true;
+                    }
+
+                    if(nextStates.empty()) {
+                        deadlockDetected = true;
+                        counterExampleState = state;
+                        stopThreads = true;
+                    }
+
+                });
+
+                waitFlag = true;
+                boost::asio::post(workers, std::move(task));
+
+                {
+                    std::unique_lock<std::mutex> lock(waitMutex);
+                    while (unvisitedStates.empty() && possibleQueueChanges > 0) {
+                        waitCV.wait(lock, [&] {
+                            return waitFlag == false;
+                        });
+                    }
                 }
             }
-            result.insert(copiedState);
-            transitions += 1;
+            workers.join();
+            printResult();
+        }
+
+        void initCache(LandingGear_R6& machine) {
+            invariantDependency.insert({"close_valve_door_close", {"_check_inv_10"}});
+            invariantDependency.insert({"close_valve_retract_gear", {"_check_inv_13"}});
+            invariantDependency.insert({"con_stimulate_open_door_valve", {"_check_inv_18", "_check_inv_17", "_check_inv_7"}});
+            invariantDependency.insert({"env_close_door", {"_check_inv_15", "_check_inv_21", "_check_inv_20", "_check_inv_25", "_check_inv_22"}});
+            invariantDependency.insert({"env_start_close_door", {"_check_inv_15", "_check_inv_21", "_check_inv_20", "_check_inv_25", "_check_inv_22"}});
+            invariantDependency.insert({"toggle_handle_up", {"_check_inv_4", "_check_inv_14"}});
+            invariantDependency.insert({"toggle_handle_down", {"_check_inv_4", "_check_inv_14"}});
+            invariantDependency.insert({"open_valve_door_open", {"_check_inv_12"}});
+            invariantDependency.insert({"env_retract_gear_last", {"_check_inv_16", "_check_inv_19", "_check_inv_25", "_check_inv_24", "_check_inv_23"}});
+            invariantDependency.insert({"env_open_door_last", {"_check_inv_15", "_check_inv_21", "_check_inv_20", "_check_inv_25", "_check_inv_22"}});
+            invariantDependency.insert({"con_stop_stimulate_retract_gear_valve", {"_check_inv_17", "_check_inv_8"}});
+            invariantDependency.insert({"env_close_door_skip", {"_check_inv_21", "_check_inv_20", "_check_inv_22"}});
+            invariantDependency.insert({"con_stop_stimulate_close_door_valve", {"_check_inv_18", "_check_inv_17", "_check_inv_5"}});
+            invariantDependency.insert({"env_open_analogical_switch", {"_check_inv_1"}});
+            invariantDependency.insert({"con_stop_stimulate_general_valve", {"_check_inv_17", "_check_inv_2", "_check_inv_4"}});
+            invariantDependency.insert({"env_extend_gear_last", {"_check_inv_16", "_check_inv_19", "_check_inv_25", "_check_inv_24", "_check_inv_23"}});
+            invariantDependency.insert({"evn_open_general_valve", {"_check_inv_3"}});
+            invariantDependency.insert({"land_plane", {"_check_inv_9"}});
+            invariantDependency.insert({"con_stimulate_retract_gear_valve", {"_check_inv_17", "_check_inv_8"}});
+            invariantDependency.insert({"con_stimulate_general_valve", {"_check_inv_17", "_check_inv_2"}});
+            invariantDependency.insert({"env_start_retracting_first", {"_check_inv_16", "_check_inv_19", "_check_inv_25", "_check_inv_24", "_check_inv_23"}});
+            invariantDependency.insert({"env_retract_gear_skip", {"_check_inv_19", "_check_inv_24", "_check_inv_23"}});
+            invariantDependency.insert({"open_valve_extend_gear", {"_check_inv_11"}});
+            invariantDependency.insert({"begin_flying", {"_check_inv_9"}});
+            invariantDependency.insert({"open_valve_retract_gear", {"_check_inv_13"}});
+            invariantDependency.insert({"env_close_analogical_switch", {"_check_inv_1"}});
+            invariantDependency.insert({"env_start_extending", {"_check_inv_16", "_check_inv_19", "_check_inv_25", "_check_inv_24", "_check_inv_23"}});
+            invariantDependency.insert({"open_valve_door_close", {"_check_inv_10"}});
+            invariantDependency.insert({"con_stop_stimulate_open_door_valve", {"_check_inv_18", "_check_inv_17", "_check_inv_7"}});
+            invariantDependency.insert({"con_stop_stimulate_extend_gear_valve", {"_check_inv_17", "_check_inv_6"}});
+            invariantDependency.insert({"evn_close_general_valve", {"_check_inv_3"}});
+            invariantDependency.insert({"close_valve_extend_gear", {"_check_inv_11"}});
+            invariantDependency.insert({"con_stimulate_extend_gear_valve", {"_check_inv_17", "_check_inv_6"}});
+            invariantDependency.insert({"close_valve_door_open", {"_check_inv_12"}});
+            invariantDependency.insert({"con_stimulate_close_door_valve", {"_check_inv_18", "_check_inv_17", "_check_inv_5"}});
+            invariantDependency.insert({"env_extend_gear_skip", {"_check_inv_19", "_check_inv_24", "_check_inv_23"}});
+            invariantDependency.insert({"env_open_door_skip", {"_check_inv_21", "_check_inv_20", "_check_inv_22"}});
+            invariantDependency.insert({"env_start_open_door", {"_check_inv_15", "_check_inv_21", "_check_inv_20", "_check_inv_25", "_check_inv_22"}});
+            invariantDependency.insert({"", {}});
+            guardDependency.insert({"close_valve_door_close", {"_tr_open_valve_door_close", "_tr_env_close_door_skip", "_tr_env_start_close_door", "_tr_env_close_door", "_tr_close_valve_door_close"}});
+            guardDependency.insert({"close_valve_retract_gear", {"_tr_close_valve_retract_gear", "_tr_open_valve_retract_gear", "_tr_env_start_retracting_first"}});
+            guardDependency.insert({"con_stimulate_open_door_valve", {"_tr_open_valve_door_open", "_tr_con_stimulate_extend_gear_valve", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stimulate_open_door_valve", "_tr_close_valve_door_open"}});
+            guardDependency.insert({"env_close_door", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
+            guardDependency.insert({"env_start_close_door", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
+            guardDependency.insert({"toggle_handle_up", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_close_analogical_switch", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip", "_tr_con_stimulate_general_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_toggle_handle_down", "_tr_env_open_door_last", "_tr_toggle_handle_up", "_tr_env_start_close_door", "_tr_con_stop_stimulate_close_door_valve"}});
+            guardDependency.insert({"toggle_handle_down", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_close_analogical_switch", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip", "_tr_con_stimulate_general_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_toggle_handle_down", "_tr_env_open_door_last", "_tr_toggle_handle_up", "_tr_env_start_close_door", "_tr_con_stop_stimulate_close_door_valve"}});
+            guardDependency.insert({"open_valve_door_open", {"_tr_open_valve_door_open", "_tr_env_open_door_last", "_tr_env_start_open_door", "_tr_env_open_door_skip", "_tr_close_valve_door_open"}});
+            guardDependency.insert({"env_retract_gear_last", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
+            guardDependency.insert({"env_open_door_last", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
+            guardDependency.insert({"con_stop_stimulate_retract_gear_valve", {"_tr_close_valve_retract_gear", "_tr_con_stimulate_extend_gear_valve", "_tr_open_valve_retract_gear", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_retract_gear_valve"}});
+            guardDependency.insert({"env_close_door_skip", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
+            guardDependency.insert({"con_stop_stimulate_close_door_valve", {"_tr_open_valve_door_close", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_close_valve_door_close"}});
+            guardDependency.insert({"env_open_analogical_switch", {"_tr_env_open_analogical_switch", "_tr_evn_open_general_valve", "_tr_env_close_analogical_switch", "_tr_evn_close_general_valve"}});
+            guardDependency.insert({"con_stop_stimulate_general_valve", {"_tr_con_stimulate_extend_gear_valve", "_tr_con_stimulate_general_valve", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_evn_open_general_valve", "_tr_env_close_analogical_switch", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_evn_close_general_valve", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve"}});
+            guardDependency.insert({"env_extend_gear_last", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
+            guardDependency.insert({"evn_open_general_valve", {"_tr_env_retract_gear_last", "_tr_env_close_door_skip", "_tr_evn_open_general_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_evn_close_general_valve", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
+            guardDependency.insert({"land_plane", {"_tr_land_plane", "_tr_begin_flying", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_close_door"}});
+            guardDependency.insert({"con_stimulate_retract_gear_valve", {"_tr_close_valve_retract_gear", "_tr_con_stimulate_extend_gear_valve", "_tr_open_valve_retract_gear", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_retract_gear_valve"}});
+            guardDependency.insert({"con_stimulate_general_valve", {"_tr_con_stimulate_extend_gear_valve", "_tr_con_stimulate_general_valve", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_evn_open_general_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_evn_close_general_valve", "_tr_con_stop_stimulate_retract_gear_valve"}});
+            guardDependency.insert({"env_start_retracting_first", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
+            guardDependency.insert({"env_retract_gear_skip", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
+            guardDependency.insert({"open_valve_extend_gear", {"_tr_close_valve_extend_gear", "_tr_open_valve_extend_gear", "_tr_env_start_extending"}});
+            guardDependency.insert({"begin_flying", {"_tr_land_plane", "_tr_begin_flying", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_close_door"}});
+            guardDependency.insert({"open_valve_retract_gear", {"_tr_close_valve_retract_gear", "_tr_open_valve_retract_gear", "_tr_env_start_retracting_first"}});
+            guardDependency.insert({"env_close_analogical_switch", {"_tr_env_open_analogical_switch", "_tr_evn_open_general_valve", "_tr_env_close_analogical_switch", "_tr_evn_close_general_valve"}});
+            guardDependency.insert({"env_start_extending", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
+            guardDependency.insert({"open_valve_door_close", {"_tr_open_valve_door_close", "_tr_env_close_door_skip", "_tr_env_start_close_door", "_tr_env_close_door", "_tr_close_valve_door_close"}});
+            guardDependency.insert({"con_stop_stimulate_open_door_valve", {"_tr_open_valve_door_open", "_tr_con_stimulate_extend_gear_valve", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stimulate_open_door_valve", "_tr_close_valve_door_open"}});
+            guardDependency.insert({"con_stop_stimulate_extend_gear_valve", {"_tr_con_stimulate_extend_gear_valve", "_tr_close_valve_extend_gear", "_tr_con_stop_stimulate_open_door_valve", "_tr_open_valve_extend_gear", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_extend_gear_valve"}});
+            guardDependency.insert({"evn_close_general_valve", {"_tr_env_retract_gear_last", "_tr_env_close_door_skip", "_tr_evn_open_general_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_evn_close_general_valve", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
+            guardDependency.insert({"close_valve_extend_gear", {"_tr_close_valve_extend_gear", "_tr_open_valve_extend_gear", "_tr_env_start_extending"}});
+            guardDependency.insert({"con_stimulate_extend_gear_valve", {"_tr_con_stimulate_extend_gear_valve", "_tr_close_valve_extend_gear", "_tr_con_stop_stimulate_open_door_valve", "_tr_open_valve_extend_gear", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_extend_gear_valve"}});
+            guardDependency.insert({"close_valve_door_open", {"_tr_open_valve_door_open", "_tr_env_open_door_last", "_tr_env_start_open_door", "_tr_env_open_door_skip", "_tr_close_valve_door_open"}});
+            guardDependency.insert({"con_stimulate_close_door_valve", {"_tr_open_valve_door_close", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_close_valve_door_close"}});
+            guardDependency.insert({"env_extend_gear_skip", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
+            guardDependency.insert({"env_open_door_skip", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
+            guardDependency.insert({"env_start_open_door", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
         }
-        bool _trid_10;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_close_valve_extend_gear"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_close_valve_extend_gear") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_10 = state._tr_close_valve_extend_gear();
-        } else {
-            _trid_10 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_close_valve_extend_gear", _trid_10);
-        if(_trid_10) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.close_valve_extend_gear();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["close_valve_extend_gear"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["close_valve_extend_gear"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "close_valve_extend_gear"});
+
+
+    private:
+        LandingGear_R6 next() {
+            std::unique_lock<std::mutex> lock(mutex);
+            switch(type) {
+                case LandingGear_R6::BFS: {
+                    LandingGear_R6 state = unvisitedStates.front();
+                    unvisitedStates.pop_front();
+                    return state;
+                }
+                case LandingGear_R6::DFS: {
+                    LandingGear_R6 state = unvisitedStates.back();
+                    unvisitedStates.pop_back();
+                    return state;
+                }
+                case LandingGear_R6::MIXED: {
+                    if(unvisitedStates.size() % 2 == 0) {
+                        LandingGear_R6 state = unvisitedStates.front();
+                        unvisitedStates.pop_front();
+                        return state;
+                    } else {
+                        LandingGear_R6 state = unvisitedStates.back();
+                        unvisitedStates.pop_back();
+                        return state;
+                    }
                 }
             }
-            result.insert(copiedState);
-            transitions += 1;
         }
-        bool _trid_11;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_con_stimulate_open_door_valve"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_con_stimulate_open_door_valve") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_11 = state._tr_con_stimulate_open_door_valve();
-        } else {
-            _trid_11 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_con_stimulate_open_door_valve", _trid_11);
-        if(_trid_11) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.con_stimulate_open_door_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["con_stimulate_open_door_valve"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["con_stimulate_open_door_valve"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "con_stimulate_open_door_valve"});
-                }
+
+        std::unordered_set<LandingGear_R6, LandingGear_R6::Hash, LandingGear_R6::HashEqual> generateNextStates(const LandingGear_R6& state) {
+            std::unordered_set<LandingGear_R6, LandingGear_R6::Hash, LandingGear_R6::HashEqual> result = std::unordered_set<LandingGear_R6, LandingGear_R6::Hash, LandingGear_R6::HashEqual>();
+            if(state._tr_begin_flying(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["begin_flying"]);
+                copiedState.begin_flying();
+                copiedState.stateAccessedVia = "begin_flying";
+                result.insert(copiedState);
+            }
+            if(state._tr_land_plane(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["land_plane"]);
+                copiedState.land_plane();
+                copiedState.stateAccessedVia = "land_plane";
+                result.insert(copiedState);
+            }
+            if(state._tr_open_valve_door_open(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["open_valve_door_open"]);
+                copiedState.open_valve_door_open();
+                copiedState.stateAccessedVia = "open_valve_door_open";
+                result.insert(copiedState);
+            }
+            if(state._tr_close_valve_door_open(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["close_valve_door_open"]);
+                copiedState.close_valve_door_open();
+                copiedState.stateAccessedVia = "close_valve_door_open";
+                result.insert(copiedState);
+            }
+            if(state._tr_open_valve_door_close(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["open_valve_door_close"]);
+                copiedState.open_valve_door_close();
+                copiedState.stateAccessedVia = "open_valve_door_close";
+                result.insert(copiedState);
+            }
+            if(state._tr_close_valve_door_close(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["close_valve_door_close"]);
+                copiedState.close_valve_door_close();
+                copiedState.stateAccessedVia = "close_valve_door_close";
+                result.insert(copiedState);
+            }
+            if(state._tr_open_valve_retract_gear(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["open_valve_retract_gear"]);
+                copiedState.open_valve_retract_gear();
+                copiedState.stateAccessedVia = "open_valve_retract_gear";
+                result.insert(copiedState);
+            }
+            if(state._tr_close_valve_retract_gear(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["close_valve_retract_gear"]);
+                copiedState.close_valve_retract_gear();
+                copiedState.stateAccessedVia = "close_valve_retract_gear";
+                result.insert(copiedState);
+            }
+            if(state._tr_open_valve_extend_gear(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["open_valve_extend_gear"]);
+                copiedState.open_valve_extend_gear();
+                copiedState.stateAccessedVia = "open_valve_extend_gear";
+                result.insert(copiedState);
+            }
+            if(state._tr_close_valve_extend_gear(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["close_valve_extend_gear"]);
+                copiedState.close_valve_extend_gear();
+                copiedState.stateAccessedVia = "close_valve_extend_gear";
+                result.insert(copiedState);
+            }
+            if(state._tr_con_stimulate_open_door_valve(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["con_stimulate_open_door_valve"]);
+                copiedState.con_stimulate_open_door_valve();
+                copiedState.stateAccessedVia = "con_stimulate_open_door_valve";
+                result.insert(copiedState);
+            }
+            if(state._tr_con_stop_stimulate_open_door_valve(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["con_stop_stimulate_open_door_valve"]);
+                copiedState.con_stop_stimulate_open_door_valve();
+                copiedState.stateAccessedVia = "con_stop_stimulate_open_door_valve";
+                result.insert(copiedState);
+            }
+            if(state._tr_con_stimulate_close_door_valve(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["con_stimulate_close_door_valve"]);
+                copiedState.con_stimulate_close_door_valve();
+                copiedState.stateAccessedVia = "con_stimulate_close_door_valve";
+                result.insert(copiedState);
+            }
+            if(state._tr_con_stop_stimulate_close_door_valve(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["con_stop_stimulate_close_door_valve"]);
+                copiedState.con_stop_stimulate_close_door_valve();
+                copiedState.stateAccessedVia = "con_stop_stimulate_close_door_valve";
+                result.insert(copiedState);
+            }
+            if(state._tr_con_stimulate_retract_gear_valve(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["con_stimulate_retract_gear_valve"]);
+                copiedState.con_stimulate_retract_gear_valve();
+                copiedState.stateAccessedVia = "con_stimulate_retract_gear_valve";
+                result.insert(copiedState);
+            }
+            if(state._tr_con_stop_stimulate_retract_gear_valve(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["con_stop_stimulate_retract_gear_valve"]);
+                copiedState.con_stop_stimulate_retract_gear_valve();
+                copiedState.stateAccessedVia = "con_stop_stimulate_retract_gear_valve";
+                result.insert(copiedState);
+            }
+            if(state._tr_con_stimulate_extend_gear_valve(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["con_stimulate_extend_gear_valve"]);
+                copiedState.con_stimulate_extend_gear_valve();
+                copiedState.stateAccessedVia = "con_stimulate_extend_gear_valve";
+                result.insert(copiedState);
+            }
+            if(state._tr_con_stop_stimulate_extend_gear_valve(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["con_stop_stimulate_extend_gear_valve"]);
+                copiedState.con_stop_stimulate_extend_gear_valve();
+                copiedState.stateAccessedVia = "con_stop_stimulate_extend_gear_valve";
+                result.insert(copiedState);
+            }
+            BSet<LandingGear_R6::POSITION> _trid_19 = state._tr_env_start_retracting_first(isCaching);
+            for(const LandingGear_R6::POSITION& param : _trid_19) {
+                LandingGear_R6::POSITION _tmp_1 = param;
+
+                LandingGear_R6 copiedState = state._copy(guardDependency["env_start_retracting_first"]);
+                copiedState.env_start_retracting_first(_tmp_1);
+                copiedState.stateAccessedVia = "env_start_retracting_first";
+                result.insert(copiedState);
+            }
+            BSet<LandingGear_R6::POSITION> _trid_20 = state._tr_env_retract_gear_skip(isCaching);
+            for(const LandingGear_R6::POSITION& param : _trid_20) {
+                LandingGear_R6::POSITION _tmp_1 = param;
+
+                LandingGear_R6 copiedState = state._copy(guardDependency["env_retract_gear_skip"]);
+                copiedState.env_retract_gear_skip(_tmp_1);
+                copiedState.stateAccessedVia = "env_retract_gear_skip";
+                result.insert(copiedState);
+            }
+            BSet<LandingGear_R6::POSITION> _trid_21 = state._tr_env_retract_gear_last(isCaching);
+            for(const LandingGear_R6::POSITION& param : _trid_21) {
+                LandingGear_R6::POSITION _tmp_1 = param;
+
+                LandingGear_R6 copiedState = state._copy(guardDependency["env_retract_gear_last"]);
+                copiedState.env_retract_gear_last(_tmp_1);
+                copiedState.stateAccessedVia = "env_retract_gear_last";
+                result.insert(copiedState);
+            }
+            BSet<LandingGear_R6::POSITION> _trid_22 = state._tr_env_start_extending(isCaching);
+            for(const LandingGear_R6::POSITION& param : _trid_22) {
+                LandingGear_R6::POSITION _tmp_1 = param;
+
+                LandingGear_R6 copiedState = state._copy(guardDependency["env_start_extending"]);
+                copiedState.env_start_extending(_tmp_1);
+                copiedState.stateAccessedVia = "env_start_extending";
+                result.insert(copiedState);
+            }
+            BSet<LandingGear_R6::POSITION> _trid_23 = state._tr_env_extend_gear_last(isCaching);
+            for(const LandingGear_R6::POSITION& param : _trid_23) {
+                LandingGear_R6::POSITION _tmp_1 = param;
+
+                LandingGear_R6 copiedState = state._copy(guardDependency["env_extend_gear_last"]);
+                copiedState.env_extend_gear_last(_tmp_1);
+                copiedState.stateAccessedVia = "env_extend_gear_last";
+                result.insert(copiedState);
+            }
+            BSet<LandingGear_R6::POSITION> _trid_24 = state._tr_env_extend_gear_skip(isCaching);
+            for(const LandingGear_R6::POSITION& param : _trid_24) {
+                LandingGear_R6::POSITION _tmp_1 = param;
+
+                LandingGear_R6 copiedState = state._copy(guardDependency["env_extend_gear_skip"]);
+                copiedState.env_extend_gear_skip(_tmp_1);
+                copiedState.stateAccessedVia = "env_extend_gear_skip";
+                result.insert(copiedState);
+            }
+            BSet<LandingGear_R6::POSITION> _trid_25 = state._tr_env_start_open_door(isCaching);
+            for(const LandingGear_R6::POSITION& param : _trid_25) {
+                LandingGear_R6::POSITION _tmp_1 = param;
+
+                LandingGear_R6 copiedState = state._copy(guardDependency["env_start_open_door"]);
+                copiedState.env_start_open_door(_tmp_1);
+                copiedState.stateAccessedVia = "env_start_open_door";
+                result.insert(copiedState);
+            }
+            BSet<LandingGear_R6::POSITION> _trid_26 = state._tr_env_open_door_last(isCaching);
+            for(const LandingGear_R6::POSITION& param : _trid_26) {
+                LandingGear_R6::POSITION _tmp_1 = param;
+
+                LandingGear_R6 copiedState = state._copy(guardDependency["env_open_door_last"]);
+                copiedState.env_open_door_last(_tmp_1);
+                copiedState.stateAccessedVia = "env_open_door_last";
+                result.insert(copiedState);
+            }
+            BSet<LandingGear_R6::POSITION> _trid_27 = state._tr_env_open_door_skip(isCaching);
+            for(const LandingGear_R6::POSITION& param : _trid_27) {
+                LandingGear_R6::POSITION _tmp_1 = param;
+
+                LandingGear_R6 copiedState = state._copy(guardDependency["env_open_door_skip"]);
+                copiedState.env_open_door_skip(_tmp_1);
+                copiedState.stateAccessedVia = "env_open_door_skip";
+                result.insert(copiedState);
+            }
+            BSet<LandingGear_R6::POSITION> _trid_28 = state._tr_env_start_close_door(isCaching);
+            for(const LandingGear_R6::POSITION& param : _trid_28) {
+                LandingGear_R6::POSITION _tmp_1 = param;
+
+                LandingGear_R6 copiedState = state._copy(guardDependency["env_start_close_door"]);
+                copiedState.env_start_close_door(_tmp_1);
+                copiedState.stateAccessedVia = "env_start_close_door";
+                result.insert(copiedState);
+            }
+            BSet<LandingGear_R6::POSITION> _trid_29 = state._tr_env_close_door(isCaching);
+            for(const LandingGear_R6::POSITION& param : _trid_29) {
+                LandingGear_R6::POSITION _tmp_1 = param;
+
+                LandingGear_R6 copiedState = state._copy(guardDependency["env_close_door"]);
+                copiedState.env_close_door(_tmp_1);
+                copiedState.stateAccessedVia = "env_close_door";
+                result.insert(copiedState);
+            }
+            BSet<LandingGear_R6::POSITION> _trid_30 = state._tr_env_close_door_skip(isCaching);
+            for(const LandingGear_R6::POSITION& param : _trid_30) {
+                LandingGear_R6::POSITION _tmp_1 = param;
+
+                LandingGear_R6 copiedState = state._copy(guardDependency["env_close_door_skip"]);
+                copiedState.env_close_door_skip(_tmp_1);
+                copiedState.stateAccessedVia = "env_close_door_skip";
+                result.insert(copiedState);
+            }
+            if(state._tr_toggle_handle_up(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["toggle_handle_up"]);
+                copiedState.toggle_handle_up();
+                copiedState.stateAccessedVia = "toggle_handle_up";
+                result.insert(copiedState);
+            }
+            if(state._tr_toggle_handle_down(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["toggle_handle_down"]);
+                copiedState.toggle_handle_down();
+                copiedState.stateAccessedVia = "toggle_handle_down";
+                result.insert(copiedState);
+            }
+            if(state._tr_con_stimulate_general_valve(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["con_stimulate_general_valve"]);
+                copiedState.con_stimulate_general_valve();
+                copiedState.stateAccessedVia = "con_stimulate_general_valve";
+                result.insert(copiedState);
+            }
+            if(state._tr_con_stop_stimulate_general_valve(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["con_stop_stimulate_general_valve"]);
+                copiedState.con_stop_stimulate_general_valve();
+                copiedState.stateAccessedVia = "con_stop_stimulate_general_valve";
+                result.insert(copiedState);
+            }
+            if(state._tr_evn_open_general_valve(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["evn_open_general_valve"]);
+                copiedState.evn_open_general_valve();
+                copiedState.stateAccessedVia = "evn_open_general_valve";
+                result.insert(copiedState);
+            }
+            if(state._tr_evn_close_general_valve(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["evn_close_general_valve"]);
+                copiedState.evn_close_general_valve();
+                copiedState.stateAccessedVia = "evn_close_general_valve";
+                result.insert(copiedState);
+            }
+            if(state._tr_env_close_analogical_switch(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["env_close_analogical_switch"]);
+                copiedState.env_close_analogical_switch();
+                copiedState.stateAccessedVia = "env_close_analogical_switch";
+                result.insert(copiedState);
+            }
+            if(state._tr_env_open_analogical_switch(isCaching)) {
+                LandingGear_R6 copiedState = state._copy(guardDependency["env_open_analogical_switch"]);
+                copiedState.env_open_analogical_switch();
+                copiedState.stateAccessedVia = "env_open_analogical_switch";
+                result.insert(copiedState);
             }
-            result.insert(copiedState);
-            transitions += 1;
+
+            return result;
         }
-        bool _trid_12;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_con_stop_stimulate_open_door_valve"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_con_stop_stimulate_open_door_valve") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_12 = state._tr_con_stop_stimulate_open_door_valve();
-        } else {
-            _trid_12 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_con_stop_stimulate_open_door_valve", _trid_12);
-        if(_trid_12) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.con_stop_stimulate_open_door_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["con_stop_stimulate_open_door_valve"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["con_stop_stimulate_open_door_valve"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "con_stop_stimulate_open_door_valve"});
+
+        bool invariantViolated(const LandingGear_R6& state) {
+            if(isCaching) {
+                std::unordered_set<string> dependentInvariantsOfState = invariantDependency[state.stateAccessedVia];
+                if(dependentInvariantsOfState.find("_check_inv_1") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_1()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_13;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_con_stimulate_close_door_valve"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_con_stimulate_close_door_valve") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_13 = state._tr_con_stimulate_close_door_valve();
-        } else {
-            _trid_13 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_con_stimulate_close_door_valve", _trid_13);
-        if(_trid_13) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.con_stimulate_close_door_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["con_stimulate_close_door_valve"]});
+                if(dependentInvariantsOfState.find("_check_inv_2") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_2()) {
+                        return false;
+                    }
                 }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["con_stimulate_close_door_valve"]});
+                if(dependentInvariantsOfState.find("_check_inv_3") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_3()) {
+                        return false;
+                    }
                 }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_4") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_4()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "con_stimulate_close_door_valve"});
+                if(dependentInvariantsOfState.find("_check_inv_5") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_5()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_14;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_con_stop_stimulate_close_door_valve"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_con_stop_stimulate_close_door_valve") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_14 = state._tr_con_stop_stimulate_close_door_valve();
-        } else {
-            _trid_14 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_con_stop_stimulate_close_door_valve", _trid_14);
-        if(_trid_14) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.con_stop_stimulate_close_door_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["con_stop_stimulate_close_door_valve"]});
+                if(dependentInvariantsOfState.find("_check_inv_6") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_6()) {
+                        return false;
+                    }
                 }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["con_stop_stimulate_close_door_valve"]});
+                if(dependentInvariantsOfState.find("_check_inv_7") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_7()) {
+                        return false;
+                    }
                 }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_8") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_8()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "con_stop_stimulate_close_door_valve"});
+                if(dependentInvariantsOfState.find("_check_inv_9") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_9()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_15;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_con_stimulate_retract_gear_valve"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_con_stimulate_retract_gear_valve") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_15 = state._tr_con_stimulate_retract_gear_valve();
-        } else {
-            _trid_15 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_con_stimulate_retract_gear_valve", _trid_15);
-        if(_trid_15) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.con_stimulate_retract_gear_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["con_stimulate_retract_gear_valve"]});
+                if(dependentInvariantsOfState.find("_check_inv_10") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_10()) {
+                        return false;
+                    }
                 }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["con_stimulate_retract_gear_valve"]});
+                if(dependentInvariantsOfState.find("_check_inv_11") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_11()) {
+                        return false;
+                    }
                 }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_12") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_12()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "con_stimulate_retract_gear_valve"});
+                if(dependentInvariantsOfState.find("_check_inv_13") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_13()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_16;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_con_stop_stimulate_retract_gear_valve"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_con_stop_stimulate_retract_gear_valve") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_16 = state._tr_con_stop_stimulate_retract_gear_valve();
-        } else {
-            _trid_16 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_con_stop_stimulate_retract_gear_valve", _trid_16);
-        if(_trid_16) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.con_stop_stimulate_retract_gear_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["con_stop_stimulate_retract_gear_valve"]});
+                if(dependentInvariantsOfState.find("_check_inv_14") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_14()) {
+                        return false;
+                    }
                 }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["con_stop_stimulate_retract_gear_valve"]});
+                if(dependentInvariantsOfState.find("_check_inv_15") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_15()) {
+                        return false;
+                    }
                 }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_16") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_16()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "con_stop_stimulate_retract_gear_valve"});
+                if(dependentInvariantsOfState.find("_check_inv_17") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_17()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_17;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_con_stimulate_extend_gear_valve"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_con_stimulate_extend_gear_valve") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_17 = state._tr_con_stimulate_extend_gear_valve();
-        } else {
-            _trid_17 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_con_stimulate_extend_gear_valve", _trid_17);
-        if(_trid_17) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.con_stimulate_extend_gear_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["con_stimulate_extend_gear_valve"]});
+                if(dependentInvariantsOfState.find("_check_inv_18") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_18()) {
+                        return false;
+                    }
                 }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["con_stimulate_extend_gear_valve"]});
+                if(dependentInvariantsOfState.find("_check_inv_19") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_19()) {
+                        return false;
+                    }
                 }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_20") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_20()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "con_stimulate_extend_gear_valve"});
+                if(dependentInvariantsOfState.find("_check_inv_21") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_21()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_18;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_con_stop_stimulate_extend_gear_valve"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_con_stop_stimulate_extend_gear_valve") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_18 = state._tr_con_stop_stimulate_extend_gear_valve();
-        } else {
-            _trid_18 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_con_stop_stimulate_extend_gear_valve", _trid_18);
-        if(_trid_18) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.con_stop_stimulate_extend_gear_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["con_stop_stimulate_extend_gear_valve"]});
+                if(dependentInvariantsOfState.find("_check_inv_22") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_22()) {
+                        return false;
+                    }
                 }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["con_stop_stimulate_extend_gear_valve"]});
+                if(dependentInvariantsOfState.find("_check_inv_23") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_23()) {
+                        return false;
+                    }
                 }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_24") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_24()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "con_stop_stimulate_extend_gear_valve"});
+                if(dependentInvariantsOfState.find("_check_inv_25") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_25()) {
+                        return false;
+                    }
                 }
+                return false;
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_19;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_env_start_retracting_first"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_env_start_retracting_first") != dependentGuardsOfState.end());
+            return !(state._check_inv_1() && state._check_inv_2() && state._check_inv_3() && state._check_inv_4() && state._check_inv_5() && state._check_inv_6() && state._check_inv_7() && state._check_inv_8() && state._check_inv_9() && state._check_inv_10() && state._check_inv_11() && state._check_inv_12() && state._check_inv_13() && state._check_inv_14() && state._check_inv_15() && state._check_inv_16() && state._check_inv_17() && state._check_inv_18() && state._check_inv_19() && state._check_inv_20() && state._check_inv_21() && state._check_inv_22() && state._check_inv_23() && state._check_inv_24() && state._check_inv_25());
         }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_19 = state._tr_env_start_retracting_first();
-        } else {
-            _trid_19 = boost::any_cast<BSet<LandingGear_R6::POSITION>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_env_start_retracting_first", _trid_19);
-        for(const LandingGear_R6::POSITION& param : _trid_19) {
-            LandingGear_R6::POSITION _tmp_1 = param;
 
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_start_retracting_first(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["env_start_retracting_first"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["env_start_retracting_first"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_start_retracting_first"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_20;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_env_retract_gear_skip"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_env_retract_gear_skip") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_20 = state._tr_env_retract_gear_skip();
-        } else {
-            _trid_20 = boost::any_cast<BSet<LandingGear_R6::POSITION>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_env_retract_gear_skip", _trid_20);
-        for(const LandingGear_R6::POSITION& param : _trid_20) {
-            LandingGear_R6::POSITION _tmp_1 = param;
 
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_retract_gear_skip(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["env_retract_gear_skip"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["env_retract_gear_skip"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_retract_gear_skip"});
+        void printResult() {
+            if(deadlockDetected || invariantViolatedBool) {
+                if(deadlockDetected) {
+                    cout << "DEADLOCK DETECTED" << "\n";
+                } else {
+                    cout << "INVARIANT VIOLATED" << "\n";
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_21;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_env_retract_gear_last"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_env_retract_gear_last") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_21 = state._tr_env_retract_gear_last();
-        } else {
-            _trid_21 = boost::any_cast<BSet<LandingGear_R6::POSITION>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_env_retract_gear_last", _trid_21);
-        for(const LandingGear_R6::POSITION& param : _trid_21) {
-            LandingGear_R6::POSITION _tmp_1 = param;
 
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_retract_gear_last(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["env_retract_gear_last"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["env_retract_gear_last"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_retract_gear_last"});
+                cout << "COUNTER EXAMPLE TRACE: " << "\n";
+
+                std::string trace = "";
+                while(parents.find(counterExampleState) != parents.end()) {
+                    std::stringstream stringStream;
+                    stringStream << counterExampleState;
+                    trace.insert(0, stringStream.str());
+                    trace.insert(0, "\n");
+                    trace.insert(0, counterExampleState.stateAccessedVia);
+                    trace.insert(0, "\n\n");
+                    counterExampleState = parents[counterExampleState];
                 }
+                cout << trace;
+            } else {
+                cout << "MODEL CHECKING SUCCESSFUL" << "\n";
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_22;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_env_start_extending"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_env_start_extending") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_22 = state._tr_env_start_extending();
-        } else {
-            _trid_22 = boost::any_cast<BSet<LandingGear_R6::POSITION>>(cachedValue);
+
+            cout << "Number of States: " << states.size() << "\n";
+            cout << "Number of Transitions: " << transitions << "\n";
         }
-        newCache = newCache.set("_tr_env_start_extending", _trid_22);
-        for(const LandingGear_R6::POSITION& param : _trid_22) {
-            LandingGear_R6::POSITION _tmp_1 = param;
-
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_start_extending(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["env_start_extending"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["env_start_extending"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_start_extending"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_23;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_env_extend_gear_last"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_env_extend_gear_last") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_23 = state._tr_env_extend_gear_last();
-        } else {
-            _trid_23 = boost::any_cast<BSet<LandingGear_R6::POSITION>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_env_extend_gear_last", _trid_23);
-        for(const LandingGear_R6::POSITION& param : _trid_23) {
-            LandingGear_R6::POSITION _tmp_1 = param;
-
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_extend_gear_last(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["env_extend_gear_last"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["env_extend_gear_last"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_extend_gear_last"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_24;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_env_extend_gear_skip"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_env_extend_gear_skip") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_24 = state._tr_env_extend_gear_skip();
-        } else {
-            _trid_24 = boost::any_cast<BSet<LandingGear_R6::POSITION>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_env_extend_gear_skip", _trid_24);
-        for(const LandingGear_R6::POSITION& param : _trid_24) {
-            LandingGear_R6::POSITION _tmp_1 = param;
-
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_extend_gear_skip(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["env_extend_gear_skip"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["env_extend_gear_skip"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_extend_gear_skip"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_25;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_env_start_open_door"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_env_start_open_door") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_25 = state._tr_env_start_open_door();
-        } else {
-            _trid_25 = boost::any_cast<BSet<LandingGear_R6::POSITION>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_env_start_open_door", _trid_25);
-        for(const LandingGear_R6::POSITION& param : _trid_25) {
-            LandingGear_R6::POSITION _tmp_1 = param;
-
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_start_open_door(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["env_start_open_door"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["env_start_open_door"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_start_open_door"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_26;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_env_open_door_last"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_env_open_door_last") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_26 = state._tr_env_open_door_last();
-        } else {
-            _trid_26 = boost::any_cast<BSet<LandingGear_R6::POSITION>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_env_open_door_last", _trid_26);
-        for(const LandingGear_R6::POSITION& param : _trid_26) {
-            LandingGear_R6::POSITION _tmp_1 = param;
-
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_open_door_last(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["env_open_door_last"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["env_open_door_last"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_open_door_last"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_27;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_env_open_door_skip"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_env_open_door_skip") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_27 = state._tr_env_open_door_skip();
-        } else {
-            _trid_27 = boost::any_cast<BSet<LandingGear_R6::POSITION>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_env_open_door_skip", _trid_27);
-        for(const LandingGear_R6::POSITION& param : _trid_27) {
-            LandingGear_R6::POSITION _tmp_1 = param;
-
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_open_door_skip(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["env_open_door_skip"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["env_open_door_skip"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_open_door_skip"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_28;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_env_start_close_door"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_env_start_close_door") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_28 = state._tr_env_start_close_door();
-        } else {
-            _trid_28 = boost::any_cast<BSet<LandingGear_R6::POSITION>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_env_start_close_door", _trid_28);
-        for(const LandingGear_R6::POSITION& param : _trid_28) {
-            LandingGear_R6::POSITION _tmp_1 = param;
-
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_start_close_door(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["env_start_close_door"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["env_start_close_door"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_start_close_door"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_29;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_env_close_door"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_env_close_door") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_29 = state._tr_env_close_door();
-        } else {
-            _trid_29 = boost::any_cast<BSet<LandingGear_R6::POSITION>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_env_close_door", _trid_29);
-        for(const LandingGear_R6::POSITION& param : _trid_29) {
-            LandingGear_R6::POSITION _tmp_1 = param;
-
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_close_door(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["env_close_door"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["env_close_door"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_close_door"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_30;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_env_close_door_skip"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_env_close_door_skip") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_30 = state._tr_env_close_door_skip();
-        } else {
-            _trid_30 = boost::any_cast<BSet<LandingGear_R6::POSITION>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_env_close_door_skip", _trid_30);
-        for(const LandingGear_R6::POSITION& param : _trid_30) {
-            LandingGear_R6::POSITION _tmp_1 = param;
-
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_close_door_skip(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["env_close_door_skip"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["env_close_door_skip"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_close_door_skip"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_31;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_toggle_handle_up"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_toggle_handle_up") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_31 = state._tr_toggle_handle_up();
-        } else {
-            _trid_31 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_toggle_handle_up", _trid_31);
-        if(_trid_31) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.toggle_handle_up();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["toggle_handle_up"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["toggle_handle_up"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "toggle_handle_up"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_32;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_toggle_handle_down"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_toggle_handle_down") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_32 = state._tr_toggle_handle_down();
-        } else {
-            _trid_32 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_toggle_handle_down", _trid_32);
-        if(_trid_32) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.toggle_handle_down();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["toggle_handle_down"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["toggle_handle_down"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "toggle_handle_down"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_33;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_con_stimulate_general_valve"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_con_stimulate_general_valve") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_33 = state._tr_con_stimulate_general_valve();
-        } else {
-            _trid_33 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_con_stimulate_general_valve", _trid_33);
-        if(_trid_33) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.con_stimulate_general_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["con_stimulate_general_valve"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["con_stimulate_general_valve"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "con_stimulate_general_valve"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_34;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_con_stop_stimulate_general_valve"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_con_stop_stimulate_general_valve") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_34 = state._tr_con_stop_stimulate_general_valve();
-        } else {
-            _trid_34 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_con_stop_stimulate_general_valve", _trid_34);
-        if(_trid_34) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.con_stop_stimulate_general_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["con_stop_stimulate_general_valve"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["con_stop_stimulate_general_valve"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "con_stop_stimulate_general_valve"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_35;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_evn_open_general_valve"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_evn_open_general_valve") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_35 = state._tr_evn_open_general_valve();
-        } else {
-            _trid_35 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_evn_open_general_valve", _trid_35);
-        if(_trid_35) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.evn_open_general_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["evn_open_general_valve"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["evn_open_general_valve"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "evn_open_general_valve"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_36;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_evn_close_general_valve"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_evn_close_general_valve") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_36 = state._tr_evn_close_general_valve();
-        } else {
-            _trid_36 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_evn_close_general_valve", _trid_36);
-        if(_trid_36) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.evn_close_general_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["evn_close_general_valve"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["evn_close_general_valve"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "evn_close_general_valve"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_37;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_env_close_analogical_switch"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_env_close_analogical_switch") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_37 = state._tr_env_close_analogical_switch();
-        } else {
-            _trid_37 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_env_close_analogical_switch", _trid_37);
-        if(_trid_37) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_close_analogical_switch();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["env_close_analogical_switch"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["env_close_analogical_switch"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_close_analogical_switch"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_38;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_env_open_analogical_switch"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_env_open_analogical_switch") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_38 = state._tr_env_open_analogical_switch();
-        } else {
-            _trid_38 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_env_open_analogical_switch", _trid_38);
-        if(_trid_38) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_open_analogical_switch();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["env_open_analogical_switch"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["env_open_analogical_switch"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_open_analogical_switch"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            guardCache.insert({state, newCache});
-        }
-    } else {
-        if(state._tr_begin_flying()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.begin_flying();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "begin_flying"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_land_plane()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.land_plane();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "land_plane"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_open_valve_door_open()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.open_valve_door_open();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "open_valve_door_open"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_close_valve_door_open()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.close_valve_door_open();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "close_valve_door_open"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_open_valve_door_close()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.open_valve_door_close();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "open_valve_door_close"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_close_valve_door_close()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.close_valve_door_close();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "close_valve_door_close"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_open_valve_retract_gear()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.open_valve_retract_gear();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "open_valve_retract_gear"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_close_valve_retract_gear()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.close_valve_retract_gear();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "close_valve_retract_gear"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_open_valve_extend_gear()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.open_valve_extend_gear();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "open_valve_extend_gear"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_close_valve_extend_gear()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.close_valve_extend_gear();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "close_valve_extend_gear"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_con_stimulate_open_door_valve()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.con_stimulate_open_door_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "con_stimulate_open_door_valve"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_con_stop_stimulate_open_door_valve()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.con_stop_stimulate_open_door_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "con_stop_stimulate_open_door_valve"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_con_stimulate_close_door_valve()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.con_stimulate_close_door_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "con_stimulate_close_door_valve"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_con_stop_stimulate_close_door_valve()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.con_stop_stimulate_close_door_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "con_stop_stimulate_close_door_valve"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_con_stimulate_retract_gear_valve()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.con_stimulate_retract_gear_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "con_stimulate_retract_gear_valve"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_con_stop_stimulate_retract_gear_valve()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.con_stop_stimulate_retract_gear_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "con_stop_stimulate_retract_gear_valve"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_con_stimulate_extend_gear_valve()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.con_stimulate_extend_gear_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "con_stimulate_extend_gear_valve"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_con_stop_stimulate_extend_gear_valve()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.con_stop_stimulate_extend_gear_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "con_stop_stimulate_extend_gear_valve"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_19 = state._tr_env_start_retracting_first();
-        for(const LandingGear_R6::POSITION& param : _trid_19) {
-            LandingGear_R6::POSITION _tmp_1 = param;
-
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_start_retracting_first(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_start_retracting_first"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_20 = state._tr_env_retract_gear_skip();
-        for(const LandingGear_R6::POSITION& param : _trid_20) {
-            LandingGear_R6::POSITION _tmp_1 = param;
-
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_retract_gear_skip(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_retract_gear_skip"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_21 = state._tr_env_retract_gear_last();
-        for(const LandingGear_R6::POSITION& param : _trid_21) {
-            LandingGear_R6::POSITION _tmp_1 = param;
-
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_retract_gear_last(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_retract_gear_last"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_22 = state._tr_env_start_extending();
-        for(const LandingGear_R6::POSITION& param : _trid_22) {
-            LandingGear_R6::POSITION _tmp_1 = param;
-
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_start_extending(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_start_extending"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_23 = state._tr_env_extend_gear_last();
-        for(const LandingGear_R6::POSITION& param : _trid_23) {
-            LandingGear_R6::POSITION _tmp_1 = param;
-
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_extend_gear_last(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_extend_gear_last"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_24 = state._tr_env_extend_gear_skip();
-        for(const LandingGear_R6::POSITION& param : _trid_24) {
-            LandingGear_R6::POSITION _tmp_1 = param;
-
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_extend_gear_skip(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_extend_gear_skip"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_25 = state._tr_env_start_open_door();
-        for(const LandingGear_R6::POSITION& param : _trid_25) {
-            LandingGear_R6::POSITION _tmp_1 = param;
-
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_start_open_door(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_start_open_door"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_26 = state._tr_env_open_door_last();
-        for(const LandingGear_R6::POSITION& param : _trid_26) {
-            LandingGear_R6::POSITION _tmp_1 = param;
-
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_open_door_last(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_open_door_last"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_27 = state._tr_env_open_door_skip();
-        for(const LandingGear_R6::POSITION& param : _trid_27) {
-            LandingGear_R6::POSITION _tmp_1 = param;
-
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_open_door_skip(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_open_door_skip"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_28 = state._tr_env_start_close_door();
-        for(const LandingGear_R6::POSITION& param : _trid_28) {
-            LandingGear_R6::POSITION _tmp_1 = param;
-
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_start_close_door(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_start_close_door"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_29 = state._tr_env_close_door();
-        for(const LandingGear_R6::POSITION& param : _trid_29) {
-            LandingGear_R6::POSITION _tmp_1 = param;
-
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_close_door(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_close_door"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<LandingGear_R6::POSITION> _trid_30 = state._tr_env_close_door_skip();
-        for(const LandingGear_R6::POSITION& param : _trid_30) {
-            LandingGear_R6::POSITION _tmp_1 = param;
-
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_close_door_skip(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_close_door_skip"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_toggle_handle_up()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.toggle_handle_up();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "toggle_handle_up"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_toggle_handle_down()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.toggle_handle_down();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "toggle_handle_down"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_con_stimulate_general_valve()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.con_stimulate_general_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "con_stimulate_general_valve"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_con_stop_stimulate_general_valve()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.con_stop_stimulate_general_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "con_stop_stimulate_general_valve"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_evn_open_general_valve()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.evn_open_general_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "evn_open_general_valve"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_evn_close_general_valve()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.evn_close_general_valve();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "evn_close_general_valve"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_env_close_analogical_switch()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_close_analogical_switch();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_close_analogical_switch"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_env_open_analogical_switch()) {
-            LandingGear_R6 copiedState = state._copy();
-            copiedState.env_open_analogical_switch();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "env_open_analogical_switch"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-
-    }
-    return result;
-}
-
-static void printResult(int states, int transitions, bool deadlockDetected, bool invariantViolated, LandingGear_R6& counterExampleState, std::unordered_map<LandingGear_R6, LandingGear_R6, LandingGear_R6::Hash, LandingGear_R6::HashEqual>& parents, std::unordered_map<LandingGear_R6, string, LandingGear_R6::Hash, LandingGear_R6::HashEqual>& stateAccessedVia) {
-    if(deadlockDetected || invariantViolated) {
-        if(deadlockDetected) {
-            cout << "DEADLOCK DETECTED" << "\n";
-        }
-        if(invariantViolated) {
-            cout << "INVARIANT VIOLATED" << "\n";
-        }
-        cout << "COUNTER EXAMPLE TRACE: " << "\n";
-
-        LandingGear_R6 currentState = counterExampleState;
-        std::string trace = "";
-        while(parents.find(currentState) != parents.end()) {
-            std::stringstream stringStream;
-            stringStream << currentState;
-            trace.insert(0, stringStream.str());
-            trace.insert(0, "\n");
-            trace.insert(0, stateAccessedVia[currentState]);
-            trace.insert(0, "\n\n");
-            currentState = parents[currentState];
-        }
-        cout << trace;
-    }
-
-    if(!deadlockDetected && !invariantViolated) {
-        cout << "MODEL CHECKING SUCCESSFUL" << "\n";
-    }
-    cout << "Number of States: " << states << "\n";
-    cout << "Number of Transitions: " << transitions << "\n";
-}
-
-static bool checkInvariants(std::mutex& guardMutex, const LandingGear_R6& state, bool isCaching, std::unordered_map<LandingGear_R6, std::unordered_set<string>, LandingGear_R6::Hash, LandingGear_R6::HashEqual>& dependentInvariant) {
-    if(isCaching) {
-        std::unordered_set<string> dependentInvariantsOfState;
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            dependentInvariantsOfState = dependentInvariant[state];
-        }
-        if(dependentInvariantsOfState.find("_check_inv_1") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_1()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_2") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_2()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_3") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_3()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_4") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_4()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_5") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_5()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_6") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_6()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_7") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_7()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_8") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_8()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_9") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_9()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_10") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_10()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_11") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_11()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_12") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_12()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_13") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_13()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_14") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_14()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_15") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_15()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_16") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_16()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_17") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_17()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_18") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_18()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_19") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_19()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_20") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_20()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_21") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_21()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_22") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_22()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_23") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_23()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_24") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_24()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_25") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_25()) {
-                return false;
-            }
-        }
-        return true;
-    }
-    return !(!state._check_inv_1() || !state._check_inv_2() || !state._check_inv_3() || !state._check_inv_4() || !state._check_inv_5() || !state._check_inv_6() || !state._check_inv_7() || !state._check_inv_8() || !state._check_inv_9() || !state._check_inv_10() || !state._check_inv_11() || !state._check_inv_12() || !state._check_inv_13() || !state._check_inv_14() || !state._check_inv_15() || !state._check_inv_16() || !state._check_inv_17() || !state._check_inv_18() || !state._check_inv_19() || !state._check_inv_20() || !state._check_inv_21() || !state._check_inv_22() || !state._check_inv_23() || !state._check_inv_24() || !state._check_inv_25());
-}
-
-static LandingGear_R6 next(std::list<LandingGear_R6>& collection, std::mutex& mutex, LandingGear_R6::Type type) {
-    std::unique_lock<std::mutex> lock(mutex);
-    switch(type) {
-        case LandingGear_R6::BFS: {
-            LandingGear_R6 state = collection.front();
-            collection.pop_front();
-            return state;
-        }
-        case LandingGear_R6::DFS: {
-            LandingGear_R6 state = collection.back();
-            collection.pop_back();
-            return state;
-        }
-        case LandingGear_R6::MIXED: {
-            if(collection.size() % 2 == 0) {
-                LandingGear_R6 state = collection.front();
-                collection.pop_front();
-                return state;
-            } else {
-                LandingGear_R6 state = collection.back();
-                collection.pop_back();
-                return state;
-            }
-        }
-    };
-}
-
-static void modelCheckSingleThreaded(LandingGear_R6::Type type, bool isCaching) {
-    std::mutex mutex;
-    std::mutex guardMutex;
-
-    LandingGear_R6 machine = LandingGear_R6();
-
-    std::atomic<bool> invariantViolated;
-    invariantViolated = false;
-    std::atomic<bool> deadlockDetected;
-    deadlockDetected = false;
-    std::atomic<bool> stopThreads;
-    stopThreads = false;
-
-    std::unordered_set<LandingGear_R6, LandingGear_R6::Hash, LandingGear_R6::HashEqual> states = std::unordered_set<LandingGear_R6, LandingGear_R6::Hash, LandingGear_R6::HashEqual>();
-    states.insert(machine);
-    std::atomic<int> numberStates;
-    numberStates = 1;
-
-    std::list<LandingGear_R6> collection = std::list<LandingGear_R6>();
-    collection.push_back(machine);
-
-    std::atomic<int> transitions;
-    transitions = 0;
-
-    std::unordered_map<string, std::unordered_set<string>> invariantDependency;
-    std::unordered_map<string, std::unordered_set<string>> guardDependency;
-    std::unordered_map<LandingGear_R6, std::unordered_set<string>, LandingGear_R6::Hash, LandingGear_R6::HashEqual> dependentInvariant;
-    std::unordered_map<LandingGear_R6, std::unordered_set<string>, LandingGear_R6::Hash, LandingGear_R6::HashEqual> dependentGuard;
-    std::unordered_map<LandingGear_R6, immer::map<string, boost::any>, LandingGear_R6::Hash, LandingGear_R6::HashEqual> guardCache;
-    std::unordered_map<LandingGear_R6, LandingGear_R6, LandingGear_R6::Hash, LandingGear_R6::HashEqual> parents;
-    std::unordered_map<LandingGear_R6, string, LandingGear_R6::Hash, LandingGear_R6::HashEqual> stateAccessedVia;
-    if(isCaching) {
-        invariantDependency.insert({"close_valve_door_close", {"_check_inv_10"}});
-        invariantDependency.insert({"close_valve_retract_gear", {"_check_inv_13"}});
-        invariantDependency.insert({"con_stimulate_open_door_valve", {"_check_inv_18", "_check_inv_17", "_check_inv_7"}});
-        invariantDependency.insert({"env_close_door", {"_check_inv_15", "_check_inv_21", "_check_inv_20", "_check_inv_25", "_check_inv_22"}});
-        invariantDependency.insert({"env_start_close_door", {"_check_inv_15", "_check_inv_21", "_check_inv_20", "_check_inv_25", "_check_inv_22"}});
-        invariantDependency.insert({"toggle_handle_up", {"_check_inv_4", "_check_inv_14"}});
-        invariantDependency.insert({"toggle_handle_down", {"_check_inv_4", "_check_inv_14"}});
-        invariantDependency.insert({"open_valve_door_open", {"_check_inv_12"}});
-        invariantDependency.insert({"env_retract_gear_last", {"_check_inv_16", "_check_inv_19", "_check_inv_25", "_check_inv_24", "_check_inv_23"}});
-        invariantDependency.insert({"env_open_door_last", {"_check_inv_15", "_check_inv_21", "_check_inv_20", "_check_inv_25", "_check_inv_22"}});
-        invariantDependency.insert({"con_stop_stimulate_retract_gear_valve", {"_check_inv_17", "_check_inv_8"}});
-        invariantDependency.insert({"env_close_door_skip", {"_check_inv_21", "_check_inv_20", "_check_inv_22"}});
-        invariantDependency.insert({"con_stop_stimulate_close_door_valve", {"_check_inv_18", "_check_inv_17", "_check_inv_5"}});
-        invariantDependency.insert({"env_open_analogical_switch", {"_check_inv_1"}});
-        invariantDependency.insert({"con_stop_stimulate_general_valve", {"_check_inv_17", "_check_inv_2", "_check_inv_4"}});
-        invariantDependency.insert({"env_extend_gear_last", {"_check_inv_16", "_check_inv_19", "_check_inv_25", "_check_inv_24", "_check_inv_23"}});
-        invariantDependency.insert({"evn_open_general_valve", {"_check_inv_3"}});
-        invariantDependency.insert({"land_plane", {"_check_inv_9"}});
-        invariantDependency.insert({"con_stimulate_retract_gear_valve", {"_check_inv_17", "_check_inv_8"}});
-        invariantDependency.insert({"con_stimulate_general_valve", {"_check_inv_17", "_check_inv_2"}});
-        invariantDependency.insert({"env_start_retracting_first", {"_check_inv_16", "_check_inv_19", "_check_inv_25", "_check_inv_24", "_check_inv_23"}});
-        invariantDependency.insert({"env_retract_gear_skip", {"_check_inv_19", "_check_inv_24", "_check_inv_23"}});
-        invariantDependency.insert({"open_valve_extend_gear", {"_check_inv_11"}});
-        invariantDependency.insert({"begin_flying", {"_check_inv_9"}});
-        invariantDependency.insert({"open_valve_retract_gear", {"_check_inv_13"}});
-        invariantDependency.insert({"env_close_analogical_switch", {"_check_inv_1"}});
-        invariantDependency.insert({"env_start_extending", {"_check_inv_16", "_check_inv_19", "_check_inv_25", "_check_inv_24", "_check_inv_23"}});
-        invariantDependency.insert({"open_valve_door_close", {"_check_inv_10"}});
-        invariantDependency.insert({"con_stop_stimulate_open_door_valve", {"_check_inv_18", "_check_inv_17", "_check_inv_7"}});
-        invariantDependency.insert({"con_stop_stimulate_extend_gear_valve", {"_check_inv_17", "_check_inv_6"}});
-        invariantDependency.insert({"evn_close_general_valve", {"_check_inv_3"}});
-        invariantDependency.insert({"close_valve_extend_gear", {"_check_inv_11"}});
-        invariantDependency.insert({"con_stimulate_extend_gear_valve", {"_check_inv_17", "_check_inv_6"}});
-        invariantDependency.insert({"close_valve_door_open", {"_check_inv_12"}});
-        invariantDependency.insert({"con_stimulate_close_door_valve", {"_check_inv_18", "_check_inv_17", "_check_inv_5"}});
-        invariantDependency.insert({"env_extend_gear_skip", {"_check_inv_19", "_check_inv_24", "_check_inv_23"}});
-        invariantDependency.insert({"env_open_door_skip", {"_check_inv_21", "_check_inv_20", "_check_inv_22"}});
-        invariantDependency.insert({"env_start_open_door", {"_check_inv_15", "_check_inv_21", "_check_inv_20", "_check_inv_25", "_check_inv_22"}});
-        guardDependency.insert({"close_valve_door_close", {"_tr_open_valve_door_close", "_tr_env_close_door_skip", "_tr_env_start_close_door", "_tr_env_close_door", "_tr_close_valve_door_close"}});
-        guardDependency.insert({"close_valve_retract_gear", {"_tr_close_valve_retract_gear", "_tr_open_valve_retract_gear", "_tr_env_start_retracting_first"}});
-        guardDependency.insert({"con_stimulate_open_door_valve", {"_tr_open_valve_door_open", "_tr_con_stimulate_extend_gear_valve", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stimulate_open_door_valve", "_tr_close_valve_door_open"}});
-        guardDependency.insert({"env_close_door", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"env_start_close_door", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"toggle_handle_up", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_close_analogical_switch", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip", "_tr_con_stimulate_general_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_toggle_handle_down", "_tr_env_open_door_last", "_tr_toggle_handle_up", "_tr_env_start_close_door", "_tr_con_stop_stimulate_close_door_valve"}});
-        guardDependency.insert({"toggle_handle_down", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_close_analogical_switch", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip", "_tr_con_stimulate_general_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_toggle_handle_down", "_tr_env_open_door_last", "_tr_toggle_handle_up", "_tr_env_start_close_door", "_tr_con_stop_stimulate_close_door_valve"}});
-        guardDependency.insert({"open_valve_door_open", {"_tr_open_valve_door_open", "_tr_env_open_door_last", "_tr_env_start_open_door", "_tr_env_open_door_skip", "_tr_close_valve_door_open"}});
-        guardDependency.insert({"env_retract_gear_last", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"env_open_door_last", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"con_stop_stimulate_retract_gear_valve", {"_tr_close_valve_retract_gear", "_tr_con_stimulate_extend_gear_valve", "_tr_open_valve_retract_gear", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_retract_gear_valve"}});
-        guardDependency.insert({"env_close_door_skip", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"con_stop_stimulate_close_door_valve", {"_tr_open_valve_door_close", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_close_valve_door_close"}});
-        guardDependency.insert({"env_open_analogical_switch", {"_tr_env_open_analogical_switch", "_tr_evn_open_general_valve", "_tr_env_close_analogical_switch", "_tr_evn_close_general_valve"}});
-        guardDependency.insert({"con_stop_stimulate_general_valve", {"_tr_con_stimulate_extend_gear_valve", "_tr_con_stimulate_general_valve", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_evn_open_general_valve", "_tr_env_close_analogical_switch", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_evn_close_general_valve", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve"}});
-        guardDependency.insert({"env_extend_gear_last", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"evn_open_general_valve", {"_tr_env_retract_gear_last", "_tr_env_close_door_skip", "_tr_evn_open_general_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_evn_close_general_valve", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"land_plane", {"_tr_land_plane", "_tr_begin_flying", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_close_door"}});
-        guardDependency.insert({"con_stimulate_retract_gear_valve", {"_tr_close_valve_retract_gear", "_tr_con_stimulate_extend_gear_valve", "_tr_open_valve_retract_gear", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_retract_gear_valve"}});
-        guardDependency.insert({"con_stimulate_general_valve", {"_tr_con_stimulate_extend_gear_valve", "_tr_con_stimulate_general_valve", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_evn_open_general_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_evn_close_general_valve", "_tr_con_stop_stimulate_retract_gear_valve"}});
-        guardDependency.insert({"env_start_retracting_first", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"env_retract_gear_skip", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"open_valve_extend_gear", {"_tr_close_valve_extend_gear", "_tr_open_valve_extend_gear", "_tr_env_start_extending"}});
-        guardDependency.insert({"begin_flying", {"_tr_land_plane", "_tr_begin_flying", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_close_door"}});
-        guardDependency.insert({"open_valve_retract_gear", {"_tr_close_valve_retract_gear", "_tr_open_valve_retract_gear", "_tr_env_start_retracting_first"}});
-        guardDependency.insert({"env_close_analogical_switch", {"_tr_env_open_analogical_switch", "_tr_evn_open_general_valve", "_tr_env_close_analogical_switch", "_tr_evn_close_general_valve"}});
-        guardDependency.insert({"env_start_extending", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"open_valve_door_close", {"_tr_open_valve_door_close", "_tr_env_close_door_skip", "_tr_env_start_close_door", "_tr_env_close_door", "_tr_close_valve_door_close"}});
-        guardDependency.insert({"con_stop_stimulate_open_door_valve", {"_tr_open_valve_door_open", "_tr_con_stimulate_extend_gear_valve", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stimulate_open_door_valve", "_tr_close_valve_door_open"}});
-        guardDependency.insert({"con_stop_stimulate_extend_gear_valve", {"_tr_con_stimulate_extend_gear_valve", "_tr_close_valve_extend_gear", "_tr_con_stop_stimulate_open_door_valve", "_tr_open_valve_extend_gear", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_extend_gear_valve"}});
-        guardDependency.insert({"evn_close_general_valve", {"_tr_env_retract_gear_last", "_tr_env_close_door_skip", "_tr_evn_open_general_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_evn_close_general_valve", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"close_valve_extend_gear", {"_tr_close_valve_extend_gear", "_tr_open_valve_extend_gear", "_tr_env_start_extending"}});
-        guardDependency.insert({"con_stimulate_extend_gear_valve", {"_tr_con_stimulate_extend_gear_valve", "_tr_close_valve_extend_gear", "_tr_con_stop_stimulate_open_door_valve", "_tr_open_valve_extend_gear", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_extend_gear_valve"}});
-        guardDependency.insert({"close_valve_door_open", {"_tr_open_valve_door_open", "_tr_env_open_door_last", "_tr_env_start_open_door", "_tr_env_open_door_skip", "_tr_close_valve_door_open"}});
-        guardDependency.insert({"con_stimulate_close_door_valve", {"_tr_open_valve_door_close", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_close_valve_door_close"}});
-        guardDependency.insert({"env_extend_gear_skip", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"env_open_door_skip", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"env_start_open_door", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        dependentInvariant.insert({machine, std::unordered_set<string>()});
-    }
-    LandingGear_R6 counterExampleState;
-
-    while(!collection.empty() && !stopThreads) {
-        LandingGear_R6 state = next(collection, mutex, type);
-
-        std::unordered_set<LandingGear_R6, LandingGear_R6::Hash, LandingGear_R6::HashEqual> nextStates = generateNextStates(guardMutex, state, isCaching, invariantDependency, dependentInvariant, guardDependency, dependentGuard, guardCache, parents, stateAccessedVia, transitions);
-        for(auto nextState : nextStates) {
-            if(states.find(nextState) == states.end()) {
-                numberStates += 1;
-                states.insert(nextState);
-                collection.push_back(nextState);
-                if(numberStates % 50000 == 0) {
-                    cout << "VISITED STATES: " << numberStates << "\n";
-                    cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
-                    cout << "-------------------" << "\n";
-                }
-            }
-        }
-
-        if(!checkInvariants(guardMutex, state, isCaching, dependentInvariant)) {
-            invariantViolated = true;
-            stopThreads = true;
-            counterExampleState = state;
-        }
-
-        if(nextStates.empty()) {
-            deadlockDetected = true;
-            stopThreads = true;
-            counterExampleState = state;
-        }
-
-    }
-    printResult(numberStates, transitions, deadlockDetected, invariantViolated, counterExampleState, parents, stateAccessedVia);
-}
-
-static void modelCheckMultiThreaded(LandingGear_R6::Type type, int threads, bool isCaching) {
-    std::mutex mutex;
-    std::mutex waitMutex;
-    std::mutex guardMutex;
-    std::condition_variable waitCV;
-
-    LandingGear_R6 machine = LandingGear_R6();
-
-
-    std::atomic<bool> invariantViolated;
-    invariantViolated = false;
-    std::atomic<bool> deadlockDetected;
-    deadlockDetected = false;
-    std::atomic<bool> stopThreads;
-    stopThreads = false;
-
-    std::unordered_set<LandingGear_R6, LandingGear_R6::Hash, LandingGear_R6::HashEqual> states = std::unordered_set<LandingGear_R6, LandingGear_R6::Hash, LandingGear_R6::HashEqual>();
-    states.insert(machine);
-    std::atomic<int> numberStates;
-    numberStates = 1;
-
-    std::list<LandingGear_R6> collection = std::list<LandingGear_R6>();
-    collection.push_back(machine);
-
-    std::atomic<int> transitions;
-    transitions = 0;
-
-    std::atomic<int> possibleQueueChanges;
-    possibleQueueChanges = 0;
-
-    std::atomic<bool> waitFlag;
-    waitFlag = true;
-
-    std::unordered_map<string, std::unordered_set<string>> invariantDependency;
-    std::unordered_map<string, std::unordered_set<string>> guardDependency;
-    std::unordered_map<LandingGear_R6, std::unordered_set<string>, LandingGear_R6::Hash, LandingGear_R6::HashEqual> dependentInvariant;
-    std::unordered_map<LandingGear_R6, std::unordered_set<string>, LandingGear_R6::Hash, LandingGear_R6::HashEqual> dependentGuard;
-    std::unordered_map<LandingGear_R6, immer::map<string, boost::any>, LandingGear_R6::Hash, LandingGear_R6::HashEqual> guardCache;
-    std::unordered_map<LandingGear_R6, LandingGear_R6, LandingGear_R6::Hash, LandingGear_R6::HashEqual> parents;
-    std::unordered_map<LandingGear_R6, string, LandingGear_R6::Hash, LandingGear_R6::HashEqual> stateAccessedVia;
-    if(isCaching) {
-        invariantDependency.insert({"close_valve_door_close", {"_check_inv_10"}});
-        invariantDependency.insert({"close_valve_retract_gear", {"_check_inv_13"}});
-        invariantDependency.insert({"con_stimulate_open_door_valve", {"_check_inv_18", "_check_inv_17", "_check_inv_7"}});
-        invariantDependency.insert({"env_close_door", {"_check_inv_15", "_check_inv_21", "_check_inv_20", "_check_inv_25", "_check_inv_22"}});
-        invariantDependency.insert({"env_start_close_door", {"_check_inv_15", "_check_inv_21", "_check_inv_20", "_check_inv_25", "_check_inv_22"}});
-        invariantDependency.insert({"toggle_handle_up", {"_check_inv_4", "_check_inv_14"}});
-        invariantDependency.insert({"toggle_handle_down", {"_check_inv_4", "_check_inv_14"}});
-        invariantDependency.insert({"open_valve_door_open", {"_check_inv_12"}});
-        invariantDependency.insert({"env_retract_gear_last", {"_check_inv_16", "_check_inv_19", "_check_inv_25", "_check_inv_24", "_check_inv_23"}});
-        invariantDependency.insert({"env_open_door_last", {"_check_inv_15", "_check_inv_21", "_check_inv_20", "_check_inv_25", "_check_inv_22"}});
-        invariantDependency.insert({"con_stop_stimulate_retract_gear_valve", {"_check_inv_17", "_check_inv_8"}});
-        invariantDependency.insert({"env_close_door_skip", {"_check_inv_21", "_check_inv_20", "_check_inv_22"}});
-        invariantDependency.insert({"con_stop_stimulate_close_door_valve", {"_check_inv_18", "_check_inv_17", "_check_inv_5"}});
-        invariantDependency.insert({"env_open_analogical_switch", {"_check_inv_1"}});
-        invariantDependency.insert({"con_stop_stimulate_general_valve", {"_check_inv_17", "_check_inv_2", "_check_inv_4"}});
-        invariantDependency.insert({"env_extend_gear_last", {"_check_inv_16", "_check_inv_19", "_check_inv_25", "_check_inv_24", "_check_inv_23"}});
-        invariantDependency.insert({"evn_open_general_valve", {"_check_inv_3"}});
-        invariantDependency.insert({"land_plane", {"_check_inv_9"}});
-        invariantDependency.insert({"con_stimulate_retract_gear_valve", {"_check_inv_17", "_check_inv_8"}});
-        invariantDependency.insert({"con_stimulate_general_valve", {"_check_inv_17", "_check_inv_2"}});
-        invariantDependency.insert({"env_start_retracting_first", {"_check_inv_16", "_check_inv_19", "_check_inv_25", "_check_inv_24", "_check_inv_23"}});
-        invariantDependency.insert({"env_retract_gear_skip", {"_check_inv_19", "_check_inv_24", "_check_inv_23"}});
-        invariantDependency.insert({"open_valve_extend_gear", {"_check_inv_11"}});
-        invariantDependency.insert({"begin_flying", {"_check_inv_9"}});
-        invariantDependency.insert({"open_valve_retract_gear", {"_check_inv_13"}});
-        invariantDependency.insert({"env_close_analogical_switch", {"_check_inv_1"}});
-        invariantDependency.insert({"env_start_extending", {"_check_inv_16", "_check_inv_19", "_check_inv_25", "_check_inv_24", "_check_inv_23"}});
-        invariantDependency.insert({"open_valve_door_close", {"_check_inv_10"}});
-        invariantDependency.insert({"con_stop_stimulate_open_door_valve", {"_check_inv_18", "_check_inv_17", "_check_inv_7"}});
-        invariantDependency.insert({"con_stop_stimulate_extend_gear_valve", {"_check_inv_17", "_check_inv_6"}});
-        invariantDependency.insert({"evn_close_general_valve", {"_check_inv_3"}});
-        invariantDependency.insert({"close_valve_extend_gear", {"_check_inv_11"}});
-        invariantDependency.insert({"con_stimulate_extend_gear_valve", {"_check_inv_17", "_check_inv_6"}});
-        invariantDependency.insert({"close_valve_door_open", {"_check_inv_12"}});
-        invariantDependency.insert({"con_stimulate_close_door_valve", {"_check_inv_18", "_check_inv_17", "_check_inv_5"}});
-        invariantDependency.insert({"env_extend_gear_skip", {"_check_inv_19", "_check_inv_24", "_check_inv_23"}});
-        invariantDependency.insert({"env_open_door_skip", {"_check_inv_21", "_check_inv_20", "_check_inv_22"}});
-        invariantDependency.insert({"env_start_open_door", {"_check_inv_15", "_check_inv_21", "_check_inv_20", "_check_inv_25", "_check_inv_22"}});
-        guardDependency.insert({"close_valve_door_close", {"_tr_open_valve_door_close", "_tr_env_close_door_skip", "_tr_env_start_close_door", "_tr_env_close_door", "_tr_close_valve_door_close"}});
-        guardDependency.insert({"close_valve_retract_gear", {"_tr_close_valve_retract_gear", "_tr_open_valve_retract_gear", "_tr_env_start_retracting_first"}});
-        guardDependency.insert({"con_stimulate_open_door_valve", {"_tr_open_valve_door_open", "_tr_con_stimulate_extend_gear_valve", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stimulate_open_door_valve", "_tr_close_valve_door_open"}});
-        guardDependency.insert({"env_close_door", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"env_start_close_door", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"toggle_handle_up", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_close_analogical_switch", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip", "_tr_con_stimulate_general_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_toggle_handle_down", "_tr_env_open_door_last", "_tr_toggle_handle_up", "_tr_env_start_close_door", "_tr_con_stop_stimulate_close_door_valve"}});
-        guardDependency.insert({"toggle_handle_down", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_close_analogical_switch", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip", "_tr_con_stimulate_general_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_toggle_handle_down", "_tr_env_open_door_last", "_tr_toggle_handle_up", "_tr_env_start_close_door", "_tr_con_stop_stimulate_close_door_valve"}});
-        guardDependency.insert({"open_valve_door_open", {"_tr_open_valve_door_open", "_tr_env_open_door_last", "_tr_env_start_open_door", "_tr_env_open_door_skip", "_tr_close_valve_door_open"}});
-        guardDependency.insert({"env_retract_gear_last", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"env_open_door_last", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"con_stop_stimulate_retract_gear_valve", {"_tr_close_valve_retract_gear", "_tr_con_stimulate_extend_gear_valve", "_tr_open_valve_retract_gear", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_retract_gear_valve"}});
-        guardDependency.insert({"env_close_door_skip", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"con_stop_stimulate_close_door_valve", {"_tr_open_valve_door_close", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_close_valve_door_close"}});
-        guardDependency.insert({"env_open_analogical_switch", {"_tr_env_open_analogical_switch", "_tr_evn_open_general_valve", "_tr_env_close_analogical_switch", "_tr_evn_close_general_valve"}});
-        guardDependency.insert({"con_stop_stimulate_general_valve", {"_tr_con_stimulate_extend_gear_valve", "_tr_con_stimulate_general_valve", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_evn_open_general_valve", "_tr_env_close_analogical_switch", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_evn_close_general_valve", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve"}});
-        guardDependency.insert({"env_extend_gear_last", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"evn_open_general_valve", {"_tr_env_retract_gear_last", "_tr_env_close_door_skip", "_tr_evn_open_general_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_evn_close_general_valve", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"land_plane", {"_tr_land_plane", "_tr_begin_flying", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_close_door"}});
-        guardDependency.insert({"con_stimulate_retract_gear_valve", {"_tr_close_valve_retract_gear", "_tr_con_stimulate_extend_gear_valve", "_tr_open_valve_retract_gear", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_retract_gear_valve"}});
-        guardDependency.insert({"con_stimulate_general_valve", {"_tr_con_stimulate_extend_gear_valve", "_tr_con_stimulate_general_valve", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_evn_open_general_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_evn_close_general_valve", "_tr_con_stop_stimulate_retract_gear_valve"}});
-        guardDependency.insert({"env_start_retracting_first", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"env_retract_gear_skip", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"open_valve_extend_gear", {"_tr_close_valve_extend_gear", "_tr_open_valve_extend_gear", "_tr_env_start_extending"}});
-        guardDependency.insert({"begin_flying", {"_tr_land_plane", "_tr_begin_flying", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_close_door"}});
-        guardDependency.insert({"open_valve_retract_gear", {"_tr_close_valve_retract_gear", "_tr_open_valve_retract_gear", "_tr_env_start_retracting_first"}});
-        guardDependency.insert({"env_close_analogical_switch", {"_tr_env_open_analogical_switch", "_tr_evn_open_general_valve", "_tr_env_close_analogical_switch", "_tr_evn_close_general_valve"}});
-        guardDependency.insert({"env_start_extending", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"open_valve_door_close", {"_tr_open_valve_door_close", "_tr_env_close_door_skip", "_tr_env_start_close_door", "_tr_env_close_door", "_tr_close_valve_door_close"}});
-        guardDependency.insert({"con_stop_stimulate_open_door_valve", {"_tr_open_valve_door_open", "_tr_con_stimulate_extend_gear_valve", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stimulate_open_door_valve", "_tr_close_valve_door_open"}});
-        guardDependency.insert({"con_stop_stimulate_extend_gear_valve", {"_tr_con_stimulate_extend_gear_valve", "_tr_close_valve_extend_gear", "_tr_con_stop_stimulate_open_door_valve", "_tr_open_valve_extend_gear", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_extend_gear_valve"}});
-        guardDependency.insert({"evn_close_general_valve", {"_tr_env_retract_gear_last", "_tr_env_close_door_skip", "_tr_evn_open_general_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_evn_close_general_valve", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"close_valve_extend_gear", {"_tr_close_valve_extend_gear", "_tr_open_valve_extend_gear", "_tr_env_start_extending"}});
-        guardDependency.insert({"con_stimulate_extend_gear_valve", {"_tr_con_stimulate_extend_gear_valve", "_tr_close_valve_extend_gear", "_tr_con_stop_stimulate_open_door_valve", "_tr_open_valve_extend_gear", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_extend_gear_valve"}});
-        guardDependency.insert({"close_valve_door_open", {"_tr_open_valve_door_open", "_tr_env_open_door_last", "_tr_env_start_open_door", "_tr_env_open_door_skip", "_tr_close_valve_door_open"}});
-        guardDependency.insert({"con_stimulate_close_door_valve", {"_tr_open_valve_door_close", "_tr_con_stimulate_close_door_valve", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_close_valve_door_close"}});
-        guardDependency.insert({"env_extend_gear_skip", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_con_stop_stimulate_extend_gear_valve", "_tr_env_start_retracting_first", "_tr_con_stop_stimulate_retract_gear_valve", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"env_open_door_skip", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        guardDependency.insert({"env_start_open_door", {"_tr_env_retract_gear_last", "_tr_con_stimulate_extend_gear_valve", "_tr_env_close_door_skip", "_tr_con_stop_stimulate_open_door_valve", "_tr_con_stimulate_retract_gear_valve", "_tr_con_stimulate_close_door_valve", "_tr_env_retract_gear_skip", "_tr_env_start_open_door", "_tr_env_close_door", "_tr_env_start_retracting_first", "_tr_env_extend_gear_skip", "_tr_env_open_door_last", "_tr_env_start_close_door", "_tr_con_stop_stimulate_general_valve", "_tr_con_stop_stimulate_close_door_valve", "_tr_con_stimulate_open_door_valve", "_tr_env_start_extending", "_tr_env_extend_gear_last", "_tr_env_open_door_skip"}});
-        dependentInvariant.insert({machine, std::unordered_set<string>()});
-    }
-    LandingGear_R6 counterExampleState;
-
-    boost::asio::thread_pool workers(threads);
-
-    while(!collection.empty() && !stopThreads) {
-        possibleQueueChanges += 1;
-        LandingGear_R6 state = next(collection, mutex, type);
-        std::packaged_task<void()> task([&, state] {
-            std::unordered_set<LandingGear_R6, LandingGear_R6::Hash, LandingGear_R6::HashEqual> nextStates = generateNextStates(guardMutex, state, isCaching, invariantDependency, dependentInvariant, guardDependency, dependentGuard, guardCache, parents, stateAccessedVia, transitions);
-
-
-            for(auto nextState : nextStates) {
-                {
-                    std::unique_lock<std::mutex> lock(mutex);
-                    if(states.find(nextState) == states.end()) {
-                        numberStates += 1;
-                        states.insert(nextState);
-                        collection.push_back(nextState);
-                        if(numberStates % 50000 == 0) {
-                            cout << "VISITED STATES: " << numberStates << "\n";
-                            cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
-                            cout << "-------------------" << "\n";
-                        }
-                    }
-                }
-            }
-
-            {
-                std::unique_lock<std::mutex> lock(mutex);
-                possibleQueueChanges -= 1;
-                int running = possibleQueueChanges;
-                if (!collection.empty() || running == 0) {
-                    {
-                        std::unique_lock<std::mutex> lock(waitMutex);
-                        waitFlag = false;
-                        waitCV.notify_one();
-                    }
-                }
-            }
-
-            if(nextStates.empty()) {
-                deadlockDetected = true;
-                stopThreads = true;
-                counterExampleState = state;
-            }
-
-            if(!checkInvariants(guardMutex, state, isCaching, dependentInvariant)) {
-                invariantViolated = true;
-                stopThreads = true;
-                counterExampleState = state;
-            }
-
-
-        });
-        waitFlag = true;
-        boost::asio::post(workers, std::move(task));
-
-        {
-            std::unique_lock<std::mutex> lock(waitMutex);
-            if (collection.empty() && possibleQueueChanges > 0) {
-                waitCV.wait(lock, [&] {
-                    return waitFlag == false;
-                });
-            }
-        }
-    }
-    workers.join();
-    printResult(numberStates, transitions, deadlockDetected, invariantViolated, counterExampleState, parents, stateAccessedVia);
-}
+};
 
 int main(int argc, char *argv[]) {
     if(argc != 4) {
@@ -3690,11 +2274,12 @@ int main(int argc, char *argv[]) {
         return - 1;
     }
 
-    if(threads == 1) {
-        modelCheckSingleThreaded(type, isCaching);
-    } else {
-        modelCheckMultiThreaded(type, threads, isCaching);
-    }
+    bool isDebug = true;
+    // TODO
+
+    ModelChecker modelchecker(type, threads, isCaching, isDebug);
+    modelchecker.modelCheck();
+
     return 0;
 }
 
diff --git a/benchmarks/model_checking/C++/Lift_MC_Large.cpp b/benchmarks/model_checking/C++/Lift_MC_Large.cpp
index c10e8795f0f4ed5ed707d1c31291f0f87d0bb3a1..f376dcfeac819a05f0679e7e288dc3e8d597a666 100644
--- a/benchmarks/model_checking/C++/Lift_MC_Large.cpp
+++ b/benchmarks/model_checking/C++/Lift_MC_Large.cpp
@@ -11,6 +11,7 @@
 #include <boost/asio/post.hpp>
 #include <boost/asio/thread_pool.hpp>
 #include <boost/any.hpp>
+#include <boost/optional.hpp>
 #include <btypes_primitives/BUtils.hpp>
 #include <btypes_primitives/StateNotReachableError.hpp>
 #include <btypes_primitives/PreconditionOrAssertionViolation.hpp>
@@ -55,9 +56,13 @@ class Lift_MC_Large {
 
         BInteger level;
 
+        mutable boost::optional<bool> _tr_cache_inc;
+        mutable boost::optional<bool> _tr_cache_dec;
 
     public:
 
+        std::string stateAccessedVia;
+
         Lift_MC_Large() {
             level = (BInteger(0));
         }
@@ -81,12 +86,22 @@ class Lift_MC_Large {
         }
 
 
-        bool _tr_inc() const {
-            return (level.less((BInteger(1000000)))).booleanValue();
+        bool _tr_inc(bool isCaching) const {
+            if (this->_tr_cache_inc == boost::none){
+                bool __tmp_result = (level.less((BInteger(1000000)))).booleanValue();
+                if (isCaching) this->_tr_cache_inc = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_inc.get();
         }
 
-        bool _tr_dec() const {
-            return (level.greater((BInteger(0)))).booleanValue();
+        bool _tr_dec(bool isCaching) const {
+            if (this->_tr_cache_dec == boost::none){
+                bool __tmp_result = (level.greater((BInteger(0)))).booleanValue();
+                if (isCaching) this->_tr_cache_dec = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_dec.get();
         }
 
         bool _check_inv_1() const {
@@ -97,8 +112,25 @@ class Lift_MC_Large {
             return (level.lessEqual((BInteger(1000000)))).booleanValue();
         }
 
-        Lift_MC_Large _copy() const {
-            return Lift_MC_Large(level);
+        static constexpr unsigned int strHash(const char *s, int off = 0) {
+            return !s[off] ? 5381 : (strHash(s, off+1)*33) ^ s[off];
+        }
+
+        Lift_MC_Large _copy(unordered_set<string> toInvalidate) const {
+            static const char* allTransitions[] = {"_tr_inc", "_tr_dec"};
+
+            Lift_MC_Large result = Lift_MC_Large(level);
+
+            for (const auto &item : allTransitions) {
+                if(toInvalidate.find(item) == toInvalidate.end()) {
+                    switch(strHash(item)) {
+                        case strHash("_tr_inc"): result._tr_cache_inc = this->_tr_cache_inc; break;
+                        case strHash("_tr_dec"): result._tr_cache_dec = this->_tr_cache_dec; break;
+                        default: cout << "Transition " << item << " not found!";
+                    }
+                }
+            }
+            return result;
         }
 
         friend bool operator ==(const Lift_MC_Large& o1, const Lift_MC_Large& o2) {
@@ -134,401 +166,285 @@ class Lift_MC_Large {
 };
 
 
-static std::unordered_set<Lift_MC_Large, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> generateNextStates(std::mutex& guardMutex, const Lift_MC_Large& state, bool isCaching, std::unordered_map<string, std::unordered_set<string>>& invariantDependency, std::unordered_map<Lift_MC_Large, std::unordered_set<string>, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual>& dependentInvariant, std::unordered_map<string, std::unordered_set<string>>& guardDependency, std::unordered_map<Lift_MC_Large, std::unordered_set<string>, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual>& dependentGuard, std::unordered_map<Lift_MC_Large, immer::map<string, boost::any>, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual>& guardCache, std::unordered_map<Lift_MC_Large, Lift_MC_Large, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual>& parents, std::unordered_map<Lift_MC_Large, string, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual>& stateAccessedVia, std::atomic<int>& transitions) {
-    std::unordered_set<Lift_MC_Large, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> result = std::unordered_set<Lift_MC_Large, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual>();
-    if(isCaching) {
-        immer::map<string, boost::any> parentsGuard;
-        std::unordered_set<string> dependentGuardsOfState;
-        bool parentsExist = false;
-        bool dependentGuardsExist = false;
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            parentsExist = (parents.find(state) != parents.end());
-            dependentGuardsExist = (dependentGuard.find(state) != dependentGuard.end());
-            if(parentsExist) {
-                parentsGuard = guardCache[parents[state]];
-            }
-            if(dependentGuardsExist) {
-                dependentGuardsOfState = dependentGuard[state];
-            }
-        }
-        immer::map<string, boost::any> newCache = parentsGuard;
-        boost::any cachedValue;
-        bool dependentGuardsBoolean = true;
-        bool _trid_1;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_inc"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_inc") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_1 = state._tr_inc();
-        } else {
-            _trid_1 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_inc", _trid_1);
-        if(_trid_1) {
-            Lift_MC_Large copiedState = state._copy();
-            copiedState.inc();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["inc"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["inc"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "inc"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_2;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_dec"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_dec") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_2 = state._tr_dec();
-        } else {
-            _trid_2 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_dec", _trid_2);
-        if(_trid_2) {
-            Lift_MC_Large copiedState = state._copy();
-            copiedState.dec();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["dec"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["dec"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "dec"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
+class ModelChecker {
+    private:
+        Lift_MC_Large::Type type;
+        int threads;
+        bool isCaching;
+        bool isDebug;
+
+        std::list<Lift_MC_Large> unvisitedStates;
+        std::unordered_set<Lift_MC_Large, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> states;
+        std::atomic<int> transitions;
+        std::mutex mutex;
+        std::mutex waitMutex;
+        std::mutex guardMutex;
+        std::condition_variable waitCV;
+
+        std::atomic<bool> invariantViolatedBool;
+        std::atomic<bool> deadlockDetected;
+        Lift_MC_Large counterExampleState;
+
+        std::unordered_map<string, std::unordered_set<string>> invariantDependency;
+        std::unordered_map<string, std::unordered_set<string>> guardDependency;
+        std::unordered_map<Lift_MC_Large, Lift_MC_Large, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> parents;
+
+    public:
+        ModelChecker() {}
 
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            guardCache.insert({state, newCache});
+        ModelChecker(Lift_MC_Large::Type type, int threads, bool isCaching, bool isDebug) {
+            this->type = type;
+            this->threads = threads;
+            this->isCaching = isCaching;
+            this->isDebug = isDebug;
+            this->invariantViolatedBool = false;
+            this->deadlockDetected = false;
+            this->transitions = 0;
         }
-    } else {
-        if(state._tr_inc()) {
-            Lift_MC_Large copiedState = state._copy();
-            copiedState.inc();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "inc"});
-                }
+
+        void modelCheck() {
+            if (isDebug) {
+                cout << "Starting Modelchecking, STRATEGY=" << type << ", THREADS=" << threads << ", CACHING=" << isCaching << "\n";
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_dec()) {
-            Lift_MC_Large copiedState = state._copy();
-            copiedState.dec();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "dec"});
-                }
+
+            if (threads <= 1) {
+                modelCheckSingleThreaded();
+            } else {
+                boost::asio::thread_pool workers(threads); // threads indicates the number of workers (without the coordinator)
+                modelCheckMultiThreaded(workers);
             }
-            result.insert(copiedState);
-            transitions += 1;
         }
 
-    }
-    return result;
-}
+        void modelCheckSingleThreaded() {
+            Lift_MC_Large machine = Lift_MC_Large();
+            states.insert(machine);
+            unvisitedStates.push_back(machine);
 
-static void printResult(int states, int transitions, bool deadlockDetected, bool invariantViolated, Lift_MC_Large& counterExampleState, std::unordered_map<Lift_MC_Large, Lift_MC_Large, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual>& parents, std::unordered_map<Lift_MC_Large, string, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual>& stateAccessedVia) {
-    if(deadlockDetected || invariantViolated) {
-        if(deadlockDetected) {
-            cout << "DEADLOCK DETECTED" << "\n";
-        }
-        if(invariantViolated) {
-            cout << "INVARIANT VIOLATED" << "\n";
-        }
-        cout << "COUNTER EXAMPLE TRACE: " << "\n";
-
-        Lift_MC_Large currentState = counterExampleState;
-        std::string trace = "";
-        while(parents.find(currentState) != parents.end()) {
-            std::stringstream stringStream;
-            stringStream << currentState;
-            trace.insert(0, stringStream.str());
-            trace.insert(0, "\n");
-            trace.insert(0, stateAccessedVia[currentState]);
-            trace.insert(0, "\n\n");
-            currentState = parents[currentState];
-        }
-        cout << trace;
-    }
+            if (isCaching) {
+                initCache(machine);
+            }
 
-    if(!deadlockDetected && !invariantViolated) {
-        cout << "MODEL CHECKING SUCCESSFUL" << "\n";
-    }
-    cout << "Number of States: " << states << "\n";
-    cout << "Number of Transitions: " << transitions << "\n";
-}
+            while(!unvisitedStates.empty()) {
+                Lift_MC_Large state = next();
 
-static bool checkInvariants(std::mutex& guardMutex, const Lift_MC_Large& state, bool isCaching, std::unordered_map<Lift_MC_Large, std::unordered_set<string>, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual>& dependentInvariant) {
-    if(isCaching) {
-        std::unordered_set<string> dependentInvariantsOfState;
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            dependentInvariantsOfState = dependentInvariant[state];
-        }
-        if(dependentInvariantsOfState.find("_check_inv_1") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_1()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_2") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_2()) {
-                return false;
-            }
-        }
-        return true;
-    }
-    return !(!state._check_inv_1() || !state._check_inv_2());
-}
+                std::unordered_set<Lift_MC_Large, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> nextStates = generateNextStates(state);
+                transitions += nextStates.size();
 
-static Lift_MC_Large next(std::list<Lift_MC_Large>& collection, std::mutex& mutex, Lift_MC_Large::Type type) {
-    std::unique_lock<std::mutex> lock(mutex);
-    switch(type) {
-        case Lift_MC_Large::BFS: {
-            Lift_MC_Large state = collection.front();
-            collection.pop_front();
-            return state;
-        }
-        case Lift_MC_Large::DFS: {
-            Lift_MC_Large state = collection.back();
-            collection.pop_back();
-            return state;
-        }
-        case Lift_MC_Large::MIXED: {
-            if(collection.size() % 2 == 0) {
-                Lift_MC_Large state = collection.front();
-                collection.pop_front();
-                return state;
-            } else {
-                Lift_MC_Large state = collection.back();
-                collection.pop_back();
-                return state;
-            }
-        }
-    };
-}
+                for(auto& nextState : nextStates) {
+                    if(states.find(nextState) == states.end()) {
+                        states.insert(nextState);
+                        parents.insert({nextState, state});
+                        unvisitedStates.push_back(nextState);
+                        if(states.size() % 50000 == 0) {
+                            cout << "VISITED STATES: " << states.size() << "\n";
+                            cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
+                            cout << "-------------------" << "\n";
+                        }
+                    }
+                }
 
-static void modelCheckSingleThreaded(Lift_MC_Large::Type type, bool isCaching) {
-    std::mutex mutex;
-    std::mutex guardMutex;
-
-    Lift_MC_Large machine = Lift_MC_Large();
-
-    std::atomic<bool> invariantViolated;
-    invariantViolated = false;
-    std::atomic<bool> deadlockDetected;
-    deadlockDetected = false;
-    std::atomic<bool> stopThreads;
-    stopThreads = false;
-
-    std::unordered_set<Lift_MC_Large, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> states = std::unordered_set<Lift_MC_Large, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual>();
-    states.insert(machine);
-    std::atomic<int> numberStates;
-    numberStates = 1;
-
-    std::list<Lift_MC_Large> collection = std::list<Lift_MC_Large>();
-    collection.push_back(machine);
-
-    std::atomic<int> transitions;
-    transitions = 0;
-
-    std::unordered_map<string, std::unordered_set<string>> invariantDependency;
-    std::unordered_map<string, std::unordered_set<string>> guardDependency;
-    std::unordered_map<Lift_MC_Large, std::unordered_set<string>, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> dependentInvariant;
-    std::unordered_map<Lift_MC_Large, std::unordered_set<string>, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> dependentGuard;
-    std::unordered_map<Lift_MC_Large, immer::map<string, boost::any>, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> guardCache;
-    std::unordered_map<Lift_MC_Large, Lift_MC_Large, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> parents;
-    std::unordered_map<Lift_MC_Large, string, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> stateAccessedVia;
-    if(isCaching) {
-        invariantDependency.insert({"dec", {"_check_inv_2", "_check_inv_1"}});
-        invariantDependency.insert({"inc", {"_check_inv_2", "_check_inv_1"}});
-        guardDependency.insert({"dec", {"_tr_dec", "_tr_inc"}});
-        guardDependency.insert({"inc", {"_tr_dec", "_tr_inc"}});
-        dependentInvariant.insert({machine, std::unordered_set<string>()});
-    }
-    Lift_MC_Large counterExampleState;
-
-    while(!collection.empty() && !stopThreads) {
-        Lift_MC_Large state = next(collection, mutex, type);
-
-        std::unordered_set<Lift_MC_Large, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> nextStates = generateNextStates(guardMutex, state, isCaching, invariantDependency, dependentInvariant, guardDependency, dependentGuard, guardCache, parents, stateAccessedVia, transitions);
-        for(auto nextState : nextStates) {
-            if(states.find(nextState) == states.end()) {
-                numberStates += 1;
-                states.insert(nextState);
-                collection.push_back(nextState);
-                if(numberStates % 50000 == 0) {
-                    cout << "VISITED STATES: " << numberStates << "\n";
-                    cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
-                    cout << "-------------------" << "\n";
+                if(invariantViolated(state)) {
+                    invariantViolatedBool = true;
+                    counterExampleState = state;
+                    break;
                 }
+
+                if(nextStates.empty()) {
+                    deadlockDetected = true;
+                    counterExampleState = state;
+                    break;
+                }
+
             }
+            printResult();
         }
 
-        if(!checkInvariants(guardMutex, state, isCaching, dependentInvariant)) {
-            invariantViolated = true;
-            stopThreads = true;
-            counterExampleState = state;
-        }
+        void modelCheckMultiThreaded(boost::asio::thread_pool& workers) {
+            Lift_MC_Large machine = Lift_MC_Large();
+            states.insert(machine);
+            unvisitedStates.push_back(machine);
 
-        if(nextStates.empty()) {
-            deadlockDetected = true;
-            stopThreads = true;
-            counterExampleState = state;
-        }
+            std::atomic<bool> stopThreads;
+            stopThreads = false;
+            std::atomic<int> possibleQueueChanges;
+            possibleQueueChanges = 0;
 
-    }
-    printResult(numberStates, transitions, deadlockDetected, invariantViolated, counterExampleState, parents, stateAccessedVia);
-}
+            if(isCaching) {
+                initCache(machine);
+            }
 
-static void modelCheckMultiThreaded(Lift_MC_Large::Type type, int threads, bool isCaching) {
-    std::mutex mutex;
-    std::mutex waitMutex;
-    std::mutex guardMutex;
-    std::condition_variable waitCV;
-
-    Lift_MC_Large machine = Lift_MC_Large();
-
-
-    std::atomic<bool> invariantViolated;
-    invariantViolated = false;
-    std::atomic<bool> deadlockDetected;
-    deadlockDetected = false;
-    std::atomic<bool> stopThreads;
-    stopThreads = false;
-
-    std::unordered_set<Lift_MC_Large, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> states = std::unordered_set<Lift_MC_Large, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual>();
-    states.insert(machine);
-    std::atomic<int> numberStates;
-    numberStates = 1;
-
-    std::list<Lift_MC_Large> collection = std::list<Lift_MC_Large>();
-    collection.push_back(machine);
-
-    std::atomic<int> transitions;
-    transitions = 0;
-
-    std::atomic<int> possibleQueueChanges;
-    possibleQueueChanges = 0;
-
-    std::atomic<bool> waitFlag;
-    waitFlag = true;
-
-    std::unordered_map<string, std::unordered_set<string>> invariantDependency;
-    std::unordered_map<string, std::unordered_set<string>> guardDependency;
-    std::unordered_map<Lift_MC_Large, std::unordered_set<string>, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> dependentInvariant;
-    std::unordered_map<Lift_MC_Large, std::unordered_set<string>, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> dependentGuard;
-    std::unordered_map<Lift_MC_Large, immer::map<string, boost::any>, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> guardCache;
-    std::unordered_map<Lift_MC_Large, Lift_MC_Large, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> parents;
-    std::unordered_map<Lift_MC_Large, string, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> stateAccessedVia;
-    if(isCaching) {
-        invariantDependency.insert({"dec", {"_check_inv_2", "_check_inv_1"}});
-        invariantDependency.insert({"inc", {"_check_inv_2", "_check_inv_1"}});
-        guardDependency.insert({"dec", {"_tr_dec", "_tr_inc"}});
-        guardDependency.insert({"inc", {"_tr_dec", "_tr_inc"}});
-        dependentInvariant.insert({machine, std::unordered_set<string>()});
-    }
-    Lift_MC_Large counterExampleState;
+            std::atomic<bool> waitFlag;
+            waitFlag = true;
+
+            while(!unvisitedStates.empty() && !stopThreads) {
+                possibleQueueChanges += 1;
+                Lift_MC_Large state = next();
+                std::packaged_task<void()> task([&, state] {
+                    std::unordered_set<Lift_MC_Large, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> nextStates = generateNextStates(state);
+                    transitions += nextStates.size();
+
+                    for(auto& nextState : nextStates) {
+                        {
+                            std::unique_lock<std::mutex> lock(mutex);
+                            if(states.find(nextState) == states.end()) {
+                                states.insert(nextState);
+                                parents.insert({nextState, state});
+                                unvisitedStates.push_back(nextState); // TODO: sync ?
+                                if(isDebug && states.size() % 50000 == 0) {
+                                    cout << "VISITED STATES: " << states.size() << "\n";
+                                    cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
+                                    cout << "-------------------" << "\n";
+                                }
+                            }
+                        }
+                    }
+
+                    {
+                        std::unique_lock<std::mutex> lock(mutex);
+                        possibleQueueChanges -= 1;
+                        int running = possibleQueueChanges;
+                        if (!unvisitedStates.empty() || running == 0) {
+                            {
+                                std::unique_lock<std::mutex> lock(waitMutex);
+                                waitFlag = false;
+                                waitCV.notify_one();
+                            }
+                        }
+                    }
+
+                    if(invariantViolated(state)) {
+                        invariantViolatedBool = true;
+                        counterExampleState = state;
+                        stopThreads = true;
+                    }
 
-    boost::asio::thread_pool workers(threads);
+                    if(nextStates.empty()) {
+                        deadlockDetected = true;
+                        counterExampleState = state;
+                        stopThreads = true;
+                    }
 
-    while(!collection.empty() && !stopThreads) {
-        possibleQueueChanges += 1;
-        Lift_MC_Large state = next(collection, mutex, type);
-        std::packaged_task<void()> task([&, state] {
-            std::unordered_set<Lift_MC_Large, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> nextStates = generateNextStates(guardMutex, state, isCaching, invariantDependency, dependentInvariant, guardDependency, dependentGuard, guardCache, parents, stateAccessedVia, transitions);
+                });
 
+                waitFlag = true;
+                boost::asio::post(workers, std::move(task));
 
-            for(auto nextState : nextStates) {
                 {
-                    std::unique_lock<std::mutex> lock(mutex);
-                    if(states.find(nextState) == states.end()) {
-                        numberStates += 1;
-                        states.insert(nextState);
-                        collection.push_back(nextState);
-                        if(numberStates % 50000 == 0) {
-                            cout << "VISITED STATES: " << numberStates << "\n";
-                            cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
-                            cout << "-------------------" << "\n";
-                        }
+                    std::unique_lock<std::mutex> lock(waitMutex);
+                    while (unvisitedStates.empty() && possibleQueueChanges > 0) {
+                        waitCV.wait(lock, [&] {
+                            return waitFlag == false;
+                        });
                     }
                 }
             }
+            workers.join();
+            printResult();
+        }
 
-            {
-                std::unique_lock<std::mutex> lock(mutex);
-                possibleQueueChanges -= 1;
-                int running = possibleQueueChanges;
-                if (!collection.empty() || running == 0) {
-                    {
-                        std::unique_lock<std::mutex> lock(waitMutex);
-                        waitFlag = false;
-                        waitCV.notify_one();
+        void initCache(Lift_MC_Large& machine) {
+            invariantDependency.insert({"dec", {"_check_inv_2", "_check_inv_1"}});
+            invariantDependency.insert({"inc", {"_check_inv_2", "_check_inv_1"}});
+            invariantDependency.insert({"", {}});
+            guardDependency.insert({"dec", {"_tr_dec", "_tr_inc"}});
+            guardDependency.insert({"inc", {"_tr_dec", "_tr_inc"}});
+        }
+
+
+    private:
+        Lift_MC_Large next() {
+            std::unique_lock<std::mutex> lock(mutex);
+            switch(type) {
+                case Lift_MC_Large::BFS: {
+                    Lift_MC_Large state = unvisitedStates.front();
+                    unvisitedStates.pop_front();
+                    return state;
+                }
+                case Lift_MC_Large::DFS: {
+                    Lift_MC_Large state = unvisitedStates.back();
+                    unvisitedStates.pop_back();
+                    return state;
+                }
+                case Lift_MC_Large::MIXED: {
+                    if(unvisitedStates.size() % 2 == 0) {
+                        Lift_MC_Large state = unvisitedStates.front();
+                        unvisitedStates.pop_front();
+                        return state;
+                    } else {
+                        Lift_MC_Large state = unvisitedStates.back();
+                        unvisitedStates.pop_back();
+                        return state;
                     }
                 }
             }
+        }
 
-            if(nextStates.empty()) {
-                deadlockDetected = true;
-                stopThreads = true;
-                counterExampleState = state;
+        std::unordered_set<Lift_MC_Large, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> generateNextStates(const Lift_MC_Large& state) {
+            std::unordered_set<Lift_MC_Large, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual> result = std::unordered_set<Lift_MC_Large, Lift_MC_Large::Hash, Lift_MC_Large::HashEqual>();
+            if(state._tr_inc(isCaching)) {
+                Lift_MC_Large copiedState = state._copy(guardDependency["inc"]);
+                copiedState.inc();
+                copiedState.stateAccessedVia = "inc";
+                result.insert(copiedState);
             }
+            if(state._tr_dec(isCaching)) {
+                Lift_MC_Large copiedState = state._copy(guardDependency["dec"]);
+                copiedState.dec();
+                copiedState.stateAccessedVia = "dec";
+                result.insert(copiedState);
+            }
+
+            return result;
+        }
 
-            if(!checkInvariants(guardMutex, state, isCaching, dependentInvariant)) {
-                invariantViolated = true;
-                stopThreads = true;
-                counterExampleState = state;
+        bool invariantViolated(const Lift_MC_Large& state) {
+            if(isCaching) {
+                std::unordered_set<string> dependentInvariantsOfState = invariantDependency[state.stateAccessedVia];
+                if(dependentInvariantsOfState.find("_check_inv_1") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_1()) {
+                        return false;
+                    }
+                }
+                if(dependentInvariantsOfState.find("_check_inv_2") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_2()) {
+                        return false;
+                    }
+                }
+                return false;
             }
+            return !(state._check_inv_1() && state._check_inv_2());
+        }
 
 
-        });
-        waitFlag = true;
-        boost::asio::post(workers, std::move(task));
+        void printResult() {
+            if(deadlockDetected || invariantViolatedBool) {
+                if(deadlockDetected) {
+                    cout << "DEADLOCK DETECTED" << "\n";
+                } else {
+                    cout << "INVARIANT VIOLATED" << "\n";
+                }
 
-        {
-            std::unique_lock<std::mutex> lock(waitMutex);
-            if (collection.empty() && possibleQueueChanges > 0) {
-                waitCV.wait(lock, [&] {
-                    return waitFlag == false;
-                });
+                cout << "COUNTER EXAMPLE TRACE: " << "\n";
+
+                std::string trace = "";
+                while(parents.find(counterExampleState) != parents.end()) {
+                    std::stringstream stringStream;
+                    stringStream << counterExampleState;
+                    trace.insert(0, stringStream.str());
+                    trace.insert(0, "\n");
+                    trace.insert(0, counterExampleState.stateAccessedVia);
+                    trace.insert(0, "\n\n");
+                    counterExampleState = parents[counterExampleState];
+                }
+                cout << trace;
+            } else {
+                cout << "MODEL CHECKING SUCCESSFUL" << "\n";
             }
+
+            cout << "Number of States: " << states.size() << "\n";
+            cout << "Number of Transitions: " << transitions << "\n";
         }
-    }
-    workers.join();
-    printResult(numberStates, transitions, deadlockDetected, invariantViolated, counterExampleState, parents, stateAccessedVia);
-}
+};
 
 int main(int argc, char *argv[]) {
     if(argc != 4) {
@@ -577,11 +493,12 @@ int main(int argc, char *argv[]) {
         return - 1;
     }
 
-    if(threads == 1) {
-        modelCheckSingleThreaded(type, isCaching);
-    } else {
-        modelCheckMultiThreaded(type, threads, isCaching);
-    }
+    bool isDebug = true;
+    // TODO
+
+    ModelChecker modelchecker(type, threads, isCaching, isDebug);
+    modelchecker.modelCheck();
+
     return 0;
 }
 
diff --git a/benchmarks/model_checking/C++/QueensWithEvents_4.cpp b/benchmarks/model_checking/C++/QueensWithEvents_4.cpp
index d2348cbd8ea32a9b79bf61e536eeadcd20ae8cca..6e5afa8c9850197d7cb68539a4ffdb9ad1ed6ba0 100644
--- a/benchmarks/model_checking/C++/QueensWithEvents_4.cpp
+++ b/benchmarks/model_checking/C++/QueensWithEvents_4.cpp
@@ -11,6 +11,7 @@
 #include <boost/asio/post.hpp>
 #include <boost/asio/thread_pool.hpp>
 #include <boost/any.hpp>
+#include <boost/optional.hpp>
 #include <btypes_primitives/BUtils.hpp>
 #include <btypes_primitives/StateNotReachableError.hpp>
 #include <btypes_primitives/PreconditionOrAssertionViolation.hpp>
@@ -60,9 +61,12 @@ class QueensWithEvents_4 {
 
         BRelation<BInteger, BInteger > queens;
 
+        mutable boost::optional<BSet<BRelation<BInteger, BInteger >>> _tr_cache_Solve;
 
     public:
 
+        std::string stateAccessedVia;
+
         QueensWithEvents_4() {
             n = (BInteger(4));
             interval = (BSet<BInteger>::interval((BInteger(1)),n));
@@ -99,67 +103,87 @@ class QueensWithEvents_4 {
         }
 
 
-        BSet<BRelation<BInteger, BInteger >> _tr_Solve() const {
-            BSet<BRelation<BInteger, BInteger >> _ic_set_4 = BSet<BRelation<BInteger, BInteger >>();
-            for(BRelation<BInteger, BInteger > _ic_solution_1 : allFields) {
-                BBoolean _ic_boolean_5 = BBoolean(true);
-                if(((BBoolean(_ic_solution_1.domain().equal(interval).booleanValue() && _ic_solution_1.range().equal(interval).booleanValue()))).booleanValue()) {
-                    for(BInteger _ic_x_1 : interval) {
-                        for(BInteger _ic_y_1 : interval) {
-                            BBoolean _ic_boolean_4 = BBoolean(true);
-                            for(BInteger _ic_z_1 : interval) {
-                                if(!((BBoolean(!_ic_solution_1.elementOf((BTuple<BInteger, BInteger >(_ic_x_1, _ic_z_1))).booleanValue() || _ic_y_1.equal(_ic_z_1).booleanValue()))).booleanValue()) {
-                                    _ic_boolean_4 = BBoolean(false);
+        BSet<BRelation<BInteger, BInteger >> _tr_Solve(bool isCaching) const {
+            if (this->_tr_cache_Solve == boost::none){
+                BSet<BRelation<BInteger, BInteger >> _ic_set_4 = BSet<BRelation<BInteger, BInteger >>();
+                for(const BRelation<BInteger, BInteger >& _ic_solution_1 : allFields) {
+                    BBoolean _ic_boolean_5 = BBoolean(true);
+                    if(((BBoolean(_ic_solution_1.domain().equal(interval).booleanValue() && _ic_solution_1.range().equal(interval).booleanValue()))).booleanValue()) {
+                        for(const BInteger& _ic_x_1 : interval) {
+                            for(const BInteger& _ic_y_1 : interval) {
+                                BBoolean _ic_boolean_4 = BBoolean(true);
+                                for(const BInteger& _ic_z_1 : interval) {
+                                    if(!((BBoolean(!_ic_solution_1.elementOf((BTuple<BInteger, BInteger >(_ic_x_1, _ic_z_1))).booleanValue() || _ic_y_1.equal(_ic_z_1).booleanValue()))).booleanValue()) {
+                                        _ic_boolean_4 = BBoolean(false);
+                                        break;
+                                    }
+
+                                }
+
+                                if(!((BBoolean(!_ic_solution_1.elementOf((BTuple<BInteger, BInteger >(_ic_x_1, _ic_y_1))).booleanValue() || _ic_boolean_4.booleanValue()))).booleanValue()) {
+                                    _ic_boolean_5 = BBoolean(false);
                                     break;
                                 }
 
                             }
+                        }
+                    }
+                    BBoolean _ic_boolean_6 = BBoolean(true);
+                    if(((BBoolean((BBoolean(_ic_solution_1.domain().equal(interval).booleanValue() && _ic_solution_1.range().equal(interval).booleanValue())).booleanValue() && _ic_boolean_5.booleanValue()))).booleanValue()) {
+                        for(const BInteger& _ic_q1_1 : interval) {
+                            for(const BInteger& _ic_q2_1 : interval.difference((BSet<BInteger >((BInteger(1)))))) {
+                                if(!((BBoolean(!_ic_q2_1.greater(_ic_q1_1).booleanValue() || (BBoolean(_ic_solution_1.functionCall(_ic_q1_1).plus(_ic_q2_1).minus(_ic_q1_1).unequal(_ic_solution_1.functionCall(_ic_q2_1)).booleanValue() && _ic_solution_1.functionCall(_ic_q1_1).minus(_ic_q2_1).plus(_ic_q1_1).unequal(_ic_solution_1.functionCall(_ic_q2_1)).booleanValue())).booleanValue()))).booleanValue()) {
+                                    _ic_boolean_6 = BBoolean(false);
+                                    break;
+                                }
 
-                            if(!((BBoolean(!_ic_solution_1.elementOf((BTuple<BInteger, BInteger >(_ic_x_1, _ic_y_1))).booleanValue() || _ic_boolean_4.booleanValue()))).booleanValue()) {
-                                _ic_boolean_5 = BBoolean(false);
-                                break;
                             }
-
                         }
                     }
-                }
-                BBoolean _ic_boolean_6 = BBoolean(true);
-                if(((BBoolean((BBoolean(_ic_solution_1.domain().equal(interval).booleanValue() && _ic_solution_1.range().equal(interval).booleanValue())).booleanValue() && _ic_boolean_5.booleanValue()))).booleanValue()) {
-                    for(BInteger _ic_q1_1 : interval) {
-                        for(BInteger _ic_q2_1 : interval.difference((BSet<BInteger >((BInteger(1)))))) {
-                            if(!((BBoolean(!_ic_q2_1.greater(_ic_q1_1).booleanValue() || (BBoolean(_ic_solution_1.functionCall(_ic_q1_1).plus(_ic_q2_1).minus(_ic_q1_1).unequal(_ic_solution_1.functionCall(_ic_q2_1)).booleanValue() && _ic_solution_1.functionCall(_ic_q1_1).minus(_ic_q2_1).plus(_ic_q1_1).unequal(_ic_solution_1.functionCall(_ic_q2_1)).booleanValue())).booleanValue()))).booleanValue()) {
-                                _ic_boolean_6 = BBoolean(false);
+                    BBoolean _ic_boolean_7 = BBoolean(true);
+                    if(((BBoolean((BBoolean((BBoolean(_ic_solution_1.domain().equal(interval).booleanValue() && _ic_solution_1.range().equal(interval).booleanValue())).booleanValue() && _ic_boolean_5.booleanValue())).booleanValue() && _ic_boolean_6.booleanValue()))).booleanValue()) {
+                        for(const BInteger& _ic_x_1 : queens.domain()) {
+                            if(!(_ic_solution_1.functionCall(_ic_x_1).equal(queens.functionCall(_ic_x_1))).booleanValue()) {
+                                _ic_boolean_7 = BBoolean(false);
                                 break;
                             }
 
                         }
                     }
-                }
-                BBoolean _ic_boolean_7 = BBoolean(true);
-                if(((BBoolean((BBoolean((BBoolean(_ic_solution_1.domain().equal(interval).booleanValue() && _ic_solution_1.range().equal(interval).booleanValue())).booleanValue() && _ic_boolean_5.booleanValue())).booleanValue() && _ic_boolean_6.booleanValue()))).booleanValue()) {
-                    for(BInteger _ic_x_1 : queens.domain()) {
-                        if(!(_ic_solution_1.functionCall(_ic_x_1).equal(queens.functionCall(_ic_x_1))).booleanValue()) {
-                            _ic_boolean_7 = BBoolean(false);
-                            break;
-                        }
 
+                    if(((BBoolean((BBoolean((BBoolean((BBoolean(_ic_solution_1.domain().equal(interval).booleanValue() && _ic_solution_1.range().equal(interval).booleanValue())).booleanValue() && _ic_boolean_5.booleanValue())).booleanValue() && _ic_boolean_6.booleanValue())).booleanValue() && _ic_boolean_7.booleanValue()))).booleanValue()) {
+                        _ic_set_4 = _ic_set_4._union(BSet<BRelation<BInteger, BInteger >>(_ic_solution_1));
                     }
-                }
 
-                if(((BBoolean((BBoolean((BBoolean((BBoolean(_ic_solution_1.domain().equal(interval).booleanValue() && _ic_solution_1.range().equal(interval).booleanValue())).booleanValue() && _ic_boolean_5.booleanValue())).booleanValue() && _ic_boolean_6.booleanValue())).booleanValue() && _ic_boolean_7.booleanValue()))).booleanValue()) {
-                    _ic_set_4 = _ic_set_4._union(BSet<BRelation<BInteger, BInteger >>(_ic_solution_1));
                 }
-
+                if (isCaching) this->_tr_cache_Solve = _ic_set_4;
+                else return _ic_set_4;
             }
-            return _ic_set_4;
+            return this->_tr_cache_Solve.get();
         }
 
         bool _check_inv_1() const {
             return (((queens.checkDomain(interval))._and((queens.checkRange(interval)))._and((queens.isFunction()))._and((queens.isPartial(interval))))).booleanValue();
         }
 
-        QueensWithEvents_4 _copy() const {
-            return QueensWithEvents_4(n, interval, allFields, queens);
+        static constexpr unsigned int strHash(const char *s, int off = 0) {
+            return !s[off] ? 5381 : (strHash(s, off+1)*33) ^ s[off];
+        }
+
+        QueensWithEvents_4 _copy(unordered_set<string> toInvalidate) const {
+            static const char* allTransitions[] = {"_tr_Solve"};
+
+            QueensWithEvents_4 result = QueensWithEvents_4(n, interval, allFields, queens);
+
+            for (const auto &item : allTransitions) {
+                if(toInvalidate.find(item) == toInvalidate.end()) {
+                    switch(strHash(item)) {
+                        case strHash("_tr_Solve"): result._tr_cache_Solve = this->_tr_cache_Solve; break;
+                        default: cout << "Transition " << item << " not found!";
+                    }
+                }
+            }
+            return result;
         }
 
         friend bool operator ==(const QueensWithEvents_4& o1, const QueensWithEvents_4& o2) {
@@ -195,350 +219,275 @@ class QueensWithEvents_4 {
 };
 
 
-static std::unordered_set<QueensWithEvents_4, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> generateNextStates(std::mutex& guardMutex, const QueensWithEvents_4& state, bool isCaching, std::unordered_map<string, std::unordered_set<string>>& invariantDependency, std::unordered_map<QueensWithEvents_4, std::unordered_set<string>, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual>& dependentInvariant, std::unordered_map<string, std::unordered_set<string>>& guardDependency, std::unordered_map<QueensWithEvents_4, std::unordered_set<string>, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual>& dependentGuard, std::unordered_map<QueensWithEvents_4, immer::map<string, boost::any>, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual>& guardCache, std::unordered_map<QueensWithEvents_4, QueensWithEvents_4, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual>& parents, std::unordered_map<QueensWithEvents_4, string, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual>& stateAccessedVia, std::atomic<int>& transitions) {
-    std::unordered_set<QueensWithEvents_4, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> result = std::unordered_set<QueensWithEvents_4, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual>();
-    if(isCaching) {
-        immer::map<string, boost::any> parentsGuard;
-        std::unordered_set<string> dependentGuardsOfState;
-        bool parentsExist = false;
-        bool dependentGuardsExist = false;
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            parentsExist = (parents.find(state) != parents.end());
-            dependentGuardsExist = (dependentGuard.find(state) != dependentGuard.end());
-            if(parentsExist) {
-                parentsGuard = guardCache[parents[state]];
-            }
-            if(dependentGuardsExist) {
-                dependentGuardsOfState = dependentGuard[state];
-            }
-        }
-        immer::map<string, boost::any> newCache = parentsGuard;
-        boost::any cachedValue;
-        bool dependentGuardsBoolean = true;
-        BSet<BRelation<BInteger, BInteger >> _trid_1;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_Solve"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_Solve") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_1 = state._tr_Solve();
-        } else {
-            _trid_1 = boost::any_cast<BSet<BRelation<BInteger, BInteger >>>(cachedValue);
+class ModelChecker {
+    private:
+        QueensWithEvents_4::Type type;
+        int threads;
+        bool isCaching;
+        bool isDebug;
+
+        std::list<QueensWithEvents_4> unvisitedStates;
+        std::unordered_set<QueensWithEvents_4, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> states;
+        std::atomic<int> transitions;
+        std::mutex mutex;
+        std::mutex waitMutex;
+        std::mutex guardMutex;
+        std::condition_variable waitCV;
+
+        std::atomic<bool> invariantViolatedBool;
+        std::atomic<bool> deadlockDetected;
+        QueensWithEvents_4 counterExampleState;
+
+        std::unordered_map<string, std::unordered_set<string>> invariantDependency;
+        std::unordered_map<string, std::unordered_set<string>> guardDependency;
+        std::unordered_map<QueensWithEvents_4, QueensWithEvents_4, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> parents;
+
+    public:
+        ModelChecker() {}
+
+        ModelChecker(QueensWithEvents_4::Type type, int threads, bool isCaching, bool isDebug) {
+            this->type = type;
+            this->threads = threads;
+            this->isCaching = isCaching;
+            this->isDebug = isDebug;
+            this->invariantViolatedBool = false;
+            this->deadlockDetected = false;
+            this->transitions = 0;
         }
-        newCache = newCache.set("_tr_Solve", _trid_1);
-        for(const BRelation<BInteger, BInteger >& param : _trid_1) {
-            BRelation<BInteger, BInteger > _tmp_1 = param;
-
-            QueensWithEvents_4 copiedState = state._copy();
-            copiedState.Solve(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["Solve"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["Solve"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "Solve"});
-                }
+
+        void modelCheck() {
+            if (isDebug) {
+                cout << "Starting Modelchecking, STRATEGY=" << type << ", THREADS=" << threads << ", CACHING=" << isCaching << "\n";
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
 
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            guardCache.insert({state, newCache});
-        }
-    } else {
-        BSet<BRelation<BInteger, BInteger >> _trid_1 = state._tr_Solve();
-        for(const BRelation<BInteger, BInteger >& param : _trid_1) {
-            BRelation<BInteger, BInteger > _tmp_1 = param;
-
-            QueensWithEvents_4 copiedState = state._copy();
-            copiedState.Solve(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "Solve"});
-                }
+            if (threads <= 1) {
+                modelCheckSingleThreaded();
+            } else {
+                boost::asio::thread_pool workers(threads); // threads indicates the number of workers (without the coordinator)
+                modelCheckMultiThreaded(workers);
             }
-            result.insert(copiedState);
-            transitions += 1;
         }
 
-    }
-    return result;
-}
+        void modelCheckSingleThreaded() {
+            QueensWithEvents_4 machine = QueensWithEvents_4();
+            states.insert(machine);
+            unvisitedStates.push_back(machine);
 
-static void printResult(int states, int transitions, bool deadlockDetected, bool invariantViolated, QueensWithEvents_4& counterExampleState, std::unordered_map<QueensWithEvents_4, QueensWithEvents_4, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual>& parents, std::unordered_map<QueensWithEvents_4, string, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual>& stateAccessedVia) {
-    if(deadlockDetected || invariantViolated) {
-        if(deadlockDetected) {
-            cout << "DEADLOCK DETECTED" << "\n";
-        }
-        if(invariantViolated) {
-            cout << "INVARIANT VIOLATED" << "\n";
-        }
-        cout << "COUNTER EXAMPLE TRACE: " << "\n";
-
-        QueensWithEvents_4 currentState = counterExampleState;
-        std::string trace = "";
-        while(parents.find(currentState) != parents.end()) {
-            std::stringstream stringStream;
-            stringStream << currentState;
-            trace.insert(0, stringStream.str());
-            trace.insert(0, "\n");
-            trace.insert(0, stateAccessedVia[currentState]);
-            trace.insert(0, "\n\n");
-            currentState = parents[currentState];
-        }
-        cout << trace;
-    }
+            if (isCaching) {
+                initCache(machine);
+            }
 
-    if(!deadlockDetected && !invariantViolated) {
-        cout << "MODEL CHECKING SUCCESSFUL" << "\n";
-    }
-    cout << "Number of States: " << states << "\n";
-    cout << "Number of Transitions: " << transitions << "\n";
-}
+            while(!unvisitedStates.empty()) {
+                QueensWithEvents_4 state = next();
 
-static bool checkInvariants(std::mutex& guardMutex, const QueensWithEvents_4& state, bool isCaching, std::unordered_map<QueensWithEvents_4, std::unordered_set<string>, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual>& dependentInvariant) {
-    if(isCaching) {
-        std::unordered_set<string> dependentInvariantsOfState;
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            dependentInvariantsOfState = dependentInvariant[state];
-        }
-        if(dependentInvariantsOfState.find("_check_inv_1") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_1()) {
-                return false;
-            }
-        }
-        return true;
-    }
-    return !(!state._check_inv_1());
-}
+                std::unordered_set<QueensWithEvents_4, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> nextStates = generateNextStates(state);
+                transitions += nextStates.size();
 
-static QueensWithEvents_4 next(std::list<QueensWithEvents_4>& collection, std::mutex& mutex, QueensWithEvents_4::Type type) {
-    std::unique_lock<std::mutex> lock(mutex);
-    switch(type) {
-        case QueensWithEvents_4::BFS: {
-            QueensWithEvents_4 state = collection.front();
-            collection.pop_front();
-            return state;
-        }
-        case QueensWithEvents_4::DFS: {
-            QueensWithEvents_4 state = collection.back();
-            collection.pop_back();
-            return state;
-        }
-        case QueensWithEvents_4::MIXED: {
-            if(collection.size() % 2 == 0) {
-                QueensWithEvents_4 state = collection.front();
-                collection.pop_front();
-                return state;
-            } else {
-                QueensWithEvents_4 state = collection.back();
-                collection.pop_back();
-                return state;
-            }
-        }
-    };
-}
+                for(auto& nextState : nextStates) {
+                    if(states.find(nextState) == states.end()) {
+                        states.insert(nextState);
+                        parents.insert({nextState, state});
+                        unvisitedStates.push_back(nextState);
+                        if(states.size() % 50000 == 0) {
+                            cout << "VISITED STATES: " << states.size() << "\n";
+                            cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
+                            cout << "-------------------" << "\n";
+                        }
+                    }
+                }
 
-static void modelCheckSingleThreaded(QueensWithEvents_4::Type type, bool isCaching) {
-    std::mutex mutex;
-    std::mutex guardMutex;
-
-    QueensWithEvents_4 machine = QueensWithEvents_4();
-
-    std::atomic<bool> invariantViolated;
-    invariantViolated = false;
-    std::atomic<bool> deadlockDetected;
-    deadlockDetected = false;
-    std::atomic<bool> stopThreads;
-    stopThreads = false;
-
-    std::unordered_set<QueensWithEvents_4, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> states = std::unordered_set<QueensWithEvents_4, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual>();
-    states.insert(machine);
-    std::atomic<int> numberStates;
-    numberStates = 1;
-
-    std::list<QueensWithEvents_4> collection = std::list<QueensWithEvents_4>();
-    collection.push_back(machine);
-
-    std::atomic<int> transitions;
-    transitions = 0;
-
-    std::unordered_map<string, std::unordered_set<string>> invariantDependency;
-    std::unordered_map<string, std::unordered_set<string>> guardDependency;
-    std::unordered_map<QueensWithEvents_4, std::unordered_set<string>, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> dependentInvariant;
-    std::unordered_map<QueensWithEvents_4, std::unordered_set<string>, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> dependentGuard;
-    std::unordered_map<QueensWithEvents_4, immer::map<string, boost::any>, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> guardCache;
-    std::unordered_map<QueensWithEvents_4, QueensWithEvents_4, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> parents;
-    std::unordered_map<QueensWithEvents_4, string, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> stateAccessedVia;
-    if(isCaching) {
-        invariantDependency.insert({"Solve", {"_check_inv_1"}});
-        guardDependency.insert({"Solve", {"_tr_Solve"}});
-        dependentInvariant.insert({machine, std::unordered_set<string>()});
-    }
-    QueensWithEvents_4 counterExampleState;
-
-    while(!collection.empty() && !stopThreads) {
-        QueensWithEvents_4 state = next(collection, mutex, type);
-
-        std::unordered_set<QueensWithEvents_4, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> nextStates = generateNextStates(guardMutex, state, isCaching, invariantDependency, dependentInvariant, guardDependency, dependentGuard, guardCache, parents, stateAccessedVia, transitions);
-        for(auto nextState : nextStates) {
-            if(states.find(nextState) == states.end()) {
-                numberStates += 1;
-                states.insert(nextState);
-                collection.push_back(nextState);
-                if(numberStates % 50000 == 0) {
-                    cout << "VISITED STATES: " << numberStates << "\n";
-                    cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
-                    cout << "-------------------" << "\n";
+                if(invariantViolated(state)) {
+                    invariantViolatedBool = true;
+                    counterExampleState = state;
+                    break;
+                }
+
+                if(nextStates.empty()) {
+                    deadlockDetected = true;
+                    counterExampleState = state;
+                    break;
                 }
+
             }
+            printResult();
         }
 
-        if(!checkInvariants(guardMutex, state, isCaching, dependentInvariant)) {
-            invariantViolated = true;
-            stopThreads = true;
-            counterExampleState = state;
-        }
+        void modelCheckMultiThreaded(boost::asio::thread_pool& workers) {
+            QueensWithEvents_4 machine = QueensWithEvents_4();
+            states.insert(machine);
+            unvisitedStates.push_back(machine);
 
-        if(nextStates.empty()) {
-            deadlockDetected = true;
-            stopThreads = true;
-            counterExampleState = state;
-        }
+            std::atomic<bool> stopThreads;
+            stopThreads = false;
+            std::atomic<int> possibleQueueChanges;
+            possibleQueueChanges = 0;
 
-    }
-    printResult(numberStates, transitions, deadlockDetected, invariantViolated, counterExampleState, parents, stateAccessedVia);
-}
+            if(isCaching) {
+                initCache(machine);
+            }
 
-static void modelCheckMultiThreaded(QueensWithEvents_4::Type type, int threads, bool isCaching) {
-    std::mutex mutex;
-    std::mutex waitMutex;
-    std::mutex guardMutex;
-    std::condition_variable waitCV;
-
-    QueensWithEvents_4 machine = QueensWithEvents_4();
-
-
-    std::atomic<bool> invariantViolated;
-    invariantViolated = false;
-    std::atomic<bool> deadlockDetected;
-    deadlockDetected = false;
-    std::atomic<bool> stopThreads;
-    stopThreads = false;
-
-    std::unordered_set<QueensWithEvents_4, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> states = std::unordered_set<QueensWithEvents_4, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual>();
-    states.insert(machine);
-    std::atomic<int> numberStates;
-    numberStates = 1;
-
-    std::list<QueensWithEvents_4> collection = std::list<QueensWithEvents_4>();
-    collection.push_back(machine);
-
-    std::atomic<int> transitions;
-    transitions = 0;
-
-    std::atomic<int> possibleQueueChanges;
-    possibleQueueChanges = 0;
-
-    std::atomic<bool> waitFlag;
-    waitFlag = true;
-
-    std::unordered_map<string, std::unordered_set<string>> invariantDependency;
-    std::unordered_map<string, std::unordered_set<string>> guardDependency;
-    std::unordered_map<QueensWithEvents_4, std::unordered_set<string>, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> dependentInvariant;
-    std::unordered_map<QueensWithEvents_4, std::unordered_set<string>, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> dependentGuard;
-    std::unordered_map<QueensWithEvents_4, immer::map<string, boost::any>, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> guardCache;
-    std::unordered_map<QueensWithEvents_4, QueensWithEvents_4, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> parents;
-    std::unordered_map<QueensWithEvents_4, string, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> stateAccessedVia;
-    if(isCaching) {
-        invariantDependency.insert({"Solve", {"_check_inv_1"}});
-        guardDependency.insert({"Solve", {"_tr_Solve"}});
-        dependentInvariant.insert({machine, std::unordered_set<string>()});
-    }
-    QueensWithEvents_4 counterExampleState;
+            std::atomic<bool> waitFlag;
+            waitFlag = true;
+
+            while(!unvisitedStates.empty() && !stopThreads) {
+                possibleQueueChanges += 1;
+                QueensWithEvents_4 state = next();
+                std::packaged_task<void()> task([&, state] {
+                    std::unordered_set<QueensWithEvents_4, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> nextStates = generateNextStates(state);
+                    transitions += nextStates.size();
+
+                    for(auto& nextState : nextStates) {
+                        {
+                            std::unique_lock<std::mutex> lock(mutex);
+                            if(states.find(nextState) == states.end()) {
+                                states.insert(nextState);
+                                parents.insert({nextState, state});
+                                unvisitedStates.push_back(nextState); // TODO: sync ?
+                                if(isDebug && states.size() % 50000 == 0) {
+                                    cout << "VISITED STATES: " << states.size() << "\n";
+                                    cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
+                                    cout << "-------------------" << "\n";
+                                }
+                            }
+                        }
+                    }
+
+                    {
+                        std::unique_lock<std::mutex> lock(mutex);
+                        possibleQueueChanges -= 1;
+                        int running = possibleQueueChanges;
+                        if (!unvisitedStates.empty() || running == 0) {
+                            {
+                                std::unique_lock<std::mutex> lock(waitMutex);
+                                waitFlag = false;
+                                waitCV.notify_one();
+                            }
+                        }
+                    }
+
+                    if(invariantViolated(state)) {
+                        invariantViolatedBool = true;
+                        counterExampleState = state;
+                        stopThreads = true;
+                    }
 
-    boost::asio::thread_pool workers(threads);
+                    if(nextStates.empty()) {
+                        deadlockDetected = true;
+                        counterExampleState = state;
+                        stopThreads = true;
+                    }
 
-    while(!collection.empty() && !stopThreads) {
-        possibleQueueChanges += 1;
-        QueensWithEvents_4 state = next(collection, mutex, type);
-        std::packaged_task<void()> task([&, state] {
-            std::unordered_set<QueensWithEvents_4, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> nextStates = generateNextStates(guardMutex, state, isCaching, invariantDependency, dependentInvariant, guardDependency, dependentGuard, guardCache, parents, stateAccessedVia, transitions);
+                });
 
+                waitFlag = true;
+                boost::asio::post(workers, std::move(task));
 
-            for(auto nextState : nextStates) {
                 {
-                    std::unique_lock<std::mutex> lock(mutex);
-                    if(states.find(nextState) == states.end()) {
-                        numberStates += 1;
-                        states.insert(nextState);
-                        collection.push_back(nextState);
-                        if(numberStates % 50000 == 0) {
-                            cout << "VISITED STATES: " << numberStates << "\n";
-                            cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
-                            cout << "-------------------" << "\n";
-                        }
+                    std::unique_lock<std::mutex> lock(waitMutex);
+                    while (unvisitedStates.empty() && possibleQueueChanges > 0) {
+                        waitCV.wait(lock, [&] {
+                            return waitFlag == false;
+                        });
                     }
                 }
             }
+            workers.join();
+            printResult();
+        }
 
-            {
-                std::unique_lock<std::mutex> lock(mutex);
-                possibleQueueChanges -= 1;
-                int running = possibleQueueChanges;
-                if (!collection.empty() || running == 0) {
-                    {
-                        std::unique_lock<std::mutex> lock(waitMutex);
-                        waitFlag = false;
-                        waitCV.notify_one();
+        void initCache(QueensWithEvents_4& machine) {
+            invariantDependency.insert({"Solve", {"_check_inv_1"}});
+            invariantDependency.insert({"", {}});
+            guardDependency.insert({"Solve", {"_tr_Solve"}});
+        }
+
+
+    private:
+        QueensWithEvents_4 next() {
+            std::unique_lock<std::mutex> lock(mutex);
+            switch(type) {
+                case QueensWithEvents_4::BFS: {
+                    QueensWithEvents_4 state = unvisitedStates.front();
+                    unvisitedStates.pop_front();
+                    return state;
+                }
+                case QueensWithEvents_4::DFS: {
+                    QueensWithEvents_4 state = unvisitedStates.back();
+                    unvisitedStates.pop_back();
+                    return state;
+                }
+                case QueensWithEvents_4::MIXED: {
+                    if(unvisitedStates.size() % 2 == 0) {
+                        QueensWithEvents_4 state = unvisitedStates.front();
+                        unvisitedStates.pop_front();
+                        return state;
+                    } else {
+                        QueensWithEvents_4 state = unvisitedStates.back();
+                        unvisitedStates.pop_back();
+                        return state;
                     }
                 }
             }
+        }
+
+        std::unordered_set<QueensWithEvents_4, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> generateNextStates(const QueensWithEvents_4& state) {
+            std::unordered_set<QueensWithEvents_4, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual> result = std::unordered_set<QueensWithEvents_4, QueensWithEvents_4::Hash, QueensWithEvents_4::HashEqual>();
+            BSet<BRelation<BInteger, BInteger >> _trid_1 = state._tr_Solve(isCaching);
+            for(const BRelation<BInteger, BInteger >& param : _trid_1) {
+                BRelation<BInteger, BInteger > _tmp_1 = param;
 
-            if(nextStates.empty()) {
-                deadlockDetected = true;
-                stopThreads = true;
-                counterExampleState = state;
+                QueensWithEvents_4 copiedState = state._copy(guardDependency["Solve"]);
+                copiedState.Solve(_tmp_1);
+                copiedState.stateAccessedVia = "Solve";
+                result.insert(copiedState);
             }
 
-            if(!checkInvariants(guardMutex, state, isCaching, dependentInvariant)) {
-                invariantViolated = true;
-                stopThreads = true;
-                counterExampleState = state;
+            return result;
+        }
+
+        bool invariantViolated(const QueensWithEvents_4& state) {
+            if(isCaching) {
+                std::unordered_set<string> dependentInvariantsOfState = invariantDependency[state.stateAccessedVia];
+                if(dependentInvariantsOfState.find("_check_inv_1") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_1()) {
+                        return false;
+                    }
+                }
+                return false;
             }
+            return !(state._check_inv_1());
+        }
 
 
-        });
-        waitFlag = true;
-        boost::asio::post(workers, std::move(task));
+        void printResult() {
+            if(deadlockDetected || invariantViolatedBool) {
+                if(deadlockDetected) {
+                    cout << "DEADLOCK DETECTED" << "\n";
+                } else {
+                    cout << "INVARIANT VIOLATED" << "\n";
+                }
 
-        {
-            std::unique_lock<std::mutex> lock(waitMutex);
-            if (collection.empty() && possibleQueueChanges > 0) {
-                waitCV.wait(lock, [&] {
-                    return waitFlag == false;
-                });
+                cout << "COUNTER EXAMPLE TRACE: " << "\n";
+
+                std::string trace = "";
+                while(parents.find(counterExampleState) != parents.end()) {
+                    std::stringstream stringStream;
+                    stringStream << counterExampleState;
+                    trace.insert(0, stringStream.str());
+                    trace.insert(0, "\n");
+                    trace.insert(0, counterExampleState.stateAccessedVia);
+                    trace.insert(0, "\n\n");
+                    counterExampleState = parents[counterExampleState];
+                }
+                cout << trace;
+            } else {
+                cout << "MODEL CHECKING SUCCESSFUL" << "\n";
             }
+
+            cout << "Number of States: " << states.size() << "\n";
+            cout << "Number of Transitions: " << transitions << "\n";
         }
-    }
-    workers.join();
-    printResult(numberStates, transitions, deadlockDetected, invariantViolated, counterExampleState, parents, stateAccessedVia);
-}
+};
 
 int main(int argc, char *argv[]) {
     if(argc != 4) {
@@ -587,11 +536,12 @@ int main(int argc, char *argv[]) {
         return - 1;
     }
 
-    if(threads == 1) {
-        modelCheckSingleThreaded(type, isCaching);
-    } else {
-        modelCheckMultiThreaded(type, threads, isCaching);
-    }
+    bool isDebug = true;
+    // TODO
+
+    ModelChecker modelchecker(type, threads, isCaching, isDebug);
+    modelchecker.modelCheck();
+
     return 0;
 }
 
diff --git a/benchmarks/model_checking/C++/Train1_Lukas_POR_v3.cpp b/benchmarks/model_checking/C++/Train1_Lukas_POR_v3.cpp
index 1f20891ba789df91b876d0e18a565f52ce1bdd12..28efdeae29bf433f603d1de9cf6957a44997770e 100644
--- a/benchmarks/model_checking/C++/Train1_Lukas_POR_v3.cpp
+++ b/benchmarks/model_checking/C++/Train1_Lukas_POR_v3.cpp
@@ -11,6 +11,7 @@
 #include <boost/asio/post.hpp>
 #include <boost/asio/thread_pool.hpp>
 #include <boost/any.hpp>
+#include <boost/optional.hpp>
 #include <btypes_primitives/BUtils.hpp>
 #include <btypes_primitives/StateNotReachableError.hpp>
 #include <btypes_primitives/PreconditionOrAssertionViolation.hpp>
@@ -31,7 +32,6 @@ class Train1_Lukas_POR_v3 {
 
         enum Type { BFS, DFS, MIXED };
 
-
         class BLOCKS : public BObject {
             public:
 
@@ -164,6 +164,7 @@ class Train1_Lukas_POR_v3 {
                 }
         };
 
+
         struct Hash {
             public:
                 size_t operator()(const Train1_Lukas_POR_v3& obj) const {
@@ -200,13 +201,23 @@ class Train1_Lukas_POR_v3 {
         BSet<ROUTES > resrt;
         BRelation<BLOCKS, ROUTES > rsrtbl;
 
+        mutable boost::optional<BSet<ROUTES>> _tr_cache_route_reservation;
+        mutable boost::optional<BSet<ROUTES>> _tr_cache_route_freeing;
+        mutable boost::optional<BSet<ROUTES>> _tr_cache_FRONT_MOVE_1;
+        mutable boost::optional<BSet<BLOCKS>> _tr_cache_FRONT_MOVE_2;
+        mutable boost::optional<BSet<BLOCKS>> _tr_cache_BACK_MOVE_1;
+        mutable boost::optional<BSet<BLOCKS>> _tr_cache_BACK_MOVE_2;
+        mutable boost::optional<BSet<ROUTES>> _tr_cache_point_positionning;
+        mutable boost::optional<BSet<ROUTES>> _tr_cache_route_formation;
 
     public:
 
+        std::string stateAccessedVia;
+
         Train1_Lukas_POR_v3() {
+            nxt = (BRelation<ROUTES, BRelation<BLOCKS, BLOCKS > >((BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R1)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::A)), (BLOCKS(BLOCKS::B)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::B)), (BLOCKS(BLOCKS::C)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R2)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::A)), (BLOCKS(BLOCKS::B)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::B)), (BLOCKS(BLOCKS::D)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::D)), (BLOCKS(BLOCKS::E)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::E)), (BLOCKS(BLOCKS::F)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R3)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::H)), (BLOCKS(BLOCKS::G)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::G)), (BLOCKS(BLOCKS::E)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::E)), (BLOCKS(BLOCKS::F)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R4)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::I)), (BLOCKS(BLOCKS::G)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::G)), (BLOCKS(BLOCKS::E)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::E)), (BLOCKS(BLOCKS::F)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R5)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::C)), (BLOCKS(BLOCKS::B)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::B)), (BLOCKS(BLOCKS::A)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R6)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::F)), (BLOCKS(BLOCKS::E)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::E)), (BLOCKS(BLOCKS::D)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::D)), (BLOCKS(BLOCKS::B)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::B)), (BLOCKS(BLOCKS::A)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R7)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::F)), (BLOCKS(BLOCKS::E)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::E)), (BLOCKS(BLOCKS::G)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::G)), (BLOCKS(BLOCKS::H)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R8)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::F)), (BLOCKS(BLOCKS::E)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::E)), (BLOCKS(BLOCKS::G)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::G)), (BLOCKS(BLOCKS::I))))))))));
             fst = (BRelation<ROUTES, BLOCKS >((BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R1)), (BLOCKS(BLOCKS::A)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R2)), (BLOCKS(BLOCKS::A)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R3)), (BLOCKS(BLOCKS::H)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R4)), (BLOCKS(BLOCKS::I)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R5)), (BLOCKS(BLOCKS::C)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R6)), (BLOCKS(BLOCKS::F)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R7)), (BLOCKS(BLOCKS::F)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R8)), (BLOCKS(BLOCKS::F))))));
             lst = (BRelation<ROUTES, BLOCKS >((BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R1)), (BLOCKS(BLOCKS::C)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R2)), (BLOCKS(BLOCKS::F)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R3)), (BLOCKS(BLOCKS::F)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R4)), (BLOCKS(BLOCKS::F)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R5)), (BLOCKS(BLOCKS::A)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R6)), (BLOCKS(BLOCKS::A)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R7)), (BLOCKS(BLOCKS::H)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R8)), (BLOCKS(BLOCKS::I))))));
-            nxt = (BRelation<ROUTES, BRelation<BLOCKS, BLOCKS > >((BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R1)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::A)), (BLOCKS(BLOCKS::B)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::B)), (BLOCKS(BLOCKS::C)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R2)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::A)), (BLOCKS(BLOCKS::B)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::B)), (BLOCKS(BLOCKS::D)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::D)), (BLOCKS(BLOCKS::E)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::E)), (BLOCKS(BLOCKS::F)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R3)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::H)), (BLOCKS(BLOCKS::G)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::G)), (BLOCKS(BLOCKS::E)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::E)), (BLOCKS(BLOCKS::F)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R4)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::I)), (BLOCKS(BLOCKS::G)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::G)), (BLOCKS(BLOCKS::E)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::E)), (BLOCKS(BLOCKS::F)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R5)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::C)), (BLOCKS(BLOCKS::B)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::B)), (BLOCKS(BLOCKS::A)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R6)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::F)), (BLOCKS(BLOCKS::E)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::E)), (BLOCKS(BLOCKS::D)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::D)), (BLOCKS(BLOCKS::B)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::B)), (BLOCKS(BLOCKS::A)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R7)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::F)), (BLOCKS(BLOCKS::E)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::E)), (BLOCKS(BLOCKS::G)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::G)), (BLOCKS(BLOCKS::H)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R8)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::F)), (BLOCKS(BLOCKS::E)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::E)), (BLOCKS(BLOCKS::G)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::G)), (BLOCKS(BLOCKS::I))))))))));
             rtbl = (BRelation<BLOCKS, ROUTES >((BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::A)), (ROUTES(ROUTES::R1)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::A)), (ROUTES(ROUTES::R2)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::A)), (ROUTES(ROUTES::R5)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::A)), (ROUTES(ROUTES::R6)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::B)), (ROUTES(ROUTES::R1)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::B)), (ROUTES(ROUTES::R2)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::B)), (ROUTES(ROUTES::R5)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::B)), (ROUTES(ROUTES::R6)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::C)), (ROUTES(ROUTES::R1)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::C)), (ROUTES(ROUTES::R5)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::D)), (ROUTES(ROUTES::R2)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::D)), (ROUTES(ROUTES::R6)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::E)), (ROUTES(ROUTES::R2)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::E)), (ROUTES(ROUTES::R3)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::E)), (ROUTES(ROUTES::R4)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::E)), (ROUTES(ROUTES::R6)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::E)), (ROUTES(ROUTES::R7)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::E)), (ROUTES(ROUTES::R8)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::F)), (ROUTES(ROUTES::R2)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::F)), (ROUTES(ROUTES::R3)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::F)), (ROUTES(ROUTES::R4)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::F)), (ROUTES(ROUTES::R6)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::F)), (ROUTES(ROUTES::R7)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::F)), (ROUTES(ROUTES::R8)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::G)), (ROUTES(ROUTES::R3)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::G)), (ROUTES(ROUTES::R4)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::G)), (ROUTES(ROUTES::R4)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::G)), (ROUTES(ROUTES::R7)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::G)), (ROUTES(ROUTES::R8)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::H)), (ROUTES(ROUTES::R3)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::H)), (ROUTES(ROUTES::R7)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::I)), (ROUTES(ROUTES::R4)))), (BTuple<BLOCKS, ROUTES >((BLOCKS(BLOCKS::I)), (ROUTES(ROUTES::R8))))));
             resrt = (BSet<ROUTES >());
             resbl = (BSet<BLOCKS >());
@@ -349,90 +360,122 @@ class Train1_Lukas_POR_v3 {
         }
 
 
-        BSet<ROUTES> _tr_route_reservation() const {
-            BSet<ROUTES> _ic_set_0 = BSet<ROUTES>();
-            for(ROUTES _ic_r_1 : _ROUTES.difference(resrt)) {
-                if(((BBoolean(rtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1))).intersect(resbl).equal((BSet<BLOCKS >())).booleanValue() && (BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range())).booleanValue()))).booleanValue()) {
-                    _ic_set_0 = _ic_set_0._union(BSet<ROUTES>(_ic_r_1));
-                }
+        BSet<ROUTES> _tr_route_reservation(bool isCaching) const {
+            if (this->_tr_cache_route_reservation == boost::none){
+                BSet<ROUTES> _ic_set_0 = BSet<ROUTES>();
+                for(const ROUTES& _ic_r_1 : _ROUTES.difference(resrt)) {
+                    if(((BBoolean(rtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1))).intersect(resbl).equal((BSet<BLOCKS >())).booleanValue() && (BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range())).booleanValue()))).booleanValue()) {
+                        _ic_set_0 = _ic_set_0._union(BSet<ROUTES>(_ic_r_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_route_reservation = _ic_set_0;
+                else return _ic_set_0;
             }
-            return _ic_set_0;
+            return this->_tr_cache_route_reservation.get();
         }
 
-        BSet<ROUTES> _tr_route_freeing() const {
-            BSet<ROUTES> _ic_set_1 = BSet<ROUTES>();
-            for(ROUTES _ic_r_1 : resrt.difference(rsrtbl.range())) {
-                _ic_set_1 = _ic_set_1._union(BSet<ROUTES>(_ic_r_1));
+        BSet<ROUTES> _tr_route_freeing(bool isCaching) const {
+            if (this->_tr_cache_route_freeing == boost::none){
+                BSet<ROUTES> _ic_set_1 = BSet<ROUTES>();
+                for(const ROUTES& _ic_r_1 : resrt.difference(rsrtbl.range())) {
+                    _ic_set_1 = _ic_set_1._union(BSet<ROUTES>(_ic_r_1));
 
+                }
+                if (isCaching) this->_tr_cache_route_freeing = _ic_set_1;
+                else return _ic_set_1;
             }
-            return _ic_set_1;
+            return this->_tr_cache_route_freeing.get();
         }
 
-        BSet<ROUTES> _tr_FRONT_MOVE_1() const {
-            BSet<ROUTES> _ic_set_2 = BSet<ROUTES>();
-            for(ROUTES _ic_r_1 : frm) {
-                if(((BBoolean((BBoolean(resbl.difference(OCC).elementOf(fst.functionCall(_ic_r_1)).booleanValue() && _ic_r_1.equal(rsrtbl.functionCall(fst.functionCall(_ic_r_1))).booleanValue())).booleanValue() && (BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range())).booleanValue()))).booleanValue()) {
-                    _ic_set_2 = _ic_set_2._union(BSet<ROUTES>(_ic_r_1));
-                }
+        BSet<ROUTES> _tr_FRONT_MOVE_1(bool isCaching) const {
+            if (this->_tr_cache_FRONT_MOVE_1 == boost::none){
+                BSet<ROUTES> _ic_set_2 = BSet<ROUTES>();
+                for(const ROUTES& _ic_r_1 : frm) {
+                    if(((BBoolean((BBoolean(resbl.difference(OCC).elementOf(fst.functionCall(_ic_r_1)).booleanValue() && _ic_r_1.equal(rsrtbl.functionCall(fst.functionCall(_ic_r_1))).booleanValue())).booleanValue() && (BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range())).booleanValue()))).booleanValue()) {
+                        _ic_set_2 = _ic_set_2._union(BSet<ROUTES>(_ic_r_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_FRONT_MOVE_1 = _ic_set_2;
+                else return _ic_set_2;
             }
-            return _ic_set_2;
+            return this->_tr_cache_FRONT_MOVE_1.get();
         }
 
-        BSet<BLOCKS> _tr_FRONT_MOVE_2() const {
-            BSet<BLOCKS> _ic_set_3 = BSet<BLOCKS>();
-            for(BLOCKS _ic_b_1 : OCC.intersect(TRK.domain())) {
-                if(((BBoolean(OCC.notElementOf(TRK.functionCall(_ic_b_1)).booleanValue() && (BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range())).booleanValue()))).booleanValue()) {
-                    _ic_set_3 = _ic_set_3._union(BSet<BLOCKS>(_ic_b_1));
-                }
+        BSet<BLOCKS> _tr_FRONT_MOVE_2(bool isCaching) const {
+            if (this->_tr_cache_FRONT_MOVE_2 == boost::none){
+                BSet<BLOCKS> _ic_set_3 = BSet<BLOCKS>();
+                for(const BLOCKS& _ic_b_1 : OCC.intersect(TRK.domain())) {
+                    if(((BBoolean(OCC.notElementOf(TRK.functionCall(_ic_b_1)).booleanValue() && (BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range())).booleanValue()))).booleanValue()) {
+                        _ic_set_3 = _ic_set_3._union(BSet<BLOCKS>(_ic_b_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_FRONT_MOVE_2 = _ic_set_3;
+                else return _ic_set_3;
             }
-            return _ic_set_3;
+            return this->_tr_cache_FRONT_MOVE_2.get();
         }
 
-        BSet<BLOCKS> _tr_BACK_MOVE_1() const {
-            BSet<BLOCKS> _ic_set_4 = BSet<BLOCKS>();
-            for(BLOCKS _ic_b_1 : LBT.difference(TRK.domain())) {
-                if(((BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range()))).booleanValue()) {
-                    _ic_set_4 = _ic_set_4._union(BSet<BLOCKS>(_ic_b_1));
-                }
+        BSet<BLOCKS> _tr_BACK_MOVE_1(bool isCaching) const {
+            if (this->_tr_cache_BACK_MOVE_1 == boost::none){
+                BSet<BLOCKS> _ic_set_4 = BSet<BLOCKS>();
+                for(const BLOCKS& _ic_b_1 : LBT.difference(TRK.domain())) {
+                    if(((BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range()))).booleanValue()) {
+                        _ic_set_4 = _ic_set_4._union(BSet<BLOCKS>(_ic_b_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_BACK_MOVE_1 = _ic_set_4;
+                else return _ic_set_4;
             }
-            return _ic_set_4;
+            return this->_tr_cache_BACK_MOVE_1.get();
         }
 
-        BSet<BLOCKS> _tr_BACK_MOVE_2() const {
-            BSet<BLOCKS> _ic_set_5 = BSet<BLOCKS>();
-            for(BLOCKS _ic_b_1 : LBT.intersect(TRK.domain())) {
-                if(((BBoolean(OCC.elementOf(TRK.functionCall(_ic_b_1)).booleanValue() && (BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range())).booleanValue()))).booleanValue()) {
-                    _ic_set_5 = _ic_set_5._union(BSet<BLOCKS>(_ic_b_1));
-                }
+        BSet<BLOCKS> _tr_BACK_MOVE_2(bool isCaching) const {
+            if (this->_tr_cache_BACK_MOVE_2 == boost::none){
+                BSet<BLOCKS> _ic_set_5 = BSet<BLOCKS>();
+                for(const BLOCKS& _ic_b_1 : LBT.intersect(TRK.domain())) {
+                    if(((BBoolean(OCC.elementOf(TRK.functionCall(_ic_b_1)).booleanValue() && (BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range())).booleanValue()))).booleanValue()) {
+                        _ic_set_5 = _ic_set_5._union(BSet<BLOCKS>(_ic_b_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_BACK_MOVE_2 = _ic_set_5;
+                else return _ic_set_5;
             }
-            return _ic_set_5;
+            return this->_tr_cache_BACK_MOVE_2.get();
         }
 
-        BSet<ROUTES> _tr_point_positionning() const {
-            BSet<ROUTES> _ic_set_6 = BSet<ROUTES>();
-            for(ROUTES _ic_r_1 : resrt.difference(frm)) {
-                if(((BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range()))).booleanValue()) {
-                    _ic_set_6 = _ic_set_6._union(BSet<ROUTES>(_ic_r_1));
-                }
+        BSet<ROUTES> _tr_point_positionning(bool isCaching) const {
+            if (this->_tr_cache_point_positionning == boost::none){
+                BSet<ROUTES> _ic_set_6 = BSet<ROUTES>();
+                for(const ROUTES& _ic_r_1 : resrt.difference(frm)) {
+                    if(((BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range()))).booleanValue()) {
+                        _ic_set_6 = _ic_set_6._union(BSet<ROUTES>(_ic_r_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_point_positionning = _ic_set_6;
+                else return _ic_set_6;
             }
-            return _ic_set_6;
+            return this->_tr_cache_point_positionning.get();
         }
 
-        BSet<ROUTES> _tr_route_formation() const {
-            BSet<ROUTES> _ic_set_7 = BSet<ROUTES>();
-            for(ROUTES _ic_r_1 : resrt.difference(frm)) {
-                if(((BBoolean(nxt.functionCall(_ic_r_1).domainRestriction(rsrtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1)))).equal(TRK.domainRestriction(rsrtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1))))).booleanValue() && (BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range())).booleanValue()))).booleanValue()) {
-                    _ic_set_7 = _ic_set_7._union(BSet<ROUTES>(_ic_r_1));
-                }
+        BSet<ROUTES> _tr_route_formation(bool isCaching) const {
+            if (this->_tr_cache_route_formation == boost::none){
+                BSet<ROUTES> _ic_set_7 = BSet<ROUTES>();
+                for(const ROUTES& _ic_r_1 : resrt.difference(frm)) {
+                    if(((BBoolean(nxt.functionCall(_ic_r_1).domainRestriction(rsrtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1)))).equal(TRK.domainRestriction(rsrtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1))))).booleanValue() && (BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range())).booleanValue()))).booleanValue()) {
+                        _ic_set_7 = _ic_set_7._union(BSet<ROUTES>(_ic_r_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_route_formation = _ic_set_7;
+                else return _ic_set_7;
             }
-            return _ic_set_7;
+            return this->_tr_cache_route_formation.get();
         }
 
         bool _check_inv_1() const {
@@ -441,8 +484,8 @@ class Train1_Lukas_POR_v3 {
 
         bool _check_inv_2() const {
             BBoolean _ic_boolean_8 = BBoolean(true);
-            for(ROUTES _ic_r_1 : resrt.difference(frm)) {
-                for(BSet<ROUTES > _ic_a_1 : {(BSet<ROUTES >(_ic_r_1))}) {
+            for(const ROUTES& _ic_r_1 : resrt.difference(frm)) {
+                for(const BSet<ROUTES >& _ic_a_1 : {(BSet<ROUTES >(_ic_r_1))}) {
                     if(!(rtbl.rangeRestriction(_ic_a_1).equal(rsrtbl.rangeRestriction(_ic_a_1))).booleanValue()) {
                         _ic_boolean_8 = BBoolean(false);
                         break;
@@ -457,10 +500,10 @@ class Train1_Lukas_POR_v3 {
 
         bool _check_inv_3() const {
             BBoolean _ic_boolean_10 = BBoolean(true);
-            for(BLOCKS _ic_x_1 : TRK.domain()) {
-                for(BLOCKS _ic_y_1 : TRK.relationImage((BSet<BLOCKS >(_ic_x_1)))) {
+            for(const BLOCKS& _ic_x_1 : TRK.domain()) {
+                for(const BLOCKS& _ic_y_1 : TRK.relationImage((BSet<BLOCKS >(_ic_x_1)))) {
                     BBoolean _ic_boolean_9 = BBoolean(false);
-                    for(ROUTES _ic_r_1 : _ROUTES) {
+                    for(const ROUTES& _ic_r_1 : _ROUTES) {
                         if((nxt.functionCall(_ic_r_1).elementOf((BTuple<BLOCKS, BLOCKS >(_ic_x_1, _ic_y_1)))).booleanValue()) {
                             _ic_boolean_9 = BBoolean(true);
                             break;
@@ -481,8 +524,8 @@ class Train1_Lukas_POR_v3 {
 
         bool _check_inv_4() const {
             BBoolean _ic_boolean_11 = BBoolean(true);
-            for(ROUTES _ic_r_1 : frm) {
-                for(BSet<BLOCKS > _ic_a_1 : {rsrtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1)))}) {
+            for(const ROUTES& _ic_r_1 : frm) {
+                for(const BSet<BLOCKS >& _ic_a_1 : {rsrtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1)))}) {
                     if(!(nxt.functionCall(_ic_r_1).domainRestriction(_ic_a_1).equal(TRK.domainRestriction(_ic_a_1))).booleanValue()) {
                         _ic_boolean_11 = BBoolean(false);
                         break;
@@ -501,10 +544,10 @@ class Train1_Lukas_POR_v3 {
 
         bool _check_inv_6() const {
             BBoolean _ic_boolean_12 = BBoolean(true);
-            for(BLOCKS _ic_a_1 : rsrtbl.domain()) {
-                for(BLOCKS _ic_b_1 : LBT) {
-                    for(ROUTES _ic_c_1 : {rsrtbl.functionCall(_ic_b_1)}) {
-                        for(BRelation<BLOCKS, BLOCKS > _ic_d_1 : {nxt.functionCall(_ic_c_1)}) {
+            for(const BLOCKS& _ic_a_1 : rsrtbl.domain()) {
+                for(const BLOCKS& _ic_b_1 : LBT) {
+                    for(const ROUTES& _ic_c_1 : {rsrtbl.functionCall(_ic_b_1)}) {
+                        for(const BRelation<BLOCKS, BLOCKS >& _ic_d_1 : {nxt.functionCall(_ic_c_1)}) {
                             if(!((BBoolean(!(BBoolean(_ic_d_1.range().elementOf(_ic_b_1).booleanValue() && _ic_a_1.equal(_ic_d_1.inverse().functionCall(_ic_b_1)).booleanValue())).booleanValue() || rsrtbl.functionCall(_ic_a_1).unequal(_ic_c_1).booleanValue()))).booleanValue()) {
                                 _ic_boolean_12 = BBoolean(false);
                                 break;
@@ -534,10 +577,10 @@ class Train1_Lukas_POR_v3 {
 
         bool _check_inv_10() const {
             BBoolean _ic_boolean_13 = BBoolean(true);
-            for(ROUTES _ic_r_1 : _ROUTES) {
-                for(BRelation<BLOCKS, BLOCKS > _ic_a_1 : {nxt.functionCall(_ic_r_1)}) {
-                    for(BSet<BLOCKS > _ic_b_1 : {rsrtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1)))}) {
-                        for(BSet<BLOCKS > _ic_c_1 : {_ic_b_1.difference(OCC)}) {
+            for(const ROUTES& _ic_r_1 : _ROUTES) {
+                for(const BRelation<BLOCKS, BLOCKS >& _ic_a_1 : {nxt.functionCall(_ic_r_1)}) {
+                    for(const BSet<BLOCKS >& _ic_b_1 : {rsrtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1)))}) {
+                        for(const BSet<BLOCKS >& _ic_c_1 : {_ic_b_1.difference(OCC)}) {
                             if(!((BBoolean((BBoolean(_ic_a_1.relationImage(rtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1))).difference(_ic_b_1)).intersect(_ic_c_1).equal((BSet<BLOCKS >())).booleanValue() && _ic_a_1.relationImage(_ic_b_1).subset(_ic_b_1).booleanValue())).booleanValue() && _ic_a_1.relationImage(_ic_c_1).subset(_ic_c_1).booleanValue()))).booleanValue()) {
                                 _ic_boolean_13 = BBoolean(false);
                                 break;
@@ -562,8 +605,31 @@ class Train1_Lukas_POR_v3 {
             return (rsrtbl.relationImage(OCC).subset(frm)).booleanValue();
         }
 
-        Train1_Lukas_POR_v3 _copy() const {
-            return Train1_Lukas_POR_v3(fst, lst, nxt, rtbl, LBT, TRK, frm, OCC, resbl, resrt, rsrtbl);
+        static constexpr unsigned int strHash(const char *s, int off = 0) {
+            return !s[off] ? 5381 : (strHash(s, off+1)*33) ^ s[off];
+        }
+
+        Train1_Lukas_POR_v3 _copy(unordered_set<string> toInvalidate) const {
+            static const char* allTransitions[] = {"_tr_route_reservation", "_tr_route_freeing", "_tr_FRONT_MOVE_1", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_1", "_tr_BACK_MOVE_2", "_tr_point_positionning", "_tr_route_formation"};
+
+            Train1_Lukas_POR_v3 result = Train1_Lukas_POR_v3(fst, lst, nxt, rtbl, LBT, TRK, frm, OCC, resbl, resrt, rsrtbl);
+
+            for (const auto &item : allTransitions) {
+                if(toInvalidate.find(item) == toInvalidate.end()) {
+                    switch(strHash(item)) {
+                        case strHash("_tr_route_reservation"): result._tr_cache_route_reservation = this->_tr_cache_route_reservation; break;
+                        case strHash("_tr_route_freeing"): result._tr_cache_route_freeing = this->_tr_cache_route_freeing; break;
+                        case strHash("_tr_FRONT_MOVE_1"): result._tr_cache_FRONT_MOVE_1 = this->_tr_cache_FRONT_MOVE_1; break;
+                        case strHash("_tr_FRONT_MOVE_2"): result._tr_cache_FRONT_MOVE_2 = this->_tr_cache_FRONT_MOVE_2; break;
+                        case strHash("_tr_BACK_MOVE_1"): result._tr_cache_BACK_MOVE_1 = this->_tr_cache_BACK_MOVE_1; break;
+                        case strHash("_tr_BACK_MOVE_2"): result._tr_cache_BACK_MOVE_2 = this->_tr_cache_BACK_MOVE_2; break;
+                        case strHash("_tr_point_positionning"): result._tr_cache_point_positionning = this->_tr_cache_point_positionning; break;
+                        case strHash("_tr_route_formation"): result._tr_cache_route_formation = this->_tr_cache_route_formation; break;
+                        default: cout << "Transition " << item << " not found!";
+                    }
+                }
+            }
+            return result;
         }
 
         friend bool operator ==(const Train1_Lukas_POR_v3& o1, const Train1_Lukas_POR_v3& o2) {
@@ -617,797 +683,407 @@ class Train1_Lukas_POR_v3 {
 };
 
 
-static std::unordered_set<Train1_Lukas_POR_v3, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> generateNextStates(std::mutex& guardMutex, const Train1_Lukas_POR_v3& state, bool isCaching, std::unordered_map<string, std::unordered_set<string>>& invariantDependency, std::unordered_map<Train1_Lukas_POR_v3, std::unordered_set<string>, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual>& dependentInvariant, std::unordered_map<string, std::unordered_set<string>>& guardDependency, std::unordered_map<Train1_Lukas_POR_v3, std::unordered_set<string>, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual>& dependentGuard, std::unordered_map<Train1_Lukas_POR_v3, immer::map<string, boost::any>, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual>& guardCache, std::unordered_map<Train1_Lukas_POR_v3, Train1_Lukas_POR_v3, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual>& parents, std::unordered_map<Train1_Lukas_POR_v3, string, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual>& stateAccessedVia, std::atomic<int>& transitions) {
-    std::unordered_set<Train1_Lukas_POR_v3, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> result = std::unordered_set<Train1_Lukas_POR_v3, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual>();
-    if(isCaching) {
-        immer::map<string, boost::any> parentsGuard;
-        std::unordered_set<string> dependentGuardsOfState;
-        bool parentsExist = false;
-        bool dependentGuardsExist = false;
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            parentsExist = (parents.find(state) != parents.end());
-            dependentGuardsExist = (dependentGuard.find(state) != dependentGuard.end());
-            if(parentsExist) {
-                parentsGuard = guardCache[parents[state]];
+class ModelChecker {
+    private:
+        Train1_Lukas_POR_v3::Type type;
+        int threads;
+        bool isCaching;
+        bool isDebug;
+
+        std::list<Train1_Lukas_POR_v3> unvisitedStates;
+        std::unordered_set<Train1_Lukas_POR_v3, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> states;
+        std::atomic<int> transitions;
+        std::mutex mutex;
+        std::mutex waitMutex;
+        std::mutex guardMutex;
+        std::condition_variable waitCV;
+
+        std::atomic<bool> invariantViolatedBool;
+        std::atomic<bool> deadlockDetected;
+        Train1_Lukas_POR_v3 counterExampleState;
+
+        std::unordered_map<string, std::unordered_set<string>> invariantDependency;
+        std::unordered_map<string, std::unordered_set<string>> guardDependency;
+        std::unordered_map<Train1_Lukas_POR_v3, Train1_Lukas_POR_v3, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> parents;
+
+    public:
+        ModelChecker() {}
+
+        ModelChecker(Train1_Lukas_POR_v3::Type type, int threads, bool isCaching, bool isDebug) {
+            this->type = type;
+            this->threads = threads;
+            this->isCaching = isCaching;
+            this->isDebug = isDebug;
+            this->invariantViolatedBool = false;
+            this->deadlockDetected = false;
+            this->transitions = 0;
+        }
+
+        void modelCheck() {
+            if (isDebug) {
+                cout << "Starting Modelchecking, STRATEGY=" << type << ", THREADS=" << threads << ", CACHING=" << isCaching << "\n";
             }
-            if(dependentGuardsExist) {
-                dependentGuardsOfState = dependentGuard[state];
+
+            if (threads <= 1) {
+                modelCheckSingleThreaded();
+            } else {
+                boost::asio::thread_pool workers(threads); // threads indicates the number of workers (without the coordinator)
+                modelCheckMultiThreaded(workers);
             }
         }
-        immer::map<string, boost::any> newCache = parentsGuard;
-        boost::any cachedValue;
-        bool dependentGuardsBoolean = true;
-        BSet<Train1_Lukas_POR_v3::ROUTES> _trid_1;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_route_reservation"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_route_reservation") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_1 = state._tr_route_reservation();
-        } else {
-            _trid_1 = boost::any_cast<BSet<Train1_Lukas_POR_v3::ROUTES>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_route_reservation", _trid_1);
-        for(const Train1_Lukas_POR_v3::ROUTES& param : _trid_1) {
-            Train1_Lukas_POR_v3::ROUTES _tmp_1 = param;
-
-            Train1_Lukas_POR_v3 copiedState = state._copy();
-            copiedState.route_reservation(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["route_reservation"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["route_reservation"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "route_reservation"});
-                }
+
+        void modelCheckSingleThreaded() {
+            Train1_Lukas_POR_v3 machine = Train1_Lukas_POR_v3();
+            states.insert(machine);
+            unvisitedStates.push_back(machine);
+
+            if (isCaching) {
+                initCache(machine);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train1_Lukas_POR_v3::ROUTES> _trid_2;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_route_freeing"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_route_freeing") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_2 = state._tr_route_freeing();
-        } else {
-            _trid_2 = boost::any_cast<BSet<Train1_Lukas_POR_v3::ROUTES>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_route_freeing", _trid_2);
-        for(const Train1_Lukas_POR_v3::ROUTES& param : _trid_2) {
-            Train1_Lukas_POR_v3::ROUTES _tmp_1 = param;
-
-            Train1_Lukas_POR_v3 copiedState = state._copy();
-            copiedState.route_freeing(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["route_freeing"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["route_freeing"]});
+
+            while(!unvisitedStates.empty()) {
+                Train1_Lukas_POR_v3 state = next();
+
+                std::unordered_set<Train1_Lukas_POR_v3, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> nextStates = generateNextStates(state);
+                transitions += nextStates.size();
+
+                for(auto& nextState : nextStates) {
+                    if(states.find(nextState) == states.end()) {
+                        states.insert(nextState);
+                        parents.insert({nextState, state});
+                        unvisitedStates.push_back(nextState);
+                        if(states.size() % 50000 == 0) {
+                            cout << "VISITED STATES: " << states.size() << "\n";
+                            cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
+                            cout << "-------------------" << "\n";
+                        }
+                    }
                 }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+
+                if(invariantViolated(state)) {
+                    invariantViolatedBool = true;
+                    counterExampleState = state;
+                    break;
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "route_freeing"});
+
+                if(nextStates.empty()) {
+                    deadlockDetected = true;
+                    counterExampleState = state;
+                    break;
                 }
+
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train1_Lukas_POR_v3::ROUTES> _trid_3;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_FRONT_MOVE_1"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_FRONT_MOVE_1") != dependentGuardsOfState.end());
+            printResult();
         }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_3 = state._tr_FRONT_MOVE_1();
-        } else {
-            _trid_3 = boost::any_cast<BSet<Train1_Lukas_POR_v3::ROUTES>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_FRONT_MOVE_1", _trid_3);
-        for(const Train1_Lukas_POR_v3::ROUTES& param : _trid_3) {
-            Train1_Lukas_POR_v3::ROUTES _tmp_1 = param;
-
-            Train1_Lukas_POR_v3 copiedState = state._copy();
-            copiedState.FRONT_MOVE_1(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["FRONT_MOVE_1"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["FRONT_MOVE_1"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "FRONT_MOVE_1"});
-                }
+
+        void modelCheckMultiThreaded(boost::asio::thread_pool& workers) {
+            Train1_Lukas_POR_v3 machine = Train1_Lukas_POR_v3();
+            states.insert(machine);
+            unvisitedStates.push_back(machine);
+
+            std::atomic<bool> stopThreads;
+            stopThreads = false;
+            std::atomic<int> possibleQueueChanges;
+            possibleQueueChanges = 0;
+
+            if(isCaching) {
+                initCache(machine);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train1_Lukas_POR_v3::BLOCKS> _trid_4;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_FRONT_MOVE_2"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_FRONT_MOVE_2") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_4 = state._tr_FRONT_MOVE_2();
-        } else {
-            _trid_4 = boost::any_cast<BSet<Train1_Lukas_POR_v3::BLOCKS>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_FRONT_MOVE_2", _trid_4);
-        for(const Train1_Lukas_POR_v3::BLOCKS& param : _trid_4) {
-            Train1_Lukas_POR_v3::BLOCKS _tmp_1 = param;
-
-            Train1_Lukas_POR_v3 copiedState = state._copy();
-            copiedState.FRONT_MOVE_2(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["FRONT_MOVE_2"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["FRONT_MOVE_2"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "FRONT_MOVE_2"});
+
+            std::atomic<bool> waitFlag;
+            waitFlag = true;
+
+            while(!unvisitedStates.empty() && !stopThreads) {
+                possibleQueueChanges += 1;
+                Train1_Lukas_POR_v3 state = next();
+                std::packaged_task<void()> task([&, state] {
+                    std::unordered_set<Train1_Lukas_POR_v3, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> nextStates = generateNextStates(state);
+                    transitions += nextStates.size();
+
+                    for(auto& nextState : nextStates) {
+                        {
+                            std::unique_lock<std::mutex> lock(mutex);
+                            if(states.find(nextState) == states.end()) {
+                                states.insert(nextState);
+                                parents.insert({nextState, state});
+                                unvisitedStates.push_back(nextState); // TODO: sync ?
+                                if(isDebug && states.size() % 50000 == 0) {
+                                    cout << "VISITED STATES: " << states.size() << "\n";
+                                    cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
+                                    cout << "-------------------" << "\n";
+                                }
+                            }
+                        }
+                    }
+
+                    {
+                        std::unique_lock<std::mutex> lock(mutex);
+                        possibleQueueChanges -= 1;
+                        int running = possibleQueueChanges;
+                        if (!unvisitedStates.empty() || running == 0) {
+                            {
+                                std::unique_lock<std::mutex> lock(waitMutex);
+                                waitFlag = false;
+                                waitCV.notify_one();
+                            }
+                        }
+                    }
+
+                    if(invariantViolated(state)) {
+                        invariantViolatedBool = true;
+                        counterExampleState = state;
+                        stopThreads = true;
+                    }
+
+                    if(nextStates.empty()) {
+                        deadlockDetected = true;
+                        counterExampleState = state;
+                        stopThreads = true;
+                    }
+
+                });
+
+                waitFlag = true;
+                boost::asio::post(workers, std::move(task));
+
+                {
+                    std::unique_lock<std::mutex> lock(waitMutex);
+                    while (unvisitedStates.empty() && possibleQueueChanges > 0) {
+                        waitCV.wait(lock, [&] {
+                            return waitFlag == false;
+                        });
+                    }
                 }
             }
-            result.insert(copiedState);
-            transitions += 1;
+            workers.join();
+            printResult();
+        }
+
+        void initCache(Train1_Lukas_POR_v3& machine) {
+            invariantDependency.insert({"point_positionning", {"_check_inv_3", "_check_inv_1", "_check_inv_4"}});
+            invariantDependency.insert({"route_reservation", {"_check_inv_2", "_check_inv_6", "_check_inv_10", "_check_inv_7", "_check_inv_4", "_check_inv_8", "_check_inv_12", "_check_inv_9", "_check_inv_11"}});
+            invariantDependency.insert({"FRONT_MOVE_1", {"_check_inv_6", "_check_inv_10", "_check_inv_5", "_check_inv_12", "_check_inv_9"}});
+            invariantDependency.insert({"BACK_MOVE_1", {"_check_inv_2", "_check_inv_6", "_check_inv_10", "_check_inv_7", "_check_inv_4", "_check_inv_5", "_check_inv_8", "_check_inv_12", "_check_inv_9"}});
+            invariantDependency.insert({"FRONT_MOVE_2", {"_check_inv_10", "_check_inv_5", "_check_inv_12", "_check_inv_9"}});
+            invariantDependency.insert({"route_formation", {"_check_inv_2", "_check_inv_4", "_check_inv_12", "_check_inv_11"}});
+            invariantDependency.insert({"route_freeing", {"_check_inv_2", "_check_inv_7", "_check_inv_4", "_check_inv_12", "_check_inv_11"}});
+            invariantDependency.insert({"BACK_MOVE_2", {"_check_inv_2", "_check_inv_6", "_check_inv_10", "_check_inv_7", "_check_inv_4", "_check_inv_5", "_check_inv_8", "_check_inv_12", "_check_inv_9"}});
+            invariantDependency.insert({"", {}});
+            guardDependency.insert({"point_positionning", {"_tr_route_formation", "_tr_BACK_MOVE_1", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
+            guardDependency.insert({"route_reservation", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
+            guardDependency.insert({"FRONT_MOVE_1", {"_tr_FRONT_MOVE_1", "_tr_BACK_MOVE_1", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
+            guardDependency.insert({"BACK_MOVE_1", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
+            guardDependency.insert({"FRONT_MOVE_2", {"_tr_FRONT_MOVE_1", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
+            guardDependency.insert({"route_formation", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_point_positionning"}});
+            guardDependency.insert({"route_freeing", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
+            guardDependency.insert({"BACK_MOVE_2", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
         }
-        BSet<Train1_Lukas_POR_v3::BLOCKS> _trid_5;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_BACK_MOVE_1"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_BACK_MOVE_1") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_5 = state._tr_BACK_MOVE_1();
-        } else {
-            _trid_5 = boost::any_cast<BSet<Train1_Lukas_POR_v3::BLOCKS>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_BACK_MOVE_1", _trid_5);
-        for(const Train1_Lukas_POR_v3::BLOCKS& param : _trid_5) {
-            Train1_Lukas_POR_v3::BLOCKS _tmp_1 = param;
-
-            Train1_Lukas_POR_v3 copiedState = state._copy();
-            copiedState.BACK_MOVE_1(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["BACK_MOVE_1"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["BACK_MOVE_1"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "BACK_MOVE_1"});
+
+
+    private:
+        Train1_Lukas_POR_v3 next() {
+            std::unique_lock<std::mutex> lock(mutex);
+            switch(type) {
+                case Train1_Lukas_POR_v3::BFS: {
+                    Train1_Lukas_POR_v3 state = unvisitedStates.front();
+                    unvisitedStates.pop_front();
+                    return state;
+                }
+                case Train1_Lukas_POR_v3::DFS: {
+                    Train1_Lukas_POR_v3 state = unvisitedStates.back();
+                    unvisitedStates.pop_back();
+                    return state;
+                }
+                case Train1_Lukas_POR_v3::MIXED: {
+                    if(unvisitedStates.size() % 2 == 0) {
+                        Train1_Lukas_POR_v3 state = unvisitedStates.front();
+                        unvisitedStates.pop_front();
+                        return state;
+                    } else {
+                        Train1_Lukas_POR_v3 state = unvisitedStates.back();
+                        unvisitedStates.pop_back();
+                        return state;
+                    }
                 }
             }
-            result.insert(copiedState);
-            transitions += 1;
         }
-        BSet<Train1_Lukas_POR_v3::BLOCKS> _trid_6;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_BACK_MOVE_2"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_BACK_MOVE_2") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_6 = state._tr_BACK_MOVE_2();
-        } else {
-            _trid_6 = boost::any_cast<BSet<Train1_Lukas_POR_v3::BLOCKS>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_BACK_MOVE_2", _trid_6);
-        for(const Train1_Lukas_POR_v3::BLOCKS& param : _trid_6) {
-            Train1_Lukas_POR_v3::BLOCKS _tmp_1 = param;
-
-            Train1_Lukas_POR_v3 copiedState = state._copy();
-            copiedState.BACK_MOVE_2(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["BACK_MOVE_2"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["BACK_MOVE_2"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "BACK_MOVE_2"});
-                }
+
+        std::unordered_set<Train1_Lukas_POR_v3, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> generateNextStates(const Train1_Lukas_POR_v3& state) {
+            std::unordered_set<Train1_Lukas_POR_v3, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> result = std::unordered_set<Train1_Lukas_POR_v3, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual>();
+            BSet<Train1_Lukas_POR_v3::ROUTES> _trid_1 = state._tr_route_reservation(isCaching);
+            for(const Train1_Lukas_POR_v3::ROUTES& param : _trid_1) {
+                Train1_Lukas_POR_v3::ROUTES _tmp_1 = param;
+
+                Train1_Lukas_POR_v3 copiedState = state._copy(guardDependency["route_reservation"]);
+                copiedState.route_reservation(_tmp_1);
+                copiedState.stateAccessedVia = "route_reservation";
+                result.insert(copiedState);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train1_Lukas_POR_v3::ROUTES> _trid_7;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_point_positionning"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_point_positionning") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_7 = state._tr_point_positionning();
-        } else {
-            _trid_7 = boost::any_cast<BSet<Train1_Lukas_POR_v3::ROUTES>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_point_positionning", _trid_7);
-        for(const Train1_Lukas_POR_v3::ROUTES& param : _trid_7) {
-            Train1_Lukas_POR_v3::ROUTES _tmp_1 = param;
-
-            Train1_Lukas_POR_v3 copiedState = state._copy();
-            copiedState.point_positionning(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["point_positionning"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["point_positionning"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "point_positionning"});
-                }
+            BSet<Train1_Lukas_POR_v3::ROUTES> _trid_2 = state._tr_route_freeing(isCaching);
+            for(const Train1_Lukas_POR_v3::ROUTES& param : _trid_2) {
+                Train1_Lukas_POR_v3::ROUTES _tmp_1 = param;
+
+                Train1_Lukas_POR_v3 copiedState = state._copy(guardDependency["route_freeing"]);
+                copiedState.route_freeing(_tmp_1);
+                copiedState.stateAccessedVia = "route_freeing";
+                result.insert(copiedState);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train1_Lukas_POR_v3::ROUTES> _trid_8;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_route_formation"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_route_formation") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_8 = state._tr_route_formation();
-        } else {
-            _trid_8 = boost::any_cast<BSet<Train1_Lukas_POR_v3::ROUTES>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_route_formation", _trid_8);
-        for(const Train1_Lukas_POR_v3::ROUTES& param : _trid_8) {
-            Train1_Lukas_POR_v3::ROUTES _tmp_1 = param;
-
-            Train1_Lukas_POR_v3 copiedState = state._copy();
-            copiedState.route_formation(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["route_formation"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["route_formation"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "route_formation"});
-                }
+            BSet<Train1_Lukas_POR_v3::ROUTES> _trid_3 = state._tr_FRONT_MOVE_1(isCaching);
+            for(const Train1_Lukas_POR_v3::ROUTES& param : _trid_3) {
+                Train1_Lukas_POR_v3::ROUTES _tmp_1 = param;
+
+                Train1_Lukas_POR_v3 copiedState = state._copy(guardDependency["FRONT_MOVE_1"]);
+                copiedState.FRONT_MOVE_1(_tmp_1);
+                copiedState.stateAccessedVia = "FRONT_MOVE_1";
+                result.insert(copiedState);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            guardCache.insert({state, newCache});
-        }
-    } else {
-        BSet<Train1_Lukas_POR_v3::ROUTES> _trid_1 = state._tr_route_reservation();
-        for(const Train1_Lukas_POR_v3::ROUTES& param : _trid_1) {
-            Train1_Lukas_POR_v3::ROUTES _tmp_1 = param;
-
-            Train1_Lukas_POR_v3 copiedState = state._copy();
-            copiedState.route_reservation(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "route_reservation"});
-                }
+            BSet<Train1_Lukas_POR_v3::BLOCKS> _trid_4 = state._tr_FRONT_MOVE_2(isCaching);
+            for(const Train1_Lukas_POR_v3::BLOCKS& param : _trid_4) {
+                Train1_Lukas_POR_v3::BLOCKS _tmp_1 = param;
+
+                Train1_Lukas_POR_v3 copiedState = state._copy(guardDependency["FRONT_MOVE_2"]);
+                copiedState.FRONT_MOVE_2(_tmp_1);
+                copiedState.stateAccessedVia = "FRONT_MOVE_2";
+                result.insert(copiedState);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train1_Lukas_POR_v3::ROUTES> _trid_2 = state._tr_route_freeing();
-        for(const Train1_Lukas_POR_v3::ROUTES& param : _trid_2) {
-            Train1_Lukas_POR_v3::ROUTES _tmp_1 = param;
-
-            Train1_Lukas_POR_v3 copiedState = state._copy();
-            copiedState.route_freeing(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "route_freeing"});
-                }
+            BSet<Train1_Lukas_POR_v3::BLOCKS> _trid_5 = state._tr_BACK_MOVE_1(isCaching);
+            for(const Train1_Lukas_POR_v3::BLOCKS& param : _trid_5) {
+                Train1_Lukas_POR_v3::BLOCKS _tmp_1 = param;
+
+                Train1_Lukas_POR_v3 copiedState = state._copy(guardDependency["BACK_MOVE_1"]);
+                copiedState.BACK_MOVE_1(_tmp_1);
+                copiedState.stateAccessedVia = "BACK_MOVE_1";
+                result.insert(copiedState);
+            }
+            BSet<Train1_Lukas_POR_v3::BLOCKS> _trid_6 = state._tr_BACK_MOVE_2(isCaching);
+            for(const Train1_Lukas_POR_v3::BLOCKS& param : _trid_6) {
+                Train1_Lukas_POR_v3::BLOCKS _tmp_1 = param;
+
+                Train1_Lukas_POR_v3 copiedState = state._copy(guardDependency["BACK_MOVE_2"]);
+                copiedState.BACK_MOVE_2(_tmp_1);
+                copiedState.stateAccessedVia = "BACK_MOVE_2";
+                result.insert(copiedState);
+            }
+            BSet<Train1_Lukas_POR_v3::ROUTES> _trid_7 = state._tr_point_positionning(isCaching);
+            for(const Train1_Lukas_POR_v3::ROUTES& param : _trid_7) {
+                Train1_Lukas_POR_v3::ROUTES _tmp_1 = param;
+
+                Train1_Lukas_POR_v3 copiedState = state._copy(guardDependency["point_positionning"]);
+                copiedState.point_positionning(_tmp_1);
+                copiedState.stateAccessedVia = "point_positionning";
+                result.insert(copiedState);
             }
-            result.insert(copiedState);
-            transitions += 1;
+            BSet<Train1_Lukas_POR_v3::ROUTES> _trid_8 = state._tr_route_formation(isCaching);
+            for(const Train1_Lukas_POR_v3::ROUTES& param : _trid_8) {
+                Train1_Lukas_POR_v3::ROUTES _tmp_1 = param;
+
+                Train1_Lukas_POR_v3 copiedState = state._copy(guardDependency["route_formation"]);
+                copiedState.route_formation(_tmp_1);
+                copiedState.stateAccessedVia = "route_formation";
+                result.insert(copiedState);
+            }
+
+            return result;
         }
-        BSet<Train1_Lukas_POR_v3::ROUTES> _trid_3 = state._tr_FRONT_MOVE_1();
-        for(const Train1_Lukas_POR_v3::ROUTES& param : _trid_3) {
-            Train1_Lukas_POR_v3::ROUTES _tmp_1 = param;
-
-            Train1_Lukas_POR_v3 copiedState = state._copy();
-            copiedState.FRONT_MOVE_1(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+
+        bool invariantViolated(const Train1_Lukas_POR_v3& state) {
+            if(isCaching) {
+                std::unordered_set<string> dependentInvariantsOfState = invariantDependency[state.stateAccessedVia];
+                if(dependentInvariantsOfState.find("_check_inv_1") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_1()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "FRONT_MOVE_1"});
+                if(dependentInvariantsOfState.find("_check_inv_2") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_2()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train1_Lukas_POR_v3::BLOCKS> _trid_4 = state._tr_FRONT_MOVE_2();
-        for(const Train1_Lukas_POR_v3::BLOCKS& param : _trid_4) {
-            Train1_Lukas_POR_v3::BLOCKS _tmp_1 = param;
-
-            Train1_Lukas_POR_v3 copiedState = state._copy();
-            copiedState.FRONT_MOVE_2(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_3") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_3()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "FRONT_MOVE_2"});
+                if(dependentInvariantsOfState.find("_check_inv_4") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_4()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train1_Lukas_POR_v3::BLOCKS> _trid_5 = state._tr_BACK_MOVE_1();
-        for(const Train1_Lukas_POR_v3::BLOCKS& param : _trid_5) {
-            Train1_Lukas_POR_v3::BLOCKS _tmp_1 = param;
-
-            Train1_Lukas_POR_v3 copiedState = state._copy();
-            copiedState.BACK_MOVE_1(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_5") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_5()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "BACK_MOVE_1"});
+                if(dependentInvariantsOfState.find("_check_inv_6") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_6()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train1_Lukas_POR_v3::BLOCKS> _trid_6 = state._tr_BACK_MOVE_2();
-        for(const Train1_Lukas_POR_v3::BLOCKS& param : _trid_6) {
-            Train1_Lukas_POR_v3::BLOCKS _tmp_1 = param;
-
-            Train1_Lukas_POR_v3 copiedState = state._copy();
-            copiedState.BACK_MOVE_2(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_7") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_7()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "BACK_MOVE_2"});
+                if(dependentInvariantsOfState.find("_check_inv_8") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_8()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train1_Lukas_POR_v3::ROUTES> _trid_7 = state._tr_point_positionning();
-        for(const Train1_Lukas_POR_v3::ROUTES& param : _trid_7) {
-            Train1_Lukas_POR_v3::ROUTES _tmp_1 = param;
-
-            Train1_Lukas_POR_v3 copiedState = state._copy();
-            copiedState.point_positionning(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_9") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_9()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "point_positionning"});
+                if(dependentInvariantsOfState.find("_check_inv_10") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_10()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train1_Lukas_POR_v3::ROUTES> _trid_8 = state._tr_route_formation();
-        for(const Train1_Lukas_POR_v3::ROUTES& param : _trid_8) {
-            Train1_Lukas_POR_v3::ROUTES _tmp_1 = param;
-
-            Train1_Lukas_POR_v3 copiedState = state._copy();
-            copiedState.route_formation(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_11") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_11()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "route_formation"});
+                if(dependentInvariantsOfState.find("_check_inv_12") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_12()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-
-    }
-    return result;
-}
-
-static void printResult(int states, int transitions, bool deadlockDetected, bool invariantViolated, Train1_Lukas_POR_v3& counterExampleState, std::unordered_map<Train1_Lukas_POR_v3, Train1_Lukas_POR_v3, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual>& parents, std::unordered_map<Train1_Lukas_POR_v3, string, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual>& stateAccessedVia) {
-    if(deadlockDetected || invariantViolated) {
-        if(deadlockDetected) {
-            cout << "DEADLOCK DETECTED" << "\n";
-        }
-        if(invariantViolated) {
-            cout << "INVARIANT VIOLATED" << "\n";
-        }
-        cout << "COUNTER EXAMPLE TRACE: " << "\n";
-
-        Train1_Lukas_POR_v3 currentState = counterExampleState;
-        std::string trace = "";
-        while(parents.find(currentState) != parents.end()) {
-            std::stringstream stringStream;
-            stringStream << currentState;
-            trace.insert(0, stringStream.str());
-            trace.insert(0, "\n");
-            trace.insert(0, stateAccessedVia[currentState]);
-            trace.insert(0, "\n\n");
-            currentState = parents[currentState];
-        }
-        cout << trace;
-    }
-
-    if(!deadlockDetected && !invariantViolated) {
-        cout << "MODEL CHECKING SUCCESSFUL" << "\n";
-    }
-    cout << "Number of States: " << states << "\n";
-    cout << "Number of Transitions: " << transitions << "\n";
-}
-
-static bool checkInvariants(std::mutex& guardMutex, const Train1_Lukas_POR_v3& state, bool isCaching, std::unordered_map<Train1_Lukas_POR_v3, std::unordered_set<string>, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual>& dependentInvariant) {
-    if(isCaching) {
-        std::unordered_set<string> dependentInvariantsOfState;
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            dependentInvariantsOfState = dependentInvariant[state];
-        }
-        if(dependentInvariantsOfState.find("_check_inv_1") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_1()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_2") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_2()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_3") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_3()) {
                 return false;
             }
+            return !(state._check_inv_1() && state._check_inv_2() && state._check_inv_3() && state._check_inv_4() && state._check_inv_5() && state._check_inv_6() && state._check_inv_7() && state._check_inv_8() && state._check_inv_9() && state._check_inv_10() && state._check_inv_11() && state._check_inv_12());
         }
-        if(dependentInvariantsOfState.find("_check_inv_4") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_4()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_5") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_5()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_6") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_6()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_7") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_7()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_8") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_8()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_9") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_9()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_10") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_10()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_11") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_11()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_12") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_12()) {
-                return false;
-            }
-        }
-        return true;
-    }
-    return !(!state._check_inv_1() || !state._check_inv_2() || !state._check_inv_3() || !state._check_inv_4() || !state._check_inv_5() || !state._check_inv_6() || !state._check_inv_7() || !state._check_inv_8() || !state._check_inv_9() || !state._check_inv_10() || !state._check_inv_11() || !state._check_inv_12());
-}
 
-static Train1_Lukas_POR_v3 next(std::list<Train1_Lukas_POR_v3>& collection, std::mutex& mutex, Train1_Lukas_POR_v3::Type type) {
-    std::unique_lock<std::mutex> lock(mutex);
-    switch(type) {
-        case Train1_Lukas_POR_v3::BFS: {
-            Train1_Lukas_POR_v3 state = collection.front();
-            collection.pop_front();
-            return state;
-        }
-        case Train1_Lukas_POR_v3::DFS: {
-            Train1_Lukas_POR_v3 state = collection.back();
-            collection.pop_back();
-            return state;
-        }
-        case Train1_Lukas_POR_v3::MIXED: {
-            if(collection.size() % 2 == 0) {
-                Train1_Lukas_POR_v3 state = collection.front();
-                collection.pop_front();
-                return state;
-            } else {
-                Train1_Lukas_POR_v3 state = collection.back();
-                collection.pop_back();
-                return state;
-            }
-        }
-    };
-}
 
-static void modelCheckSingleThreaded(Train1_Lukas_POR_v3::Type type, bool isCaching) {
-    std::mutex mutex;
-    std::mutex guardMutex;
-
-    Train1_Lukas_POR_v3 machine = Train1_Lukas_POR_v3();
-
-    std::atomic<bool> invariantViolated;
-    invariantViolated = false;
-    std::atomic<bool> deadlockDetected;
-    deadlockDetected = false;
-    std::atomic<bool> stopThreads;
-    stopThreads = false;
-
-    std::unordered_set<Train1_Lukas_POR_v3, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> states = std::unordered_set<Train1_Lukas_POR_v3, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual>();
-    states.insert(machine);
-    std::atomic<int> numberStates;
-    numberStates = 1;
-
-    std::list<Train1_Lukas_POR_v3> collection = std::list<Train1_Lukas_POR_v3>();
-    collection.push_back(machine);
-
-    std::atomic<int> transitions;
-    transitions = 0;
-
-    std::unordered_map<string, std::unordered_set<string>> invariantDependency;
-    std::unordered_map<string, std::unordered_set<string>> guardDependency;
-    std::unordered_map<Train1_Lukas_POR_v3, std::unordered_set<string>, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> dependentInvariant;
-    std::unordered_map<Train1_Lukas_POR_v3, std::unordered_set<string>, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> dependentGuard;
-    std::unordered_map<Train1_Lukas_POR_v3, immer::map<string, boost::any>, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> guardCache;
-    std::unordered_map<Train1_Lukas_POR_v3, Train1_Lukas_POR_v3, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> parents;
-    std::unordered_map<Train1_Lukas_POR_v3, string, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> stateAccessedVia;
-    if(isCaching) {
-        invariantDependency.insert({"point_positionning", {"_check_inv_3", "_check_inv_1", "_check_inv_4"}});
-        invariantDependency.insert({"route_reservation", {"_check_inv_2", "_check_inv_6", "_check_inv_10", "_check_inv_7", "_check_inv_4", "_check_inv_8", "_check_inv_12", "_check_inv_9", "_check_inv_11"}});
-        invariantDependency.insert({"FRONT_MOVE_1", {"_check_inv_6", "_check_inv_10", "_check_inv_5", "_check_inv_12", "_check_inv_9"}});
-        invariantDependency.insert({"BACK_MOVE_1", {"_check_inv_2", "_check_inv_6", "_check_inv_10", "_check_inv_7", "_check_inv_4", "_check_inv_5", "_check_inv_8", "_check_inv_12", "_check_inv_9"}});
-        invariantDependency.insert({"FRONT_MOVE_2", {"_check_inv_10", "_check_inv_5", "_check_inv_12", "_check_inv_9"}});
-        invariantDependency.insert({"route_formation", {"_check_inv_2", "_check_inv_4", "_check_inv_12", "_check_inv_11"}});
-        invariantDependency.insert({"route_freeing", {"_check_inv_2", "_check_inv_7", "_check_inv_4", "_check_inv_12", "_check_inv_11"}});
-        invariantDependency.insert({"BACK_MOVE_2", {"_check_inv_2", "_check_inv_6", "_check_inv_10", "_check_inv_7", "_check_inv_4", "_check_inv_5", "_check_inv_8", "_check_inv_12", "_check_inv_9"}});
-        guardDependency.insert({"point_positionning", {"_tr_route_formation", "_tr_BACK_MOVE_1", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"route_reservation", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"FRONT_MOVE_1", {"_tr_FRONT_MOVE_1", "_tr_BACK_MOVE_1", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"BACK_MOVE_1", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"FRONT_MOVE_2", {"_tr_FRONT_MOVE_1", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"route_formation", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_point_positionning"}});
-        guardDependency.insert({"route_freeing", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"BACK_MOVE_2", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        dependentInvariant.insert({machine, std::unordered_set<string>()});
-    }
-    Train1_Lukas_POR_v3 counterExampleState;
-
-    while(!collection.empty() && !stopThreads) {
-        Train1_Lukas_POR_v3 state = next(collection, mutex, type);
-
-        std::unordered_set<Train1_Lukas_POR_v3, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> nextStates = generateNextStates(guardMutex, state, isCaching, invariantDependency, dependentInvariant, guardDependency, dependentGuard, guardCache, parents, stateAccessedVia, transitions);
-        for(auto nextState : nextStates) {
-            if(states.find(nextState) == states.end()) {
-                numberStates += 1;
-                states.insert(nextState);
-                collection.push_back(nextState);
-                if(numberStates % 50000 == 0) {
-                    cout << "VISITED STATES: " << numberStates << "\n";
-                    cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
-                    cout << "-------------------" << "\n";
+        void printResult() {
+            if(deadlockDetected || invariantViolatedBool) {
+                if(deadlockDetected) {
+                    cout << "DEADLOCK DETECTED" << "\n";
+                } else {
+                    cout << "INVARIANT VIOLATED" << "\n";
                 }
-            }
-        }
-
-        if(!checkInvariants(guardMutex, state, isCaching, dependentInvariant)) {
-            invariantViolated = true;
-            stopThreads = true;
-            counterExampleState = state;
-        }
 
-        if(nextStates.empty()) {
-            deadlockDetected = true;
-            stopThreads = true;
-            counterExampleState = state;
-        }
+                cout << "COUNTER EXAMPLE TRACE: " << "\n";
 
-    }
-    printResult(numberStates, transitions, deadlockDetected, invariantViolated, counterExampleState, parents, stateAccessedVia);
-}
-
-static void modelCheckMultiThreaded(Train1_Lukas_POR_v3::Type type, int threads, bool isCaching) {
-    std::mutex mutex;
-    std::mutex waitMutex;
-    std::mutex guardMutex;
-    std::condition_variable waitCV;
-
-    Train1_Lukas_POR_v3 machine = Train1_Lukas_POR_v3();
-
-
-    std::atomic<bool> invariantViolated;
-    invariantViolated = false;
-    std::atomic<bool> deadlockDetected;
-    deadlockDetected = false;
-    std::atomic<bool> stopThreads;
-    stopThreads = false;
-
-    std::unordered_set<Train1_Lukas_POR_v3, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> states = std::unordered_set<Train1_Lukas_POR_v3, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual>();
-    states.insert(machine);
-    std::atomic<int> numberStates;
-    numberStates = 1;
-
-    std::list<Train1_Lukas_POR_v3> collection = std::list<Train1_Lukas_POR_v3>();
-    collection.push_back(machine);
-
-    std::atomic<int> transitions;
-    transitions = 0;
-
-    std::atomic<int> possibleQueueChanges;
-    possibleQueueChanges = 0;
-
-    std::atomic<bool> waitFlag;
-    waitFlag = true;
-
-    std::unordered_map<string, std::unordered_set<string>> invariantDependency;
-    std::unordered_map<string, std::unordered_set<string>> guardDependency;
-    std::unordered_map<Train1_Lukas_POR_v3, std::unordered_set<string>, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> dependentInvariant;
-    std::unordered_map<Train1_Lukas_POR_v3, std::unordered_set<string>, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> dependentGuard;
-    std::unordered_map<Train1_Lukas_POR_v3, immer::map<string, boost::any>, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> guardCache;
-    std::unordered_map<Train1_Lukas_POR_v3, Train1_Lukas_POR_v3, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> parents;
-    std::unordered_map<Train1_Lukas_POR_v3, string, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> stateAccessedVia;
-    if(isCaching) {
-        invariantDependency.insert({"point_positionning", {"_check_inv_3", "_check_inv_1", "_check_inv_4"}});
-        invariantDependency.insert({"route_reservation", {"_check_inv_2", "_check_inv_6", "_check_inv_10", "_check_inv_7", "_check_inv_4", "_check_inv_8", "_check_inv_12", "_check_inv_9", "_check_inv_11"}});
-        invariantDependency.insert({"FRONT_MOVE_1", {"_check_inv_6", "_check_inv_10", "_check_inv_5", "_check_inv_12", "_check_inv_9"}});
-        invariantDependency.insert({"BACK_MOVE_1", {"_check_inv_2", "_check_inv_6", "_check_inv_10", "_check_inv_7", "_check_inv_4", "_check_inv_5", "_check_inv_8", "_check_inv_12", "_check_inv_9"}});
-        invariantDependency.insert({"FRONT_MOVE_2", {"_check_inv_10", "_check_inv_5", "_check_inv_12", "_check_inv_9"}});
-        invariantDependency.insert({"route_formation", {"_check_inv_2", "_check_inv_4", "_check_inv_12", "_check_inv_11"}});
-        invariantDependency.insert({"route_freeing", {"_check_inv_2", "_check_inv_7", "_check_inv_4", "_check_inv_12", "_check_inv_11"}});
-        invariantDependency.insert({"BACK_MOVE_2", {"_check_inv_2", "_check_inv_6", "_check_inv_10", "_check_inv_7", "_check_inv_4", "_check_inv_5", "_check_inv_8", "_check_inv_12", "_check_inv_9"}});
-        guardDependency.insert({"point_positionning", {"_tr_route_formation", "_tr_BACK_MOVE_1", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"route_reservation", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"FRONT_MOVE_1", {"_tr_FRONT_MOVE_1", "_tr_BACK_MOVE_1", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"BACK_MOVE_1", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"FRONT_MOVE_2", {"_tr_FRONT_MOVE_1", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"route_formation", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_point_positionning"}});
-        guardDependency.insert({"route_freeing", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"BACK_MOVE_2", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        dependentInvariant.insert({machine, std::unordered_set<string>()});
-    }
-    Train1_Lukas_POR_v3 counterExampleState;
-
-    boost::asio::thread_pool workers(threads);
-
-    while(!collection.empty() && !stopThreads) {
-        possibleQueueChanges += 1;
-        Train1_Lukas_POR_v3 state = next(collection, mutex, type);
-        std::packaged_task<void()> task([&, state] {
-            std::unordered_set<Train1_Lukas_POR_v3, Train1_Lukas_POR_v3::Hash, Train1_Lukas_POR_v3::HashEqual> nextStates = generateNextStates(guardMutex, state, isCaching, invariantDependency, dependentInvariant, guardDependency, dependentGuard, guardCache, parents, stateAccessedVia, transitions);
-
-
-            for(auto nextState : nextStates) {
-                {
-                    std::unique_lock<std::mutex> lock(mutex);
-                    if(states.find(nextState) == states.end()) {
-                        numberStates += 1;
-                        states.insert(nextState);
-                        collection.push_back(nextState);
-                        if(numberStates % 50000 == 0) {
-                            cout << "VISITED STATES: " << numberStates << "\n";
-                            cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
-                            cout << "-------------------" << "\n";
-                        }
-                    }
-                }
-            }
-
-            {
-                std::unique_lock<std::mutex> lock(mutex);
-                possibleQueueChanges -= 1;
-                int running = possibleQueueChanges;
-                if (!collection.empty() || running == 0) {
-                    {
-                        std::unique_lock<std::mutex> lock(waitMutex);
-                        waitFlag = false;
-                        waitCV.notify_one();
-                    }
+                std::string trace = "";
+                while(parents.find(counterExampleState) != parents.end()) {
+                    std::stringstream stringStream;
+                    stringStream << counterExampleState;
+                    trace.insert(0, stringStream.str());
+                    trace.insert(0, "\n");
+                    trace.insert(0, counterExampleState.stateAccessedVia);
+                    trace.insert(0, "\n\n");
+                    counterExampleState = parents[counterExampleState];
                 }
+                cout << trace;
+            } else {
+                cout << "MODEL CHECKING SUCCESSFUL" << "\n";
             }
 
-            if(nextStates.empty()) {
-                deadlockDetected = true;
-                stopThreads = true;
-                counterExampleState = state;
-            }
-
-            if(!checkInvariants(guardMutex, state, isCaching, dependentInvariant)) {
-                invariantViolated = true;
-                stopThreads = true;
-                counterExampleState = state;
-            }
-
-
-        });
-        waitFlag = true;
-        boost::asio::post(workers, std::move(task));
-
-        {
-            std::unique_lock<std::mutex> lock(waitMutex);
-            if (collection.empty() && possibleQueueChanges > 0) {
-                waitCV.wait(lock, [&] {
-                    return waitFlag == false;
-                });
-            }
+            cout << "Number of States: " << states.size() << "\n";
+            cout << "Number of Transitions: " << transitions << "\n";
         }
-    }
-    workers.join();
-    printResult(numberStates, transitions, deadlockDetected, invariantViolated, counterExampleState, parents, stateAccessedVia);
-}
+};
 
 int main(int argc, char *argv[]) {
     if(argc != 4) {
@@ -1456,11 +1132,12 @@ int main(int argc, char *argv[]) {
         return - 1;
     }
 
-    if(threads == 1) {
-        modelCheckSingleThreaded(type, isCaching);
-    } else {
-        modelCheckMultiThreaded(type, threads, isCaching);
-    }
+    bool isDebug = true;
+    // TODO
+
+    ModelChecker modelchecker(type, threads, isCaching, isDebug);
+    modelchecker.modelCheck();
+
     return 0;
 }
 
diff --git a/benchmarks/model_checking/C++/Train_1_beebook_deterministic_MC_POR_v2.cpp b/benchmarks/model_checking/C++/Train_1_beebook_deterministic_MC_POR_v2.cpp
index 2b68b61625aca4cdaaf8d890e644c1a356f8b7b3..6c76d2f7205718de514c37e57b0f1cdc578335b8 100644
--- a/benchmarks/model_checking/C++/Train_1_beebook_deterministic_MC_POR_v2.cpp
+++ b/benchmarks/model_checking/C++/Train_1_beebook_deterministic_MC_POR_v2.cpp
@@ -11,6 +11,7 @@
 #include <boost/asio/post.hpp>
 #include <boost/asio/thread_pool.hpp>
 #include <boost/any.hpp>
+#include <boost/optional.hpp>
 #include <btypes_primitives/BUtils.hpp>
 #include <btypes_primitives/StateNotReachableError.hpp>
 #include <btypes_primitives/PreconditionOrAssertionViolation.hpp>
@@ -31,7 +32,6 @@ class Train_1_beebook_deterministic_MC_POR_v2 {
 
         enum Type { BFS, DFS, MIXED };
 
-
         class BLOCKS : public BObject {
             public:
 
@@ -178,6 +178,7 @@ class Train_1_beebook_deterministic_MC_POR_v2 {
                 }
         };
 
+
         struct Hash {
             public:
                 size_t operator()(const Train_1_beebook_deterministic_MC_POR_v2& obj) const {
@@ -214,16 +215,26 @@ class Train_1_beebook_deterministic_MC_POR_v2 {
         BSet<ROUTES > resrt;
         BRelation<BLOCKS, ROUTES > rsrtbl;
 
+        mutable boost::optional<BSet<ROUTES>> _tr_cache_route_reservation;
+        mutable boost::optional<BSet<ROUTES>> _tr_cache_route_freeing;
+        mutable boost::optional<BSet<ROUTES>> _tr_cache_FRONT_MOVE_1;
+        mutable boost::optional<BSet<BLOCKS>> _tr_cache_FRONT_MOVE_2;
+        mutable boost::optional<BSet<BLOCKS>> _tr_cache_BACK_MOVE_1;
+        mutable boost::optional<BSet<BLOCKS>> _tr_cache_BACK_MOVE_2;
+        mutable boost::optional<BSet<ROUTES>> _tr_cache_point_positionning;
+        mutable boost::optional<BSet<ROUTES>> _tr_cache_route_formation;
 
     public:
 
+        std::string stateAccessedVia;
+
         Train_1_beebook_deterministic_MC_POR_v2() {
+            nxt = (BRelation<ROUTES, BRelation<BLOCKS, BLOCKS > >((BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R1)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::L)), (BLOCKS(BLOCKS::A)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::A)), (BLOCKS(BLOCKS::B)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::B)), (BLOCKS(BLOCKS::C)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R2)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::L)), (BLOCKS(BLOCKS::A)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::A)), (BLOCKS(BLOCKS::B)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::B)), (BLOCKS(BLOCKS::D)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::D)), (BLOCKS(BLOCKS::E)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::E)), (BLOCKS(BLOCKS::F)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::F)), (BLOCKS(BLOCKS::G)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R3)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::L)), (BLOCKS(BLOCKS::A)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::A)), (BLOCKS(BLOCKS::B)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::B)), (BLOCKS(BLOCKS::D)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::D)), (BLOCKS(BLOCKS::K)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::K)), (BLOCKS(BLOCKS::J)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::J)), (BLOCKS(BLOCKS::N)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R4)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::M)), (BLOCKS(BLOCKS::H)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::H)), (BLOCKS(BLOCKS::I)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::I)), (BLOCKS(BLOCKS::K)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::K)), (BLOCKS(BLOCKS::F)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::F)), (BLOCKS(BLOCKS::G)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R5)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::M)), (BLOCKS(BLOCKS::H)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::H)), (BLOCKS(BLOCKS::I)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::I)), (BLOCKS(BLOCKS::J)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::J)), (BLOCKS(BLOCKS::N)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R6)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::C)), (BLOCKS(BLOCKS::B)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::B)), (BLOCKS(BLOCKS::A)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::A)), (BLOCKS(BLOCKS::L)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R7)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::G)), (BLOCKS(BLOCKS::F)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::F)), (BLOCKS(BLOCKS::E)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::E)), (BLOCKS(BLOCKS::D)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::D)), (BLOCKS(BLOCKS::B)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::B)), (BLOCKS(BLOCKS::A)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::A)), (BLOCKS(BLOCKS::L)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R8)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::N)), (BLOCKS(BLOCKS::J)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::J)), (BLOCKS(BLOCKS::K)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::K)), (BLOCKS(BLOCKS::D)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::D)), (BLOCKS(BLOCKS::B)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::B)), (BLOCKS(BLOCKS::A)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::A)), (BLOCKS(BLOCKS::L)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R9)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::G)), (BLOCKS(BLOCKS::F)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::F)), (BLOCKS(BLOCKS::K)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::K)), (BLOCKS(BLOCKS::I)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::I)), (BLOCKS(BLOCKS::H)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::H)), (BLOCKS(BLOCKS::M)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R10)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::N)), (BLOCKS(BLOCKS::J)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::J)), (BLOCKS(BLOCKS::I)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::I)), (BLOCKS(BLOCKS::H)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::H)), (BLOCKS(BLOCKS::M))))))))));
             fst = (BRelation<ROUTES, BLOCKS >((BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R1)), (BLOCKS(BLOCKS::L)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R2)), (BLOCKS(BLOCKS::L)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R3)), (BLOCKS(BLOCKS::L)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R4)), (BLOCKS(BLOCKS::M)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R5)), (BLOCKS(BLOCKS::M)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R6)), (BLOCKS(BLOCKS::C)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R7)), (BLOCKS(BLOCKS::G)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R8)), (BLOCKS(BLOCKS::N)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R9)), (BLOCKS(BLOCKS::G)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R10)), (BLOCKS(BLOCKS::N))))));
             lst = (BRelation<ROUTES, BLOCKS >((BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R1)), (BLOCKS(BLOCKS::C)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R2)), (BLOCKS(BLOCKS::G)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R3)), (BLOCKS(BLOCKS::N)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R4)), (BLOCKS(BLOCKS::G)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R5)), (BLOCKS(BLOCKS::N)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R6)), (BLOCKS(BLOCKS::L)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R7)), (BLOCKS(BLOCKS::L)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R8)), (BLOCKS(BLOCKS::L)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R9)), (BLOCKS(BLOCKS::M)))), (BTuple<ROUTES, BLOCKS >((ROUTES(ROUTES::R10)), (BLOCKS(BLOCKS::M))))));
-            nxt = (BRelation<ROUTES, BRelation<BLOCKS, BLOCKS > >((BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R1)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::L)), (BLOCKS(BLOCKS::A)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::A)), (BLOCKS(BLOCKS::B)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::B)), (BLOCKS(BLOCKS::C)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R2)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::L)), (BLOCKS(BLOCKS::A)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::A)), (BLOCKS(BLOCKS::B)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::B)), (BLOCKS(BLOCKS::D)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::D)), (BLOCKS(BLOCKS::E)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::E)), (BLOCKS(BLOCKS::F)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::F)), (BLOCKS(BLOCKS::G)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R3)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::L)), (BLOCKS(BLOCKS::A)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::A)), (BLOCKS(BLOCKS::B)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::B)), (BLOCKS(BLOCKS::D)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::D)), (BLOCKS(BLOCKS::K)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::K)), (BLOCKS(BLOCKS::J)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::J)), (BLOCKS(BLOCKS::N)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R4)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::M)), (BLOCKS(BLOCKS::H)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::H)), (BLOCKS(BLOCKS::I)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::I)), (BLOCKS(BLOCKS::K)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::K)), (BLOCKS(BLOCKS::F)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::F)), (BLOCKS(BLOCKS::G)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R5)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::M)), (BLOCKS(BLOCKS::H)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::H)), (BLOCKS(BLOCKS::I)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::I)), (BLOCKS(BLOCKS::J)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::J)), (BLOCKS(BLOCKS::N)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R6)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::C)), (BLOCKS(BLOCKS::B)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::B)), (BLOCKS(BLOCKS::A)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::A)), (BLOCKS(BLOCKS::L)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R7)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::G)), (BLOCKS(BLOCKS::F)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::F)), (BLOCKS(BLOCKS::E)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::E)), (BLOCKS(BLOCKS::D)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::D)), (BLOCKS(BLOCKS::B)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::B)), (BLOCKS(BLOCKS::A)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::A)), (BLOCKS(BLOCKS::L)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R8)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::N)), (BLOCKS(BLOCKS::J)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::J)), (BLOCKS(BLOCKS::K)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::K)), (BLOCKS(BLOCKS::D)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::D)), (BLOCKS(BLOCKS::B)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::B)), (BLOCKS(BLOCKS::A)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::A)), (BLOCKS(BLOCKS::L)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R9)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::G)), (BLOCKS(BLOCKS::F)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::F)), (BLOCKS(BLOCKS::K)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::K)), (BLOCKS(BLOCKS::I)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::I)), (BLOCKS(BLOCKS::H)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::H)), (BLOCKS(BLOCKS::M)))))))), (BTuple<ROUTES, BRelation<BLOCKS, BLOCKS > >((ROUTES(ROUTES::R10)), (BRelation<BLOCKS, BLOCKS >((BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::N)), (BLOCKS(BLOCKS::J)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::J)), (BLOCKS(BLOCKS::I)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::I)), (BLOCKS(BLOCKS::H)))), (BTuple<BLOCKS, BLOCKS >((BLOCKS(BLOCKS::H)), (BLOCKS(BLOCKS::M))))))))));
             BRelation<BLOCKS, ROUTES > _ic_set_0 = BRelation<BLOCKS, ROUTES >();
-            for(BLOCKS _ic_b_1 : _BLOCKS) {
-                for(ROUTES _ic_r_1 : _ROUTES) {
+            for(const BLOCKS& _ic_b_1 : _BLOCKS) {
+                for(const ROUTES& _ic_r_1 : _ROUTES) {
                     if(((BBoolean(nxt.domain().elementOf(_ic_r_1).booleanValue() && (BBoolean(nxt.functionCall(_ic_r_1).domain().elementOf(_ic_b_1).booleanValue() || nxt.functionCall(_ic_r_1).range().elementOf(_ic_b_1).booleanValue())).booleanValue()))).booleanValue()) {
                         _ic_set_0 = _ic_set_0._union(BRelation<BLOCKS, ROUTES >((BTuple<BLOCKS, ROUTES >(_ic_b_1, _ic_r_1))));
                     }
@@ -373,90 +384,122 @@ class Train_1_beebook_deterministic_MC_POR_v2 {
         }
 
 
-        BSet<ROUTES> _tr_route_reservation() const {
-            BSet<ROUTES> _ic_set_1 = BSet<ROUTES>();
-            for(ROUTES _ic_r_1 : _ROUTES.difference(resrt)) {
-                if(((BBoolean(rtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1))).intersect(resbl).equal((BSet<BLOCKS >())).booleanValue() && (BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range())).booleanValue()))).booleanValue()) {
-                    _ic_set_1 = _ic_set_1._union(BSet<ROUTES>(_ic_r_1));
-                }
+        BSet<ROUTES> _tr_route_reservation(bool isCaching) const {
+            if (this->_tr_cache_route_reservation == boost::none){
+                BSet<ROUTES> _ic_set_1 = BSet<ROUTES>();
+                for(const ROUTES& _ic_r_1 : _ROUTES.difference(resrt)) {
+                    if(((BBoolean(rtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1))).intersect(resbl).equal((BSet<BLOCKS >())).booleanValue() && (BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range())).booleanValue()))).booleanValue()) {
+                        _ic_set_1 = _ic_set_1._union(BSet<ROUTES>(_ic_r_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_route_reservation = _ic_set_1;
+                else return _ic_set_1;
             }
-            return _ic_set_1;
+            return this->_tr_cache_route_reservation.get();
         }
 
-        BSet<ROUTES> _tr_route_freeing() const {
-            BSet<ROUTES> _ic_set_2 = BSet<ROUTES>();
-            for(ROUTES _ic_r_1 : resrt.difference(rsrtbl.range())) {
-                _ic_set_2 = _ic_set_2._union(BSet<ROUTES>(_ic_r_1));
+        BSet<ROUTES> _tr_route_freeing(bool isCaching) const {
+            if (this->_tr_cache_route_freeing == boost::none){
+                BSet<ROUTES> _ic_set_2 = BSet<ROUTES>();
+                for(const ROUTES& _ic_r_1 : resrt.difference(rsrtbl.range())) {
+                    _ic_set_2 = _ic_set_2._union(BSet<ROUTES>(_ic_r_1));
 
+                }
+                if (isCaching) this->_tr_cache_route_freeing = _ic_set_2;
+                else return _ic_set_2;
             }
-            return _ic_set_2;
+            return this->_tr_cache_route_freeing.get();
         }
 
-        BSet<ROUTES> _tr_FRONT_MOVE_1() const {
-            BSet<ROUTES> _ic_set_3 = BSet<ROUTES>();
-            for(ROUTES _ic_r_1 : frm) {
-                if(((BBoolean((BBoolean(resbl.difference(OCC).elementOf(fst.functionCall(_ic_r_1)).booleanValue() && _ic_r_1.equal(rsrtbl.functionCall(fst.functionCall(_ic_r_1))).booleanValue())).booleanValue() && (BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range())).booleanValue()))).booleanValue()) {
-                    _ic_set_3 = _ic_set_3._union(BSet<ROUTES>(_ic_r_1));
-                }
+        BSet<ROUTES> _tr_FRONT_MOVE_1(bool isCaching) const {
+            if (this->_tr_cache_FRONT_MOVE_1 == boost::none){
+                BSet<ROUTES> _ic_set_3 = BSet<ROUTES>();
+                for(const ROUTES& _ic_r_1 : frm) {
+                    if(((BBoolean((BBoolean(resbl.difference(OCC).elementOf(fst.functionCall(_ic_r_1)).booleanValue() && _ic_r_1.equal(rsrtbl.functionCall(fst.functionCall(_ic_r_1))).booleanValue())).booleanValue() && (BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range())).booleanValue()))).booleanValue()) {
+                        _ic_set_3 = _ic_set_3._union(BSet<ROUTES>(_ic_r_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_FRONT_MOVE_1 = _ic_set_3;
+                else return _ic_set_3;
             }
-            return _ic_set_3;
+            return this->_tr_cache_FRONT_MOVE_1.get();
         }
 
-        BSet<BLOCKS> _tr_FRONT_MOVE_2() const {
-            BSet<BLOCKS> _ic_set_4 = BSet<BLOCKS>();
-            for(BLOCKS _ic_b_1 : OCC.intersect(TRK.domain())) {
-                if((OCC.notElementOf(TRK.functionCall(_ic_b_1))).booleanValue()) {
-                    _ic_set_4 = _ic_set_4._union(BSet<BLOCKS>(_ic_b_1));
-                }
+        BSet<BLOCKS> _tr_FRONT_MOVE_2(bool isCaching) const {
+            if (this->_tr_cache_FRONT_MOVE_2 == boost::none){
+                BSet<BLOCKS> _ic_set_4 = BSet<BLOCKS>();
+                for(const BLOCKS& _ic_b_1 : OCC.intersect(TRK.domain())) {
+                    if((OCC.notElementOf(TRK.functionCall(_ic_b_1))).booleanValue()) {
+                        _ic_set_4 = _ic_set_4._union(BSet<BLOCKS>(_ic_b_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_FRONT_MOVE_2 = _ic_set_4;
+                else return _ic_set_4;
             }
-            return _ic_set_4;
+            return this->_tr_cache_FRONT_MOVE_2.get();
         }
 
-        BSet<BLOCKS> _tr_BACK_MOVE_1() const {
-            BSet<BLOCKS> _ic_set_5 = BSet<BLOCKS>();
-            for(BLOCKS _ic_b_1 : LBT.difference(TRK.domain())) {
-                if(((BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range()))).booleanValue()) {
-                    _ic_set_5 = _ic_set_5._union(BSet<BLOCKS>(_ic_b_1));
-                }
+        BSet<BLOCKS> _tr_BACK_MOVE_1(bool isCaching) const {
+            if (this->_tr_cache_BACK_MOVE_1 == boost::none){
+                BSet<BLOCKS> _ic_set_5 = BSet<BLOCKS>();
+                for(const BLOCKS& _ic_b_1 : LBT.difference(TRK.domain())) {
+                    if(((BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range()))).booleanValue()) {
+                        _ic_set_5 = _ic_set_5._union(BSet<BLOCKS>(_ic_b_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_BACK_MOVE_1 = _ic_set_5;
+                else return _ic_set_5;
             }
-            return _ic_set_5;
+            return this->_tr_cache_BACK_MOVE_1.get();
         }
 
-        BSet<BLOCKS> _tr_BACK_MOVE_2() const {
-            BSet<BLOCKS> _ic_set_6 = BSet<BLOCKS>();
-            for(BLOCKS _ic_b_1 : LBT.intersect(TRK.domain())) {
-                if(((BBoolean(OCC.elementOf(TRK.functionCall(_ic_b_1)).booleanValue() && (BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range())).booleanValue()))).booleanValue()) {
-                    _ic_set_6 = _ic_set_6._union(BSet<BLOCKS>(_ic_b_1));
-                }
+        BSet<BLOCKS> _tr_BACK_MOVE_2(bool isCaching) const {
+            if (this->_tr_cache_BACK_MOVE_2 == boost::none){
+                BSet<BLOCKS> _ic_set_6 = BSet<BLOCKS>();
+                for(const BLOCKS& _ic_b_1 : LBT.intersect(TRK.domain())) {
+                    if(((BBoolean(OCC.elementOf(TRK.functionCall(_ic_b_1)).booleanValue() && (BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range())).booleanValue()))).booleanValue()) {
+                        _ic_set_6 = _ic_set_6._union(BSet<BLOCKS>(_ic_b_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_BACK_MOVE_2 = _ic_set_6;
+                else return _ic_set_6;
             }
-            return _ic_set_6;
+            return this->_tr_cache_BACK_MOVE_2.get();
         }
 
-        BSet<ROUTES> _tr_point_positionning() const {
-            BSet<ROUTES> _ic_set_7 = BSet<ROUTES>();
-            for(ROUTES _ic_r_1 : resrt.difference(frm)) {
-                if(((BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range()))).booleanValue()) {
-                    _ic_set_7 = _ic_set_7._union(BSet<ROUTES>(_ic_r_1));
-                }
+        BSet<ROUTES> _tr_point_positionning(bool isCaching) const {
+            if (this->_tr_cache_point_positionning == boost::none){
+                BSet<ROUTES> _ic_set_7 = BSet<ROUTES>();
+                for(const ROUTES& _ic_r_1 : resrt.difference(frm)) {
+                    if(((BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range()))).booleanValue()) {
+                        _ic_set_7 = _ic_set_7._union(BSet<ROUTES>(_ic_r_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_point_positionning = _ic_set_7;
+                else return _ic_set_7;
             }
-            return _ic_set_7;
+            return this->_tr_cache_point_positionning.get();
         }
 
-        BSet<ROUTES> _tr_route_formation() const {
-            BSet<ROUTES> _ic_set_8 = BSet<ROUTES>();
-            for(ROUTES _ic_r_1 : resrt.difference(frm)) {
-                if(((BBoolean(nxt.functionCall(_ic_r_1).domainRestriction(rsrtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1)))).equal(TRK.domainRestriction(rsrtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1))))).booleanValue() && (BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range())).booleanValue()))).booleanValue()) {
-                    _ic_set_8 = _ic_set_8._union(BSet<ROUTES>(_ic_r_1));
-                }
+        BSet<ROUTES> _tr_route_formation(bool isCaching) const {
+            if (this->_tr_cache_route_formation == boost::none){
+                BSet<ROUTES> _ic_set_8 = BSet<ROUTES>();
+                for(const ROUTES& _ic_r_1 : resrt.difference(frm)) {
+                    if(((BBoolean(nxt.functionCall(_ic_r_1).domainRestriction(rsrtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1)))).equal(TRK.domainRestriction(rsrtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1))))).booleanValue() && (BSet<ROUTES >()).equal(resrt.difference(rsrtbl.range())).booleanValue()))).booleanValue()) {
+                        _ic_set_8 = _ic_set_8._union(BSet<ROUTES>(_ic_r_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_route_formation = _ic_set_8;
+                else return _ic_set_8;
             }
-            return _ic_set_8;
+            return this->_tr_cache_route_formation.get();
         }
 
         bool _check_inv_1() const {
@@ -465,8 +508,8 @@ class Train_1_beebook_deterministic_MC_POR_v2 {
 
         bool _check_inv_2() const {
             BBoolean _ic_boolean_9 = BBoolean(true);
-            for(ROUTES _ic_r_1 : resrt.difference(frm)) {
-                for(BSet<ROUTES > _ic_a_1 : {(BSet<ROUTES >(_ic_r_1))}) {
+            for(const ROUTES& _ic_r_1 : resrt.difference(frm)) {
+                for(const BSet<ROUTES >& _ic_a_1 : {(BSet<ROUTES >(_ic_r_1))}) {
                     if(!(rtbl.rangeRestriction(_ic_a_1).equal(rsrtbl.rangeRestriction(_ic_a_1))).booleanValue()) {
                         _ic_boolean_9 = BBoolean(false);
                         break;
@@ -481,10 +524,10 @@ class Train_1_beebook_deterministic_MC_POR_v2 {
 
         bool _check_inv_3() const {
             BBoolean _ic_boolean_11 = BBoolean(true);
-            for(BLOCKS _ic_x_1 : TRK.domain()) {
-                for(BLOCKS _ic_y_1 : TRK.relationImage((BSet<BLOCKS >(_ic_x_1)))) {
+            for(const BLOCKS& _ic_x_1 : TRK.domain()) {
+                for(const BLOCKS& _ic_y_1 : TRK.relationImage((BSet<BLOCKS >(_ic_x_1)))) {
                     BBoolean _ic_boolean_10 = BBoolean(false);
-                    for(ROUTES _ic_r_1 : _ROUTES) {
+                    for(const ROUTES& _ic_r_1 : _ROUTES) {
                         if((nxt.functionCall(_ic_r_1).elementOf((BTuple<BLOCKS, BLOCKS >(_ic_x_1, _ic_y_1)))).booleanValue()) {
                             _ic_boolean_10 = BBoolean(true);
                             break;
@@ -505,8 +548,8 @@ class Train_1_beebook_deterministic_MC_POR_v2 {
 
         bool _check_inv_4() const {
             BBoolean _ic_boolean_12 = BBoolean(true);
-            for(ROUTES _ic_r_1 : frm) {
-                for(BSet<BLOCKS > _ic_a_1 : {rsrtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1)))}) {
+            for(const ROUTES& _ic_r_1 : frm) {
+                for(const BSet<BLOCKS >& _ic_a_1 : {rsrtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1)))}) {
                     if(!(nxt.functionCall(_ic_r_1).domainRestriction(_ic_a_1).equal(TRK.domainRestriction(_ic_a_1))).booleanValue()) {
                         _ic_boolean_12 = BBoolean(false);
                         break;
@@ -525,10 +568,10 @@ class Train_1_beebook_deterministic_MC_POR_v2 {
 
         bool _check_inv_6() const {
             BBoolean _ic_boolean_13 = BBoolean(true);
-            for(BLOCKS _ic_a_1 : rsrtbl.domain()) {
-                for(BLOCKS _ic_b_1 : LBT) {
-                    for(ROUTES _ic_c_1 : {rsrtbl.functionCall(_ic_b_1)}) {
-                        for(BRelation<BLOCKS, BLOCKS > _ic_d_1 : {nxt.functionCall(_ic_c_1)}) {
+            for(const BLOCKS& _ic_a_1 : rsrtbl.domain()) {
+                for(const BLOCKS& _ic_b_1 : LBT) {
+                    for(const ROUTES& _ic_c_1 : {rsrtbl.functionCall(_ic_b_1)}) {
+                        for(const BRelation<BLOCKS, BLOCKS >& _ic_d_1 : {nxt.functionCall(_ic_c_1)}) {
                             if(!((BBoolean(!(BBoolean(_ic_d_1.range().elementOf(_ic_b_1).booleanValue() && _ic_a_1.equal(_ic_d_1.inverse().functionCall(_ic_b_1)).booleanValue())).booleanValue() || rsrtbl.functionCall(_ic_a_1).unequal(_ic_c_1).booleanValue()))).booleanValue()) {
                                 _ic_boolean_13 = BBoolean(false);
                                 break;
@@ -558,10 +601,10 @@ class Train_1_beebook_deterministic_MC_POR_v2 {
 
         bool _check_inv_10() const {
             BBoolean _ic_boolean_14 = BBoolean(true);
-            for(ROUTES _ic_r_1 : _ROUTES) {
-                for(BRelation<BLOCKS, BLOCKS > _ic_a_1 : {nxt.functionCall(_ic_r_1)}) {
-                    for(BSet<BLOCKS > _ic_b_1 : {rsrtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1)))}) {
-                        for(BSet<BLOCKS > _ic_c_1 : {_ic_b_1.difference(OCC)}) {
+            for(const ROUTES& _ic_r_1 : _ROUTES) {
+                for(const BRelation<BLOCKS, BLOCKS >& _ic_a_1 : {nxt.functionCall(_ic_r_1)}) {
+                    for(const BSet<BLOCKS >& _ic_b_1 : {rsrtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1)))}) {
+                        for(const BSet<BLOCKS >& _ic_c_1 : {_ic_b_1.difference(OCC)}) {
                             if(!((BBoolean((BBoolean(_ic_a_1.relationImage(rtbl.inverse().relationImage((BSet<ROUTES >(_ic_r_1))).difference(_ic_b_1)).intersect(_ic_c_1).equal((BSet<BLOCKS >())).booleanValue() && _ic_a_1.relationImage(_ic_b_1).subset(_ic_b_1).booleanValue())).booleanValue() && _ic_a_1.relationImage(_ic_c_1).subset(_ic_c_1).booleanValue()))).booleanValue()) {
                                 _ic_boolean_14 = BBoolean(false);
                                 break;
@@ -586,8 +629,31 @@ class Train_1_beebook_deterministic_MC_POR_v2 {
             return (rsrtbl.relationImage(OCC).subset(frm)).booleanValue();
         }
 
-        Train_1_beebook_deterministic_MC_POR_v2 _copy() const {
-            return Train_1_beebook_deterministic_MC_POR_v2(fst, lst, nxt, rtbl, LBT, TRK, frm, OCC, resbl, resrt, rsrtbl);
+        static constexpr unsigned int strHash(const char *s, int off = 0) {
+            return !s[off] ? 5381 : (strHash(s, off+1)*33) ^ s[off];
+        }
+
+        Train_1_beebook_deterministic_MC_POR_v2 _copy(unordered_set<string> toInvalidate) const {
+            static const char* allTransitions[] = {"_tr_route_reservation", "_tr_route_freeing", "_tr_FRONT_MOVE_1", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_1", "_tr_BACK_MOVE_2", "_tr_point_positionning", "_tr_route_formation"};
+
+            Train_1_beebook_deterministic_MC_POR_v2 result = Train_1_beebook_deterministic_MC_POR_v2(fst, lst, nxt, rtbl, LBT, TRK, frm, OCC, resbl, resrt, rsrtbl);
+
+            for (const auto &item : allTransitions) {
+                if(toInvalidate.find(item) == toInvalidate.end()) {
+                    switch(strHash(item)) {
+                        case strHash("_tr_route_reservation"): result._tr_cache_route_reservation = this->_tr_cache_route_reservation; break;
+                        case strHash("_tr_route_freeing"): result._tr_cache_route_freeing = this->_tr_cache_route_freeing; break;
+                        case strHash("_tr_FRONT_MOVE_1"): result._tr_cache_FRONT_MOVE_1 = this->_tr_cache_FRONT_MOVE_1; break;
+                        case strHash("_tr_FRONT_MOVE_2"): result._tr_cache_FRONT_MOVE_2 = this->_tr_cache_FRONT_MOVE_2; break;
+                        case strHash("_tr_BACK_MOVE_1"): result._tr_cache_BACK_MOVE_1 = this->_tr_cache_BACK_MOVE_1; break;
+                        case strHash("_tr_BACK_MOVE_2"): result._tr_cache_BACK_MOVE_2 = this->_tr_cache_BACK_MOVE_2; break;
+                        case strHash("_tr_point_positionning"): result._tr_cache_point_positionning = this->_tr_cache_point_positionning; break;
+                        case strHash("_tr_route_formation"): result._tr_cache_route_formation = this->_tr_cache_route_formation; break;
+                        default: cout << "Transition " << item << " not found!";
+                    }
+                }
+            }
+            return result;
         }
 
         friend bool operator ==(const Train_1_beebook_deterministic_MC_POR_v2& o1, const Train_1_beebook_deterministic_MC_POR_v2& o2) {
@@ -641,797 +707,407 @@ class Train_1_beebook_deterministic_MC_POR_v2 {
 };
 
 
-static std::unordered_set<Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> generateNextStates(std::mutex& guardMutex, const Train_1_beebook_deterministic_MC_POR_v2& state, bool isCaching, std::unordered_map<string, std::unordered_set<string>>& invariantDependency, std::unordered_map<Train_1_beebook_deterministic_MC_POR_v2, std::unordered_set<string>, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual>& dependentInvariant, std::unordered_map<string, std::unordered_set<string>>& guardDependency, std::unordered_map<Train_1_beebook_deterministic_MC_POR_v2, std::unordered_set<string>, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual>& dependentGuard, std::unordered_map<Train_1_beebook_deterministic_MC_POR_v2, immer::map<string, boost::any>, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual>& guardCache, std::unordered_map<Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual>& parents, std::unordered_map<Train_1_beebook_deterministic_MC_POR_v2, string, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual>& stateAccessedVia, std::atomic<int>& transitions) {
-    std::unordered_set<Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> result = std::unordered_set<Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual>();
-    if(isCaching) {
-        immer::map<string, boost::any> parentsGuard;
-        std::unordered_set<string> dependentGuardsOfState;
-        bool parentsExist = false;
-        bool dependentGuardsExist = false;
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            parentsExist = (parents.find(state) != parents.end());
-            dependentGuardsExist = (dependentGuard.find(state) != dependentGuard.end());
-            if(parentsExist) {
-                parentsGuard = guardCache[parents[state]];
+class ModelChecker {
+    private:
+        Train_1_beebook_deterministic_MC_POR_v2::Type type;
+        int threads;
+        bool isCaching;
+        bool isDebug;
+
+        std::list<Train_1_beebook_deterministic_MC_POR_v2> unvisitedStates;
+        std::unordered_set<Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> states;
+        std::atomic<int> transitions;
+        std::mutex mutex;
+        std::mutex waitMutex;
+        std::mutex guardMutex;
+        std::condition_variable waitCV;
+
+        std::atomic<bool> invariantViolatedBool;
+        std::atomic<bool> deadlockDetected;
+        Train_1_beebook_deterministic_MC_POR_v2 counterExampleState;
+
+        std::unordered_map<string, std::unordered_set<string>> invariantDependency;
+        std::unordered_map<string, std::unordered_set<string>> guardDependency;
+        std::unordered_map<Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> parents;
+
+    public:
+        ModelChecker() {}
+
+        ModelChecker(Train_1_beebook_deterministic_MC_POR_v2::Type type, int threads, bool isCaching, bool isDebug) {
+            this->type = type;
+            this->threads = threads;
+            this->isCaching = isCaching;
+            this->isDebug = isDebug;
+            this->invariantViolatedBool = false;
+            this->deadlockDetected = false;
+            this->transitions = 0;
+        }
+
+        void modelCheck() {
+            if (isDebug) {
+                cout << "Starting Modelchecking, STRATEGY=" << type << ", THREADS=" << threads << ", CACHING=" << isCaching << "\n";
             }
-            if(dependentGuardsExist) {
-                dependentGuardsOfState = dependentGuard[state];
+
+            if (threads <= 1) {
+                modelCheckSingleThreaded();
+            } else {
+                boost::asio::thread_pool workers(threads); // threads indicates the number of workers (without the coordinator)
+                modelCheckMultiThreaded(workers);
             }
         }
-        immer::map<string, boost::any> newCache = parentsGuard;
-        boost::any cachedValue;
-        bool dependentGuardsBoolean = true;
-        BSet<Train_1_beebook_deterministic_MC_POR_v2::ROUTES> _trid_1;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_route_reservation"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_route_reservation") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_1 = state._tr_route_reservation();
-        } else {
-            _trid_1 = boost::any_cast<BSet<Train_1_beebook_deterministic_MC_POR_v2::ROUTES>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_route_reservation", _trid_1);
-        for(const Train_1_beebook_deterministic_MC_POR_v2::ROUTES& param : _trid_1) {
-            Train_1_beebook_deterministic_MC_POR_v2::ROUTES _tmp_1 = param;
-
-            Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy();
-            copiedState.route_reservation(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["route_reservation"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["route_reservation"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "route_reservation"});
-                }
+
+        void modelCheckSingleThreaded() {
+            Train_1_beebook_deterministic_MC_POR_v2 machine = Train_1_beebook_deterministic_MC_POR_v2();
+            states.insert(machine);
+            unvisitedStates.push_back(machine);
+
+            if (isCaching) {
+                initCache(machine);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train_1_beebook_deterministic_MC_POR_v2::ROUTES> _trid_2;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_route_freeing"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_route_freeing") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_2 = state._tr_route_freeing();
-        } else {
-            _trid_2 = boost::any_cast<BSet<Train_1_beebook_deterministic_MC_POR_v2::ROUTES>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_route_freeing", _trid_2);
-        for(const Train_1_beebook_deterministic_MC_POR_v2::ROUTES& param : _trid_2) {
-            Train_1_beebook_deterministic_MC_POR_v2::ROUTES _tmp_1 = param;
-
-            Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy();
-            copiedState.route_freeing(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["route_freeing"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["route_freeing"]});
+
+            while(!unvisitedStates.empty()) {
+                Train_1_beebook_deterministic_MC_POR_v2 state = next();
+
+                std::unordered_set<Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> nextStates = generateNextStates(state);
+                transitions += nextStates.size();
+
+                for(auto& nextState : nextStates) {
+                    if(states.find(nextState) == states.end()) {
+                        states.insert(nextState);
+                        parents.insert({nextState, state});
+                        unvisitedStates.push_back(nextState);
+                        if(states.size() % 50000 == 0) {
+                            cout << "VISITED STATES: " << states.size() << "\n";
+                            cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
+                            cout << "-------------------" << "\n";
+                        }
+                    }
                 }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+
+                if(invariantViolated(state)) {
+                    invariantViolatedBool = true;
+                    counterExampleState = state;
+                    break;
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "route_freeing"});
+
+                if(nextStates.empty()) {
+                    deadlockDetected = true;
+                    counterExampleState = state;
+                    break;
                 }
+
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train_1_beebook_deterministic_MC_POR_v2::ROUTES> _trid_3;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_FRONT_MOVE_1"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_FRONT_MOVE_1") != dependentGuardsOfState.end());
+            printResult();
         }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_3 = state._tr_FRONT_MOVE_1();
-        } else {
-            _trid_3 = boost::any_cast<BSet<Train_1_beebook_deterministic_MC_POR_v2::ROUTES>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_FRONT_MOVE_1", _trid_3);
-        for(const Train_1_beebook_deterministic_MC_POR_v2::ROUTES& param : _trid_3) {
-            Train_1_beebook_deterministic_MC_POR_v2::ROUTES _tmp_1 = param;
-
-            Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy();
-            copiedState.FRONT_MOVE_1(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["FRONT_MOVE_1"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["FRONT_MOVE_1"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "FRONT_MOVE_1"});
-                }
+
+        void modelCheckMultiThreaded(boost::asio::thread_pool& workers) {
+            Train_1_beebook_deterministic_MC_POR_v2 machine = Train_1_beebook_deterministic_MC_POR_v2();
+            states.insert(machine);
+            unvisitedStates.push_back(machine);
+
+            std::atomic<bool> stopThreads;
+            stopThreads = false;
+            std::atomic<int> possibleQueueChanges;
+            possibleQueueChanges = 0;
+
+            if(isCaching) {
+                initCache(machine);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train_1_beebook_deterministic_MC_POR_v2::BLOCKS> _trid_4;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_FRONT_MOVE_2"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_FRONT_MOVE_2") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_4 = state._tr_FRONT_MOVE_2();
-        } else {
-            _trid_4 = boost::any_cast<BSet<Train_1_beebook_deterministic_MC_POR_v2::BLOCKS>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_FRONT_MOVE_2", _trid_4);
-        for(const Train_1_beebook_deterministic_MC_POR_v2::BLOCKS& param : _trid_4) {
-            Train_1_beebook_deterministic_MC_POR_v2::BLOCKS _tmp_1 = param;
-
-            Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy();
-            copiedState.FRONT_MOVE_2(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["FRONT_MOVE_2"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["FRONT_MOVE_2"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "FRONT_MOVE_2"});
+
+            std::atomic<bool> waitFlag;
+            waitFlag = true;
+
+            while(!unvisitedStates.empty() && !stopThreads) {
+                possibleQueueChanges += 1;
+                Train_1_beebook_deterministic_MC_POR_v2 state = next();
+                std::packaged_task<void()> task([&, state] {
+                    std::unordered_set<Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> nextStates = generateNextStates(state);
+                    transitions += nextStates.size();
+
+                    for(auto& nextState : nextStates) {
+                        {
+                            std::unique_lock<std::mutex> lock(mutex);
+                            if(states.find(nextState) == states.end()) {
+                                states.insert(nextState);
+                                parents.insert({nextState, state});
+                                unvisitedStates.push_back(nextState); // TODO: sync ?
+                                if(isDebug && states.size() % 50000 == 0) {
+                                    cout << "VISITED STATES: " << states.size() << "\n";
+                                    cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
+                                    cout << "-------------------" << "\n";
+                                }
+                            }
+                        }
+                    }
+
+                    {
+                        std::unique_lock<std::mutex> lock(mutex);
+                        possibleQueueChanges -= 1;
+                        int running = possibleQueueChanges;
+                        if (!unvisitedStates.empty() || running == 0) {
+                            {
+                                std::unique_lock<std::mutex> lock(waitMutex);
+                                waitFlag = false;
+                                waitCV.notify_one();
+                            }
+                        }
+                    }
+
+                    if(invariantViolated(state)) {
+                        invariantViolatedBool = true;
+                        counterExampleState = state;
+                        stopThreads = true;
+                    }
+
+                    if(nextStates.empty()) {
+                        deadlockDetected = true;
+                        counterExampleState = state;
+                        stopThreads = true;
+                    }
+
+                });
+
+                waitFlag = true;
+                boost::asio::post(workers, std::move(task));
+
+                {
+                    std::unique_lock<std::mutex> lock(waitMutex);
+                    while (unvisitedStates.empty() && possibleQueueChanges > 0) {
+                        waitCV.wait(lock, [&] {
+                            return waitFlag == false;
+                        });
+                    }
                 }
             }
-            result.insert(copiedState);
-            transitions += 1;
+            workers.join();
+            printResult();
+        }
+
+        void initCache(Train_1_beebook_deterministic_MC_POR_v2& machine) {
+            invariantDependency.insert({"point_positionning", {"_check_inv_3", "_check_inv_1", "_check_inv_4"}});
+            invariantDependency.insert({"route_reservation", {"_check_inv_2", "_check_inv_6", "_check_inv_10", "_check_inv_7", "_check_inv_4", "_check_inv_8", "_check_inv_12", "_check_inv_9", "_check_inv_11"}});
+            invariantDependency.insert({"FRONT_MOVE_1", {"_check_inv_6", "_check_inv_10", "_check_inv_5", "_check_inv_12", "_check_inv_9"}});
+            invariantDependency.insert({"BACK_MOVE_1", {"_check_inv_2", "_check_inv_6", "_check_inv_10", "_check_inv_7", "_check_inv_4", "_check_inv_5", "_check_inv_8", "_check_inv_12", "_check_inv_9"}});
+            invariantDependency.insert({"FRONT_MOVE_2", {"_check_inv_10", "_check_inv_5", "_check_inv_12", "_check_inv_9"}});
+            invariantDependency.insert({"route_formation", {"_check_inv_2", "_check_inv_4", "_check_inv_12", "_check_inv_11"}});
+            invariantDependency.insert({"route_freeing", {"_check_inv_2", "_check_inv_7", "_check_inv_4", "_check_inv_12", "_check_inv_11"}});
+            invariantDependency.insert({"BACK_MOVE_2", {"_check_inv_2", "_check_inv_6", "_check_inv_10", "_check_inv_7", "_check_inv_4", "_check_inv_5", "_check_inv_8", "_check_inv_12", "_check_inv_9"}});
+            invariantDependency.insert({"", {}});
+            guardDependency.insert({"point_positionning", {"_tr_route_formation", "_tr_BACK_MOVE_1", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
+            guardDependency.insert({"route_reservation", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_BACK_MOVE_2"}});
+            guardDependency.insert({"FRONT_MOVE_1", {"_tr_FRONT_MOVE_1", "_tr_BACK_MOVE_1", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
+            guardDependency.insert({"BACK_MOVE_1", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
+            guardDependency.insert({"FRONT_MOVE_2", {"_tr_FRONT_MOVE_1", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
+            guardDependency.insert({"route_formation", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_point_positionning"}});
+            guardDependency.insert({"route_freeing", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_BACK_MOVE_2"}});
+            guardDependency.insert({"BACK_MOVE_2", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
         }
-        BSet<Train_1_beebook_deterministic_MC_POR_v2::BLOCKS> _trid_5;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_BACK_MOVE_1"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_BACK_MOVE_1") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_5 = state._tr_BACK_MOVE_1();
-        } else {
-            _trid_5 = boost::any_cast<BSet<Train_1_beebook_deterministic_MC_POR_v2::BLOCKS>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_BACK_MOVE_1", _trid_5);
-        for(const Train_1_beebook_deterministic_MC_POR_v2::BLOCKS& param : _trid_5) {
-            Train_1_beebook_deterministic_MC_POR_v2::BLOCKS _tmp_1 = param;
-
-            Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy();
-            copiedState.BACK_MOVE_1(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["BACK_MOVE_1"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["BACK_MOVE_1"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "BACK_MOVE_1"});
+
+
+    private:
+        Train_1_beebook_deterministic_MC_POR_v2 next() {
+            std::unique_lock<std::mutex> lock(mutex);
+            switch(type) {
+                case Train_1_beebook_deterministic_MC_POR_v2::BFS: {
+                    Train_1_beebook_deterministic_MC_POR_v2 state = unvisitedStates.front();
+                    unvisitedStates.pop_front();
+                    return state;
+                }
+                case Train_1_beebook_deterministic_MC_POR_v2::DFS: {
+                    Train_1_beebook_deterministic_MC_POR_v2 state = unvisitedStates.back();
+                    unvisitedStates.pop_back();
+                    return state;
+                }
+                case Train_1_beebook_deterministic_MC_POR_v2::MIXED: {
+                    if(unvisitedStates.size() % 2 == 0) {
+                        Train_1_beebook_deterministic_MC_POR_v2 state = unvisitedStates.front();
+                        unvisitedStates.pop_front();
+                        return state;
+                    } else {
+                        Train_1_beebook_deterministic_MC_POR_v2 state = unvisitedStates.back();
+                        unvisitedStates.pop_back();
+                        return state;
+                    }
                 }
             }
-            result.insert(copiedState);
-            transitions += 1;
         }
-        BSet<Train_1_beebook_deterministic_MC_POR_v2::BLOCKS> _trid_6;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_BACK_MOVE_2"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_BACK_MOVE_2") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_6 = state._tr_BACK_MOVE_2();
-        } else {
-            _trid_6 = boost::any_cast<BSet<Train_1_beebook_deterministic_MC_POR_v2::BLOCKS>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_BACK_MOVE_2", _trid_6);
-        for(const Train_1_beebook_deterministic_MC_POR_v2::BLOCKS& param : _trid_6) {
-            Train_1_beebook_deterministic_MC_POR_v2::BLOCKS _tmp_1 = param;
-
-            Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy();
-            copiedState.BACK_MOVE_2(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["BACK_MOVE_2"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["BACK_MOVE_2"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "BACK_MOVE_2"});
-                }
+
+        std::unordered_set<Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> generateNextStates(const Train_1_beebook_deterministic_MC_POR_v2& state) {
+            std::unordered_set<Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> result = std::unordered_set<Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual>();
+            BSet<Train_1_beebook_deterministic_MC_POR_v2::ROUTES> _trid_1 = state._tr_route_reservation(isCaching);
+            for(const Train_1_beebook_deterministic_MC_POR_v2::ROUTES& param : _trid_1) {
+                Train_1_beebook_deterministic_MC_POR_v2::ROUTES _tmp_1 = param;
+
+                Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy(guardDependency["route_reservation"]);
+                copiedState.route_reservation(_tmp_1);
+                copiedState.stateAccessedVia = "route_reservation";
+                result.insert(copiedState);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train_1_beebook_deterministic_MC_POR_v2::ROUTES> _trid_7;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_point_positionning"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_point_positionning") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_7 = state._tr_point_positionning();
-        } else {
-            _trid_7 = boost::any_cast<BSet<Train_1_beebook_deterministic_MC_POR_v2::ROUTES>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_point_positionning", _trid_7);
-        for(const Train_1_beebook_deterministic_MC_POR_v2::ROUTES& param : _trid_7) {
-            Train_1_beebook_deterministic_MC_POR_v2::ROUTES _tmp_1 = param;
-
-            Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy();
-            copiedState.point_positionning(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["point_positionning"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["point_positionning"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "point_positionning"});
-                }
+            BSet<Train_1_beebook_deterministic_MC_POR_v2::ROUTES> _trid_2 = state._tr_route_freeing(isCaching);
+            for(const Train_1_beebook_deterministic_MC_POR_v2::ROUTES& param : _trid_2) {
+                Train_1_beebook_deterministic_MC_POR_v2::ROUTES _tmp_1 = param;
+
+                Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy(guardDependency["route_freeing"]);
+                copiedState.route_freeing(_tmp_1);
+                copiedState.stateAccessedVia = "route_freeing";
+                result.insert(copiedState);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train_1_beebook_deterministic_MC_POR_v2::ROUTES> _trid_8;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_route_formation"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_route_formation") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_8 = state._tr_route_formation();
-        } else {
-            _trid_8 = boost::any_cast<BSet<Train_1_beebook_deterministic_MC_POR_v2::ROUTES>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_route_formation", _trid_8);
-        for(const Train_1_beebook_deterministic_MC_POR_v2::ROUTES& param : _trid_8) {
-            Train_1_beebook_deterministic_MC_POR_v2::ROUTES _tmp_1 = param;
-
-            Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy();
-            copiedState.route_formation(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["route_formation"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["route_formation"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "route_formation"});
-                }
+            BSet<Train_1_beebook_deterministic_MC_POR_v2::ROUTES> _trid_3 = state._tr_FRONT_MOVE_1(isCaching);
+            for(const Train_1_beebook_deterministic_MC_POR_v2::ROUTES& param : _trid_3) {
+                Train_1_beebook_deterministic_MC_POR_v2::ROUTES _tmp_1 = param;
+
+                Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy(guardDependency["FRONT_MOVE_1"]);
+                copiedState.FRONT_MOVE_1(_tmp_1);
+                copiedState.stateAccessedVia = "FRONT_MOVE_1";
+                result.insert(copiedState);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            guardCache.insert({state, newCache});
-        }
-    } else {
-        BSet<Train_1_beebook_deterministic_MC_POR_v2::ROUTES> _trid_1 = state._tr_route_reservation();
-        for(const Train_1_beebook_deterministic_MC_POR_v2::ROUTES& param : _trid_1) {
-            Train_1_beebook_deterministic_MC_POR_v2::ROUTES _tmp_1 = param;
-
-            Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy();
-            copiedState.route_reservation(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "route_reservation"});
-                }
+            BSet<Train_1_beebook_deterministic_MC_POR_v2::BLOCKS> _trid_4 = state._tr_FRONT_MOVE_2(isCaching);
+            for(const Train_1_beebook_deterministic_MC_POR_v2::BLOCKS& param : _trid_4) {
+                Train_1_beebook_deterministic_MC_POR_v2::BLOCKS _tmp_1 = param;
+
+                Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy(guardDependency["FRONT_MOVE_2"]);
+                copiedState.FRONT_MOVE_2(_tmp_1);
+                copiedState.stateAccessedVia = "FRONT_MOVE_2";
+                result.insert(copiedState);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train_1_beebook_deterministic_MC_POR_v2::ROUTES> _trid_2 = state._tr_route_freeing();
-        for(const Train_1_beebook_deterministic_MC_POR_v2::ROUTES& param : _trid_2) {
-            Train_1_beebook_deterministic_MC_POR_v2::ROUTES _tmp_1 = param;
-
-            Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy();
-            copiedState.route_freeing(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "route_freeing"});
-                }
+            BSet<Train_1_beebook_deterministic_MC_POR_v2::BLOCKS> _trid_5 = state._tr_BACK_MOVE_1(isCaching);
+            for(const Train_1_beebook_deterministic_MC_POR_v2::BLOCKS& param : _trid_5) {
+                Train_1_beebook_deterministic_MC_POR_v2::BLOCKS _tmp_1 = param;
+
+                Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy(guardDependency["BACK_MOVE_1"]);
+                copiedState.BACK_MOVE_1(_tmp_1);
+                copiedState.stateAccessedVia = "BACK_MOVE_1";
+                result.insert(copiedState);
+            }
+            BSet<Train_1_beebook_deterministic_MC_POR_v2::BLOCKS> _trid_6 = state._tr_BACK_MOVE_2(isCaching);
+            for(const Train_1_beebook_deterministic_MC_POR_v2::BLOCKS& param : _trid_6) {
+                Train_1_beebook_deterministic_MC_POR_v2::BLOCKS _tmp_1 = param;
+
+                Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy(guardDependency["BACK_MOVE_2"]);
+                copiedState.BACK_MOVE_2(_tmp_1);
+                copiedState.stateAccessedVia = "BACK_MOVE_2";
+                result.insert(copiedState);
+            }
+            BSet<Train_1_beebook_deterministic_MC_POR_v2::ROUTES> _trid_7 = state._tr_point_positionning(isCaching);
+            for(const Train_1_beebook_deterministic_MC_POR_v2::ROUTES& param : _trid_7) {
+                Train_1_beebook_deterministic_MC_POR_v2::ROUTES _tmp_1 = param;
+
+                Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy(guardDependency["point_positionning"]);
+                copiedState.point_positionning(_tmp_1);
+                copiedState.stateAccessedVia = "point_positionning";
+                result.insert(copiedState);
             }
-            result.insert(copiedState);
-            transitions += 1;
+            BSet<Train_1_beebook_deterministic_MC_POR_v2::ROUTES> _trid_8 = state._tr_route_formation(isCaching);
+            for(const Train_1_beebook_deterministic_MC_POR_v2::ROUTES& param : _trid_8) {
+                Train_1_beebook_deterministic_MC_POR_v2::ROUTES _tmp_1 = param;
+
+                Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy(guardDependency["route_formation"]);
+                copiedState.route_formation(_tmp_1);
+                copiedState.stateAccessedVia = "route_formation";
+                result.insert(copiedState);
+            }
+
+            return result;
         }
-        BSet<Train_1_beebook_deterministic_MC_POR_v2::ROUTES> _trid_3 = state._tr_FRONT_MOVE_1();
-        for(const Train_1_beebook_deterministic_MC_POR_v2::ROUTES& param : _trid_3) {
-            Train_1_beebook_deterministic_MC_POR_v2::ROUTES _tmp_1 = param;
-
-            Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy();
-            copiedState.FRONT_MOVE_1(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+
+        bool invariantViolated(const Train_1_beebook_deterministic_MC_POR_v2& state) {
+            if(isCaching) {
+                std::unordered_set<string> dependentInvariantsOfState = invariantDependency[state.stateAccessedVia];
+                if(dependentInvariantsOfState.find("_check_inv_1") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_1()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "FRONT_MOVE_1"});
+                if(dependentInvariantsOfState.find("_check_inv_2") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_2()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train_1_beebook_deterministic_MC_POR_v2::BLOCKS> _trid_4 = state._tr_FRONT_MOVE_2();
-        for(const Train_1_beebook_deterministic_MC_POR_v2::BLOCKS& param : _trid_4) {
-            Train_1_beebook_deterministic_MC_POR_v2::BLOCKS _tmp_1 = param;
-
-            Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy();
-            copiedState.FRONT_MOVE_2(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_3") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_3()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "FRONT_MOVE_2"});
+                if(dependentInvariantsOfState.find("_check_inv_4") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_4()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train_1_beebook_deterministic_MC_POR_v2::BLOCKS> _trid_5 = state._tr_BACK_MOVE_1();
-        for(const Train_1_beebook_deterministic_MC_POR_v2::BLOCKS& param : _trid_5) {
-            Train_1_beebook_deterministic_MC_POR_v2::BLOCKS _tmp_1 = param;
-
-            Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy();
-            copiedState.BACK_MOVE_1(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_5") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_5()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "BACK_MOVE_1"});
+                if(dependentInvariantsOfState.find("_check_inv_6") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_6()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train_1_beebook_deterministic_MC_POR_v2::BLOCKS> _trid_6 = state._tr_BACK_MOVE_2();
-        for(const Train_1_beebook_deterministic_MC_POR_v2::BLOCKS& param : _trid_6) {
-            Train_1_beebook_deterministic_MC_POR_v2::BLOCKS _tmp_1 = param;
-
-            Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy();
-            copiedState.BACK_MOVE_2(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_7") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_7()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "BACK_MOVE_2"});
+                if(dependentInvariantsOfState.find("_check_inv_8") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_8()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train_1_beebook_deterministic_MC_POR_v2::ROUTES> _trid_7 = state._tr_point_positionning();
-        for(const Train_1_beebook_deterministic_MC_POR_v2::ROUTES& param : _trid_7) {
-            Train_1_beebook_deterministic_MC_POR_v2::ROUTES _tmp_1 = param;
-
-            Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy();
-            copiedState.point_positionning(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_9") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_9()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "point_positionning"});
+                if(dependentInvariantsOfState.find("_check_inv_10") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_10()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<Train_1_beebook_deterministic_MC_POR_v2::ROUTES> _trid_8 = state._tr_route_formation();
-        for(const Train_1_beebook_deterministic_MC_POR_v2::ROUTES& param : _trid_8) {
-            Train_1_beebook_deterministic_MC_POR_v2::ROUTES _tmp_1 = param;
-
-            Train_1_beebook_deterministic_MC_POR_v2 copiedState = state._copy();
-            copiedState.route_formation(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_11") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_11()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "route_formation"});
+                if(dependentInvariantsOfState.find("_check_inv_12") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_12()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-
-    }
-    return result;
-}
-
-static void printResult(int states, int transitions, bool deadlockDetected, bool invariantViolated, Train_1_beebook_deterministic_MC_POR_v2& counterExampleState, std::unordered_map<Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual>& parents, std::unordered_map<Train_1_beebook_deterministic_MC_POR_v2, string, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual>& stateAccessedVia) {
-    if(deadlockDetected || invariantViolated) {
-        if(deadlockDetected) {
-            cout << "DEADLOCK DETECTED" << "\n";
-        }
-        if(invariantViolated) {
-            cout << "INVARIANT VIOLATED" << "\n";
-        }
-        cout << "COUNTER EXAMPLE TRACE: " << "\n";
-
-        Train_1_beebook_deterministic_MC_POR_v2 currentState = counterExampleState;
-        std::string trace = "";
-        while(parents.find(currentState) != parents.end()) {
-            std::stringstream stringStream;
-            stringStream << currentState;
-            trace.insert(0, stringStream.str());
-            trace.insert(0, "\n");
-            trace.insert(0, stateAccessedVia[currentState]);
-            trace.insert(0, "\n\n");
-            currentState = parents[currentState];
-        }
-        cout << trace;
-    }
-
-    if(!deadlockDetected && !invariantViolated) {
-        cout << "MODEL CHECKING SUCCESSFUL" << "\n";
-    }
-    cout << "Number of States: " << states << "\n";
-    cout << "Number of Transitions: " << transitions << "\n";
-}
-
-static bool checkInvariants(std::mutex& guardMutex, const Train_1_beebook_deterministic_MC_POR_v2& state, bool isCaching, std::unordered_map<Train_1_beebook_deterministic_MC_POR_v2, std::unordered_set<string>, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual>& dependentInvariant) {
-    if(isCaching) {
-        std::unordered_set<string> dependentInvariantsOfState;
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            dependentInvariantsOfState = dependentInvariant[state];
-        }
-        if(dependentInvariantsOfState.find("_check_inv_1") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_1()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_2") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_2()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_3") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_3()) {
                 return false;
             }
+            return !(state._check_inv_1() && state._check_inv_2() && state._check_inv_3() && state._check_inv_4() && state._check_inv_5() && state._check_inv_6() && state._check_inv_7() && state._check_inv_8() && state._check_inv_9() && state._check_inv_10() && state._check_inv_11() && state._check_inv_12());
         }
-        if(dependentInvariantsOfState.find("_check_inv_4") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_4()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_5") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_5()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_6") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_6()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_7") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_7()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_8") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_8()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_9") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_9()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_10") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_10()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_11") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_11()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_12") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_12()) {
-                return false;
-            }
-        }
-        return true;
-    }
-    return !(!state._check_inv_1() || !state._check_inv_2() || !state._check_inv_3() || !state._check_inv_4() || !state._check_inv_5() || !state._check_inv_6() || !state._check_inv_7() || !state._check_inv_8() || !state._check_inv_9() || !state._check_inv_10() || !state._check_inv_11() || !state._check_inv_12());
-}
 
-static Train_1_beebook_deterministic_MC_POR_v2 next(std::list<Train_1_beebook_deterministic_MC_POR_v2>& collection, std::mutex& mutex, Train_1_beebook_deterministic_MC_POR_v2::Type type) {
-    std::unique_lock<std::mutex> lock(mutex);
-    switch(type) {
-        case Train_1_beebook_deterministic_MC_POR_v2::BFS: {
-            Train_1_beebook_deterministic_MC_POR_v2 state = collection.front();
-            collection.pop_front();
-            return state;
-        }
-        case Train_1_beebook_deterministic_MC_POR_v2::DFS: {
-            Train_1_beebook_deterministic_MC_POR_v2 state = collection.back();
-            collection.pop_back();
-            return state;
-        }
-        case Train_1_beebook_deterministic_MC_POR_v2::MIXED: {
-            if(collection.size() % 2 == 0) {
-                Train_1_beebook_deterministic_MC_POR_v2 state = collection.front();
-                collection.pop_front();
-                return state;
-            } else {
-                Train_1_beebook_deterministic_MC_POR_v2 state = collection.back();
-                collection.pop_back();
-                return state;
-            }
-        }
-    };
-}
 
-static void modelCheckSingleThreaded(Train_1_beebook_deterministic_MC_POR_v2::Type type, bool isCaching) {
-    std::mutex mutex;
-    std::mutex guardMutex;
-
-    Train_1_beebook_deterministic_MC_POR_v2 machine = Train_1_beebook_deterministic_MC_POR_v2();
-
-    std::atomic<bool> invariantViolated;
-    invariantViolated = false;
-    std::atomic<bool> deadlockDetected;
-    deadlockDetected = false;
-    std::atomic<bool> stopThreads;
-    stopThreads = false;
-
-    std::unordered_set<Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> states = std::unordered_set<Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual>();
-    states.insert(machine);
-    std::atomic<int> numberStates;
-    numberStates = 1;
-
-    std::list<Train_1_beebook_deterministic_MC_POR_v2> collection = std::list<Train_1_beebook_deterministic_MC_POR_v2>();
-    collection.push_back(machine);
-
-    std::atomic<int> transitions;
-    transitions = 0;
-
-    std::unordered_map<string, std::unordered_set<string>> invariantDependency;
-    std::unordered_map<string, std::unordered_set<string>> guardDependency;
-    std::unordered_map<Train_1_beebook_deterministic_MC_POR_v2, std::unordered_set<string>, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> dependentInvariant;
-    std::unordered_map<Train_1_beebook_deterministic_MC_POR_v2, std::unordered_set<string>, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> dependentGuard;
-    std::unordered_map<Train_1_beebook_deterministic_MC_POR_v2, immer::map<string, boost::any>, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> guardCache;
-    std::unordered_map<Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> parents;
-    std::unordered_map<Train_1_beebook_deterministic_MC_POR_v2, string, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> stateAccessedVia;
-    if(isCaching) {
-        invariantDependency.insert({"point_positionning", {"_check_inv_3", "_check_inv_1", "_check_inv_4"}});
-        invariantDependency.insert({"route_reservation", {"_check_inv_2", "_check_inv_6", "_check_inv_10", "_check_inv_7", "_check_inv_4", "_check_inv_8", "_check_inv_12", "_check_inv_9", "_check_inv_11"}});
-        invariantDependency.insert({"FRONT_MOVE_1", {"_check_inv_6", "_check_inv_10", "_check_inv_5", "_check_inv_12", "_check_inv_9"}});
-        invariantDependency.insert({"BACK_MOVE_1", {"_check_inv_2", "_check_inv_6", "_check_inv_10", "_check_inv_7", "_check_inv_4", "_check_inv_5", "_check_inv_8", "_check_inv_12", "_check_inv_9"}});
-        invariantDependency.insert({"FRONT_MOVE_2", {"_check_inv_10", "_check_inv_5", "_check_inv_12", "_check_inv_9"}});
-        invariantDependency.insert({"route_formation", {"_check_inv_2", "_check_inv_4", "_check_inv_12", "_check_inv_11"}});
-        invariantDependency.insert({"route_freeing", {"_check_inv_2", "_check_inv_7", "_check_inv_4", "_check_inv_12", "_check_inv_11"}});
-        invariantDependency.insert({"BACK_MOVE_2", {"_check_inv_2", "_check_inv_6", "_check_inv_10", "_check_inv_7", "_check_inv_4", "_check_inv_5", "_check_inv_8", "_check_inv_12", "_check_inv_9"}});
-        guardDependency.insert({"point_positionning", {"_tr_route_formation", "_tr_BACK_MOVE_1", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"route_reservation", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"FRONT_MOVE_1", {"_tr_FRONT_MOVE_1", "_tr_BACK_MOVE_1", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"BACK_MOVE_1", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"FRONT_MOVE_2", {"_tr_FRONT_MOVE_1", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"route_formation", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_point_positionning"}});
-        guardDependency.insert({"route_freeing", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"BACK_MOVE_2", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        dependentInvariant.insert({machine, std::unordered_set<string>()});
-    }
-    Train_1_beebook_deterministic_MC_POR_v2 counterExampleState;
-
-    while(!collection.empty() && !stopThreads) {
-        Train_1_beebook_deterministic_MC_POR_v2 state = next(collection, mutex, type);
-
-        std::unordered_set<Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> nextStates = generateNextStates(guardMutex, state, isCaching, invariantDependency, dependentInvariant, guardDependency, dependentGuard, guardCache, parents, stateAccessedVia, transitions);
-        for(auto nextState : nextStates) {
-            if(states.find(nextState) == states.end()) {
-                numberStates += 1;
-                states.insert(nextState);
-                collection.push_back(nextState);
-                if(numberStates % 50000 == 0) {
-                    cout << "VISITED STATES: " << numberStates << "\n";
-                    cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
-                    cout << "-------------------" << "\n";
+        void printResult() {
+            if(deadlockDetected || invariantViolatedBool) {
+                if(deadlockDetected) {
+                    cout << "DEADLOCK DETECTED" << "\n";
+                } else {
+                    cout << "INVARIANT VIOLATED" << "\n";
                 }
-            }
-        }
-
-        if(!checkInvariants(guardMutex, state, isCaching, dependentInvariant)) {
-            invariantViolated = true;
-            stopThreads = true;
-            counterExampleState = state;
-        }
 
-        if(nextStates.empty()) {
-            deadlockDetected = true;
-            stopThreads = true;
-            counterExampleState = state;
-        }
+                cout << "COUNTER EXAMPLE TRACE: " << "\n";
 
-    }
-    printResult(numberStates, transitions, deadlockDetected, invariantViolated, counterExampleState, parents, stateAccessedVia);
-}
-
-static void modelCheckMultiThreaded(Train_1_beebook_deterministic_MC_POR_v2::Type type, int threads, bool isCaching) {
-    std::mutex mutex;
-    std::mutex waitMutex;
-    std::mutex guardMutex;
-    std::condition_variable waitCV;
-
-    Train_1_beebook_deterministic_MC_POR_v2 machine = Train_1_beebook_deterministic_MC_POR_v2();
-
-
-    std::atomic<bool> invariantViolated;
-    invariantViolated = false;
-    std::atomic<bool> deadlockDetected;
-    deadlockDetected = false;
-    std::atomic<bool> stopThreads;
-    stopThreads = false;
-
-    std::unordered_set<Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> states = std::unordered_set<Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual>();
-    states.insert(machine);
-    std::atomic<int> numberStates;
-    numberStates = 1;
-
-    std::list<Train_1_beebook_deterministic_MC_POR_v2> collection = std::list<Train_1_beebook_deterministic_MC_POR_v2>();
-    collection.push_back(machine);
-
-    std::atomic<int> transitions;
-    transitions = 0;
-
-    std::atomic<int> possibleQueueChanges;
-    possibleQueueChanges = 0;
-
-    std::atomic<bool> waitFlag;
-    waitFlag = true;
-
-    std::unordered_map<string, std::unordered_set<string>> invariantDependency;
-    std::unordered_map<string, std::unordered_set<string>> guardDependency;
-    std::unordered_map<Train_1_beebook_deterministic_MC_POR_v2, std::unordered_set<string>, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> dependentInvariant;
-    std::unordered_map<Train_1_beebook_deterministic_MC_POR_v2, std::unordered_set<string>, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> dependentGuard;
-    std::unordered_map<Train_1_beebook_deterministic_MC_POR_v2, immer::map<string, boost::any>, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> guardCache;
-    std::unordered_map<Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> parents;
-    std::unordered_map<Train_1_beebook_deterministic_MC_POR_v2, string, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> stateAccessedVia;
-    if(isCaching) {
-        invariantDependency.insert({"point_positionning", {"_check_inv_3", "_check_inv_1", "_check_inv_4"}});
-        invariantDependency.insert({"route_reservation", {"_check_inv_2", "_check_inv_6", "_check_inv_10", "_check_inv_7", "_check_inv_4", "_check_inv_8", "_check_inv_12", "_check_inv_9", "_check_inv_11"}});
-        invariantDependency.insert({"FRONT_MOVE_1", {"_check_inv_6", "_check_inv_10", "_check_inv_5", "_check_inv_12", "_check_inv_9"}});
-        invariantDependency.insert({"BACK_MOVE_1", {"_check_inv_2", "_check_inv_6", "_check_inv_10", "_check_inv_7", "_check_inv_4", "_check_inv_5", "_check_inv_8", "_check_inv_12", "_check_inv_9"}});
-        invariantDependency.insert({"FRONT_MOVE_2", {"_check_inv_10", "_check_inv_5", "_check_inv_12", "_check_inv_9"}});
-        invariantDependency.insert({"route_formation", {"_check_inv_2", "_check_inv_4", "_check_inv_12", "_check_inv_11"}});
-        invariantDependency.insert({"route_freeing", {"_check_inv_2", "_check_inv_7", "_check_inv_4", "_check_inv_12", "_check_inv_11"}});
-        invariantDependency.insert({"BACK_MOVE_2", {"_check_inv_2", "_check_inv_6", "_check_inv_10", "_check_inv_7", "_check_inv_4", "_check_inv_5", "_check_inv_8", "_check_inv_12", "_check_inv_9"}});
-        guardDependency.insert({"point_positionning", {"_tr_route_formation", "_tr_BACK_MOVE_1", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"route_reservation", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"FRONT_MOVE_1", {"_tr_FRONT_MOVE_1", "_tr_BACK_MOVE_1", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"BACK_MOVE_1", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"FRONT_MOVE_2", {"_tr_FRONT_MOVE_1", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"route_formation", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_point_positionning"}});
-        guardDependency.insert({"route_freeing", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_BACK_MOVE_2"}});
-        guardDependency.insert({"BACK_MOVE_2", {"_tr_route_formation", "_tr_FRONT_MOVE_1", "_tr_route_reservation", "_tr_route_freeing", "_tr_BACK_MOVE_1", "_tr_point_positionning", "_tr_FRONT_MOVE_2", "_tr_BACK_MOVE_2"}});
-        dependentInvariant.insert({machine, std::unordered_set<string>()});
-    }
-    Train_1_beebook_deterministic_MC_POR_v2 counterExampleState;
-
-    boost::asio::thread_pool workers(threads);
-
-    while(!collection.empty() && !stopThreads) {
-        possibleQueueChanges += 1;
-        Train_1_beebook_deterministic_MC_POR_v2 state = next(collection, mutex, type);
-        std::packaged_task<void()> task([&, state] {
-            std::unordered_set<Train_1_beebook_deterministic_MC_POR_v2, Train_1_beebook_deterministic_MC_POR_v2::Hash, Train_1_beebook_deterministic_MC_POR_v2::HashEqual> nextStates = generateNextStates(guardMutex, state, isCaching, invariantDependency, dependentInvariant, guardDependency, dependentGuard, guardCache, parents, stateAccessedVia, transitions);
-
-
-            for(auto nextState : nextStates) {
-                {
-                    std::unique_lock<std::mutex> lock(mutex);
-                    if(states.find(nextState) == states.end()) {
-                        numberStates += 1;
-                        states.insert(nextState);
-                        collection.push_back(nextState);
-                        if(numberStates % 50000 == 0) {
-                            cout << "VISITED STATES: " << numberStates << "\n";
-                            cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
-                            cout << "-------------------" << "\n";
-                        }
-                    }
-                }
-            }
-
-            {
-                std::unique_lock<std::mutex> lock(mutex);
-                possibleQueueChanges -= 1;
-                int running = possibleQueueChanges;
-                if (!collection.empty() || running == 0) {
-                    {
-                        std::unique_lock<std::mutex> lock(waitMutex);
-                        waitFlag = false;
-                        waitCV.notify_one();
-                    }
+                std::string trace = "";
+                while(parents.find(counterExampleState) != parents.end()) {
+                    std::stringstream stringStream;
+                    stringStream << counterExampleState;
+                    trace.insert(0, stringStream.str());
+                    trace.insert(0, "\n");
+                    trace.insert(0, counterExampleState.stateAccessedVia);
+                    trace.insert(0, "\n\n");
+                    counterExampleState = parents[counterExampleState];
                 }
+                cout << trace;
+            } else {
+                cout << "MODEL CHECKING SUCCESSFUL" << "\n";
             }
 
-            if(nextStates.empty()) {
-                deadlockDetected = true;
-                stopThreads = true;
-                counterExampleState = state;
-            }
-
-            if(!checkInvariants(guardMutex, state, isCaching, dependentInvariant)) {
-                invariantViolated = true;
-                stopThreads = true;
-                counterExampleState = state;
-            }
-
-
-        });
-        waitFlag = true;
-        boost::asio::post(workers, std::move(task));
-
-        {
-            std::unique_lock<std::mutex> lock(waitMutex);
-            if (collection.empty() && possibleQueueChanges > 0) {
-                waitCV.wait(lock, [&] {
-                    return waitFlag == false;
-                });
-            }
+            cout << "Number of States: " << states.size() << "\n";
+            cout << "Number of Transitions: " << transitions << "\n";
         }
-    }
-    workers.join();
-    printResult(numberStates, transitions, deadlockDetected, invariantViolated, counterExampleState, parents, stateAccessedVia);
-}
+};
 
 int main(int argc, char *argv[]) {
     if(argc != 4) {
@@ -1480,11 +1156,12 @@ int main(int argc, char *argv[]) {
         return - 1;
     }
 
-    if(threads == 1) {
-        modelCheckSingleThreaded(type, isCaching);
-    } else {
-        modelCheckMultiThreaded(type, threads, isCaching);
-    }
+    bool isDebug = true;
+    // TODO
+
+    ModelChecker modelchecker(type, threads, isCaching, isDebug);
+    modelchecker.modelCheck();
+
     return 0;
 }
 
diff --git a/benchmarks/model_checking/C++/nota_v2.cpp b/benchmarks/model_checking/C++/nota_v2.cpp
index dd6bfc234dc9d56c3535083a75e5aca171a8ba93..a4ebf27e7eb5a666e0adcab48f7cbad2be3479a0 100644
--- a/benchmarks/model_checking/C++/nota_v2.cpp
+++ b/benchmarks/model_checking/C++/nota_v2.cpp
@@ -11,6 +11,7 @@
 #include <boost/asio/post.hpp>
 #include <boost/asio/thread_pool.hpp>
 #include <boost/any.hpp>
+#include <boost/optional.hpp>
 #include <btypes_primitives/BUtils.hpp>
 #include <btypes_primitives/StateNotReachableError.hpp>
 #include <btypes_primitives/PreconditionOrAssertionViolation.hpp>
@@ -420,18 +421,18 @@ class nota_v2 {
                 }
         };
 
-        class _Struct3 : public BStruct {
+        class _Struct1 : public BStruct {
             private:
                 BSet<SID > sid;
-                IN_ERROR_CODES err;
+                RM_ERROR_CODES err;
 
             public:
-                typedef _Struct3 current_type;
+                typedef _Struct1 current_type;
                 typedef void value_type;
                 typedef void left_type;
                 typedef void right_type;
 
-                _Struct3(const BSet<SID >& sid, const IN_ERROR_CODES& err) {
+                _Struct1(const BSet<SID >& sid, const RM_ERROR_CODES& err) {
                     this->sid = sid;
                     this->err = err;
                 }
@@ -440,43 +441,43 @@ class nota_v2 {
                     return this->sid;
                 }
 
-                IN_ERROR_CODES get_err() {
+                RM_ERROR_CODES get_err() {
                     return this->err;
                 }
 
-                _Struct3 override_sid(const BSet<SID >& sid) {
-                    return _Struct3(sid, err);
+                _Struct1 override_sid(const BSet<SID >& sid) {
+                    return _Struct1(sid, err);
                 }
 
-                _Struct3 override_err(const IN_ERROR_CODES& err) {
-                    return _Struct3(sid, err);
+                _Struct1 override_err(const RM_ERROR_CODES& err) {
+                    return _Struct1(sid, err);
                 }
 
-                _Struct3() {
+                _Struct1() {
                 }
 
-                void operator =(const _Struct3& other) {
+                void operator =(const _Struct1& other) {
                     this->sid = other.sid;
                     this->err = other.err;
                 }
 
-                BBoolean equal(const _Struct3& o) const {
+                BBoolean equal(const _Struct1& o) const {
                     return this->sid == o.sid && this->err == o.err;
                 }
 
-                BBoolean unequal(const _Struct3& o) const {
+                BBoolean unequal(const _Struct1& o) const {
                     return this->sid != o.sid || this->err != o.err;
                 }
 
-                friend bool operator ==(const _Struct3& p1, const _Struct3& p2) {
+                friend bool operator ==(const _Struct1& p1, const _Struct1& p2) {
                     return (p1.equal(p2)).booleanValue();
                 }
 
-                friend bool operator !=(const _Struct3& p1, const _Struct3& p2) {
+                friend bool operator !=(const _Struct1& p1, const _Struct1& p2) {
                     return (p1.unequal(p2)).booleanValue();
                 }
 
-                friend std::ostream& operator<<(std::ostream &strm, const _Struct3& e) {
+                friend std::ostream& operator<<(std::ostream &strm, const _Struct1& e) {
                     strm << "(";
                     strm << "sid : ";
                     strm << e.sid;
@@ -494,66 +495,66 @@ class nota_v2 {
                 }
         };
 
-        class _Struct1 : public BStruct {
+        class _Struct5 : public BStruct {
             private:
-                BSet<SID > sid;
-                RM_ERROR_CODES err;
+                BSet<SOCKET > soc;
+                IN_ERROR_CODES err;
 
             public:
-                typedef _Struct1 current_type;
+                typedef _Struct5 current_type;
                 typedef void value_type;
                 typedef void left_type;
                 typedef void right_type;
 
-                _Struct1(const BSet<SID >& sid, const RM_ERROR_CODES& err) {
-                    this->sid = sid;
+                _Struct5(const BSet<SOCKET >& soc, const IN_ERROR_CODES& err) {
+                    this->soc = soc;
                     this->err = err;
                 }
 
-                BSet<SID > get_sid() {
-                    return this->sid;
+                BSet<SOCKET > get_soc() {
+                    return this->soc;
                 }
 
-                RM_ERROR_CODES get_err() {
+                IN_ERROR_CODES get_err() {
                     return this->err;
                 }
 
-                _Struct1 override_sid(const BSet<SID >& sid) {
-                    return _Struct1(sid, err);
+                _Struct5 override_soc(const BSet<SOCKET >& soc) {
+                    return _Struct5(soc, err);
                 }
 
-                _Struct1 override_err(const RM_ERROR_CODES& err) {
-                    return _Struct1(sid, err);
+                _Struct5 override_err(const IN_ERROR_CODES& err) {
+                    return _Struct5(soc, err);
                 }
 
-                _Struct1() {
+                _Struct5() {
                 }
 
-                void operator =(const _Struct1& other) {
-                    this->sid = other.sid;
+                void operator =(const _Struct5& other) {
+                    this->soc = other.soc;
                     this->err = other.err;
                 }
 
-                BBoolean equal(const _Struct1& o) const {
-                    return this->sid == o.sid && this->err == o.err;
+                BBoolean equal(const _Struct5& o) const {
+                    return this->soc == o.soc && this->err == o.err;
                 }
 
-                BBoolean unequal(const _Struct1& o) const {
-                    return this->sid != o.sid || this->err != o.err;
+                BBoolean unequal(const _Struct5& o) const {
+                    return this->soc != o.soc || this->err != o.err;
                 }
 
-                friend bool operator ==(const _Struct1& p1, const _Struct1& p2) {
+                friend bool operator ==(const _Struct5& p1, const _Struct5& p2) {
                     return (p1.equal(p2)).booleanValue();
                 }
 
-                friend bool operator !=(const _Struct1& p1, const _Struct1& p2) {
+                friend bool operator !=(const _Struct5& p1, const _Struct5& p2) {
                     return (p1.unequal(p2)).booleanValue();
                 }
 
-                friend std::ostream& operator<<(std::ostream &strm, const _Struct1& e) {
+                friend std::ostream& operator<<(std::ostream &strm, const _Struct5& e) {
                     strm << "(";
-                    strm << "sid : ";
-                    strm << e.sid;
+                    strm << "soc : ";
+                    strm << e.soc;
                     strm << "err : ";
                     strm << e.err;
                     strm << ")";
@@ -562,72 +563,72 @@ class nota_v2 {
 
                 int hashCode() const {
                     int result = 1;
-                    result = 31 * result + (sid.hashCode() << 1);
+                    result = 31 * result + (soc.hashCode() << 1);
                     result = 31 * result + (err.hashCode() << 1);
                     return result;
                 }
         };
 
-        class _Struct5 : public BStruct {
+        class _Struct3 : public BStruct {
             private:
-                BSet<SOCKET > soc;
+                BSet<SID > sid;
                 IN_ERROR_CODES err;
 
             public:
-                typedef _Struct5 current_type;
+                typedef _Struct3 current_type;
                 typedef void value_type;
                 typedef void left_type;
                 typedef void right_type;
 
-                _Struct5(const BSet<SOCKET >& soc, const IN_ERROR_CODES& err) {
-                    this->soc = soc;
+                _Struct3(const BSet<SID >& sid, const IN_ERROR_CODES& err) {
+                    this->sid = sid;
                     this->err = err;
                 }
 
-                BSet<SOCKET > get_soc() {
-                    return this->soc;
+                BSet<SID > get_sid() {
+                    return this->sid;
                 }
 
                 IN_ERROR_CODES get_err() {
                     return this->err;
                 }
 
-                _Struct5 override_soc(const BSet<SOCKET >& soc) {
-                    return _Struct5(soc, err);
+                _Struct3 override_sid(const BSet<SID >& sid) {
+                    return _Struct3(sid, err);
                 }
 
-                _Struct5 override_err(const IN_ERROR_CODES& err) {
-                    return _Struct5(soc, err);
+                _Struct3 override_err(const IN_ERROR_CODES& err) {
+                    return _Struct3(sid, err);
                 }
 
-                _Struct5() {
+                _Struct3() {
                 }
 
-                void operator =(const _Struct5& other) {
-                    this->soc = other.soc;
+                void operator =(const _Struct3& other) {
+                    this->sid = other.sid;
                     this->err = other.err;
                 }
 
-                BBoolean equal(const _Struct5& o) const {
-                    return this->soc == o.soc && this->err == o.err;
+                BBoolean equal(const _Struct3& o) const {
+                    return this->sid == o.sid && this->err == o.err;
                 }
 
-                BBoolean unequal(const _Struct5& o) const {
-                    return this->soc != o.soc || this->err != o.err;
+                BBoolean unequal(const _Struct3& o) const {
+                    return this->sid != o.sid || this->err != o.err;
                 }
 
-                friend bool operator ==(const _Struct5& p1, const _Struct5& p2) {
+                friend bool operator ==(const _Struct3& p1, const _Struct3& p2) {
                     return (p1.equal(p2)).booleanValue();
                 }
 
-                friend bool operator !=(const _Struct5& p1, const _Struct5& p2) {
+                friend bool operator !=(const _Struct3& p1, const _Struct3& p2) {
                     return (p1.unequal(p2)).booleanValue();
                 }
 
-                friend std::ostream& operator<<(std::ostream &strm, const _Struct5& e) {
+                friend std::ostream& operator<<(std::ostream &strm, const _Struct3& e) {
                     strm << "(";
-                    strm << "soc : ";
-                    strm << e.soc;
+                    strm << "sid : ";
+                    strm << e.sid;
                     strm << "err : ";
                     strm << e.err;
                     strm << ")";
@@ -636,7 +637,7 @@ class nota_v2 {
 
                 int hashCode() const {
                     int result = 1;
-                    result = 31 * result + (soc.hashCode() << 1);
+                    result = 31 * result + (sid.hashCode() << 1);
                     result = 31 * result + (err.hashCode() << 1);
                     return result;
                 }
@@ -688,9 +689,25 @@ class nota_v2 {
         BRelation<SERVICE, INTERCONNECTNODE > svc_ICNode;
         BRelation<SERVICE, BBoolean > svc_registered;
 
+        mutable boost::optional<BSet<INTERCONNECTNODE>> _tr_cache_constructor_interconnectNode;
+        mutable boost::optional<BSet<RESOURCEMANAGER>> _tr_cache_constructor_resourceManager;
+        mutable boost::optional<BSet<BTuple<INTERCONNECTNODE, SERVICE >>> _tr_cache_constructor_service;
+        mutable boost::optional<BSet<BTuple<BTuple<BTuple<INTERCONNECTNODE, SID >, SID >, SOCKET >>> _tr_cache_constructor_socket;
+        mutable boost::optional<BSet<BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >>> _tr_cache_rm_register;
+        mutable boost::optional<BSet<BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >>> _tr_cache_rm_deregister;
+        mutable boost::optional<BSet<BTuple<RESOURCEMANAGER, SERVICE >>> _tr_cache_rm_getSid;
+        mutable boost::optional<BSet<BTuple<RESOURCEMANAGER, SERVICE >>> _tr_cache_rm_getSid_Not_Found;
+        mutable boost::optional<BSet<BTuple<INTERCONNECTNODE, RESOURCEMANAGER >>> _tr_cache_in_announceResourceManager;
+        mutable boost::optional<BSet<BTuple<BTuple<INTERCONNECTNODE, SERVICE >, SID >>> _tr_cache_in_register_success;
+        mutable boost::optional<BSet<BTuple<INTERCONNECTNODE, SERVICE >>> _tr_cache_in_register_failed;
+        mutable boost::optional<BSet<BTuple<BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >, SOCKET >>> _tr_cache_in_requestTargetSocket_Granted;
+        mutable boost::optional<BSet<BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >>> _tr_cache_in_requestTargetSocket_NotGranted;
+        mutable boost::optional<BSet<SERVICE>> _tr_cache_svc_register;
 
     public:
 
+        std::string stateAccessedVia;
+
         nota_v2() {
             interconnectNodes = (BSet<INTERCONNECTNODE >());
             sockets = (BSet<SOCKET >());
@@ -947,190 +964,246 @@ class nota_v2 {
         }
 
 
-        BSet<INTERCONNECTNODE> _tr_constructor_interconnectNode() const {
-            BSet<INTERCONNECTNODE> _ic_set_0 = BSet<INTERCONNECTNODE>();
-            for(INTERCONNECTNODE _ic_newic_1 : _INTERCONNECTNODE.difference(interconnectNodes)) {
-                _ic_set_0 = _ic_set_0._union(BSet<INTERCONNECTNODE>(_ic_newic_1));
+        BSet<INTERCONNECTNODE> _tr_constructor_interconnectNode(bool isCaching) const {
+            if (this->_tr_cache_constructor_interconnectNode == boost::none){
+                BSet<INTERCONNECTNODE> _ic_set_0 = BSet<INTERCONNECTNODE>();
+                for(const INTERCONNECTNODE& _ic_newic_1 : _INTERCONNECTNODE.difference(interconnectNodes)) {
+                    _ic_set_0 = _ic_set_0._union(BSet<INTERCONNECTNODE>(_ic_newic_1));
 
+                }
+                if (isCaching) this->_tr_cache_constructor_interconnectNode = _ic_set_0;
+                else return _ic_set_0;
             }
-            return _ic_set_0;
+            return this->_tr_cache_constructor_interconnectNode.get();
         }
 
-        BSet<RESOURCEMANAGER> _tr_constructor_resourceManager() const {
-            BSet<RESOURCEMANAGER> _ic_set_1 = BSet<RESOURCEMANAGER>();
-            for(RESOURCEMANAGER _ic_newrm_1 : _RESOURCEMANAGER.difference(resourceManagers)) {
-                if(((BBoolean(rm_services.domain().notElementOf(_ic_newrm_1).booleanValue() && resourceManagers.equal((BSet<RESOURCEMANAGER >())).booleanValue()))).booleanValue()) {
-                    _ic_set_1 = _ic_set_1._union(BSet<RESOURCEMANAGER>(_ic_newrm_1));
-                }
+        BSet<RESOURCEMANAGER> _tr_constructor_resourceManager(bool isCaching) const {
+            if (this->_tr_cache_constructor_resourceManager == boost::none){
+                BSet<RESOURCEMANAGER> _ic_set_1 = BSet<RESOURCEMANAGER>();
+                for(const RESOURCEMANAGER& _ic_newrm_1 : _RESOURCEMANAGER.difference(resourceManagers)) {
+                    if(((BBoolean(rm_services.domain().notElementOf(_ic_newrm_1).booleanValue() && resourceManagers.equal((BSet<RESOURCEMANAGER >())).booleanValue()))).booleanValue()) {
+                        _ic_set_1 = _ic_set_1._union(BSet<RESOURCEMANAGER>(_ic_newrm_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_constructor_resourceManager = _ic_set_1;
+                else return _ic_set_1;
             }
-            return _ic_set_1;
+            return this->_tr_cache_constructor_resourceManager.get();
         }
 
-        BSet<BTuple<INTERCONNECTNODE, SERVICE >> _tr_constructor_service() const {
-            BSet<BTuple<INTERCONNECTNODE, SERVICE >> _ic_set_2 = BSet<BTuple<INTERCONNECTNODE, SERVICE >>();
-            for(INTERCONNECTNODE _ic_ii_1 : interconnectNodes) {
-                for(SERVICE _ic_newsvc_1 : _SERVICE.difference(services)) {
-                    _ic_set_2 = _ic_set_2._union(BSet<BTuple<INTERCONNECTNODE, SERVICE >>((BTuple<INTERCONNECTNODE, SERVICE >(_ic_ii_1, _ic_newsvc_1))));
+        BSet<BTuple<INTERCONNECTNODE, SERVICE >> _tr_constructor_service(bool isCaching) const {
+            if (this->_tr_cache_constructor_service == boost::none){
+                BSet<BTuple<INTERCONNECTNODE, SERVICE >> _ic_set_2 = BSet<BTuple<INTERCONNECTNODE, SERVICE >>();
+                for(const INTERCONNECTNODE& _ic_ii_1 : interconnectNodes) {
+                    for(const SERVICE& _ic_newsvc_1 : _SERVICE.difference(services)) {
+                        _ic_set_2 = _ic_set_2._union(BSet<BTuple<INTERCONNECTNODE, SERVICE >>((BTuple<INTERCONNECTNODE, SERVICE >(_ic_ii_1, _ic_newsvc_1))));
 
+                    }
                 }
+                if (isCaching) this->_tr_cache_constructor_service = _ic_set_2;
+                else return _ic_set_2;
             }
-            return _ic_set_2;
+            return this->_tr_cache_constructor_service.get();
         }
 
-        BSet<BTuple<BTuple<BTuple<INTERCONNECTNODE, SID >, SID >, SOCKET >> _tr_constructor_socket() const {
-            BSet<BTuple<BTuple<BTuple<INTERCONNECTNODE, SID >, SID >, SOCKET >> _ic_set_3 = BSet<BTuple<BTuple<BTuple<INTERCONNECTNODE, SID >, SID >, SOCKET >>();
-            for(INTERCONNECTNODE _ic_ii_1 : interconnectNodes) {
-                for(SID _ic_srcsid_1 : sids) {
-                    for(SID _ic_targsid_1 : sids) {
-                        for(SOCKET _ic_newsoc_1 : _SOCKET.difference(sockets)) {
-                            _ic_set_3 = _ic_set_3._union(BSet<BTuple<BTuple<BTuple<INTERCONNECTNODE, SID >, SID >, SOCKET >>((BTuple<BTuple<BTuple<INTERCONNECTNODE, SID >, SID >, SOCKET >((BTuple<BTuple<INTERCONNECTNODE, SID >, SID >((BTuple<INTERCONNECTNODE, SID >(_ic_ii_1, _ic_srcsid_1)), _ic_targsid_1)), _ic_newsoc_1))));
+        BSet<BTuple<BTuple<BTuple<INTERCONNECTNODE, SID >, SID >, SOCKET >> _tr_constructor_socket(bool isCaching) const {
+            if (this->_tr_cache_constructor_socket == boost::none){
+                BSet<BTuple<BTuple<BTuple<INTERCONNECTNODE, SID >, SID >, SOCKET >> _ic_set_3 = BSet<BTuple<BTuple<BTuple<INTERCONNECTNODE, SID >, SID >, SOCKET >>();
+                for(const INTERCONNECTNODE& _ic_ii_1 : interconnectNodes) {
+                    for(const SID& _ic_srcsid_1 : sids) {
+                        for(const SID& _ic_targsid_1 : sids) {
+                            for(const SOCKET& _ic_newsoc_1 : _SOCKET.difference(sockets)) {
+                                _ic_set_3 = _ic_set_3._union(BSet<BTuple<BTuple<BTuple<INTERCONNECTNODE, SID >, SID >, SOCKET >>((BTuple<BTuple<BTuple<INTERCONNECTNODE, SID >, SID >, SOCKET >((BTuple<BTuple<INTERCONNECTNODE, SID >, SID >((BTuple<INTERCONNECTNODE, SID >(_ic_ii_1, _ic_srcsid_1)), _ic_targsid_1)), _ic_newsoc_1))));
 
+                            }
                         }
                     }
                 }
+                if (isCaching) this->_tr_cache_constructor_socket = _ic_set_3;
+                else return _ic_set_3;
             }
-            return _ic_set_3;
+            return this->_tr_cache_constructor_socket.get();
         }
 
-        BSet<BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >> _tr_rm_register() const {
-            BSet<BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >> _ic_set_4 = BSet<BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >>();
-            for(RESOURCEMANAGER _ic_self_1 : resourceManagers) {
-                for(SERVICE _ic_ss_1 : services) {
-                    for(INTERCONNECTNODE _ic_ii_1 : interconnectNodes) {
-                        _ic_set_4 = _ic_set_4._union(BSet<BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >>((BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >((BTuple<RESOURCEMANAGER, SERVICE >(_ic_self_1, _ic_ss_1)), _ic_ii_1))));
+        BSet<BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >> _tr_rm_register(bool isCaching) const {
+            if (this->_tr_cache_rm_register == boost::none){
+                BSet<BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >> _ic_set_4 = BSet<BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >>();
+                for(const RESOURCEMANAGER& _ic_self_1 : resourceManagers) {
+                    for(const SERVICE& _ic_ss_1 : services) {
+                        for(const INTERCONNECTNODE& _ic_ii_1 : interconnectNodes) {
+                            _ic_set_4 = _ic_set_4._union(BSet<BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >>((BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >((BTuple<RESOURCEMANAGER, SERVICE >(_ic_self_1, _ic_ss_1)), _ic_ii_1))));
 
+                        }
                     }
                 }
+                if (isCaching) this->_tr_cache_rm_register = _ic_set_4;
+                else return _ic_set_4;
             }
-            return _ic_set_4;
+            return this->_tr_cache_rm_register.get();
         }
 
-        BSet<BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >> _tr_rm_deregister() const {
-            BSet<BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >> _ic_set_5 = BSet<BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >>();
-            for(RESOURCEMANAGER _ic_self_1 : resourceManagers) {
-                for(SERVICE _ic_ss_1 : services) {
-                    for(INTERCONNECTNODE _ic_ii_1 : interconnectNodes) {
-                        _ic_set_5 = _ic_set_5._union(BSet<BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >>((BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >((BTuple<RESOURCEMANAGER, SERVICE >(_ic_self_1, _ic_ss_1)), _ic_ii_1))));
+        BSet<BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >> _tr_rm_deregister(bool isCaching) const {
+            if (this->_tr_cache_rm_deregister == boost::none){
+                BSet<BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >> _ic_set_5 = BSet<BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >>();
+                for(const RESOURCEMANAGER& _ic_self_1 : resourceManagers) {
+                    for(const SERVICE& _ic_ss_1 : services) {
+                        for(const INTERCONNECTNODE& _ic_ii_1 : interconnectNodes) {
+                            _ic_set_5 = _ic_set_5._union(BSet<BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >>((BTuple<BTuple<RESOURCEMANAGER, SERVICE >, INTERCONNECTNODE >((BTuple<RESOURCEMANAGER, SERVICE >(_ic_self_1, _ic_ss_1)), _ic_ii_1))));
 
+                        }
                     }
                 }
+                if (isCaching) this->_tr_cache_rm_deregister = _ic_set_5;
+                else return _ic_set_5;
             }
-            return _ic_set_5;
+            return this->_tr_cache_rm_deregister.get();
         }
 
-        BSet<BTuple<RESOURCEMANAGER, SERVICE >> _tr_rm_getSid() const {
-            BSet<BTuple<RESOURCEMANAGER, SERVICE >> _ic_set_6 = BSet<BTuple<RESOURCEMANAGER, SERVICE >>();
-            for(RESOURCEMANAGER _ic_self_1 : resourceManagers) {
-                for(SERVICE _ic_ss_1 : services) {
-                    if((rm_sids.domain().elementOf(_ic_ss_1)).booleanValue()) {
-                        _ic_set_6 = _ic_set_6._union(BSet<BTuple<RESOURCEMANAGER, SERVICE >>((BTuple<RESOURCEMANAGER, SERVICE >(_ic_self_1, _ic_ss_1))));
-                    }
+        BSet<BTuple<RESOURCEMANAGER, SERVICE >> _tr_rm_getSid(bool isCaching) const {
+            if (this->_tr_cache_rm_getSid == boost::none){
+                BSet<BTuple<RESOURCEMANAGER, SERVICE >> _ic_set_6 = BSet<BTuple<RESOURCEMANAGER, SERVICE >>();
+                for(const RESOURCEMANAGER& _ic_self_1 : resourceManagers) {
+                    for(const SERVICE& _ic_ss_1 : services) {
+                        if((rm_sids.domain().elementOf(_ic_ss_1)).booleanValue()) {
+                            _ic_set_6 = _ic_set_6._union(BSet<BTuple<RESOURCEMANAGER, SERVICE >>((BTuple<RESOURCEMANAGER, SERVICE >(_ic_self_1, _ic_ss_1))));
+                        }
 
+                    }
                 }
+                if (isCaching) this->_tr_cache_rm_getSid = _ic_set_6;
+                else return _ic_set_6;
             }
-            return _ic_set_6;
+            return this->_tr_cache_rm_getSid.get();
         }
 
-        BSet<BTuple<RESOURCEMANAGER, SERVICE >> _tr_rm_getSid_Not_Found() const {
-            BSet<BTuple<RESOURCEMANAGER, SERVICE >> _ic_set_7 = BSet<BTuple<RESOURCEMANAGER, SERVICE >>();
-            for(RESOURCEMANAGER _ic_self_1 : resourceManagers) {
-                for(SERVICE _ic_ss_1 : services) {
-                    _ic_set_7 = _ic_set_7._union(BSet<BTuple<RESOURCEMANAGER, SERVICE >>((BTuple<RESOURCEMANAGER, SERVICE >(_ic_self_1, _ic_ss_1))));
+        BSet<BTuple<RESOURCEMANAGER, SERVICE >> _tr_rm_getSid_Not_Found(bool isCaching) const {
+            if (this->_tr_cache_rm_getSid_Not_Found == boost::none){
+                BSet<BTuple<RESOURCEMANAGER, SERVICE >> _ic_set_7 = BSet<BTuple<RESOURCEMANAGER, SERVICE >>();
+                for(const RESOURCEMANAGER& _ic_self_1 : resourceManagers) {
+                    for(const SERVICE& _ic_ss_1 : services) {
+                        _ic_set_7 = _ic_set_7._union(BSet<BTuple<RESOURCEMANAGER, SERVICE >>((BTuple<RESOURCEMANAGER, SERVICE >(_ic_self_1, _ic_ss_1))));
 
+                    }
                 }
+                if (isCaching) this->_tr_cache_rm_getSid_Not_Found = _ic_set_7;
+                else return _ic_set_7;
             }
-            return _ic_set_7;
+            return this->_tr_cache_rm_getSid_Not_Found.get();
         }
 
-        BSet<BTuple<INTERCONNECTNODE, RESOURCEMANAGER >> _tr_in_announceResourceManager() const {
-            BSet<BTuple<INTERCONNECTNODE, RESOURCEMANAGER >> _ic_set_8 = BSet<BTuple<INTERCONNECTNODE, RESOURCEMANAGER >>();
-            for(INTERCONNECTNODE _ic_self_1 : interconnectNodes) {
-                for(RESOURCEMANAGER _ic_rm_1 : resourceManagers) {
-                    if((in_resourceManager.functionCall(_ic_self_1).equal((BSet<RESOURCEMANAGER >()))).booleanValue()) {
-                        _ic_set_8 = _ic_set_8._union(BSet<BTuple<INTERCONNECTNODE, RESOURCEMANAGER >>((BTuple<INTERCONNECTNODE, RESOURCEMANAGER >(_ic_self_1, _ic_rm_1))));
-                    }
+        BSet<BTuple<INTERCONNECTNODE, RESOURCEMANAGER >> _tr_in_announceResourceManager(bool isCaching) const {
+            if (this->_tr_cache_in_announceResourceManager == boost::none){
+                BSet<BTuple<INTERCONNECTNODE, RESOURCEMANAGER >> _ic_set_8 = BSet<BTuple<INTERCONNECTNODE, RESOURCEMANAGER >>();
+                for(const INTERCONNECTNODE& _ic_self_1 : interconnectNodes) {
+                    for(const RESOURCEMANAGER& _ic_rm_1 : resourceManagers) {
+                        if((in_resourceManager.functionCall(_ic_self_1).equal((BSet<RESOURCEMANAGER >()))).booleanValue()) {
+                            _ic_set_8 = _ic_set_8._union(BSet<BTuple<INTERCONNECTNODE, RESOURCEMANAGER >>((BTuple<INTERCONNECTNODE, RESOURCEMANAGER >(_ic_self_1, _ic_rm_1))));
+                        }
 
+                    }
                 }
+                if (isCaching) this->_tr_cache_in_announceResourceManager = _ic_set_8;
+                else return _ic_set_8;
             }
-            return _ic_set_8;
+            return this->_tr_cache_in_announceResourceManager.get();
         }
 
-        BSet<BTuple<BTuple<INTERCONNECTNODE, SERVICE >, SID >> _tr_in_register_success() const {
-            BSet<BTuple<BTuple<INTERCONNECTNODE, SERVICE >, SID >> _ic_set_9 = BSet<BTuple<BTuple<INTERCONNECTNODE, SERVICE >, SID >>();
-            for(INTERCONNECTNODE _ic_self_1 : interconnectNodes) {
-                for(SERVICE _ic_ss_1 : services) {
-                    for(SID _ic_si_1 : _SID.difference(sids)) {
-                        if((in_localServices.domain().elementOf(_ic_si_1)._not()).booleanValue()) {
-                            _ic_set_9 = _ic_set_9._union(BSet<BTuple<BTuple<INTERCONNECTNODE, SERVICE >, SID >>((BTuple<BTuple<INTERCONNECTNODE, SERVICE >, SID >((BTuple<INTERCONNECTNODE, SERVICE >(_ic_self_1, _ic_ss_1)), _ic_si_1))));
-                        }
+        BSet<BTuple<BTuple<INTERCONNECTNODE, SERVICE >, SID >> _tr_in_register_success(bool isCaching) const {
+            if (this->_tr_cache_in_register_success == boost::none){
+                BSet<BTuple<BTuple<INTERCONNECTNODE, SERVICE >, SID >> _ic_set_9 = BSet<BTuple<BTuple<INTERCONNECTNODE, SERVICE >, SID >>();
+                for(const INTERCONNECTNODE& _ic_self_1 : interconnectNodes) {
+                    for(const SERVICE& _ic_ss_1 : services) {
+                        for(const SID& _ic_si_1 : _SID.difference(sids)) {
+                            if((in_localServices.domain().elementOf(_ic_si_1)._not()).booleanValue()) {
+                                _ic_set_9 = _ic_set_9._union(BSet<BTuple<BTuple<INTERCONNECTNODE, SERVICE >, SID >>((BTuple<BTuple<INTERCONNECTNODE, SERVICE >, SID >((BTuple<INTERCONNECTNODE, SERVICE >(_ic_self_1, _ic_ss_1)), _ic_si_1))));
+                            }
 
+                        }
                     }
                 }
+                if (isCaching) this->_tr_cache_in_register_success = _ic_set_9;
+                else return _ic_set_9;
             }
-            return _ic_set_9;
+            return this->_tr_cache_in_register_success.get();
         }
 
-        BSet<BTuple<INTERCONNECTNODE, SERVICE >> _tr_in_register_failed() const {
-            BSet<BTuple<INTERCONNECTNODE, SERVICE >> _ic_set_10 = BSet<BTuple<INTERCONNECTNODE, SERVICE >>();
-            for(INTERCONNECTNODE _ic_self_1 : interconnectNodes) {
-                for(SERVICE _ic_ss_1 : services) {
-                    _ic_set_10 = _ic_set_10._union(BSet<BTuple<INTERCONNECTNODE, SERVICE >>((BTuple<INTERCONNECTNODE, SERVICE >(_ic_self_1, _ic_ss_1))));
+        BSet<BTuple<INTERCONNECTNODE, SERVICE >> _tr_in_register_failed(bool isCaching) const {
+            if (this->_tr_cache_in_register_failed == boost::none){
+                BSet<BTuple<INTERCONNECTNODE, SERVICE >> _ic_set_10 = BSet<BTuple<INTERCONNECTNODE, SERVICE >>();
+                for(const INTERCONNECTNODE& _ic_self_1 : interconnectNodes) {
+                    for(const SERVICE& _ic_ss_1 : services) {
+                        _ic_set_10 = _ic_set_10._union(BSet<BTuple<INTERCONNECTNODE, SERVICE >>((BTuple<INTERCONNECTNODE, SERVICE >(_ic_self_1, _ic_ss_1))));
 
+                    }
                 }
+                if (isCaching) this->_tr_cache_in_register_failed = _ic_set_10;
+                else return _ic_set_10;
             }
-            return _ic_set_10;
+            return this->_tr_cache_in_register_failed.get();
         }
 
-        BSet<BTuple<BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >, SOCKET >> _tr_in_requestTargetSocket_Granted() const {
-            BSet<BTuple<BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >, SOCKET >> _ic_set_11 = BSet<BTuple<BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >, SOCKET >>();
-            for(INTERCONNECTNODE _ic_self_1 : interconnectNodes) {
-                for(INTERCONNECTNODE _ic_ii_1 : interconnectNodes) {
-                    for(SOCKET _ic_srcsoc_1 : sockets) {
-                        for(SID _ic_srcsid_1 : sids) {
-                            for(SID _ic_targsid_1 : sids) {
-                                for(SOCKET _ic_newsoc_1 : _SOCKET.difference(sockets)) {
-                                    if(((BBoolean(_ic_self_1.unequal(_ic_ii_1).booleanValue() && in_sockets.functionCall(_ic_srcsoc_1).equal(_ic_ii_1).booleanValue()))).booleanValue()) {
-                                        _ic_set_11 = _ic_set_11._union(BSet<BTuple<BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >, SOCKET >>((BTuple<BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >, SOCKET >((BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >((BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >((BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >((BTuple<INTERCONNECTNODE, INTERCONNECTNODE >(_ic_self_1, _ic_ii_1)), _ic_srcsoc_1)), _ic_srcsid_1)), _ic_targsid_1)), _ic_newsoc_1))));
-                                    }
+        BSet<BTuple<BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >, SOCKET >> _tr_in_requestTargetSocket_Granted(bool isCaching) const {
+            if (this->_tr_cache_in_requestTargetSocket_Granted == boost::none){
+                BSet<BTuple<BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >, SOCKET >> _ic_set_11 = BSet<BTuple<BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >, SOCKET >>();
+                for(const INTERCONNECTNODE& _ic_self_1 : interconnectNodes) {
+                    for(const INTERCONNECTNODE& _ic_ii_1 : interconnectNodes) {
+                        for(const SOCKET& _ic_srcsoc_1 : sockets) {
+                            for(const SID& _ic_srcsid_1 : sids) {
+                                for(const SID& _ic_targsid_1 : sids) {
+                                    for(const SOCKET& _ic_newsoc_1 : _SOCKET.difference(sockets)) {
+                                        if(((BBoolean(_ic_self_1.unequal(_ic_ii_1).booleanValue() && in_sockets.functionCall(_ic_srcsoc_1).equal(_ic_ii_1).booleanValue()))).booleanValue()) {
+                                            _ic_set_11 = _ic_set_11._union(BSet<BTuple<BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >, SOCKET >>((BTuple<BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >, SOCKET >((BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >((BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >((BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >((BTuple<INTERCONNECTNODE, INTERCONNECTNODE >(_ic_self_1, _ic_ii_1)), _ic_srcsoc_1)), _ic_srcsid_1)), _ic_targsid_1)), _ic_newsoc_1))));
+                                        }
 
+                                    }
                                 }
                             }
                         }
                     }
                 }
+                if (isCaching) this->_tr_cache_in_requestTargetSocket_Granted = _ic_set_11;
+                else return _ic_set_11;
             }
-            return _ic_set_11;
-        }
-
-        BSet<BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >> _tr_in_requestTargetSocket_NotGranted() const {
-            BSet<BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >> _ic_set_12 = BSet<BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >>();
-            for(INTERCONNECTNODE _ic_self_1 : interconnectNodes) {
-                for(INTERCONNECTNODE _ic_ii_1 : interconnectNodes) {
-                    for(SOCKET _ic_srcsoc_1 : sockets) {
-                        for(SID _ic_srcsid_1 : sids) {
-                            for(SID _ic_targsid_1 : sids) {
-                                if(((BBoolean(_ic_self_1.unequal(_ic_ii_1).booleanValue() && in_sockets.functionCall(_ic_srcsoc_1).equal(_ic_ii_1).booleanValue()))).booleanValue()) {
-                                    _ic_set_12 = _ic_set_12._union(BSet<BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >>((BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >((BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >((BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >((BTuple<INTERCONNECTNODE, INTERCONNECTNODE >(_ic_self_1, _ic_ii_1)), _ic_srcsoc_1)), _ic_srcsid_1)), _ic_targsid_1))));
-                                }
+            return this->_tr_cache_in_requestTargetSocket_Granted.get();
+        }
+
+        BSet<BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >> _tr_in_requestTargetSocket_NotGranted(bool isCaching) const {
+            if (this->_tr_cache_in_requestTargetSocket_NotGranted == boost::none){
+                BSet<BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >> _ic_set_12 = BSet<BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >>();
+                for(const INTERCONNECTNODE& _ic_self_1 : interconnectNodes) {
+                    for(const INTERCONNECTNODE& _ic_ii_1 : interconnectNodes) {
+                        for(const SOCKET& _ic_srcsoc_1 : sockets) {
+                            for(const SID& _ic_srcsid_1 : sids) {
+                                for(const SID& _ic_targsid_1 : sids) {
+                                    if(((BBoolean(_ic_self_1.unequal(_ic_ii_1).booleanValue() && in_sockets.functionCall(_ic_srcsoc_1).equal(_ic_ii_1).booleanValue()))).booleanValue()) {
+                                        _ic_set_12 = _ic_set_12._union(BSet<BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >>((BTuple<BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >, SID >((BTuple<BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >, SID >((BTuple<BTuple<INTERCONNECTNODE, INTERCONNECTNODE >, SOCKET >((BTuple<INTERCONNECTNODE, INTERCONNECTNODE >(_ic_self_1, _ic_ii_1)), _ic_srcsoc_1)), _ic_srcsid_1)), _ic_targsid_1))));
+                                    }
 
+                                }
                             }
                         }
                     }
                 }
+                if (isCaching) this->_tr_cache_in_requestTargetSocket_NotGranted = _ic_set_12;
+                else return _ic_set_12;
             }
-            return _ic_set_12;
+            return this->_tr_cache_in_requestTargetSocket_NotGranted.get();
         }
 
-        BSet<SERVICE> _tr_svc_register() const {
-            BSet<SERVICE> _ic_set_13 = BSet<SERVICE>();
-            for(SERVICE _ic_self_1 : services) {
-                if((svc_registered.functionCall(_ic_self_1).equal((BBoolean(false)))).booleanValue()) {
-                    _ic_set_13 = _ic_set_13._union(BSet<SERVICE>(_ic_self_1));
-                }
+        BSet<SERVICE> _tr_svc_register(bool isCaching) const {
+            if (this->_tr_cache_svc_register == boost::none){
+                BSet<SERVICE> _ic_set_13 = BSet<SERVICE>();
+                for(const SERVICE& _ic_self_1 : services) {
+                    if((svc_registered.functionCall(_ic_self_1).equal((BBoolean(false)))).booleanValue()) {
+                        _ic_set_13 = _ic_set_13._union(BSet<SERVICE>(_ic_self_1));
+                    }
 
+                }
+                if (isCaching) this->_tr_cache_svc_register = _ic_set_13;
+                else return _ic_set_13;
             }
-            return _ic_set_13;
+            return this->_tr_cache_svc_register.get();
         }
 
         bool _check_inv_1() const {
@@ -1159,8 +1232,8 @@ class nota_v2 {
 
         bool _check_inv_7() const {
             BBoolean _ic_boolean_14 = BBoolean(true);
-            for(RESOURCEMANAGER _ic_a1_1 : rm_services.domain()) {
-                for(RESOURCEMANAGER _ic_a2_1 : rm_services.domain()) {
+            for(const RESOURCEMANAGER& _ic_a1_1 : rm_services.domain()) {
+                for(const RESOURCEMANAGER& _ic_a2_1 : rm_services.domain()) {
                     if(!((BBoolean(!_ic_a1_1.unequal(_ic_a2_1).booleanValue() || rm_services.functionCall(_ic_a1_1).intersect(rm_services.functionCall(_ic_a2_1)).equal((BSet<SERVICE >())).booleanValue()))).booleanValue()) {
                         _ic_boolean_14 = BBoolean(false);
                         break;
@@ -1216,8 +1289,37 @@ class nota_v2 {
             return ((BBoolean(!resourceManagers.equal((BSet<RESOURCEMANAGER >()))._not().booleanValue() || resourceManagers.card().equal((BInteger(1))).booleanValue()))).booleanValue();
         }
 
-        nota_v2 _copy() const {
-            return nota_v2(interconnectNodes, sockets, services, resourceManagers, sids, rm_services, rm_sids, in_localServices, in_sockets, in_resourceManager, soc_to, soc_from, svc_serviceID, svc_sockets, svc_ICNode, svc_registered);
+        static constexpr unsigned int strHash(const char *s, int off = 0) {
+            return !s[off] ? 5381 : (strHash(s, off+1)*33) ^ s[off];
+        }
+
+        nota_v2 _copy(unordered_set<string> toInvalidate) const {
+            static const char* allTransitions[] = {"_tr_constructor_interconnectNode", "_tr_constructor_resourceManager", "_tr_constructor_service", "_tr_constructor_socket", "_tr_rm_register", "_tr_rm_deregister", "_tr_rm_getSid", "_tr_rm_getSid_Not_Found", "_tr_in_announceResourceManager", "_tr_in_register_success", "_tr_in_register_failed", "_tr_in_requestTargetSocket_Granted", "_tr_in_requestTargetSocket_NotGranted", "_tr_svc_register"};
+
+            nota_v2 result = nota_v2(interconnectNodes, sockets, services, resourceManagers, sids, rm_services, rm_sids, in_localServices, in_sockets, in_resourceManager, soc_to, soc_from, svc_serviceID, svc_sockets, svc_ICNode, svc_registered);
+
+            for (const auto &item : allTransitions) {
+                if(toInvalidate.find(item) == toInvalidate.end()) {
+                    switch(strHash(item)) {
+                        case strHash("_tr_constructor_interconnectNode"): result._tr_cache_constructor_interconnectNode = this->_tr_cache_constructor_interconnectNode; break;
+                        case strHash("_tr_constructor_resourceManager"): result._tr_cache_constructor_resourceManager = this->_tr_cache_constructor_resourceManager; break;
+                        case strHash("_tr_constructor_service"): result._tr_cache_constructor_service = this->_tr_cache_constructor_service; break;
+                        case strHash("_tr_constructor_socket"): result._tr_cache_constructor_socket = this->_tr_cache_constructor_socket; break;
+                        case strHash("_tr_rm_register"): result._tr_cache_rm_register = this->_tr_cache_rm_register; break;
+                        case strHash("_tr_rm_deregister"): result._tr_cache_rm_deregister = this->_tr_cache_rm_deregister; break;
+                        case strHash("_tr_rm_getSid"): result._tr_cache_rm_getSid = this->_tr_cache_rm_getSid; break;
+                        case strHash("_tr_rm_getSid_Not_Found"): result._tr_cache_rm_getSid_Not_Found = this->_tr_cache_rm_getSid_Not_Found; break;
+                        case strHash("_tr_in_announceResourceManager"): result._tr_cache_in_announceResourceManager = this->_tr_cache_in_announceResourceManager; break;
+                        case strHash("_tr_in_register_success"): result._tr_cache_in_register_success = this->_tr_cache_in_register_success; break;
+                        case strHash("_tr_in_register_failed"): result._tr_cache_in_register_failed = this->_tr_cache_in_register_failed; break;
+                        case strHash("_tr_in_requestTargetSocket_Granted"): result._tr_cache_in_requestTargetSocket_Granted = this->_tr_cache_in_requestTargetSocket_Granted; break;
+                        case strHash("_tr_in_requestTargetSocket_NotGranted"): result._tr_cache_in_requestTargetSocket_NotGranted = this->_tr_cache_in_requestTargetSocket_NotGranted; break;
+                        case strHash("_tr_svc_register"): result._tr_cache_svc_register = this->_tr_cache_svc_register; break;
+                        default: cout << "Transition " << item << " not found!";
+                    }
+                }
+            }
+            return result;
         }
 
         friend bool operator ==(const nota_v2& o1, const nota_v2& o2) {
@@ -1298,1233 +1400,538 @@ class nota_v2 {
 };
 
 
-static std::unordered_set<nota_v2, nota_v2::Hash, nota_v2::HashEqual> generateNextStates(std::mutex& guardMutex, const nota_v2& state, bool isCaching, std::unordered_map<string, std::unordered_set<string>>& invariantDependency, std::unordered_map<nota_v2, std::unordered_set<string>, nota_v2::Hash, nota_v2::HashEqual>& dependentInvariant, std::unordered_map<string, std::unordered_set<string>>& guardDependency, std::unordered_map<nota_v2, std::unordered_set<string>, nota_v2::Hash, nota_v2::HashEqual>& dependentGuard, std::unordered_map<nota_v2, immer::map<string, boost::any>, nota_v2::Hash, nota_v2::HashEqual>& guardCache, std::unordered_map<nota_v2, nota_v2, nota_v2::Hash, nota_v2::HashEqual>& parents, std::unordered_map<nota_v2, string, nota_v2::Hash, nota_v2::HashEqual>& stateAccessedVia, std::atomic<int>& transitions) {
-    std::unordered_set<nota_v2, nota_v2::Hash, nota_v2::HashEqual> result = std::unordered_set<nota_v2, nota_v2::Hash, nota_v2::HashEqual>();
-    if(isCaching) {
-        immer::map<string, boost::any> parentsGuard;
-        std::unordered_set<string> dependentGuardsOfState;
-        bool parentsExist = false;
-        bool dependentGuardsExist = false;
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            parentsExist = (parents.find(state) != parents.end());
-            dependentGuardsExist = (dependentGuard.find(state) != dependentGuard.end());
-            if(parentsExist) {
-                parentsGuard = guardCache[parents[state]];
-            }
-            if(dependentGuardsExist) {
-                dependentGuardsOfState = dependentGuard[state];
-            }
-        }
-        immer::map<string, boost::any> newCache = parentsGuard;
-        boost::any cachedValue;
-        bool dependentGuardsBoolean = true;
-        BSet<nota_v2::INTERCONNECTNODE> _trid_1;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_constructor_interconnectNode"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_constructor_interconnectNode") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_1 = state._tr_constructor_interconnectNode();
-        } else {
-            _trid_1 = boost::any_cast<BSet<nota_v2::INTERCONNECTNODE>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_constructor_interconnectNode", _trid_1);
-        for(const nota_v2::INTERCONNECTNODE& param : _trid_1) {
-            nota_v2::INTERCONNECTNODE _tmp_1 = param;
+class ModelChecker {
+    private:
+        nota_v2::Type type;
+        int threads;
+        bool isCaching;
+        bool isDebug;
+
+        std::list<nota_v2> unvisitedStates;
+        std::unordered_set<nota_v2, nota_v2::Hash, nota_v2::HashEqual> states;
+        std::atomic<int> transitions;
+        std::mutex mutex;
+        std::mutex waitMutex;
+        std::mutex guardMutex;
+        std::condition_variable waitCV;
+
+        std::atomic<bool> invariantViolatedBool;
+        std::atomic<bool> deadlockDetected;
+        nota_v2 counterExampleState;
+
+        std::unordered_map<string, std::unordered_set<string>> invariantDependency;
+        std::unordered_map<string, std::unordered_set<string>> guardDependency;
+        std::unordered_map<nota_v2, nota_v2, nota_v2::Hash, nota_v2::HashEqual> parents;
 
-            nota_v2 copiedState = state._copy();
-            copiedState.constructor_interconnectNode(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["constructor_interconnectNode"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["constructor_interconnectNode"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "constructor_interconnectNode"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<nota_v2::RESOURCEMANAGER> _trid_2;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_constructor_resourceManager"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_constructor_resourceManager") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_2 = state._tr_constructor_resourceManager();
-        } else {
-            _trid_2 = boost::any_cast<BSet<nota_v2::RESOURCEMANAGER>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_constructor_resourceManager", _trid_2);
-        for(const nota_v2::RESOURCEMANAGER& param : _trid_2) {
-            nota_v2::RESOURCEMANAGER _tmp_1 = param;
+    public:
+        ModelChecker() {}
 
-            nota_v2 copiedState = state._copy();
-            copiedState.constructor_resourceManager(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["constructor_resourceManager"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["constructor_resourceManager"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "constructor_resourceManager"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
+        ModelChecker(nota_v2::Type type, int threads, bool isCaching, bool isDebug) {
+            this->type = type;
+            this->threads = threads;
+            this->isCaching = isCaching;
+            this->isDebug = isDebug;
+            this->invariantViolatedBool = false;
+            this->deadlockDetected = false;
+            this->transitions = 0;
         }
-        BSet<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE >> _trid_3;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_constructor_service"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_constructor_service") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_3 = state._tr_constructor_service();
-        } else {
-            _trid_3 = boost::any_cast<BSet<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE >>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_constructor_service", _trid_3);
-        for(const BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE >& param : _trid_3) {
-            nota_v2::SERVICE _tmp_1 = param.projection2();
-            nota_v2::INTERCONNECTNODE _tmp_2 = param.projection1();
 
-            nota_v2 copiedState = state._copy();
-            copiedState.constructor_service(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["constructor_service"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["constructor_service"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "constructor_service"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SID >, nota_v2::SID >, nota_v2::SOCKET >> _trid_4;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_constructor_socket"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_constructor_socket") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_4 = state._tr_constructor_socket();
-        } else {
-            _trid_4 = boost::any_cast<BSet<BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SID >, nota_v2::SID >, nota_v2::SOCKET >>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_constructor_socket", _trid_4);
-        for(const BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SID >, nota_v2::SID >, nota_v2::SOCKET >& param : _trid_4) {
-            nota_v2::SOCKET _tmp_1 = param.projection2();
-            BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SID >, nota_v2::SID > _tmp_2 = param.projection1();
-            nota_v2::SID _tmp_3 = _tmp_2.projection2();
-            BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SID > _tmp_4 = _tmp_2.projection1();
-            nota_v2::SID _tmp_5 = _tmp_4.projection2();
-            nota_v2::INTERCONNECTNODE _tmp_6 = _tmp_4.projection1();
-
-            nota_v2 copiedState = state._copy();
-            copiedState.constructor_socket(_tmp_6, _tmp_5, _tmp_3, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["constructor_socket"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["constructor_socket"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "constructor_socket"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >, nota_v2::INTERCONNECTNODE >> _trid_5;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_rm_register"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_rm_register") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_5 = state._tr_rm_register();
-        } else {
-            _trid_5 = boost::any_cast<BSet<BTuple<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >, nota_v2::INTERCONNECTNODE >>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_rm_register", _trid_5);
-        for(const BTuple<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >, nota_v2::INTERCONNECTNODE >& param : _trid_5) {
-            nota_v2::INTERCONNECTNODE _tmp_1 = param.projection2();
-            BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE > _tmp_2 = param.projection1();
-            nota_v2::SERVICE _tmp_3 = _tmp_2.projection2();
-            nota_v2::RESOURCEMANAGER _tmp_4 = _tmp_2.projection1();
-
-            nota_v2 copiedState = state._copy();
-            copiedState.rm_register(_tmp_4, _tmp_3, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["rm_register"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["rm_register"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "rm_register"});
-                }
+        void modelCheck() {
+            if (isDebug) {
+                cout << "Starting Modelchecking, STRATEGY=" << type << ", THREADS=" << threads << ", CACHING=" << isCaching << "\n";
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >, nota_v2::INTERCONNECTNODE >> _trid_6;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_rm_deregister"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_rm_deregister") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_6 = state._tr_rm_deregister();
-        } else {
-            _trid_6 = boost::any_cast<BSet<BTuple<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >, nota_v2::INTERCONNECTNODE >>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_rm_deregister", _trid_6);
-        for(const BTuple<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >, nota_v2::INTERCONNECTNODE >& param : _trid_6) {
-            nota_v2::INTERCONNECTNODE _tmp_1 = param.projection2();
-            BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE > _tmp_2 = param.projection1();
-            nota_v2::SERVICE _tmp_3 = _tmp_2.projection2();
-            nota_v2::RESOURCEMANAGER _tmp_4 = _tmp_2.projection1();
-
-            nota_v2 copiedState = state._copy();
-            copiedState.rm_deregister(_tmp_4, _tmp_3, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["rm_deregister"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["rm_deregister"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "rm_deregister"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >> _trid_7;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_rm_getSid"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_rm_getSid") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_7 = state._tr_rm_getSid();
-        } else {
-            _trid_7 = boost::any_cast<BSet<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_rm_getSid", _trid_7);
-        for(const BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >& param : _trid_7) {
-            nota_v2::SERVICE _tmp_1 = param.projection2();
-            nota_v2::RESOURCEMANAGER _tmp_2 = param.projection1();
 
-            nota_v2 copiedState = state._copy();
-            copiedState.rm_getSid(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["rm_getSid"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["rm_getSid"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "rm_getSid"});
-                }
+            if (threads <= 1) {
+                modelCheckSingleThreaded();
+            } else {
+                boost::asio::thread_pool workers(threads); // threads indicates the number of workers (without the coordinator)
+                modelCheckMultiThreaded(workers);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >> _trid_8;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_rm_getSid_Not_Found"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_rm_getSid_Not_Found") != dependentGuardsOfState.end());
         }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_8 = state._tr_rm_getSid_Not_Found();
-        } else {
-            _trid_8 = boost::any_cast<BSet<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_rm_getSid_Not_Found", _trid_8);
-        for(const BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >& param : _trid_8) {
-            nota_v2::SERVICE _tmp_1 = param.projection2();
-            nota_v2::RESOURCEMANAGER _tmp_2 = param.projection1();
 
-            nota_v2 copiedState = state._copy();
-            copiedState.rm_getSid_Not_Found(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["rm_getSid_Not_Found"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["rm_getSid_Not_Found"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "rm_getSid_Not_Found"});
-                }
+        void modelCheckSingleThreaded() {
+            nota_v2 machine = nota_v2();
+            states.insert(machine);
+            unvisitedStates.push_back(machine);
+
+            if (isCaching) {
+                initCache(machine);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::RESOURCEMANAGER >> _trid_9;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_in_announceResourceManager"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_in_announceResourceManager") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_9 = state._tr_in_announceResourceManager();
-        } else {
-            _trid_9 = boost::any_cast<BSet<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::RESOURCEMANAGER >>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_in_announceResourceManager", _trid_9);
-        for(const BTuple<nota_v2::INTERCONNECTNODE, nota_v2::RESOURCEMANAGER >& param : _trid_9) {
-            nota_v2::RESOURCEMANAGER _tmp_1 = param.projection2();
-            nota_v2::INTERCONNECTNODE _tmp_2 = param.projection1();
 
-            nota_v2 copiedState = state._copy();
-            copiedState.in_announceResourceManager(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["in_announceResourceManager"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["in_announceResourceManager"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+            while(!unvisitedStates.empty()) {
+                nota_v2 state = next();
+
+                std::unordered_set<nota_v2, nota_v2::Hash, nota_v2::HashEqual> nextStates = generateNextStates(state);
+                transitions += nextStates.size();
+
+                for(auto& nextState : nextStates) {
+                    if(states.find(nextState) == states.end()) {
+                        states.insert(nextState);
+                        parents.insert({nextState, state});
+                        unvisitedStates.push_back(nextState);
+                        if(states.size() % 50000 == 0) {
+                            cout << "VISITED STATES: " << states.size() << "\n";
+                            cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
+                            cout << "-------------------" << "\n";
+                        }
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "in_announceResourceManager"});
+
+                if(invariantViolated(state)) {
+                    invariantViolatedBool = true;
+                    counterExampleState = state;
+                    break;
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE >, nota_v2::SID >> _trid_10;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_in_register_success"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_in_register_success") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_10 = state._tr_in_register_success();
-        } else {
-            _trid_10 = boost::any_cast<BSet<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE >, nota_v2::SID >>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_in_register_success", _trid_10);
-        for(const BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE >, nota_v2::SID >& param : _trid_10) {
-            nota_v2::SID _tmp_1 = param.projection2();
-            BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE > _tmp_2 = param.projection1();
-            nota_v2::SERVICE _tmp_3 = _tmp_2.projection2();
-            nota_v2::INTERCONNECTNODE _tmp_4 = _tmp_2.projection1();
-
-            nota_v2 copiedState = state._copy();
-            copiedState.in_register_success(_tmp_4, _tmp_3, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["in_register_success"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["in_register_success"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "in_register_success"});
+
+                if(nextStates.empty()) {
+                    deadlockDetected = true;
+                    counterExampleState = state;
+                    break;
                 }
+
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE >> _trid_11;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_in_register_failed"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_in_register_failed") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_11 = state._tr_in_register_failed();
-        } else {
-            _trid_11 = boost::any_cast<BSet<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE >>>(cachedValue);
+            printResult();
         }
-        newCache = newCache.set("_tr_in_register_failed", _trid_11);
-        for(const BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE >& param : _trid_11) {
-            nota_v2::SERVICE _tmp_1 = param.projection2();
-            nota_v2::INTERCONNECTNODE _tmp_2 = param.projection1();
 
-            nota_v2 copiedState = state._copy();
-            copiedState.in_register_failed(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["in_register_failed"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["in_register_failed"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "in_register_failed"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BTuple<BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID >, nota_v2::SID >, nota_v2::SOCKET >> _trid_12;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_in_requestTargetSocket_Granted"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_in_requestTargetSocket_Granted") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_12 = state._tr_in_requestTargetSocket_Granted();
-        } else {
-            _trid_12 = boost::any_cast<BSet<BTuple<BTuple<BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID >, nota_v2::SID >, nota_v2::SOCKET >>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_in_requestTargetSocket_Granted", _trid_12);
-        for(const BTuple<BTuple<BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID >, nota_v2::SID >, nota_v2::SOCKET >& param : _trid_12) {
-            nota_v2::SOCKET _tmp_1 = param.projection2();
-            BTuple<BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID >, nota_v2::SID > _tmp_2 = param.projection1();
-            nota_v2::SID _tmp_3 = _tmp_2.projection2();
-            BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID > _tmp_4 = _tmp_2.projection1();
-            nota_v2::SID _tmp_5 = _tmp_4.projection2();
-            BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET > _tmp_6 = _tmp_4.projection1();
-            nota_v2::SOCKET _tmp_7 = _tmp_6.projection2();
-            BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE > _tmp_8 = _tmp_6.projection1();
-            nota_v2::INTERCONNECTNODE _tmp_9 = _tmp_8.projection2();
-            nota_v2::INTERCONNECTNODE _tmp_10 = _tmp_8.projection1();
-
-            nota_v2 copiedState = state._copy();
-            copiedState.in_requestTargetSocket_Granted(_tmp_10, _tmp_9, _tmp_7, _tmp_5, _tmp_3, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["in_requestTargetSocket_Granted"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["in_requestTargetSocket_Granted"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "in_requestTargetSocket_Granted"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID >, nota_v2::SID >> _trid_13;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_in_requestTargetSocket_NotGranted"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_in_requestTargetSocket_NotGranted") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_13 = state._tr_in_requestTargetSocket_NotGranted();
-        } else {
-            _trid_13 = boost::any_cast<BSet<BTuple<BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID >, nota_v2::SID >>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_in_requestTargetSocket_NotGranted", _trid_13);
-        for(const BTuple<BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID >, nota_v2::SID >& param : _trid_13) {
-            nota_v2::SID _tmp_1 = param.projection2();
-            BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID > _tmp_2 = param.projection1();
-            nota_v2::SID _tmp_3 = _tmp_2.projection2();
-            BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET > _tmp_4 = _tmp_2.projection1();
-            nota_v2::SOCKET _tmp_5 = _tmp_4.projection2();
-            BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE > _tmp_6 = _tmp_4.projection1();
-            nota_v2::INTERCONNECTNODE _tmp_7 = _tmp_6.projection2();
-            nota_v2::INTERCONNECTNODE _tmp_8 = _tmp_6.projection1();
-
-            nota_v2 copiedState = state._copy();
-            copiedState.in_requestTargetSocket_NotGranted(_tmp_8, _tmp_7, _tmp_5, _tmp_3, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["in_requestTargetSocket_NotGranted"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["in_requestTargetSocket_NotGranted"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "in_requestTargetSocket_NotGranted"});
-                }
+        void modelCheckMultiThreaded(boost::asio::thread_pool& workers) {
+            nota_v2 machine = nota_v2();
+            states.insert(machine);
+            unvisitedStates.push_back(machine);
+
+            std::atomic<bool> stopThreads;
+            stopThreads = false;
+            std::atomic<int> possibleQueueChanges;
+            possibleQueueChanges = 0;
+
+            if(isCaching) {
+                initCache(machine);
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<nota_v2::SERVICE> _trid_14;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_svc_register"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_svc_register") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || !parentsExist) {
-            _trid_14 = state._tr_svc_register();
-        } else {
-            _trid_14 = boost::any_cast<BSet<nota_v2::SERVICE>>(cachedValue);
-        }
-        newCache = newCache.set("_tr_svc_register", _trid_14);
-        for(const nota_v2::SERVICE& param : _trid_14) {
-            nota_v2::SERVICE _tmp_1 = param;
 
-            nota_v2 copiedState = state._copy();
-            copiedState.svc_register(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["svc_register"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["svc_register"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "svc_register"});
+            std::atomic<bool> waitFlag;
+            waitFlag = true;
+
+            while(!unvisitedStates.empty() && !stopThreads) {
+                possibleQueueChanges += 1;
+                nota_v2 state = next();
+                std::packaged_task<void()> task([&, state] {
+                    std::unordered_set<nota_v2, nota_v2::Hash, nota_v2::HashEqual> nextStates = generateNextStates(state);
+                    transitions += nextStates.size();
+
+                    for(auto& nextState : nextStates) {
+                        {
+                            std::unique_lock<std::mutex> lock(mutex);
+                            if(states.find(nextState) == states.end()) {
+                                states.insert(nextState);
+                                parents.insert({nextState, state});
+                                unvisitedStates.push_back(nextState); // TODO: sync ?
+                                if(isDebug && states.size() % 50000 == 0) {
+                                    cout << "VISITED STATES: " << states.size() << "\n";
+                                    cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
+                                    cout << "-------------------" << "\n";
+                                }
+                            }
+                        }
+                    }
+
+                    {
+                        std::unique_lock<std::mutex> lock(mutex);
+                        possibleQueueChanges -= 1;
+                        int running = possibleQueueChanges;
+                        if (!unvisitedStates.empty() || running == 0) {
+                            {
+                                std::unique_lock<std::mutex> lock(waitMutex);
+                                waitFlag = false;
+                                waitCV.notify_one();
+                            }
+                        }
+                    }
+
+                    if(invariantViolated(state)) {
+                        invariantViolatedBool = true;
+                        counterExampleState = state;
+                        stopThreads = true;
+                    }
+
+                    if(nextStates.empty()) {
+                        deadlockDetected = true;
+                        counterExampleState = state;
+                        stopThreads = true;
+                    }
+
+                });
+
+                waitFlag = true;
+                boost::asio::post(workers, std::move(task));
+
+                {
+                    std::unique_lock<std::mutex> lock(waitMutex);
+                    while (unvisitedStates.empty() && possibleQueueChanges > 0) {
+                        waitCV.wait(lock, [&] {
+                            return waitFlag == false;
+                        });
+                    }
                 }
             }
-            result.insert(copiedState);
-            transitions += 1;
+            workers.join();
+            printResult();
+        }
+
+        void initCache(nota_v2& machine) {
+            invariantDependency.insert({"in_register_success", {"_check_inv_5", "_check_inv_14", "_check_inv_13", "_check_inv_8", "_check_inv_12", "_check_inv_9"}});
+            invariantDependency.insert({"in_announceResourceManager", {"_check_inv_11"}});
+            invariantDependency.insert({"in_requestTargetSocket_Granted", {"_check_inv_15", "_check_inv_2", "_check_inv_10", "_check_inv_13", "_check_inv_12"}});
+            invariantDependency.insert({"constructor_service", {"_check_inv_17", "_check_inv_16", "_check_inv_15", "_check_inv_3", "_check_inv_6", "_check_inv_14", "_check_inv_8"}});
+            invariantDependency.insert({"constructor_socket", {"_check_inv_15", "_check_inv_2", "_check_inv_10", "_check_inv_13", "_check_inv_12"}});
+            invariantDependency.insert({"in_requestTargetSocket_NotGranted", {}});
+            invariantDependency.insert({"constructor_interconnectNode", {"_check_inv_16", "_check_inv_1", "_check_inv_10", "_check_inv_9", "_check_inv_11"}});
+            invariantDependency.insert({"rm_getSid", {}});
+            invariantDependency.insert({"rm_deregister", {}});
+            invariantDependency.insert({"constructor_resourceManager", {"_check_inv_18", "_check_inv_6", "_check_inv_7", "_check_inv_4", "_check_inv_11"}});
+            invariantDependency.insert({"in_register_failed", {}});
+            invariantDependency.insert({"rm_register", {}});
+            invariantDependency.insert({"rm_getSid_Not_Found", {}});
+            invariantDependency.insert({"svc_register", {"_check_inv_17"}});
+            invariantDependency.insert({"", {}});
+            guardDependency.insert({"in_register_success", {"_tr_in_register_success", "_tr_in_requestTargetSocket_Granted", "_tr_in_requestTargetSocket_NotGranted", "_tr_constructor_socket"}});
+            guardDependency.insert({"in_announceResourceManager", {"_tr_in_announceResourceManager"}});
+            guardDependency.insert({"in_requestTargetSocket_Granted", {"_tr_in_requestTargetSocket_Granted", "_tr_in_requestTargetSocket_NotGranted", "_tr_constructor_socket"}});
+            guardDependency.insert({"constructor_service", {"_tr_constructor_service", "_tr_rm_getSid", "_tr_in_register_success", "_tr_svc_register", "_tr_in_register_failed", "_tr_rm_register", "_tr_rm_getSid_Not_Found", "_tr_rm_deregister"}});
+            guardDependency.insert({"constructor_socket", {"_tr_in_requestTargetSocket_Granted", "_tr_in_requestTargetSocket_NotGranted", "_tr_constructor_socket"}});
+            guardDependency.insert({"in_requestTargetSocket_NotGranted", {}});
+            guardDependency.insert({"constructor_interconnectNode", {"_tr_constructor_service", "_tr_in_register_success", "_tr_in_requestTargetSocket_Granted", "_tr_in_register_failed", "_tr_rm_register", "_tr_in_requestTargetSocket_NotGranted", "_tr_constructor_socket", "_tr_rm_deregister", "_tr_constructor_interconnectNode", "_tr_in_announceResourceManager"}});
+            guardDependency.insert({"rm_getSid", {}});
+            guardDependency.insert({"rm_deregister", {}});
+            guardDependency.insert({"constructor_resourceManager", {"_tr_rm_getSid", "_tr_constructor_resourceManager", "_tr_rm_register", "_tr_rm_getSid_Not_Found", "_tr_rm_deregister", "_tr_in_announceResourceManager"}});
+            guardDependency.insert({"in_register_failed", {}});
+            guardDependency.insert({"rm_register", {}});
+            guardDependency.insert({"rm_getSid_Not_Found", {}});
+            guardDependency.insert({"svc_register", {"_tr_svc_register"}});
         }
 
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            guardCache.insert({state, newCache});
-        }
-    } else {
-        BSet<nota_v2::INTERCONNECTNODE> _trid_1 = state._tr_constructor_interconnectNode();
-        for(const nota_v2::INTERCONNECTNODE& param : _trid_1) {
-            nota_v2::INTERCONNECTNODE _tmp_1 = param;
 
-            nota_v2 copiedState = state._copy();
-            copiedState.constructor_interconnectNode(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "constructor_interconnectNode"});
+    private:
+        nota_v2 next() {
+            std::unique_lock<std::mutex> lock(mutex);
+            switch(type) {
+                case nota_v2::BFS: {
+                    nota_v2 state = unvisitedStates.front();
+                    unvisitedStates.pop_front();
+                    return state;
+                }
+                case nota_v2::DFS: {
+                    nota_v2 state = unvisitedStates.back();
+                    unvisitedStates.pop_back();
+                    return state;
+                }
+                case nota_v2::MIXED: {
+                    if(unvisitedStates.size() % 2 == 0) {
+                        nota_v2 state = unvisitedStates.front();
+                        unvisitedStates.pop_front();
+                        return state;
+                    } else {
+                        nota_v2 state = unvisitedStates.back();
+                        unvisitedStates.pop_back();
+                        return state;
+                    }
                 }
             }
-            result.insert(copiedState);
-            transitions += 1;
         }
-        BSet<nota_v2::RESOURCEMANAGER> _trid_2 = state._tr_constructor_resourceManager();
-        for(const nota_v2::RESOURCEMANAGER& param : _trid_2) {
-            nota_v2::RESOURCEMANAGER _tmp_1 = param;
 
-            nota_v2 copiedState = state._copy();
-            copiedState.constructor_resourceManager(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "constructor_resourceManager"});
-                }
+        std::unordered_set<nota_v2, nota_v2::Hash, nota_v2::HashEqual> generateNextStates(const nota_v2& state) {
+            std::unordered_set<nota_v2, nota_v2::Hash, nota_v2::HashEqual> result = std::unordered_set<nota_v2, nota_v2::Hash, nota_v2::HashEqual>();
+            BSet<nota_v2::INTERCONNECTNODE> _trid_1 = state._tr_constructor_interconnectNode(isCaching);
+            for(const nota_v2::INTERCONNECTNODE& param : _trid_1) {
+                nota_v2::INTERCONNECTNODE _tmp_1 = param;
+
+                nota_v2 copiedState = state._copy(guardDependency["constructor_interconnectNode"]);
+                copiedState.constructor_interconnectNode(_tmp_1);
+                copiedState.stateAccessedVia = "constructor_interconnectNode";
+                result.insert(copiedState);
+            }
+            BSet<nota_v2::RESOURCEMANAGER> _trid_2 = state._tr_constructor_resourceManager(isCaching);
+            for(const nota_v2::RESOURCEMANAGER& param : _trid_2) {
+                nota_v2::RESOURCEMANAGER _tmp_1 = param;
+
+                nota_v2 copiedState = state._copy(guardDependency["constructor_resourceManager"]);
+                copiedState.constructor_resourceManager(_tmp_1);
+                copiedState.stateAccessedVia = "constructor_resourceManager";
+                result.insert(copiedState);
+            }
+            BSet<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE >> _trid_3 = state._tr_constructor_service(isCaching);
+            for(const BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE >& param : _trid_3) {
+                nota_v2::SERVICE _tmp_1 = param.projection2();
+                nota_v2::INTERCONNECTNODE _tmp_2 = param.projection1();
+
+                nota_v2 copiedState = state._copy(guardDependency["constructor_service"]);
+                copiedState.constructor_service(_tmp_2, _tmp_1);
+                copiedState.stateAccessedVia = "constructor_service";
+                result.insert(copiedState);
+            }
+            BSet<BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SID >, nota_v2::SID >, nota_v2::SOCKET >> _trid_4 = state._tr_constructor_socket(isCaching);
+            for(const BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SID >, nota_v2::SID >, nota_v2::SOCKET >& param : _trid_4) {
+                nota_v2::SOCKET _tmp_1 = param.projection2();
+                BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SID >, nota_v2::SID > _tmp_2 = param.projection1();
+                nota_v2::SID _tmp_3 = _tmp_2.projection2();
+                BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SID > _tmp_4 = _tmp_2.projection1();
+                nota_v2::SID _tmp_5 = _tmp_4.projection2();
+                nota_v2::INTERCONNECTNODE _tmp_6 = _tmp_4.projection1();
+
+                nota_v2 copiedState = state._copy(guardDependency["constructor_socket"]);
+                copiedState.constructor_socket(_tmp_6, _tmp_5, _tmp_3, _tmp_1);
+                copiedState.stateAccessedVia = "constructor_socket";
+                result.insert(copiedState);
+            }
+            BSet<BTuple<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >, nota_v2::INTERCONNECTNODE >> _trid_5 = state._tr_rm_register(isCaching);
+            for(const BTuple<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >, nota_v2::INTERCONNECTNODE >& param : _trid_5) {
+                nota_v2::INTERCONNECTNODE _tmp_1 = param.projection2();
+                BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE > _tmp_2 = param.projection1();
+                nota_v2::SERVICE _tmp_3 = _tmp_2.projection2();
+                nota_v2::RESOURCEMANAGER _tmp_4 = _tmp_2.projection1();
+
+                nota_v2 copiedState = state._copy(guardDependency["rm_register"]);
+                copiedState.rm_register(_tmp_4, _tmp_3, _tmp_1);
+                copiedState.stateAccessedVia = "rm_register";
+                result.insert(copiedState);
+            }
+            BSet<BTuple<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >, nota_v2::INTERCONNECTNODE >> _trid_6 = state._tr_rm_deregister(isCaching);
+            for(const BTuple<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >, nota_v2::INTERCONNECTNODE >& param : _trid_6) {
+                nota_v2::INTERCONNECTNODE _tmp_1 = param.projection2();
+                BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE > _tmp_2 = param.projection1();
+                nota_v2::SERVICE _tmp_3 = _tmp_2.projection2();
+                nota_v2::RESOURCEMANAGER _tmp_4 = _tmp_2.projection1();
+
+                nota_v2 copiedState = state._copy(guardDependency["rm_deregister"]);
+                copiedState.rm_deregister(_tmp_4, _tmp_3, _tmp_1);
+                copiedState.stateAccessedVia = "rm_deregister";
+                result.insert(copiedState);
+            }
+            BSet<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >> _trid_7 = state._tr_rm_getSid(isCaching);
+            for(const BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >& param : _trid_7) {
+                nota_v2::SERVICE _tmp_1 = param.projection2();
+                nota_v2::RESOURCEMANAGER _tmp_2 = param.projection1();
+
+                nota_v2 copiedState = state._copy(guardDependency["rm_getSid"]);
+                copiedState.rm_getSid(_tmp_2, _tmp_1);
+                copiedState.stateAccessedVia = "rm_getSid";
+                result.insert(copiedState);
+            }
+            BSet<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >> _trid_8 = state._tr_rm_getSid_Not_Found(isCaching);
+            for(const BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >& param : _trid_8) {
+                nota_v2::SERVICE _tmp_1 = param.projection2();
+                nota_v2::RESOURCEMANAGER _tmp_2 = param.projection1();
+
+                nota_v2 copiedState = state._copy(guardDependency["rm_getSid_Not_Found"]);
+                copiedState.rm_getSid_Not_Found(_tmp_2, _tmp_1);
+                copiedState.stateAccessedVia = "rm_getSid_Not_Found";
+                result.insert(copiedState);
+            }
+            BSet<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::RESOURCEMANAGER >> _trid_9 = state._tr_in_announceResourceManager(isCaching);
+            for(const BTuple<nota_v2::INTERCONNECTNODE, nota_v2::RESOURCEMANAGER >& param : _trid_9) {
+                nota_v2::RESOURCEMANAGER _tmp_1 = param.projection2();
+                nota_v2::INTERCONNECTNODE _tmp_2 = param.projection1();
+
+                nota_v2 copiedState = state._copy(guardDependency["in_announceResourceManager"]);
+                copiedState.in_announceResourceManager(_tmp_2, _tmp_1);
+                copiedState.stateAccessedVia = "in_announceResourceManager";
+                result.insert(copiedState);
+            }
+            BSet<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE >, nota_v2::SID >> _trid_10 = state._tr_in_register_success(isCaching);
+            for(const BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE >, nota_v2::SID >& param : _trid_10) {
+                nota_v2::SID _tmp_1 = param.projection2();
+                BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE > _tmp_2 = param.projection1();
+                nota_v2::SERVICE _tmp_3 = _tmp_2.projection2();
+                nota_v2::INTERCONNECTNODE _tmp_4 = _tmp_2.projection1();
+
+                nota_v2 copiedState = state._copy(guardDependency["in_register_success"]);
+                copiedState.in_register_success(_tmp_4, _tmp_3, _tmp_1);
+                copiedState.stateAccessedVia = "in_register_success";
+                result.insert(copiedState);
+            }
+            BSet<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE >> _trid_11 = state._tr_in_register_failed(isCaching);
+            for(const BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE >& param : _trid_11) {
+                nota_v2::SERVICE _tmp_1 = param.projection2();
+                nota_v2::INTERCONNECTNODE _tmp_2 = param.projection1();
+
+                nota_v2 copiedState = state._copy(guardDependency["in_register_failed"]);
+                copiedState.in_register_failed(_tmp_2, _tmp_1);
+                copiedState.stateAccessedVia = "in_register_failed";
+                result.insert(copiedState);
+            }
+            BSet<BTuple<BTuple<BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID >, nota_v2::SID >, nota_v2::SOCKET >> _trid_12 = state._tr_in_requestTargetSocket_Granted(isCaching);
+            for(const BTuple<BTuple<BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID >, nota_v2::SID >, nota_v2::SOCKET >& param : _trid_12) {
+                nota_v2::SOCKET _tmp_1 = param.projection2();
+                BTuple<BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID >, nota_v2::SID > _tmp_2 = param.projection1();
+                nota_v2::SID _tmp_3 = _tmp_2.projection2();
+                BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID > _tmp_4 = _tmp_2.projection1();
+                nota_v2::SID _tmp_5 = _tmp_4.projection2();
+                BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET > _tmp_6 = _tmp_4.projection1();
+                nota_v2::SOCKET _tmp_7 = _tmp_6.projection2();
+                BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE > _tmp_8 = _tmp_6.projection1();
+                nota_v2::INTERCONNECTNODE _tmp_9 = _tmp_8.projection2();
+                nota_v2::INTERCONNECTNODE _tmp_10 = _tmp_8.projection1();
+
+                nota_v2 copiedState = state._copy(guardDependency["in_requestTargetSocket_Granted"]);
+                copiedState.in_requestTargetSocket_Granted(_tmp_10, _tmp_9, _tmp_7, _tmp_5, _tmp_3, _tmp_1);
+                copiedState.stateAccessedVia = "in_requestTargetSocket_Granted";
+                result.insert(copiedState);
+            }
+            BSet<BTuple<BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID >, nota_v2::SID >> _trid_13 = state._tr_in_requestTargetSocket_NotGranted(isCaching);
+            for(const BTuple<BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID >, nota_v2::SID >& param : _trid_13) {
+                nota_v2::SID _tmp_1 = param.projection2();
+                BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID > _tmp_2 = param.projection1();
+                nota_v2::SID _tmp_3 = _tmp_2.projection2();
+                BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET > _tmp_4 = _tmp_2.projection1();
+                nota_v2::SOCKET _tmp_5 = _tmp_4.projection2();
+                BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE > _tmp_6 = _tmp_4.projection1();
+                nota_v2::INTERCONNECTNODE _tmp_7 = _tmp_6.projection2();
+                nota_v2::INTERCONNECTNODE _tmp_8 = _tmp_6.projection1();
+
+                nota_v2 copiedState = state._copy(guardDependency["in_requestTargetSocket_NotGranted"]);
+                copiedState.in_requestTargetSocket_NotGranted(_tmp_8, _tmp_7, _tmp_5, _tmp_3, _tmp_1);
+                copiedState.stateAccessedVia = "in_requestTargetSocket_NotGranted";
+                result.insert(copiedState);
+            }
+            BSet<nota_v2::SERVICE> _trid_14 = state._tr_svc_register(isCaching);
+            for(const nota_v2::SERVICE& param : _trid_14) {
+                nota_v2::SERVICE _tmp_1 = param;
+
+                nota_v2 copiedState = state._copy(guardDependency["svc_register"]);
+                copiedState.svc_register(_tmp_1);
+                copiedState.stateAccessedVia = "svc_register";
+                result.insert(copiedState);
             }
-            result.insert(copiedState);
-            transitions += 1;
+
+            return result;
         }
-        BSet<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE >> _trid_3 = state._tr_constructor_service();
-        for(const BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE >& param : _trid_3) {
-            nota_v2::SERVICE _tmp_1 = param.projection2();
-            nota_v2::INTERCONNECTNODE _tmp_2 = param.projection1();
 
-            nota_v2 copiedState = state._copy();
-            copiedState.constructor_service(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+        bool invariantViolated(const nota_v2& state) {
+            if(isCaching) {
+                std::unordered_set<string> dependentInvariantsOfState = invariantDependency[state.stateAccessedVia];
+                if(dependentInvariantsOfState.find("_check_inv_1") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_1()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "constructor_service"});
+                if(dependentInvariantsOfState.find("_check_inv_2") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_2()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SID >, nota_v2::SID >, nota_v2::SOCKET >> _trid_4 = state._tr_constructor_socket();
-        for(const BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SID >, nota_v2::SID >, nota_v2::SOCKET >& param : _trid_4) {
-            nota_v2::SOCKET _tmp_1 = param.projection2();
-            BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SID >, nota_v2::SID > _tmp_2 = param.projection1();
-            nota_v2::SID _tmp_3 = _tmp_2.projection2();
-            BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SID > _tmp_4 = _tmp_2.projection1();
-            nota_v2::SID _tmp_5 = _tmp_4.projection2();
-            nota_v2::INTERCONNECTNODE _tmp_6 = _tmp_4.projection1();
-
-            nota_v2 copiedState = state._copy();
-            copiedState.constructor_socket(_tmp_6, _tmp_5, _tmp_3, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "constructor_socket"});
+                if(dependentInvariantsOfState.find("_check_inv_3") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_3()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >, nota_v2::INTERCONNECTNODE >> _trid_5 = state._tr_rm_register();
-        for(const BTuple<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >, nota_v2::INTERCONNECTNODE >& param : _trid_5) {
-            nota_v2::INTERCONNECTNODE _tmp_1 = param.projection2();
-            BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE > _tmp_2 = param.projection1();
-            nota_v2::SERVICE _tmp_3 = _tmp_2.projection2();
-            nota_v2::RESOURCEMANAGER _tmp_4 = _tmp_2.projection1();
-
-            nota_v2 copiedState = state._copy();
-            copiedState.rm_register(_tmp_4, _tmp_3, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "rm_register"});
+                if(dependentInvariantsOfState.find("_check_inv_4") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_4()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >, nota_v2::INTERCONNECTNODE >> _trid_6 = state._tr_rm_deregister();
-        for(const BTuple<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >, nota_v2::INTERCONNECTNODE >& param : _trid_6) {
-            nota_v2::INTERCONNECTNODE _tmp_1 = param.projection2();
-            BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE > _tmp_2 = param.projection1();
-            nota_v2::SERVICE _tmp_3 = _tmp_2.projection2();
-            nota_v2::RESOURCEMANAGER _tmp_4 = _tmp_2.projection1();
-
-            nota_v2 copiedState = state._copy();
-            copiedState.rm_deregister(_tmp_4, _tmp_3, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "rm_deregister"});
+                if(dependentInvariantsOfState.find("_check_inv_5") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_5()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >> _trid_7 = state._tr_rm_getSid();
-        for(const BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >& param : _trid_7) {
-            nota_v2::SERVICE _tmp_1 = param.projection2();
-            nota_v2::RESOURCEMANAGER _tmp_2 = param.projection1();
-
-            nota_v2 copiedState = state._copy();
-            copiedState.rm_getSid(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_6") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_6()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "rm_getSid"});
+                if(dependentInvariantsOfState.find("_check_inv_7") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_7()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >> _trid_8 = state._tr_rm_getSid_Not_Found();
-        for(const BTuple<nota_v2::RESOURCEMANAGER, nota_v2::SERVICE >& param : _trid_8) {
-            nota_v2::SERVICE _tmp_1 = param.projection2();
-            nota_v2::RESOURCEMANAGER _tmp_2 = param.projection1();
-
-            nota_v2 copiedState = state._copy();
-            copiedState.rm_getSid_Not_Found(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_8") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_8()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "rm_getSid_Not_Found"});
+                if(dependentInvariantsOfState.find("_check_inv_9") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_9()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::RESOURCEMANAGER >> _trid_9 = state._tr_in_announceResourceManager();
-        for(const BTuple<nota_v2::INTERCONNECTNODE, nota_v2::RESOURCEMANAGER >& param : _trid_9) {
-            nota_v2::RESOURCEMANAGER _tmp_1 = param.projection2();
-            nota_v2::INTERCONNECTNODE _tmp_2 = param.projection1();
-
-            nota_v2 copiedState = state._copy();
-            copiedState.in_announceResourceManager(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_10") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_10()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "in_announceResourceManager"});
+                if(dependentInvariantsOfState.find("_check_inv_11") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_11()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE >, nota_v2::SID >> _trid_10 = state._tr_in_register_success();
-        for(const BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE >, nota_v2::SID >& param : _trid_10) {
-            nota_v2::SID _tmp_1 = param.projection2();
-            BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE > _tmp_2 = param.projection1();
-            nota_v2::SERVICE _tmp_3 = _tmp_2.projection2();
-            nota_v2::INTERCONNECTNODE _tmp_4 = _tmp_2.projection1();
-
-            nota_v2 copiedState = state._copy();
-            copiedState.in_register_success(_tmp_4, _tmp_3, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "in_register_success"});
+                if(dependentInvariantsOfState.find("_check_inv_12") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_12()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE >> _trid_11 = state._tr_in_register_failed();
-        for(const BTuple<nota_v2::INTERCONNECTNODE, nota_v2::SERVICE >& param : _trid_11) {
-            nota_v2::SERVICE _tmp_1 = param.projection2();
-            nota_v2::INTERCONNECTNODE _tmp_2 = param.projection1();
-
-            nota_v2 copiedState = state._copy();
-            copiedState.in_register_failed(_tmp_2, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_13") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_13()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "in_register_failed"});
+                if(dependentInvariantsOfState.find("_check_inv_14") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_14()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BTuple<BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID >, nota_v2::SID >, nota_v2::SOCKET >> _trid_12 = state._tr_in_requestTargetSocket_Granted();
-        for(const BTuple<BTuple<BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID >, nota_v2::SID >, nota_v2::SOCKET >& param : _trid_12) {
-            nota_v2::SOCKET _tmp_1 = param.projection2();
-            BTuple<BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID >, nota_v2::SID > _tmp_2 = param.projection1();
-            nota_v2::SID _tmp_3 = _tmp_2.projection2();
-            BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID > _tmp_4 = _tmp_2.projection1();
-            nota_v2::SID _tmp_5 = _tmp_4.projection2();
-            BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET > _tmp_6 = _tmp_4.projection1();
-            nota_v2::SOCKET _tmp_7 = _tmp_6.projection2();
-            BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE > _tmp_8 = _tmp_6.projection1();
-            nota_v2::INTERCONNECTNODE _tmp_9 = _tmp_8.projection2();
-            nota_v2::INTERCONNECTNODE _tmp_10 = _tmp_8.projection1();
-
-            nota_v2 copiedState = state._copy();
-            copiedState.in_requestTargetSocket_Granted(_tmp_10, _tmp_9, _tmp_7, _tmp_5, _tmp_3, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "in_requestTargetSocket_Granted"});
+                if(dependentInvariantsOfState.find("_check_inv_15") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_15()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<BTuple<BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID >, nota_v2::SID >> _trid_13 = state._tr_in_requestTargetSocket_NotGranted();
-        for(const BTuple<BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID >, nota_v2::SID >& param : _trid_13) {
-            nota_v2::SID _tmp_1 = param.projection2();
-            BTuple<BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET >, nota_v2::SID > _tmp_2 = param.projection1();
-            nota_v2::SID _tmp_3 = _tmp_2.projection2();
-            BTuple<BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE >, nota_v2::SOCKET > _tmp_4 = _tmp_2.projection1();
-            nota_v2::SOCKET _tmp_5 = _tmp_4.projection2();
-            BTuple<nota_v2::INTERCONNECTNODE, nota_v2::INTERCONNECTNODE > _tmp_6 = _tmp_4.projection1();
-            nota_v2::INTERCONNECTNODE _tmp_7 = _tmp_6.projection2();
-            nota_v2::INTERCONNECTNODE _tmp_8 = _tmp_6.projection1();
-
-            nota_v2 copiedState = state._copy();
-            copiedState.in_requestTargetSocket_NotGranted(_tmp_8, _tmp_7, _tmp_5, _tmp_3, _tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "in_requestTargetSocket_NotGranted"});
+                if(dependentInvariantsOfState.find("_check_inv_16") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_16()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        BSet<nota_v2::SERVICE> _trid_14 = state._tr_svc_register();
-        for(const nota_v2::SERVICE& param : _trid_14) {
-            nota_v2::SERVICE _tmp_1 = param;
-
-            nota_v2 copiedState = state._copy();
-            copiedState.svc_register(_tmp_1);
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
+                if(dependentInvariantsOfState.find("_check_inv_17") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_17()) {
+                        return false;
+                    }
                 }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "svc_register"});
+                if(dependentInvariantsOfState.find("_check_inv_18") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_18()) {
+                        return false;
+                    }
                 }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-
-    }
-    return result;
-}
-
-static void printResult(int states, int transitions, bool deadlockDetected, bool invariantViolated, nota_v2& counterExampleState, std::unordered_map<nota_v2, nota_v2, nota_v2::Hash, nota_v2::HashEqual>& parents, std::unordered_map<nota_v2, string, nota_v2::Hash, nota_v2::HashEqual>& stateAccessedVia) {
-    if(deadlockDetected || invariantViolated) {
-        if(deadlockDetected) {
-            cout << "DEADLOCK DETECTED" << "\n";
-        }
-        if(invariantViolated) {
-            cout << "INVARIANT VIOLATED" << "\n";
-        }
-        cout << "COUNTER EXAMPLE TRACE: " << "\n";
-
-        nota_v2 currentState = counterExampleState;
-        std::string trace = "";
-        while(parents.find(currentState) != parents.end()) {
-            std::stringstream stringStream;
-            stringStream << currentState;
-            trace.insert(0, stringStream.str());
-            trace.insert(0, "\n");
-            trace.insert(0, stateAccessedVia[currentState]);
-            trace.insert(0, "\n\n");
-            currentState = parents[currentState];
-        }
-        cout << trace;
-    }
-
-    if(!deadlockDetected && !invariantViolated) {
-        cout << "MODEL CHECKING SUCCESSFUL" << "\n";
-    }
-    cout << "Number of States: " << states << "\n";
-    cout << "Number of Transitions: " << transitions << "\n";
-}
-
-static bool checkInvariants(std::mutex& guardMutex, const nota_v2& state, bool isCaching, std::unordered_map<nota_v2, std::unordered_set<string>, nota_v2::Hash, nota_v2::HashEqual>& dependentInvariant) {
-    if(isCaching) {
-        std::unordered_set<string> dependentInvariantsOfState;
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            dependentInvariantsOfState = dependentInvariant[state];
-        }
-        if(dependentInvariantsOfState.find("_check_inv_1") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_1()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_2") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_2()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_3") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_3()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_4") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_4()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_5") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_5()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_6") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_6()) {
                 return false;
             }
+            return !(state._check_inv_1() && state._check_inv_2() && state._check_inv_3() && state._check_inv_4() && state._check_inv_5() && state._check_inv_6() && state._check_inv_7() && state._check_inv_8() && state._check_inv_9() && state._check_inv_10() && state._check_inv_11() && state._check_inv_12() && state._check_inv_13() && state._check_inv_14() && state._check_inv_15() && state._check_inv_16() && state._check_inv_17() && state._check_inv_18());
         }
-        if(dependentInvariantsOfState.find("_check_inv_7") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_7()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_8") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_8()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_9") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_9()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_10") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_10()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_11") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_11()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_12") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_12()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_13") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_13()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_14") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_14()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_15") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_15()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_16") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_16()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_17") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_17()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_18") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_18()) {
-                return false;
-            }
-        }
-        return true;
-    }
-    return !(!state._check_inv_1() || !state._check_inv_2() || !state._check_inv_3() || !state._check_inv_4() || !state._check_inv_5() || !state._check_inv_6() || !state._check_inv_7() || !state._check_inv_8() || !state._check_inv_9() || !state._check_inv_10() || !state._check_inv_11() || !state._check_inv_12() || !state._check_inv_13() || !state._check_inv_14() || !state._check_inv_15() || !state._check_inv_16() || !state._check_inv_17() || !state._check_inv_18());
-}
 
-static nota_v2 next(std::list<nota_v2>& collection, std::mutex& mutex, nota_v2::Type type) {
-    std::unique_lock<std::mutex> lock(mutex);
-    switch(type) {
-        case nota_v2::BFS: {
-            nota_v2 state = collection.front();
-            collection.pop_front();
-            return state;
-        }
-        case nota_v2::DFS: {
-            nota_v2 state = collection.back();
-            collection.pop_back();
-            return state;
-        }
-        case nota_v2::MIXED: {
-            if(collection.size() % 2 == 0) {
-                nota_v2 state = collection.front();
-                collection.pop_front();
-                return state;
-            } else {
-                nota_v2 state = collection.back();
-                collection.pop_back();
-                return state;
-            }
-        }
-    };
-}
 
-static void modelCheckSingleThreaded(nota_v2::Type type, bool isCaching) {
-    std::mutex mutex;
-    std::mutex guardMutex;
-
-    nota_v2 machine = nota_v2();
-
-    std::atomic<bool> invariantViolated;
-    invariantViolated = false;
-    std::atomic<bool> deadlockDetected;
-    deadlockDetected = false;
-    std::atomic<bool> stopThreads;
-    stopThreads = false;
-
-    std::unordered_set<nota_v2, nota_v2::Hash, nota_v2::HashEqual> states = std::unordered_set<nota_v2, nota_v2::Hash, nota_v2::HashEqual>();
-    states.insert(machine);
-    std::atomic<int> numberStates;
-    numberStates = 1;
-
-    std::list<nota_v2> collection = std::list<nota_v2>();
-    collection.push_back(machine);
-
-    std::atomic<int> transitions;
-    transitions = 0;
-
-    std::unordered_map<string, std::unordered_set<string>> invariantDependency;
-    std::unordered_map<string, std::unordered_set<string>> guardDependency;
-    std::unordered_map<nota_v2, std::unordered_set<string>, nota_v2::Hash, nota_v2::HashEqual> dependentInvariant;
-    std::unordered_map<nota_v2, std::unordered_set<string>, nota_v2::Hash, nota_v2::HashEqual> dependentGuard;
-    std::unordered_map<nota_v2, immer::map<string, boost::any>, nota_v2::Hash, nota_v2::HashEqual> guardCache;
-    std::unordered_map<nota_v2, nota_v2, nota_v2::Hash, nota_v2::HashEqual> parents;
-    std::unordered_map<nota_v2, string, nota_v2::Hash, nota_v2::HashEqual> stateAccessedVia;
-    if(isCaching) {
-        invariantDependency.insert({"in_register_success", {"_check_inv_5", "_check_inv_14", "_check_inv_13", "_check_inv_8", "_check_inv_12", "_check_inv_9"}});
-        invariantDependency.insert({"in_announceResourceManager", {"_check_inv_11"}});
-        invariantDependency.insert({"in_requestTargetSocket_Granted", {"_check_inv_15", "_check_inv_2", "_check_inv_10", "_check_inv_13", "_check_inv_12"}});
-        invariantDependency.insert({"constructor_service", {"_check_inv_17", "_check_inv_16", "_check_inv_15", "_check_inv_3", "_check_inv_6", "_check_inv_14", "_check_inv_8"}});
-        invariantDependency.insert({"constructor_socket", {"_check_inv_15", "_check_inv_2", "_check_inv_10", "_check_inv_13", "_check_inv_12"}});
-        invariantDependency.insert({"in_requestTargetSocket_NotGranted", {}});
-        invariantDependency.insert({"constructor_interconnectNode", {"_check_inv_16", "_check_inv_1", "_check_inv_10", "_check_inv_9", "_check_inv_11"}});
-        invariantDependency.insert({"rm_getSid", {}});
-        invariantDependency.insert({"rm_deregister", {}});
-        invariantDependency.insert({"constructor_resourceManager", {"_check_inv_18", "_check_inv_6", "_check_inv_7", "_check_inv_4", "_check_inv_11"}});
-        invariantDependency.insert({"in_register_failed", {}});
-        invariantDependency.insert({"rm_register", {}});
-        invariantDependency.insert({"rm_getSid_Not_Found", {}});
-        invariantDependency.insert({"svc_register", {"_check_inv_17"}});
-        guardDependency.insert({"in_register_success", {"_tr_in_register_success", "_tr_in_requestTargetSocket_Granted", "_tr_in_requestTargetSocket_NotGranted", "_tr_constructor_socket"}});
-        guardDependency.insert({"in_announceResourceManager", {"_tr_in_announceResourceManager"}});
-        guardDependency.insert({"in_requestTargetSocket_Granted", {"_tr_in_requestTargetSocket_Granted", "_tr_in_requestTargetSocket_NotGranted", "_tr_constructor_socket"}});
-        guardDependency.insert({"constructor_service", {"_tr_constructor_service", "_tr_rm_getSid", "_tr_in_register_success", "_tr_svc_register", "_tr_in_register_failed", "_tr_rm_register", "_tr_rm_getSid_Not_Found", "_tr_rm_deregister"}});
-        guardDependency.insert({"constructor_socket", {"_tr_in_requestTargetSocket_Granted", "_tr_in_requestTargetSocket_NotGranted", "_tr_constructor_socket"}});
-        guardDependency.insert({"in_requestTargetSocket_NotGranted", {}});
-        guardDependency.insert({"constructor_interconnectNode", {"_tr_constructor_service", "_tr_in_register_success", "_tr_in_requestTargetSocket_Granted", "_tr_in_register_failed", "_tr_rm_register", "_tr_in_requestTargetSocket_NotGranted", "_tr_constructor_socket", "_tr_rm_deregister", "_tr_constructor_interconnectNode", "_tr_in_announceResourceManager"}});
-        guardDependency.insert({"rm_getSid", {}});
-        guardDependency.insert({"rm_deregister", {}});
-        guardDependency.insert({"constructor_resourceManager", {"_tr_rm_getSid", "_tr_constructor_resourceManager", "_tr_rm_register", "_tr_rm_getSid_Not_Found", "_tr_rm_deregister", "_tr_in_announceResourceManager"}});
-        guardDependency.insert({"in_register_failed", {}});
-        guardDependency.insert({"rm_register", {}});
-        guardDependency.insert({"rm_getSid_Not_Found", {}});
-        guardDependency.insert({"svc_register", {"_tr_svc_register"}});
-        dependentInvariant.insert({machine, std::unordered_set<string>()});
-    }
-    nota_v2 counterExampleState;
-
-    while(!collection.empty() && !stopThreads) {
-        nota_v2 state = next(collection, mutex, type);
-
-        std::unordered_set<nota_v2, nota_v2::Hash, nota_v2::HashEqual> nextStates = generateNextStates(guardMutex, state, isCaching, invariantDependency, dependentInvariant, guardDependency, dependentGuard, guardCache, parents, stateAccessedVia, transitions);
-        for(auto nextState : nextStates) {
-            if(states.find(nextState) == states.end()) {
-                numberStates += 1;
-                states.insert(nextState);
-                collection.push_back(nextState);
-                if(numberStates % 50000 == 0) {
-                    cout << "VISITED STATES: " << numberStates << "\n";
-                    cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
-                    cout << "-------------------" << "\n";
+        void printResult() {
+            if(deadlockDetected || invariantViolatedBool) {
+                if(deadlockDetected) {
+                    cout << "DEADLOCK DETECTED" << "\n";
+                } else {
+                    cout << "INVARIANT VIOLATED" << "\n";
                 }
-            }
-        }
-
-        if(!checkInvariants(guardMutex, state, isCaching, dependentInvariant)) {
-            invariantViolated = true;
-            stopThreads = true;
-            counterExampleState = state;
-        }
-
-        if(nextStates.empty()) {
-            deadlockDetected = true;
-            stopThreads = true;
-            counterExampleState = state;
-        }
-
-    }
-    printResult(numberStates, transitions, deadlockDetected, invariantViolated, counterExampleState, parents, stateAccessedVia);
-}
-
-static void modelCheckMultiThreaded(nota_v2::Type type, int threads, bool isCaching) {
-    std::mutex mutex;
-    std::mutex waitMutex;
-    std::mutex guardMutex;
-    std::condition_variable waitCV;
-
-    nota_v2 machine = nota_v2();
-
-
-    std::atomic<bool> invariantViolated;
-    invariantViolated = false;
-    std::atomic<bool> deadlockDetected;
-    deadlockDetected = false;
-    std::atomic<bool> stopThreads;
-    stopThreads = false;
-
-    std::unordered_set<nota_v2, nota_v2::Hash, nota_v2::HashEqual> states = std::unordered_set<nota_v2, nota_v2::Hash, nota_v2::HashEqual>();
-    states.insert(machine);
-    std::atomic<int> numberStates;
-    numberStates = 1;
-
-    std::list<nota_v2> collection = std::list<nota_v2>();
-    collection.push_back(machine);
-
-    std::atomic<int> transitions;
-    transitions = 0;
-
-    std::atomic<int> possibleQueueChanges;
-    possibleQueueChanges = 0;
-
-    std::atomic<bool> waitFlag;
-    waitFlag = true;
-
-    std::unordered_map<string, std::unordered_set<string>> invariantDependency;
-    std::unordered_map<string, std::unordered_set<string>> guardDependency;
-    std::unordered_map<nota_v2, std::unordered_set<string>, nota_v2::Hash, nota_v2::HashEqual> dependentInvariant;
-    std::unordered_map<nota_v2, std::unordered_set<string>, nota_v2::Hash, nota_v2::HashEqual> dependentGuard;
-    std::unordered_map<nota_v2, immer::map<string, boost::any>, nota_v2::Hash, nota_v2::HashEqual> guardCache;
-    std::unordered_map<nota_v2, nota_v2, nota_v2::Hash, nota_v2::HashEqual> parents;
-    std::unordered_map<nota_v2, string, nota_v2::Hash, nota_v2::HashEqual> stateAccessedVia;
-    if(isCaching) {
-        invariantDependency.insert({"in_register_success", {"_check_inv_5", "_check_inv_14", "_check_inv_13", "_check_inv_8", "_check_inv_12", "_check_inv_9"}});
-        invariantDependency.insert({"in_announceResourceManager", {"_check_inv_11"}});
-        invariantDependency.insert({"in_requestTargetSocket_Granted", {"_check_inv_15", "_check_inv_2", "_check_inv_10", "_check_inv_13", "_check_inv_12"}});
-        invariantDependency.insert({"constructor_service", {"_check_inv_17", "_check_inv_16", "_check_inv_15", "_check_inv_3", "_check_inv_6", "_check_inv_14", "_check_inv_8"}});
-        invariantDependency.insert({"constructor_socket", {"_check_inv_15", "_check_inv_2", "_check_inv_10", "_check_inv_13", "_check_inv_12"}});
-        invariantDependency.insert({"in_requestTargetSocket_NotGranted", {}});
-        invariantDependency.insert({"constructor_interconnectNode", {"_check_inv_16", "_check_inv_1", "_check_inv_10", "_check_inv_9", "_check_inv_11"}});
-        invariantDependency.insert({"rm_getSid", {}});
-        invariantDependency.insert({"rm_deregister", {}});
-        invariantDependency.insert({"constructor_resourceManager", {"_check_inv_18", "_check_inv_6", "_check_inv_7", "_check_inv_4", "_check_inv_11"}});
-        invariantDependency.insert({"in_register_failed", {}});
-        invariantDependency.insert({"rm_register", {}});
-        invariantDependency.insert({"rm_getSid_Not_Found", {}});
-        invariantDependency.insert({"svc_register", {"_check_inv_17"}});
-        guardDependency.insert({"in_register_success", {"_tr_in_register_success", "_tr_in_requestTargetSocket_Granted", "_tr_in_requestTargetSocket_NotGranted", "_tr_constructor_socket"}});
-        guardDependency.insert({"in_announceResourceManager", {"_tr_in_announceResourceManager"}});
-        guardDependency.insert({"in_requestTargetSocket_Granted", {"_tr_in_requestTargetSocket_Granted", "_tr_in_requestTargetSocket_NotGranted", "_tr_constructor_socket"}});
-        guardDependency.insert({"constructor_service", {"_tr_constructor_service", "_tr_rm_getSid", "_tr_in_register_success", "_tr_svc_register", "_tr_in_register_failed", "_tr_rm_register", "_tr_rm_getSid_Not_Found", "_tr_rm_deregister"}});
-        guardDependency.insert({"constructor_socket", {"_tr_in_requestTargetSocket_Granted", "_tr_in_requestTargetSocket_NotGranted", "_tr_constructor_socket"}});
-        guardDependency.insert({"in_requestTargetSocket_NotGranted", {}});
-        guardDependency.insert({"constructor_interconnectNode", {"_tr_constructor_service", "_tr_in_register_success", "_tr_in_requestTargetSocket_Granted", "_tr_in_register_failed", "_tr_rm_register", "_tr_in_requestTargetSocket_NotGranted", "_tr_constructor_socket", "_tr_rm_deregister", "_tr_constructor_interconnectNode", "_tr_in_announceResourceManager"}});
-        guardDependency.insert({"rm_getSid", {}});
-        guardDependency.insert({"rm_deregister", {}});
-        guardDependency.insert({"constructor_resourceManager", {"_tr_rm_getSid", "_tr_constructor_resourceManager", "_tr_rm_register", "_tr_rm_getSid_Not_Found", "_tr_rm_deregister", "_tr_in_announceResourceManager"}});
-        guardDependency.insert({"in_register_failed", {}});
-        guardDependency.insert({"rm_register", {}});
-        guardDependency.insert({"rm_getSid_Not_Found", {}});
-        guardDependency.insert({"svc_register", {"_tr_svc_register"}});
-        dependentInvariant.insert({machine, std::unordered_set<string>()});
-    }
-    nota_v2 counterExampleState;
-
-    boost::asio::thread_pool workers(threads);
-
-    while(!collection.empty() && !stopThreads) {
-        possibleQueueChanges += 1;
-        nota_v2 state = next(collection, mutex, type);
-        std::packaged_task<void()> task([&, state] {
-            std::unordered_set<nota_v2, nota_v2::Hash, nota_v2::HashEqual> nextStates = generateNextStates(guardMutex, state, isCaching, invariantDependency, dependentInvariant, guardDependency, dependentGuard, guardCache, parents, stateAccessedVia, transitions);
 
+                cout << "COUNTER EXAMPLE TRACE: " << "\n";
 
-            for(auto nextState : nextStates) {
-                {
-                    std::unique_lock<std::mutex> lock(mutex);
-                    if(states.find(nextState) == states.end()) {
-                        numberStates += 1;
-                        states.insert(nextState);
-                        collection.push_back(nextState);
-                        if(numberStates % 50000 == 0) {
-                            cout << "VISITED STATES: " << numberStates << "\n";
-                            cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
-                            cout << "-------------------" << "\n";
-                        }
-                    }
+                std::string trace = "";
+                while(parents.find(counterExampleState) != parents.end()) {
+                    std::stringstream stringStream;
+                    stringStream << counterExampleState;
+                    trace.insert(0, stringStream.str());
+                    trace.insert(0, "\n");
+                    trace.insert(0, counterExampleState.stateAccessedVia);
+                    trace.insert(0, "\n\n");
+                    counterExampleState = parents[counterExampleState];
                 }
+                cout << trace;
+            } else {
+                cout << "MODEL CHECKING SUCCESSFUL" << "\n";
             }
 
-            {
-                std::unique_lock<std::mutex> lock(mutex);
-                possibleQueueChanges -= 1;
-                int running = possibleQueueChanges;
-                if (!collection.empty() || running == 0) {
-                    {
-                        std::unique_lock<std::mutex> lock(waitMutex);
-                        waitFlag = false;
-                        waitCV.notify_one();
-                    }
-                }
-            }
-
-            if(nextStates.empty()) {
-                deadlockDetected = true;
-                stopThreads = true;
-                counterExampleState = state;
-            }
-
-            if(!checkInvariants(guardMutex, state, isCaching, dependentInvariant)) {
-                invariantViolated = true;
-                stopThreads = true;
-                counterExampleState = state;
-            }
-
-
-        });
-        waitFlag = true;
-        boost::asio::post(workers, std::move(task));
-
-        {
-            std::unique_lock<std::mutex> lock(waitMutex);
-            if (collection.empty() && possibleQueueChanges > 0) {
-                waitCV.wait(lock, [&] {
-                    return waitFlag == false;
-                });
-            }
+            cout << "Number of States: " << states.size() << "\n";
+            cout << "Number of Transitions: " << transitions << "\n";
         }
-    }
-    workers.join();
-    printResult(numberStates, transitions, deadlockDetected, invariantViolated, counterExampleState, parents, stateAccessedVia);
-}
+};
 
 int main(int argc, char *argv[]) {
     if(argc != 4) {
@@ -2573,11 +1980,12 @@ int main(int argc, char *argv[]) {
         return - 1;
     }
 
-    if(threads == 1) {
-        modelCheckSingleThreaded(type, isCaching);
-    } else {
-        modelCheckMultiThreaded(type, threads, isCaching);
-    }
+    bool isDebug = true;
+    // TODO
+
+    ModelChecker modelchecker(type, threads, isCaching, isDebug);
+    modelchecker.modelCheck();
+
     return 0;
 }
 
diff --git a/benchmarks/model_checking/C++/sort_m2_data1000_MC.cpp b/benchmarks/model_checking/C++/sort_m2_data1000_MC.cpp
index fb95350535ba1384ea54cda9d8dcf398f5db2f01..f25db0620e64928a7ae0f291f8b7778249f022ec 100644
--- a/benchmarks/model_checking/C++/sort_m2_data1000_MC.cpp
+++ b/benchmarks/model_checking/C++/sort_m2_data1000_MC.cpp
@@ -11,6 +11,7 @@
 #include <boost/asio/post.hpp>
 #include <boost/asio/thread_pool.hpp>
 #include <boost/any.hpp>
+#include <boost/optional.hpp>
 #include <btypes_primitives/BUtils.hpp>
 #include <btypes_primitives/StateNotReachableError.hpp>
 #include <btypes_primitives/PreconditionOrAssertionViolation.hpp>
@@ -62,13 +63,19 @@ class sort_m2_data1000_MC {
         BInteger l;
         BRelation<BInteger, BInteger > g;
 
+        mutable boost::optional<bool> _tr_cache_progress;
+        mutable boost::optional<bool> _tr_cache_prog1;
+        mutable boost::optional<bool> _tr_cache_prog2;
+        mutable boost::optional<bool> _tr_cache_final_evt;
 
     public:
 
+        std::string stateAccessedVia;
+
         sort_m2_data1000_MC() {
             n = (BInteger(1000));
             BRelation<BInteger, BInteger > _ic_set_0 = BRelation<BInteger, BInteger >();
-            for(BInteger _ic_i_1 : (BSet<BInteger>::interval((BInteger(1)),n))) {
+            for(const BInteger& _ic_i_1 : (BSet<BInteger>::interval((BInteger(1)),n))) {
                 _ic_set_0 = _ic_set_0._union(BRelation<BInteger, BInteger>(BTuple<BInteger, BInteger>(_ic_i_1, (BInteger(15000)).minus(_ic_i_1))));
 
             }
@@ -143,20 +150,40 @@ class sort_m2_data1000_MC {
         }
 
 
-        bool _tr_progress() const {
-            return ((BBoolean(k.unequal(n).booleanValue() && j.equal(n).booleanValue()))).booleanValue();
+        bool _tr_progress(bool isCaching) const {
+            if (this->_tr_cache_progress == boost::none){
+                bool __tmp_result = ((BBoolean(k.unequal(n).booleanValue() && j.equal(n).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_progress = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_progress.get();
         }
 
-        bool _tr_prog1() const {
-            return ((BBoolean((BBoolean(k.unequal(n).booleanValue() && j.unequal(n).booleanValue())).booleanValue() && g.functionCall(l).lessEqual(g.functionCall(j.plus((BInteger(1))))).booleanValue()))).booleanValue();
+        bool _tr_prog1(bool isCaching) const {
+            if (this->_tr_cache_prog1 == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean(k.unequal(n).booleanValue() && j.unequal(n).booleanValue())).booleanValue() && g.functionCall(l).lessEqual(g.functionCall(j.plus((BInteger(1))))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_prog1 = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_prog1.get();
         }
 
-        bool _tr_prog2() const {
-            return ((BBoolean((BBoolean(k.unequal(n).booleanValue() && j.unequal(n).booleanValue())).booleanValue() && g.functionCall(l).greater(g.functionCall(j.plus((BInteger(1))))).booleanValue()))).booleanValue();
+        bool _tr_prog2(bool isCaching) const {
+            if (this->_tr_cache_prog2 == boost::none){
+                bool __tmp_result = ((BBoolean((BBoolean(k.unequal(n).booleanValue() && j.unequal(n).booleanValue())).booleanValue() && g.functionCall(l).greater(g.functionCall(j.plus((BInteger(1))))).booleanValue()))).booleanValue();
+                if (isCaching) this->_tr_cache_prog2 = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_prog2.get();
         }
 
-        bool _tr_final_evt() const {
-            return (k.equal(n)).booleanValue();
+        bool _tr_final_evt(bool isCaching) const {
+            if (this->_tr_cache_final_evt == boost::none){
+                bool __tmp_result = (k.equal(n)).booleanValue();
+                if (isCaching) this->_tr_cache_final_evt = __tmp_result;
+                else return __tmp_result;
+            }
+            return this->_tr_cache_final_evt.get();
         }
 
         bool _check_inv_1() const {
@@ -183,8 +210,27 @@ class sort_m2_data1000_MC {
             return (((g.checkDomain((BSet<BInteger>::interval((BInteger(1)),n))))._and((g.checkRangeNatural()))._and((g.isFunction()))._and((g.isTotal((BSet<BInteger>::interval((BInteger(1)),n))))))).booleanValue();
         }
 
-        sort_m2_data1000_MC _copy() const {
-            return sort_m2_data1000_MC(n, f, j, k, l, g);
+        static constexpr unsigned int strHash(const char *s, int off = 0) {
+            return !s[off] ? 5381 : (strHash(s, off+1)*33) ^ s[off];
+        }
+
+        sort_m2_data1000_MC _copy(unordered_set<string> toInvalidate) const {
+            static const char* allTransitions[] = {"_tr_progress", "_tr_prog1", "_tr_prog2", "_tr_final_evt"};
+
+            sort_m2_data1000_MC result = sort_m2_data1000_MC(n, f, j, k, l, g);
+
+            for (const auto &item : allTransitions) {
+                if(toInvalidate.find(item) == toInvalidate.end()) {
+                    switch(strHash(item)) {
+                        case strHash("_tr_progress"): result._tr_cache_progress = this->_tr_cache_progress; break;
+                        case strHash("_tr_prog1"): result._tr_cache_prog1 = this->_tr_cache_prog1; break;
+                        case strHash("_tr_prog2"): result._tr_cache_prog2 = this->_tr_cache_prog2; break;
+                        case strHash("_tr_final_evt"): result._tr_cache_final_evt = this->_tr_cache_final_evt; break;
+                        default: cout << "Transition " << item << " not found!";
+                    }
+                }
+            }
+            return result;
         }
 
         friend bool operator ==(const sort_m2_data1000_MC& o1, const sort_m2_data1000_MC& o2) {
@@ -229,523 +275,321 @@ class sort_m2_data1000_MC {
 };
 
 
-static std::unordered_set<sort_m2_data1000_MC, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> generateNextStates(std::mutex& guardMutex, const sort_m2_data1000_MC& state, bool isCaching, std::unordered_map<string, std::unordered_set<string>>& invariantDependency, std::unordered_map<sort_m2_data1000_MC, std::unordered_set<string>, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual>& dependentInvariant, std::unordered_map<string, std::unordered_set<string>>& guardDependency, std::unordered_map<sort_m2_data1000_MC, std::unordered_set<string>, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual>& dependentGuard, std::unordered_map<sort_m2_data1000_MC, immer::map<string, boost::any>, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual>& guardCache, std::unordered_map<sort_m2_data1000_MC, sort_m2_data1000_MC, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual>& parents, std::unordered_map<sort_m2_data1000_MC, string, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual>& stateAccessedVia, std::atomic<int>& transitions) {
-    std::unordered_set<sort_m2_data1000_MC, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> result = std::unordered_set<sort_m2_data1000_MC, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual>();
-    if(isCaching) {
-        immer::map<string, boost::any> parentsGuard;
-        std::unordered_set<string> dependentGuardsOfState;
-        bool parentsExist = false;
-        bool dependentGuardsExist = false;
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            parentsExist = (parents.find(state) != parents.end());
-            dependentGuardsExist = (dependentGuard.find(state) != dependentGuard.end());
-            if(parentsExist) {
-                parentsGuard = guardCache[parents[state]];
-            }
-            if(dependentGuardsExist) {
-                dependentGuardsOfState = dependentGuard[state];
-            }
-        }
-        immer::map<string, boost::any> newCache = parentsGuard;
-        boost::any cachedValue;
-        bool dependentGuardsBoolean = true;
-        bool _trid_1;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_progress"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_progress") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_1 = state._tr_progress();
-        } else {
-            _trid_1 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_progress", _trid_1);
-        if(_trid_1) {
-            sort_m2_data1000_MC copiedState = state._copy();
-            copiedState.progress();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["progress"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["progress"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "progress"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_2;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_prog1"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_prog1") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_2 = state._tr_prog1();
-        } else {
-            _trid_2 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_prog1", _trid_2);
-        if(_trid_2) {
-            sort_m2_data1000_MC copiedState = state._copy();
-            copiedState.prog1();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["prog1"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["prog1"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "prog1"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_3;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_prog2"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_prog2") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_3 = state._tr_prog2();
-        } else {
-            _trid_3 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_prog2", _trid_3);
-        if(_trid_3) {
-            sort_m2_data1000_MC copiedState = state._copy();
-            copiedState.prog2();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["prog2"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["prog2"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "prog2"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        bool _trid_4;
-        if(dependentGuardsExist) {
-            cachedValue = parentsGuard["_tr_final_evt"];
-            dependentGuardsBoolean = (dependentGuardsOfState.find("_tr_final_evt") != dependentGuardsOfState.end());
-        }
-        if(dependentGuardsExist || dependentGuardsBoolean || parentsExist) {
-            _trid_4 = state._tr_final_evt();
-        } else {
-            _trid_4 = boost::any_cast<bool>(cachedValue);
-        }
-        newCache = newCache.set("_tr_final_evt", _trid_4);
-        if(_trid_4) {
-            sort_m2_data1000_MC copiedState = state._copy();
-            copiedState.final_evt();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(dependentInvariant.find(copiedState) == dependentInvariant.end()) {
-                    dependentInvariant.insert({copiedState, invariantDependency["final_evt"]});
-                }
-                if(dependentGuard.find(copiedState) == dependentGuard.end()) {
-                    dependentGuard.insert({copiedState, guardDependency["final_evt"]});
-                }
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "final_evt"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
+class ModelChecker {
+    private:
+        sort_m2_data1000_MC::Type type;
+        int threads;
+        bool isCaching;
+        bool isDebug;
+
+        std::list<sort_m2_data1000_MC> unvisitedStates;
+        std::unordered_set<sort_m2_data1000_MC, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> states;
+        std::atomic<int> transitions;
+        std::mutex mutex;
+        std::mutex waitMutex;
+        std::mutex guardMutex;
+        std::condition_variable waitCV;
+
+        std::atomic<bool> invariantViolatedBool;
+        std::atomic<bool> deadlockDetected;
+        sort_m2_data1000_MC counterExampleState;
+
+        std::unordered_map<string, std::unordered_set<string>> invariantDependency;
+        std::unordered_map<string, std::unordered_set<string>> guardDependency;
+        std::unordered_map<sort_m2_data1000_MC, sort_m2_data1000_MC, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> parents;
+
+    public:
+        ModelChecker() {}
 
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            guardCache.insert({state, newCache});
+        ModelChecker(sort_m2_data1000_MC::Type type, int threads, bool isCaching, bool isDebug) {
+            this->type = type;
+            this->threads = threads;
+            this->isCaching = isCaching;
+            this->isDebug = isDebug;
+            this->invariantViolatedBool = false;
+            this->deadlockDetected = false;
+            this->transitions = 0;
         }
-    } else {
-        if(state._tr_progress()) {
-            sort_m2_data1000_MC copiedState = state._copy();
-            copiedState.progress();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "progress"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_prog1()) {
-            sort_m2_data1000_MC copiedState = state._copy();
-            copiedState.prog1();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "prog1"});
-                }
-            }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_prog2()) {
-            sort_m2_data1000_MC copiedState = state._copy();
-            copiedState.prog2();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "prog2"});
-                }
+
+        void modelCheck() {
+            if (isDebug) {
+                cout << "Starting Modelchecking, STRATEGY=" << type << ", THREADS=" << threads << ", CACHING=" << isCaching << "\n";
             }
-            result.insert(copiedState);
-            transitions += 1;
-        }
-        if(state._tr_final_evt()) {
-            sort_m2_data1000_MC copiedState = state._copy();
-            copiedState.final_evt();
-            {
-                std::unique_lock<std::mutex> lock(guardMutex);
-                if(parents.find(copiedState) == parents.end()) {
-                    parents.insert({copiedState, state});
-                }
-                if(stateAccessedVia.find(copiedState) == stateAccessedVia.end()) {
-                    stateAccessedVia.insert({copiedState, "final_evt"});
-                }
+
+            if (threads <= 1) {
+                modelCheckSingleThreaded();
+            } else {
+                boost::asio::thread_pool workers(threads); // threads indicates the number of workers (without the coordinator)
+                modelCheckMultiThreaded(workers);
             }
-            result.insert(copiedState);
-            transitions += 1;
         }
 
-    }
-    return result;
-}
+        void modelCheckSingleThreaded() {
+            sort_m2_data1000_MC machine = sort_m2_data1000_MC();
+            states.insert(machine);
+            unvisitedStates.push_back(machine);
 
-static void printResult(int states, int transitions, bool deadlockDetected, bool invariantViolated, sort_m2_data1000_MC& counterExampleState, std::unordered_map<sort_m2_data1000_MC, sort_m2_data1000_MC, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual>& parents, std::unordered_map<sort_m2_data1000_MC, string, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual>& stateAccessedVia) {
-    if(deadlockDetected || invariantViolated) {
-        if(deadlockDetected) {
-            cout << "DEADLOCK DETECTED" << "\n";
-        }
-        if(invariantViolated) {
-            cout << "INVARIANT VIOLATED" << "\n";
-        }
-        cout << "COUNTER EXAMPLE TRACE: " << "\n";
+            if (isCaching) {
+                initCache(machine);
+            }
 
-        sort_m2_data1000_MC currentState = counterExampleState;
-        std::string trace = "";
-        while(parents.find(currentState) != parents.end()) {
-            std::stringstream stringStream;
-            stringStream << currentState;
-            trace.insert(0, stringStream.str());
-            trace.insert(0, "\n");
-            trace.insert(0, stateAccessedVia[currentState]);
-            trace.insert(0, "\n\n");
-            currentState = parents[currentState];
-        }
-        cout << trace;
-    }
+            while(!unvisitedStates.empty()) {
+                sort_m2_data1000_MC state = next();
 
-    if(!deadlockDetected && !invariantViolated) {
-        cout << "MODEL CHECKING SUCCESSFUL" << "\n";
-    }
-    cout << "Number of States: " << states << "\n";
-    cout << "Number of Transitions: " << transitions << "\n";
-}
+                std::unordered_set<sort_m2_data1000_MC, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> nextStates = generateNextStates(state);
+                transitions += nextStates.size();
 
-static bool checkInvariants(std::mutex& guardMutex, const sort_m2_data1000_MC& state, bool isCaching, std::unordered_map<sort_m2_data1000_MC, std::unordered_set<string>, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual>& dependentInvariant) {
-    if(isCaching) {
-        std::unordered_set<string> dependentInvariantsOfState;
-        {
-            std::unique_lock<std::mutex> lock(guardMutex);
-            dependentInvariantsOfState = dependentInvariant[state];
-        }
-        if(dependentInvariantsOfState.find("_check_inv_1") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_1()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_2") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_2()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_3") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_3()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_4") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_4()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_5") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_5()) {
-                return false;
-            }
-        }
-        if(dependentInvariantsOfState.find("_check_inv_6") == dependentInvariantsOfState.end()) {
-            if(!state._check_inv_6()) {
-                return false;
-            }
-        }
-        return true;
-    }
-    return !(!state._check_inv_1() || !state._check_inv_2() || !state._check_inv_3() || !state._check_inv_4() || !state._check_inv_5() || !state._check_inv_6());
-}
+                for(auto& nextState : nextStates) {
+                    if(states.find(nextState) == states.end()) {
+                        states.insert(nextState);
+                        parents.insert({nextState, state});
+                        unvisitedStates.push_back(nextState);
+                        if(states.size() % 50000 == 0) {
+                            cout << "VISITED STATES: " << states.size() << "\n";
+                            cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
+                            cout << "-------------------" << "\n";
+                        }
+                    }
+                }
 
-static sort_m2_data1000_MC next(std::list<sort_m2_data1000_MC>& collection, std::mutex& mutex, sort_m2_data1000_MC::Type type) {
-    std::unique_lock<std::mutex> lock(mutex);
-    switch(type) {
-        case sort_m2_data1000_MC::BFS: {
-            sort_m2_data1000_MC state = collection.front();
-            collection.pop_front();
-            return state;
-        }
-        case sort_m2_data1000_MC::DFS: {
-            sort_m2_data1000_MC state = collection.back();
-            collection.pop_back();
-            return state;
-        }
-        case sort_m2_data1000_MC::MIXED: {
-            if(collection.size() % 2 == 0) {
-                sort_m2_data1000_MC state = collection.front();
-                collection.pop_front();
-                return state;
-            } else {
-                sort_m2_data1000_MC state = collection.back();
-                collection.pop_back();
-                return state;
-            }
-        }
-    };
-}
+                if(invariantViolated(state)) {
+                    invariantViolatedBool = true;
+                    counterExampleState = state;
+                    break;
+                }
 
-static void modelCheckSingleThreaded(sort_m2_data1000_MC::Type type, bool isCaching) {
-    std::mutex mutex;
-    std::mutex guardMutex;
-
-    sort_m2_data1000_MC machine = sort_m2_data1000_MC();
-
-    std::atomic<bool> invariantViolated;
-    invariantViolated = false;
-    std::atomic<bool> deadlockDetected;
-    deadlockDetected = false;
-    std::atomic<bool> stopThreads;
-    stopThreads = false;
-
-    std::unordered_set<sort_m2_data1000_MC, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> states = std::unordered_set<sort_m2_data1000_MC, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual>();
-    states.insert(machine);
-    std::atomic<int> numberStates;
-    numberStates = 1;
-
-    std::list<sort_m2_data1000_MC> collection = std::list<sort_m2_data1000_MC>();
-    collection.push_back(machine);
-
-    std::atomic<int> transitions;
-    transitions = 0;
-
-    std::unordered_map<string, std::unordered_set<string>> invariantDependency;
-    std::unordered_map<string, std::unordered_set<string>> guardDependency;
-    std::unordered_map<sort_m2_data1000_MC, std::unordered_set<string>, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> dependentInvariant;
-    std::unordered_map<sort_m2_data1000_MC, std::unordered_set<string>, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> dependentGuard;
-    std::unordered_map<sort_m2_data1000_MC, immer::map<string, boost::any>, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> guardCache;
-    std::unordered_map<sort_m2_data1000_MC, sort_m2_data1000_MC, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> parents;
-    std::unordered_map<sort_m2_data1000_MC, string, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> stateAccessedVia;
-    if(isCaching) {
-        invariantDependency.insert({"prog2", {"_check_inv_2", "_check_inv_3", "_check_inv_1", "_check_inv_4", "_check_inv_5"}});
-        invariantDependency.insert({"prog1", {"_check_inv_2", "_check_inv_3", "_check_inv_1", "_check_inv_4", "_check_inv_5"}});
-        invariantDependency.insert({"progress", {"_check_inv_2", "_check_inv_3", "_check_inv_1", "_check_inv_6", "_check_inv_4", "_check_inv_5"}});
-        invariantDependency.insert({"final_evt", {}});
-        guardDependency.insert({"prog2", {"_tr_progress", "_tr_prog1", "_tr_prog2"}});
-        guardDependency.insert({"prog1", {"_tr_progress", "_tr_prog1", "_tr_prog2"}});
-        guardDependency.insert({"progress", {"_tr_final_evt", "_tr_progress", "_tr_prog1", "_tr_prog2"}});
-        guardDependency.insert({"final_evt", {}});
-        dependentInvariant.insert({machine, std::unordered_set<string>()});
-    }
-    sort_m2_data1000_MC counterExampleState;
-
-    while(!collection.empty() && !stopThreads) {
-        sort_m2_data1000_MC state = next(collection, mutex, type);
-
-        std::unordered_set<sort_m2_data1000_MC, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> nextStates = generateNextStates(guardMutex, state, isCaching, invariantDependency, dependentInvariant, guardDependency, dependentGuard, guardCache, parents, stateAccessedVia, transitions);
-        for(auto nextState : nextStates) {
-            if(states.find(nextState) == states.end()) {
-                numberStates += 1;
-                states.insert(nextState);
-                collection.push_back(nextState);
-                if(numberStates % 50000 == 0) {
-                    cout << "VISITED STATES: " << numberStates << "\n";
-                    cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
-                    cout << "-------------------" << "\n";
+                if(nextStates.empty()) {
+                    deadlockDetected = true;
+                    counterExampleState = state;
+                    break;
                 }
+
             }
+            printResult();
         }
 
-        if(!checkInvariants(guardMutex, state, isCaching, dependentInvariant)) {
-            invariantViolated = true;
-            stopThreads = true;
-            counterExampleState = state;
-        }
+        void modelCheckMultiThreaded(boost::asio::thread_pool& workers) {
+            sort_m2_data1000_MC machine = sort_m2_data1000_MC();
+            states.insert(machine);
+            unvisitedStates.push_back(machine);
 
-        if(nextStates.empty()) {
-            deadlockDetected = true;
-            stopThreads = true;
-            counterExampleState = state;
-        }
+            std::atomic<bool> stopThreads;
+            stopThreads = false;
+            std::atomic<int> possibleQueueChanges;
+            possibleQueueChanges = 0;
 
-    }
-    printResult(numberStates, transitions, deadlockDetected, invariantViolated, counterExampleState, parents, stateAccessedVia);
-}
+            if(isCaching) {
+                initCache(machine);
+            }
 
-static void modelCheckMultiThreaded(sort_m2_data1000_MC::Type type, int threads, bool isCaching) {
-    std::mutex mutex;
-    std::mutex waitMutex;
-    std::mutex guardMutex;
-    std::condition_variable waitCV;
-
-    sort_m2_data1000_MC machine = sort_m2_data1000_MC();
-
-
-    std::atomic<bool> invariantViolated;
-    invariantViolated = false;
-    std::atomic<bool> deadlockDetected;
-    deadlockDetected = false;
-    std::atomic<bool> stopThreads;
-    stopThreads = false;
-
-    std::unordered_set<sort_m2_data1000_MC, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> states = std::unordered_set<sort_m2_data1000_MC, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual>();
-    states.insert(machine);
-    std::atomic<int> numberStates;
-    numberStates = 1;
-
-    std::list<sort_m2_data1000_MC> collection = std::list<sort_m2_data1000_MC>();
-    collection.push_back(machine);
-
-    std::atomic<int> transitions;
-    transitions = 0;
-
-    std::atomic<int> possibleQueueChanges;
-    possibleQueueChanges = 0;
-
-    std::atomic<bool> waitFlag;
-    waitFlag = true;
-
-    std::unordered_map<string, std::unordered_set<string>> invariantDependency;
-    std::unordered_map<string, std::unordered_set<string>> guardDependency;
-    std::unordered_map<sort_m2_data1000_MC, std::unordered_set<string>, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> dependentInvariant;
-    std::unordered_map<sort_m2_data1000_MC, std::unordered_set<string>, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> dependentGuard;
-    std::unordered_map<sort_m2_data1000_MC, immer::map<string, boost::any>, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> guardCache;
-    std::unordered_map<sort_m2_data1000_MC, sort_m2_data1000_MC, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> parents;
-    std::unordered_map<sort_m2_data1000_MC, string, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> stateAccessedVia;
-    if(isCaching) {
-        invariantDependency.insert({"prog2", {"_check_inv_2", "_check_inv_3", "_check_inv_1", "_check_inv_4", "_check_inv_5"}});
-        invariantDependency.insert({"prog1", {"_check_inv_2", "_check_inv_3", "_check_inv_1", "_check_inv_4", "_check_inv_5"}});
-        invariantDependency.insert({"progress", {"_check_inv_2", "_check_inv_3", "_check_inv_1", "_check_inv_6", "_check_inv_4", "_check_inv_5"}});
-        invariantDependency.insert({"final_evt", {}});
-        guardDependency.insert({"prog2", {"_tr_progress", "_tr_prog1", "_tr_prog2"}});
-        guardDependency.insert({"prog1", {"_tr_progress", "_tr_prog1", "_tr_prog2"}});
-        guardDependency.insert({"progress", {"_tr_final_evt", "_tr_progress", "_tr_prog1", "_tr_prog2"}});
-        guardDependency.insert({"final_evt", {}});
-        dependentInvariant.insert({machine, std::unordered_set<string>()});
-    }
-    sort_m2_data1000_MC counterExampleState;
+            std::atomic<bool> waitFlag;
+            waitFlag = true;
+
+            while(!unvisitedStates.empty() && !stopThreads) {
+                possibleQueueChanges += 1;
+                sort_m2_data1000_MC state = next();
+                std::packaged_task<void()> task([&, state] {
+                    std::unordered_set<sort_m2_data1000_MC, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> nextStates = generateNextStates(state);
+                    transitions += nextStates.size();
+
+                    for(auto& nextState : nextStates) {
+                        {
+                            std::unique_lock<std::mutex> lock(mutex);
+                            if(states.find(nextState) == states.end()) {
+                                states.insert(nextState);
+                                parents.insert({nextState, state});
+                                unvisitedStates.push_back(nextState); // TODO: sync ?
+                                if(isDebug && states.size() % 50000 == 0) {
+                                    cout << "VISITED STATES: " << states.size() << "\n";
+                                    cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
+                                    cout << "-------------------" << "\n";
+                                }
+                            }
+                        }
+                    }
 
-    boost::asio::thread_pool workers(threads);
+                    {
+                        std::unique_lock<std::mutex> lock(mutex);
+                        possibleQueueChanges -= 1;
+                        int running = possibleQueueChanges;
+                        if (!unvisitedStates.empty() || running == 0) {
+                            {
+                                std::unique_lock<std::mutex> lock(waitMutex);
+                                waitFlag = false;
+                                waitCV.notify_one();
+                            }
+                        }
+                    }
 
-    while(!collection.empty() && !stopThreads) {
-        possibleQueueChanges += 1;
-        sort_m2_data1000_MC state = next(collection, mutex, type);
-        std::packaged_task<void()> task([&, state] {
-            std::unordered_set<sort_m2_data1000_MC, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> nextStates = generateNextStates(guardMutex, state, isCaching, invariantDependency, dependentInvariant, guardDependency, dependentGuard, guardCache, parents, stateAccessedVia, transitions);
+                    if(invariantViolated(state)) {
+                        invariantViolatedBool = true;
+                        counterExampleState = state;
+                        stopThreads = true;
+                    }
 
+                    if(nextStates.empty()) {
+                        deadlockDetected = true;
+                        counterExampleState = state;
+                        stopThreads = true;
+                    }
+
+                });
+
+                waitFlag = true;
+                boost::asio::post(workers, std::move(task));
 
-            for(auto nextState : nextStates) {
                 {
-                    std::unique_lock<std::mutex> lock(mutex);
-                    if(states.find(nextState) == states.end()) {
-                        numberStates += 1;
-                        states.insert(nextState);
-                        collection.push_back(nextState);
-                        if(numberStates % 50000 == 0) {
-                            cout << "VISITED STATES: " << numberStates << "\n";
-                            cout << "EVALUATED TRANSITIONS: " << transitions << "\n";
-                            cout << "-------------------" << "\n";
-                        }
+                    std::unique_lock<std::mutex> lock(waitMutex);
+                    while (unvisitedStates.empty() && possibleQueueChanges > 0) {
+                        waitCV.wait(lock, [&] {
+                            return waitFlag == false;
+                        });
                     }
                 }
             }
+            workers.join();
+            printResult();
+        }
 
-            {
-                std::unique_lock<std::mutex> lock(mutex);
-                possibleQueueChanges -= 1;
-                int running = possibleQueueChanges;
-                if (!collection.empty() || running == 0) {
-                    {
-                        std::unique_lock<std::mutex> lock(waitMutex);
-                        waitFlag = false;
-                        waitCV.notify_one();
+        void initCache(sort_m2_data1000_MC& machine) {
+            invariantDependency.insert({"prog2", {"_check_inv_2", "_check_inv_3", "_check_inv_1", "_check_inv_4", "_check_inv_5"}});
+            invariantDependency.insert({"prog1", {"_check_inv_2", "_check_inv_3", "_check_inv_1", "_check_inv_4", "_check_inv_5"}});
+            invariantDependency.insert({"progress", {"_check_inv_2", "_check_inv_3", "_check_inv_1", "_check_inv_6", "_check_inv_4", "_check_inv_5"}});
+            invariantDependency.insert({"final_evt", {}});
+            invariantDependency.insert({"", {}});
+            guardDependency.insert({"prog2", {"_tr_progress", "_tr_prog1", "_tr_prog2"}});
+            guardDependency.insert({"prog1", {"_tr_progress", "_tr_prog1", "_tr_prog2"}});
+            guardDependency.insert({"progress", {"_tr_final_evt", "_tr_progress", "_tr_prog1", "_tr_prog2"}});
+            guardDependency.insert({"final_evt", {}});
+        }
+
+
+    private:
+        sort_m2_data1000_MC next() {
+            std::unique_lock<std::mutex> lock(mutex);
+            switch(type) {
+                case sort_m2_data1000_MC::BFS: {
+                    sort_m2_data1000_MC state = unvisitedStates.front();
+                    unvisitedStates.pop_front();
+                    return state;
+                }
+                case sort_m2_data1000_MC::DFS: {
+                    sort_m2_data1000_MC state = unvisitedStates.back();
+                    unvisitedStates.pop_back();
+                    return state;
+                }
+                case sort_m2_data1000_MC::MIXED: {
+                    if(unvisitedStates.size() % 2 == 0) {
+                        sort_m2_data1000_MC state = unvisitedStates.front();
+                        unvisitedStates.pop_front();
+                        return state;
+                    } else {
+                        sort_m2_data1000_MC state = unvisitedStates.back();
+                        unvisitedStates.pop_back();
+                        return state;
                     }
                 }
             }
+        }
 
-            if(nextStates.empty()) {
-                deadlockDetected = true;
-                stopThreads = true;
-                counterExampleState = state;
+        std::unordered_set<sort_m2_data1000_MC, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> generateNextStates(const sort_m2_data1000_MC& state) {
+            std::unordered_set<sort_m2_data1000_MC, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual> result = std::unordered_set<sort_m2_data1000_MC, sort_m2_data1000_MC::Hash, sort_m2_data1000_MC::HashEqual>();
+            if(state._tr_progress(isCaching)) {
+                sort_m2_data1000_MC copiedState = state._copy(guardDependency["progress"]);
+                copiedState.progress();
+                copiedState.stateAccessedVia = "progress";
+                result.insert(copiedState);
+            }
+            if(state._tr_prog1(isCaching)) {
+                sort_m2_data1000_MC copiedState = state._copy(guardDependency["prog1"]);
+                copiedState.prog1();
+                copiedState.stateAccessedVia = "prog1";
+                result.insert(copiedState);
+            }
+            if(state._tr_prog2(isCaching)) {
+                sort_m2_data1000_MC copiedState = state._copy(guardDependency["prog2"]);
+                copiedState.prog2();
+                copiedState.stateAccessedVia = "prog2";
+                result.insert(copiedState);
+            }
+            if(state._tr_final_evt(isCaching)) {
+                sort_m2_data1000_MC copiedState = state._copy(guardDependency["final_evt"]);
+                copiedState.final_evt();
+                copiedState.stateAccessedVia = "final_evt";
+                result.insert(copiedState);
             }
 
-            if(!checkInvariants(guardMutex, state, isCaching, dependentInvariant)) {
-                invariantViolated = true;
-                stopThreads = true;
-                counterExampleState = state;
+            return result;
+        }
+
+        bool invariantViolated(const sort_m2_data1000_MC& state) {
+            if(isCaching) {
+                std::unordered_set<string> dependentInvariantsOfState = invariantDependency[state.stateAccessedVia];
+                if(dependentInvariantsOfState.find("_check_inv_1") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_1()) {
+                        return false;
+                    }
+                }
+                if(dependentInvariantsOfState.find("_check_inv_2") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_2()) {
+                        return false;
+                    }
+                }
+                if(dependentInvariantsOfState.find("_check_inv_3") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_3()) {
+                        return false;
+                    }
+                }
+                if(dependentInvariantsOfState.find("_check_inv_4") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_4()) {
+                        return false;
+                    }
+                }
+                if(dependentInvariantsOfState.find("_check_inv_5") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_5()) {
+                        return false;
+                    }
+                }
+                if(dependentInvariantsOfState.find("_check_inv_6") == dependentInvariantsOfState.end()) {
+                    if(!state._check_inv_6()) {
+                        return false;
+                    }
+                }
+                return false;
             }
+            return !(state._check_inv_1() && state._check_inv_2() && state._check_inv_3() && state._check_inv_4() && state._check_inv_5() && state._check_inv_6());
+        }
 
 
-        });
-        waitFlag = true;
-        boost::asio::post(workers, std::move(task));
+        void printResult() {
+            if(deadlockDetected || invariantViolatedBool) {
+                if(deadlockDetected) {
+                    cout << "DEADLOCK DETECTED" << "\n";
+                } else {
+                    cout << "INVARIANT VIOLATED" << "\n";
+                }
 
-        {
-            std::unique_lock<std::mutex> lock(waitMutex);
-            if (collection.empty() && possibleQueueChanges > 0) {
-                waitCV.wait(lock, [&] {
-                    return waitFlag == false;
-                });
+                cout << "COUNTER EXAMPLE TRACE: " << "\n";
+
+                std::string trace = "";
+                while(parents.find(counterExampleState) != parents.end()) {
+                    std::stringstream stringStream;
+                    stringStream << counterExampleState;
+                    trace.insert(0, stringStream.str());
+                    trace.insert(0, "\n");
+                    trace.insert(0, counterExampleState.stateAccessedVia);
+                    trace.insert(0, "\n\n");
+                    counterExampleState = parents[counterExampleState];
+                }
+                cout << trace;
+            } else {
+                cout << "MODEL CHECKING SUCCESSFUL" << "\n";
             }
+
+            cout << "Number of States: " << states.size() << "\n";
+            cout << "Number of Transitions: " << transitions << "\n";
         }
-    }
-    workers.join();
-    printResult(numberStates, transitions, deadlockDetected, invariantViolated, counterExampleState, parents, stateAccessedVia);
-}
+};
 
 int main(int argc, char *argv[]) {
     if(argc != 4) {
@@ -794,11 +638,12 @@ int main(int argc, char *argv[]) {
         return - 1;
     }
 
-    if(threads == 1) {
-        modelCheckSingleThreaded(type, isCaching);
-    } else {
-        modelCheckMultiThreaded(type, threads, isCaching);
-    }
+    bool isDebug = true;
+    // TODO
+
+    ModelChecker modelchecker(type, threads, isCaching, isDebug);
+    modelchecker.modelCheck();
+
     return 0;
 }
 
diff --git a/src/main/resources/de/hhu/stups/codegenerator/CppTemplate.stg b/src/main/resources/de/hhu/stups/codegenerator/CppTemplate.stg
index e8ebe59136be8f69b52b91bd424c688d3d3d4692..43c824f2a4f2f63acc76fe31d87c617c35f9456a 100644
--- a/src/main/resources/de/hhu/stups/codegenerator/CppTemplate.stg
+++ b/src/main/resources/de/hhu/stups/codegenerator/CppTemplate.stg
@@ -498,8 +498,9 @@ transition(noParameters, noPredicate, identifier, subType, operationName, predic
         <if(noPredicate)>
         return true;
         <else>
-        this->_tr_cache_<operationName> = (<predicate>).booleanValue();
-        return this->_tr_cache_<operationName>.get();
+        bool __tmp_result = (<predicate>).booleanValue();
+        if (isCaching) this->_tr_cache_<operationName> = __tmp_result;
+        else return __tmp_result;
         <endif>
         <else>
         BSet\<<subType>\> <identifier> = BSet\<<subType>\>();