Merge lp:~tapaal-ltl/verifypn/resumable-suc-generator into lp:~tapaal-ltl/verifypn/ltl_model_checker

Proposed by Simon Virenfeldt
Status: Merged
Merged at revision: 232
Proposed branch: lp:~tapaal-ltl/verifypn/resumable-suc-generator
Merge into: lp:~tapaal-ltl/verifypn/ltl_model_checker
Diff against target: 1016 lines (+357/-197)
15 files modified
CMakeLists.txt (+2/-2)
include/LTL/BuchiSuccessorGenerator.h (+2/-2)
include/LTL/LTL_algorithm/ModelChecker.h (+2/-0)
include/LTL/LTL_algorithm/NestedDepthFirstSearch.h (+9/-3)
include/LTL/LTL_algorithm/TarjanModelChecker.h (+26/-22)
include/LTL/ProductSuccessorGenerator.h (+68/-5)
include/LTL/Structures/ProductState.h (+2/-0)
include/PetriEngine/PQL/Expressions.h (+2/-2)
include/PetriEngine/SuccessorGenerator.h (+5/-1)
src/LTL/LTL_algorithm/LTLToBuchi.cpp (+17/-31)
src/LTL/LTL_algorithm/NestedDepthFirstSearch.cpp (+57/-51)
src/LTL/LTL_algorithm/ProductSuccessorGenerator.cpp (+42/-9)
src/LTL/LTL_algorithm/TarjanModelChecker.cpp (+118/-64)
src/LTLMain.cpp (+4/-4)
src/PetriEngine/SuccessorGenerator.cpp (+1/-1)
To merge this branch: bzr merge lp:~tapaal-ltl/verifypn/resumable-suc-generator
Reviewer Review Type Date Requested Status
Simon Virenfeldt Approve
Review via email: mp+393497@code.launchpad.net

Commit message

Merge branch resumable_suc_generator

To post a comment you must log in.
262. By Simon Virenfeldt

Removed some commented code lines

263. By Simon Virenfeldt

Merge remote

Revision history for this message
Simon Virenfeldt (simwir) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2020-10-19 11:13:27 +0000
+++ CMakeLists.txt 2020-11-09 13:59:57 +0000
@@ -29,7 +29,7 @@
29endif()29endif()
3030
31if (CMAKE_BUILD_TYPE MATCHES Debug)31if (CMAKE_BUILD_TYPE MATCHES Debug)
32 #add_compile_definitions(PRINTF_DEBUG)32 add_compile_definitions(PRINTF_DEBUG)
33endif()33endif()
3434
35if (VERIFYPN_Static)35if (VERIFYPN_Static)
@@ -59,7 +59,7 @@
59endif ()59endif ()
6060
61set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall -pedantic-errors -O3 -DNDEBUG")61set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall -pedantic-errors -O3 -DNDEBUG")
62set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -fno-omit-frame-pointer -fsanitize=address ")62set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -fno-omit-frame-pointer")
63set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} -O3 -DNDEBUG")63set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} -O3 -DNDEBUG")
64if (VERIFYPN_Static AND NOT APPLE)64if (VERIFYPN_Static AND NOT APPLE)
65 set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} -static")65 set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} -static")
6666
=== modified file 'include/LTL/BuchiSuccessorGenerator.h'
--- include/LTL/BuchiSuccessorGenerator.h 2020-10-05 10:15:17 +0000
+++ include/LTL/BuchiSuccessorGenerator.h 2020-11-09 13:59:57 +0000
@@ -18,7 +18,7 @@
18namespace LTL {18namespace LTL {
19 class BuchiSuccessorGenerator {19 class BuchiSuccessorGenerator {
20 public:20 public:
21 BuchiSuccessorGenerator(Structures::BuchiAutomaton automaton)21 explicit BuchiSuccessorGenerator(Structures::BuchiAutomaton automaton)
22 : aut(std::move(automaton)) {22 : aut(std::move(automaton)) {
23 }23 }
2424
@@ -31,7 +31,7 @@
31 bool next(size_t &state, bdd &cond) {31 bool next(size_t &state, bdd &cond) {
32 if (!succ->done()) {32 if (!succ->done()) {
33 state = aut.buchi->state_number(succ->dst());33 state = aut.buchi->state_number(succ->dst());
34#ifdef PRINTF_DEBUG34#ifdef _PRINTF_DEBUG
35 std::cerr << "buchi state " << state << std::endl;35 std::cerr << "buchi state " << state << std::endl;
36#endif36#endif
37 cond = succ->cond();37 cond = succ->cond();
3838
=== modified file 'include/LTL/LTL_algorithm/ModelChecker.h'
--- include/LTL/LTL_algorithm/ModelChecker.h 2020-10-16 11:34:00 +0000
+++ include/LTL/LTL_algorithm/ModelChecker.h 2020-11-09 13:59:57 +0000
@@ -20,6 +20,8 @@
20 std::unique_ptr<ProductSuccessorGenerator> successorGenerator;20 std::unique_ptr<ProductSuccessorGenerator> successorGenerator;
21 const PetriEngine::PetriNet &net;21 const PetriEngine::PetriNet &net;
22 PetriEngine::PQL::Condition_ptr formula;22 PetriEngine::PQL::Condition_ptr formula;
23
24 size_t _discovered = 0;
23 };25 };
24}26}
2527
2628
=== modified file 'include/LTL/LTL_algorithm/NestedDepthFirstSearch.h'
--- include/LTL/LTL_algorithm/NestedDepthFirstSearch.h 2020-10-05 10:15:17 +0000
+++ include/LTL/LTL_algorithm/NestedDepthFirstSearch.h 2020-11-09 13:59:57 +0000
@@ -12,6 +12,7 @@
12#include "LTL/Structures/ProductStateFactory.h"12#include "LTL/Structures/ProductStateFactory.h"
1313
14#include <ptrie/ptrie_stable.h>14#include <ptrie/ptrie_stable.h>
15#include <unordered_set>
1516
16using namespace PetriEngine;17using namespace PetriEngine;
1718
@@ -20,7 +21,7 @@
20 public:21 public:
21 NestedDepthFirstSearch(const PetriNet &net, PetriEngine::PQL::Condition_ptr ptr)22 NestedDepthFirstSearch(const PetriNet &net, PetriEngine::PQL::Condition_ptr ptr)
22 : ModelChecker(net, ptr), factory{net, successorGenerator->initial_buchi_state()},23 : ModelChecker(net, ptr), factory{net, successorGenerator->initial_buchi_state()},
23 mark1(net, 0, (int)net.numberOfPlaces() + 1), mark2(net, 0, (int)net.numberOfPlaces() + 1) {}24 states(net, 0, (int)net.numberOfPlaces() + 1) {}
2425
25 bool isSatisfied() override;26 bool isSatisfied() override;
2627
@@ -28,9 +29,14 @@
28 using State = LTL::Structures::ProductState;29 using State = LTL::Structures::ProductState;
2930
30 Structures::ProductStateFactory factory;31 Structures::ProductStateFactory factory;
31 PetriEngine::Structures::StateSet mark1;32 PetriEngine::Structures::StateSet states;
32 PetriEngine::Structures::StateSet mark2;33 std::set<size_t> mark1;
34 std::set<size_t> mark2;
3335
36 struct StackEntry {
37 size_t id;
38 successor_info sucinfo;
39 };
3440
35 State *seed;41 State *seed;
36 bool violation = false;42 bool violation = false;
3743
=== modified file 'include/LTL/LTL_algorithm/TarjanModelChecker.h'
--- include/LTL/LTL_algorithm/TarjanModelChecker.h 2020-10-19 12:35:11 +0000
+++ include/LTL/LTL_algorithm/TarjanModelChecker.h 2020-11-09 13:59:57 +0000
@@ -18,10 +18,11 @@
1818
19namespace LTL {19namespace LTL {
2020
21 template <bool SaveTrace>
21 class TarjanModelChecker : public ModelChecker {22 class TarjanModelChecker : public ModelChecker {
22 public:23 public:
23 TarjanModelChecker(const PetriEngine::PetriNet &net, const Condition_ptr &cond)24 TarjanModelChecker(const PetriEngine::PetriNet &net, const Condition_ptr &cond)
24 : ModelChecker(net, cond), successorGenerator(net, cond), factory(net, successorGenerator.initial_buchi_state()),25 : ModelChecker(net, cond), factory(net, successorGenerator->initial_buchi_state()),
25 seen(net, 0, (int) net.numberOfPlaces() + 1) {26 seen(net, 0, (int) net.numberOfPlaces() + 1) {
26 chash.fill(std::numeric_limits<idx_t>::max());27 chash.fill(std::numeric_limits<idx_t>::max());
27 }28 }
@@ -31,45 +32,46 @@
31 private:32 private:
32 using State = LTL::Structures::ProductState;33 using State = LTL::Structures::ProductState;
33 using idx_t = size_t;34 using idx_t = size_t;
35 static constexpr idx_t HashSz = 4096;
3436
35 LTL::ProductSuccessorGenerator successorGenerator;
36 LTL::Structures::ProductStateFactory factory;37 LTL::Structures::ProductStateFactory factory;
3738
38 PetriEngine::Structures::StateSet seen;39 PetriEngine::Structures::StateSet seen;
39 std::unordered_set<idx_t> store;40 std::unordered_set<idx_t> store;
40 //PetriEngine::Structures::StateSet store;
4141
42 static constexpr idx_t HashSz = 4096;
43 std::array<idx_t, HashSz> chash;42 std::array<idx_t, HashSz> chash;
44 inline idx_t hash_search(idx_t stateid) {
45 idx_t idx = chash[hash(stateid)];
46 while (idx != stateid && idx != std::numeric_limits<idx_t>::max()) {
47 idx = cstack[idx].next;
48 }
49 return idx;
50 }
5143
52 inline idx_t hash(idx_t id) {44 static inline idx_t hash(idx_t id) {
53 return id % HashSz;45 return id % HashSz;
54 }46 }
5547
56 struct CStack {48 struct PlainCEntry {
57 size_t lowlink;49 size_t lowlink;
58 size_t stateid;50 size_t stateid;
59 size_t next = std::numeric_limits<idx_t>::max();51 size_t next = std::numeric_limits<idx_t>::max();
6052
61 CStack(size_t lowlink, size_t stateid, size_t next) : lowlink(lowlink), stateid(stateid), next(next) {}53 PlainCEntry(size_t lowlink, size_t stateid, size_t next) : lowlink(lowlink), stateid(stateid), next(next) {}
62 };54 };
6355
64 struct DStack {56 struct TracableCEntry : PlainCEntry {
57 idx_t lowsource = std::numeric_limits<size_t>::max();
58 uint32_t sourcetrans;
59
60 TracableCEntry(size_t lowlink, size_t stateid, size_t next) : PlainCEntry(lowlink, stateid, next) {}
61 };
62
63 using CEntry = std::conditional_t<SaveTrace,
64 TracableCEntry,
65 PlainCEntry>;
66
67 struct DEntry {
65 size_t pos;68 size_t pos;
66 uint32_t nexttrans = -1;69 successor_info sucinfo;
67 std::optional<std::vector<size_t>> neighbors;
68 };70 };
6971
7072
71 std::vector<CStack> cstack;73 std::vector<CEntry> cstack;
72 std::stack<DStack> dstack;74 std::stack<DEntry> dstack;
73 std::stack<idx_t> astack;75 std::stack<idx_t> astack;
74 bool violation = false;76 bool violation = false;
7577
@@ -79,8 +81,10 @@
7981
80 void update(idx_t to);82 void update(idx_t to);
8183
82 bool nexttrans(State &state, DStack &delem);84 bool nexttrans(State &state, State& parent, DEntry &delem);
83 };85 };
86extern template class TarjanModelChecker<true>;
87extern template class TarjanModelChecker<false>;
84}88}
8589
86#endif //VERIFYPN_TARJANMODELCHECKER_H90#endif //VERIFYPN_TARJANMODELCHECKER_H
8791
=== modified file 'include/LTL/ProductSuccessorGenerator.h'
--- include/LTL/ProductSuccessorGenerator.h 2020-10-16 11:20:30 +0000
+++ include/LTL/ProductSuccessorGenerator.h 2020-11-09 13:59:57 +0000
@@ -11,13 +11,63 @@
11#include "LTL/BuchiSuccessorGenerator.h"11#include "LTL/BuchiSuccessorGenerator.h"
12#include "LTL/LTLToBuchi.h"12#include "LTL/LTLToBuchi.h"
1313
14
14namespace LTL {15namespace LTL {
16 /**
17 * type holding sufficient information to resume successor generation for a state from a given point.
18 */
19 struct successor_info {
20 uint32_t pcounter;
21 uint32_t tcounter;
22 size_t buchi_state;
23 size_t last_state;
24
25 friend bool operator==(const successor_info &lhs, const successor_info &rhs) {
26 return lhs.pcounter == rhs.pcounter &&
27 lhs.tcounter == rhs.tcounter &&
28 lhs.buchi_state == rhs.buchi_state &&
29 lhs.last_state == rhs.last_state;
30 }
31
32 friend bool operator!=(const successor_info &lhs, const successor_info &rhs) {
33 return !(rhs == lhs);
34 }
35
36 inline bool has_pcounter() const {
37 return pcounter != NoPCounter;
38 }
39
40 inline bool has_tcounter() const {
41 return tcounter != NoTCounter;
42 }
43
44 inline bool has_buchistate() const {
45 return buchi_state != NoBuchiState;
46 }
47
48 inline bool has_prev_state() const {
49 return last_state != NoLastState;
50 }
51
52 static constexpr auto NoPCounter = 0;
53 static constexpr auto NoTCounter = std::numeric_limits<uint32_t>::max();
54 static constexpr auto NoBuchiState = std::numeric_limits<size_t>::max();
55 static constexpr auto NoLastState = std::numeric_limits<size_t>::max();
56 };
57
58 constexpr successor_info initial_suc_info{
59 successor_info::NoPCounter,
60 successor_info::NoTCounter,
61 successor_info::NoBuchiState,
62 successor_info::NoLastState
63 };
64
15 class ProductSuccessorGenerator : public PetriEngine::SuccessorGenerator {65 class ProductSuccessorGenerator : public PetriEngine::SuccessorGenerator {
16 public:66 public:
67
17 ProductSuccessorGenerator(const PetriEngine::PetriNet &net,68 ProductSuccessorGenerator(const PetriEngine::PetriNet &net,
18 const PetriEngine::PQL::Condition_ptr& cond)69 const PetriEngine::PQL::Condition_ptr &cond)
19 : PetriEngine::SuccessorGenerator(net), buchi(makeBuchiAutomaton(cond))70 : PetriEngine::SuccessorGenerator(net), buchi(makeBuchiAutomaton(cond)) {}
20 {}
2171
22 [[nodiscard]] size_t initial_buchi_state() const { return buchi.initial_state_number(); };72 [[nodiscard]] size_t initial_buchi_state() const { return buchi.initial_state_number(); };
2373
@@ -43,8 +93,21 @@
43 }93 }
44 }94 }
4595
46 protected:96 /**
47 bool next(LTL::Structures::ProductState &write, uint32_t &tindex);97 * prepare a state for successor generation, starting from specific point in iteration
98 * @param state the source state to generate successors from
99 * @param sucinfo the point in the iteration to start from, as returned by `next`.
100 */
101 void prepare(const LTL::Structures::ProductState *state, const successor_info &sucinfo);
102
103 /**
104 * compute the next successor from the last state that was sent to `prepare`.
105 * @param[out] state the state to write
106 * @param[out] sucinfo checkpoint information from which iteration can later be resumed.
107 * @return `true` if a successor was successfully generated, `false` otherwise.
108 * @warning do not use the same State for both prepare and next, this will cause wildly incorrect behaviour!
109 */
110 bool next(Structures::ProductState &state, successor_info &sucinfo);
48111
49 private:112 private:
50 BuchiSuccessorGenerator buchi;113 BuchiSuccessorGenerator buchi;
51114
=== modified file 'include/LTL/Structures/ProductState.h'
--- include/LTL/Structures/ProductState.h 2020-10-16 11:20:30 +0000
+++ include/LTL/Structures/ProductState.h 2020-11-09 13:59:57 +0000
@@ -48,6 +48,8 @@
48 getBuchiState() == rhs.getBuchiState();*/48 getBuchiState() == rhs.getBuchiState();*/
49 }49 }
5050
51 size_t size() const { return buchi_state_idx + 1; }
52
51 bool operator!=(const ProductState &rhs) const {53 bool operator!=(const ProductState &rhs) const {
52 return !(rhs == *this);54 return !(rhs == *this);
53 }55 }
5456
=== modified file 'include/PetriEngine/PQL/Expressions.h'
--- include/PetriEngine/PQL/Expressions.h 2020-09-23 12:26:04 +0000
+++ include/PetriEngine/PQL/Expressions.h 2020-11-09 13:59:57 +0000
@@ -533,7 +533,7 @@
533 // TODO implement533 // TODO implement
534 assert(false); std::cerr << "TODO implement" << std::endl; exit(0);534 assert(false); std::cerr << "TODO implement" << std::endl; exit(0);
535 }535 }
536 bool containsNext() const override { return true; }536 bool containsNext() const override { return _cond->containsNext(); }
537 virtual bool isLoopSensitive() const override { return true; }537 virtual bool isLoopSensitive() const override { return true; }
538 void visit(Visitor&) const override;538 void visit(Visitor&) const override;
539 private:539 private:
@@ -569,7 +569,7 @@
569 // TODO implement569 // TODO implement
570 assert(false); std::cerr << "TODO implement" << std::endl; exit(0);570 assert(false); std::cerr << "TODO implement" << std::endl; exit(0);
571 }571 }
572 bool containsNext() const override { return true; }572 bool containsNext() const override { return _cond->containsNext(); }
573 virtual bool isLoopSensitive() const override { return true; }573 virtual bool isLoopSensitive() const override { return true; }
574 void visit(Visitor&) const override;574 void visit(Visitor&) const override;
575 private:575 private:
576576
=== modified file 'include/PetriEngine/SuccessorGenerator.h'
--- include/PetriEngine/SuccessorGenerator.h 2020-10-16 11:20:30 +0000
+++ include/PetriEngine/SuccessorGenerator.h 2020-11-09 13:59:57 +0000
@@ -60,16 +60,20 @@
60 */60 */
61 void producePostset(Structures::State& write, uint32_t t);61 void producePostset(Structures::State& write, uint32_t t);
6262
63 size_t last_transition() const { return _suc_tcounter == std::numeric_limits<uint32_t>::max() ? std::numeric_limits<uint32_t>::max() : _suc_tcounter - 1; }
64
63protected:65protected:
64 const PetriNet& _net;66 const PetriNet& _net;
6567
66 bool next(Structures::State &write, uint32_t &tindex);68 bool next(Structures::State &write, uint32_t &tindex);
6769
68 const Structures::State* _parent;70 const Structures::State* _parent;
69private:71
70 uint32_t _suc_pcounter;72 uint32_t _suc_pcounter;
71 uint32_t _suc_tcounter;73 uint32_t _suc_tcounter;
7274
75private:
76
73 friend class ReducingSuccessorGenerator;77 friend class ReducingSuccessorGenerator;
7478
75};79};
7680
=== modified file 'src/LTL/LTL_algorithm/LTLToBuchi.cpp'
--- src/LTL/LTL_algorithm/LTLToBuchi.cpp 2020-10-16 11:20:30 +0000
+++ src/LTL/LTL_algorithm/LTLToBuchi.cpp 2020-11-09 13:59:57 +0000
@@ -29,8 +29,6 @@
2929
30 void _accept(const PetriEngine::PQL::OrCondition *element) override;30 void _accept(const PetriEngine::PQL::OrCondition *element) override;
3131
32 //void _accept(const PetriEngine::PQL::CompareConjunction *element) override;
33
34 void _accept(const PetriEngine::PQL::LessThanCondition *element) override;32 void _accept(const PetriEngine::PQL::LessThanCondition *element) override;
3533
36 void _accept(const PetriEngine::PQL::LessThanOrEqualCondition *element) override;34 void _accept(const PetriEngine::PQL::LessThanOrEqualCondition *element) override;
@@ -63,7 +61,7 @@
6361
64 public:62 public:
6563
66 FormulaToSpotSyntax(std::ostream &os = std::cout)64 explicit FormulaToSpotSyntax(std::ostream &os = std::cout)
67 : PetriEngine::PQL::QueryPrinter(os) {}65 : PetriEngine::PQL::QueryPrinter(os) {}
6866
69 auto begin() const {67 auto begin() const {
@@ -147,88 +145,76 @@
147145
148 void FormulaToSpotSyntax::_accept(const PetriEngine::PQL::LiteralExpr *element) {146 void FormulaToSpotSyntax::_accept(const PetriEngine::PQL::LiteralExpr *element) {
149 assert(false);147 assert(false);
150 std::cerr << "LiteralExpr should not be visited by Spot serialiezr" << std::endl;148 std::cerr << "LiteralExpr should not be visited by Spot serializer" << std::endl;
151 exit(1);149 exit(1);
152 //make_atomic_prop(element->shared_from_this());150 //make_atomic_prop(element->shared_from_this());
153 }151 }
154152
155 void FormulaToSpotSyntax::_accept(const PetriEngine::PQL::PlusExpr *element) {153 void FormulaToSpotSyntax::_accept(const PetriEngine::PQL::PlusExpr *element) {
156 assert(false);154 assert(false);
157 std::cerr << "PlusExpr should not be visited by Spot serialiezr" << std::endl;155 std::cerr << "PlusExpr should not be visited by Spot serializer" << std::endl;
158 exit(1);156 exit(1);
159 //make_atomic_prop(element->shared_from_this());157 //make_atomic_prop(element->shared_from_this());
160 }158 }
161159
162 void FormulaToSpotSyntax::_accept(const PetriEngine::PQL::MultiplyExpr *element) {160 void FormulaToSpotSyntax::_accept(const PetriEngine::PQL::MultiplyExpr *element) {
163 assert(false);161 assert(false);
164 std::cerr << "MultiplyExpr should not be visited by Spot serialiezr" << std::endl;162 std::cerr << "MultiplyExpr should not be visited by Spot serializer" << std::endl;
165 exit(1);163 exit(1);
166 //make_atomic_prop(element->shared_from_this());164 //make_atomic_prop(element->shared_from_this());
167 }165 }
168166
169 void FormulaToSpotSyntax::_accept(const PetriEngine::PQL::MinusExpr *element) {167 void FormulaToSpotSyntax::_accept(const PetriEngine::PQL::MinusExpr *element) {
170 assert(false);168 assert(false);
171 std::cerr << "MinusExpr should not be visited by Spot serialiezr" << std::endl;169 std::cerr << "MinusExpr should not be visited by Spot serializer" << std::endl;
172 exit(1);170 exit(1);
173 //make_atomic_prop(element->shared_from_this());171 //make_atomic_prop(element->shared_from_this());
174 }172 }
175173
176 void FormulaToSpotSyntax::_accept(const PetriEngine::PQL::SubtractExpr *element) {174 void FormulaToSpotSyntax::_accept(const PetriEngine::PQL::SubtractExpr *element) {
177 assert(false);175 assert(false);
178 std::cerr << "LiteralExpr should not be visited by Spot serialiezr" << std::endl;176 std::cerr << "LiteralExpr should not be visited by Spot serializer" << std::endl;
179 exit(1);177 exit(1);
180 //make_atomic_prop(element->shared_from_this());178 //make_atomic_prop(element->shared_from_this());
181 }179 }
182180
183 void FormulaToSpotSyntax::_accept(const PetriEngine::PQL::IdentifierExpr *element) {181 void FormulaToSpotSyntax::_accept(const PetriEngine::PQL::IdentifierExpr *element) {
184 assert(false);182 assert(false);
185 std::cerr << "IdentifierExpr should not be visited by Spot serialiezr" << std::endl;183 std::cerr << "IdentifierExpr should not be visited by Spot serializer" << std::endl;
186 exit(1);184 exit(1);
187 //make_atomic_prop(element->shared_from_this());185 //make_atomic_prop(element->shared_from_this());
188 }186 }
189187
190
191 std::string toSpotFormat(const QueryItem &query) {
192 std::stringstream ss;
193 toSpotFormat(query, ss);
194 return ss.str();
195 }
196
197 void toSpotFormat(const QueryItem &query, std::ostream &os) {
198 FormulaToSpotSyntax spotConverter{os};
199 // FIXME nasty hack for top-level query, should be fixed elsewhere (e.g. asLTL)
200 auto top_quant = dynamic_cast<SimpleQuantifierCondition *>(query.query.get());
201 (*top_quant)[0]->visit(spotConverter);
202 }
203
204 BuchiSuccessorGenerator makeBuchiAutomaton(const Condition_ptr &query) {188 BuchiSuccessorGenerator makeBuchiAutomaton(const Condition_ptr &query) {
205 std::stringstream ss;189 std::stringstream ss;
206 FormulaToSpotSyntax spotConverter{ss};190 FormulaToSpotSyntax spotConverter{ss};
207 query->visit(spotConverter);191 query->visit(spotConverter);
208
209 const std::string spotFormula = "!(" + ss.str() + ")";192 const std::string spotFormula = "!(" + ss.str() + ")";
210#ifdef PRINTF_DEBUG193#ifdef PRINTF_DEBUG
211 std::cerr << "ORIG FORMULA: \n " << ss.str() << std::endl;194 std::cerr << "ORIG FORMULA: \n " << ss.str() << std::endl;
212 std::cerr << "SPOT FORMULA: \n " << spotFormula << std::endl;195 std::cerr << "SPOT FORMULA: \n " << spotFormula << std::endl;
213#endif196#endif
214 spot::formula formula = spot::parse_formula(spotFormula);197 spot::formula formula = spot::parse_formula(spotFormula);
215 spot::bdd_dict_ptr bdd = spot::make_bdd_dict();198 spot::translator translator;
216 auto translator = spot::translator(bdd);199 translator.set_type(spot::postprocessor::BA);
217 translator.set_pref(spot::postprocessor::Complete200 translator.set_pref(spot::postprocessor::Complete);
218 | spot::postprocessor::SBAcc);
219 spot::twa_graph_ptr automaton = translator.run(formula);201 spot::twa_graph_ptr automaton = translator.run(formula);
220#ifdef PRINTF_DEBUG202#ifdef PRINTF_DEBUG
221 automaton->get_graph().dump_storage(std::cerr);203 automaton->get_graph().dump_storage(std::cerr);
222 spot::print_dot(std::cerr, automaton);204 spot::print_dot(std::cerr, automaton);
223 bdd->dump(std::cerr);
224#endif205#endif
225 std::unordered_map<int, AtomicProposition> ap_map;206 std::unordered_map<int, AtomicProposition> ap_map;
207 // bind PQL expressions to the atomic proposition IDs used by spot.
208 // the resulting map can be indexed using variables mentioned on edges of the created Büchi automaton.
226 for (const auto &apinfo : spotConverter) {209 for (const auto &apinfo : spotConverter) {
227 int varnum = automaton->register_ap(apinfo.text);210 int varnum = automaton->register_ap(apinfo.text);
228 ap_map[varnum] = apinfo;211 ap_map[varnum] = apinfo;
229 }212 }
213#ifdef PRINTF_DEBUG
214 automaton->get_dict()->dump(std::cerr);
215#endif
230216
231 return BuchiSuccessorGenerator{Structures::BuchiAutomaton{automaton, ap_map}};217 return BuchiSuccessorGenerator{Structures::BuchiAutomaton{std::move(automaton), std::move(ap_map)}};
232 }218 }
233219
234}
235\ No newline at end of file220\ No newline at end of file
221}
236222
=== modified file 'src/LTL/LTL_algorithm/NestedDepthFirstSearch.cpp'
--- src/LTL/LTL_algorithm/NestedDepthFirstSearch.cpp 2020-10-19 12:35:11 +0000
+++ src/LTL/LTL_algorithm/NestedDepthFirstSearch.cpp 2020-11-09 13:59:57 +0000
@@ -20,100 +20,106 @@
2020
21 bool NestedDepthFirstSearch::isSatisfied() {21 bool NestedDepthFirstSearch::isSatisfied() {
22 dfs();22 dfs();
23#ifdef _PRINTF_DEBUG
24 std::cout << "discovered " << _discovered << " states." << std::endl;
25 std::cout << "mark1 size: " << mark1.size() << "\tmark2 size: " << mark2.size() << std::endl;
26#endif
23 return !violation;27 return !violation;
24 }28 }
2529
26 void NestedDepthFirstSearch::dfs() {30 void NestedDepthFirstSearch::dfs() {
27 std::stack<size_t> call_stack;31 std::stack<size_t> call_stack;
2832 std::stack<StackEntry> todo;
29 PetriEngine::Structures::StateSet states{net,0, (int)net.numberOfPlaces() + 1};
30 PetriEngine::Structures::DFSQueue todo{&states};
3133
32 State working = factory.newState();34 State working = factory.newState();
33 PQL::DistanceContext ctx{&net, working.marking()};
34 State curState = factory.newState();35 State curState = factory.newState();
36
35 {37 {
36 std::vector<State> initial_states;38 std::vector<State> initial_states;
37 successorGenerator->makeInitialState(initial_states);39 successorGenerator->makeInitialState(initial_states);
38 for (auto &state : initial_states) {40 for (auto &state : initial_states) {
39 auto res = states.add(state);41 auto res = states.add(state);
40 assert(res.first);42 assert(res.first);
41 todo.push(res.second, ctx, formula);43 todo.push(StackEntry{res.second, initial_suc_info});
44 _discovered++;
42 }45 }
43 }46 }
4447
45 while (todo.top(curState)) {48 while (!todo.empty()) {
4649 auto &top = todo.top();
47 if (!call_stack.empty() && states.lookup(curState).second == call_stack.top()) {50 states.decode(curState, top.id);
51 successorGenerator->prepare(&curState, top.sucinfo);
52 if (top.sucinfo.has_prev_state()) {
53 states.decode(working, top.sucinfo.last_state);
54 }
55 if (!successorGenerator->next(working, top.sucinfo)) {
56 // no successor
57 todo.pop();
48 if (successorGenerator->isAccepting(curState)) {58 if (successorGenerator->isAccepting(curState)) {
49 seed = &curState;59 seed = &curState;
50 ndfs(curState);60 ndfs(curState);
51 if (violation)61 if (violation) return;
52 return;
53 }62 }
54 todo.pop(curState);
55 call_stack.pop();
56 } else {63 } else {
57 call_stack.push(states.add(curState).second);64#ifdef PRINTF_DEBUG
58 if (!mark1.add(curState).first) {65 dump_state(working);
59 continue;66#endif
60 }67 auto[_, stateid] = states.add(working);
61 successorGenerator->prepare(&curState);68 auto[it, is_new] = mark1.insert(stateid);
62#ifdef PRINTF_DEBUG69 top.sucinfo.last_state = stateid;
63 std::cerr << "curState:\n";70 if (is_new) {
64 dump_state(curState);71 _discovered++;
65#endif72 todo.push(StackEntry{stateid, initial_suc_info});
66 while (successorGenerator->next(working)) {
67#ifdef PRINTF_DEBUG
68 std::cerr << "working:\n";
69 dump_state(working);
70#endif
71 auto r = states.add(working);
72 todo.push(r.second, ctx, formula);
73 }73 }
74 }74 }
75 }75 }
76 }76 }
7777
7878
79 void NestedDepthFirstSearch::ndfs(State& state) {79 void NestedDepthFirstSearch::ndfs(State &state) {
80 PetriEngine::Structures::StateSet states{net, 0, (int)net.numberOfPlaces() + 1};80#ifdef PRINTF_DEBUG
81 PetriEngine::Structures::DFSQueue todo{&states};81 std::cerr << "ENTERING NDFS" << std::endl;
82#endif
83 std::stack<StackEntry> todo;
8284
83 State working = factory.newState();85 State working = factory.newState();
84 State curState = factory.newState();86 State curState = factory.newState();
8587
86 PQL::DistanceContext ctx{&net, state.marking()};88 todo.push(StackEntry{states.add(state).second, initial_suc_info});
8789
88 todo.push(states.add(state).second, ctx, formula);90 while (!todo.empty()) {
8991 auto &top = todo.top();
90 while (todo.pop(curState)) {92 states.decode(curState, top.id);
91 if (!mark2.add(curState).first) {93 successorGenerator->prepare(&curState, top.sucinfo);
92 continue;94 if (top.sucinfo.has_prev_state()) {
95 states.decode(working, top.sucinfo.last_state);
93 }96 }
9497 if (!successorGenerator->next(working, top.sucinfo)) {
95 successorGenerator->prepare(&curState);98 todo.pop();
96#ifdef PRINTF_DEBUG99 } else {
97 std::cerr << "curState:\n";100#ifdef PRINTF_DEBUG
98 dump_state(curState);
99#endif
100 while (successorGenerator->next(working)) {
101#ifdef PRINTF_DEBUG
102 std::cerr << "working:\n";
103 dump_state(working);101 dump_state(working);
104#endif102#endif
105 if (working == *seed) {103 if (working == *seed) {
106#ifdef PRINTF_DEBUG104#ifdef _PRINTF_DEBUG
107 std::cerr << "seed:\n "; dump_state(*seed);105 std::cerr << "seed:\n "; dump_state(*seed);
108 std::cerr << "working:\n "; dump_state(working);106 std::cerr << "working:\n "; dump_state(working);
109#endif107#endif
110 violation = true;108 violation = true;
111 return;109 return;
112 }110 }
113 auto r = states.add(working);111 auto[_, stateid] = states.add(working);
114 todo.push(r.second, ctx, formula);112 auto[it, is_new] = mark2.insert(stateid);
113 top.sucinfo.last_state = stateid;
114 if (is_new) {
115 _discovered++;
116 todo.push(StackEntry{stateid, initial_suc_info});
117 }
118
115 }119 }
116 }120 }
117121#ifdef PRINTF_DEBUG
122 std::cerr << "LEAVING NDFS" << std::endl;
123#endif
118 }124 }
119}125}
120\ No newline at end of file126\ No newline at end of file
121127
=== modified file 'src/LTL/LTL_algorithm/ProductSuccessorGenerator.cpp'
--- src/LTL/LTL_algorithm/ProductSuccessorGenerator.cpp 2020-10-16 11:20:30 +0000
+++ src/LTL/LTL_algorithm/ProductSuccessorGenerator.cpp 2020-11-09 13:59:57 +0000
@@ -29,6 +29,27 @@
29 fresh_marking = true;29 fresh_marking = true;
30 }30 }
3131
32 void ProductSuccessorGenerator::prepare(const LTL::Structures::ProductState *state, const successor_info &sucinfo) {
33 SuccessorGenerator::prepare(state);
34 buchi.prepare(state->getBuchiState());
35 buchi_parent = state->getBuchiState();
36 fresh_marking = sucinfo.pcounter == 0 && sucinfo.tcounter == std::numeric_limits<uint32_t>::max();
37 _suc_pcounter = sucinfo.pcounter;
38 _suc_tcounter = sucinfo.tcounter;
39 if (!fresh_marking) {
40 assert(sucinfo.buchi_state != std::numeric_limits<size_t>::max());
41 // spool Büchi successors until last state found.
42 // TODO is there perhaps a good way to avoid this, perhaps using raw edge vector?
43 // Caveat: it seems like there usually are not that many successors, so this is probably cheap regardless
44 size_t tmp;
45 while (buchi.next(tmp, cond)) {
46 if (tmp == sucinfo.buchi_state) {
47 break;
48 }
49 }
50 }
51 }
52
32 bool ProductSuccessorGenerator::next(LTL::Structures::ProductState &state) {53 bool ProductSuccessorGenerator::next(LTL::Structures::ProductState &state) {
33 if (fresh_marking) {54 if (fresh_marking) {
34 fresh_marking = false;55 fresh_marking = false;
@@ -75,14 +96,16 @@
7596
76 bool ProductSuccessorGenerator::guard_valid(const PetriEngine::Structures::State &state, bdd bdd) {97 bool ProductSuccessorGenerator::guard_valid(const PetriEngine::Structures::State &state, bdd bdd) {
77 EvaluationContext ctx{state.marking(), &_net};98 EvaluationContext ctx{state.marking(), &_net};
78 while (!(bdd == bddtrue || bdd == bddfalse)) {99 // IDs 0 and 1 are false and true atoms, respectively
100 while (bdd.id() > 1/*!(bdd == bddtrue || bdd == bddfalse)*/) {
101 // find variable to test, and test it
79 size_t var = bdd_var(bdd);102 size_t var = bdd_var(bdd);
80 Condition::Result res = buchi.getExpression(var)->evaluate(ctx);103 Condition::Result res = buchi.getExpression(var)->evaluate(ctx);
81 switch (res) {104 switch (res) {
82 case Condition::RUNKNOWN:105 case Condition::RUNKNOWN:
83 std::cerr << "Unexpected unknown answer from evaluating query!\n";106 std::cerr << "Unexpected unknown answer from evaluating query!\n";
84 assert(false);107 assert(false);
85 exit(0);108 exit(1);
86 break;109 break;
87 case Condition::RFALSE:110 case Condition::RFALSE:
88 bdd = bdd_low(bdd);111 bdd = bdd_low(bdd);
@@ -95,23 +118,33 @@
95 return bdd == bddtrue;118 return bdd == bddtrue;
96 }119 }
97120
98 bool ProductSuccessorGenerator::next(Structures::ProductState &state, uint32_t &tindex) {121 bool ProductSuccessorGenerator::next(Structures::ProductState &state, successor_info &sucinfo) {
122 auto update_sucinfo = [&]() {
123 sucinfo.pcounter = _suc_pcounter;
124 sucinfo.tcounter = _suc_tcounter;
125 sucinfo.buchi_state = state.getBuchiState();
126 };
127
99 if (fresh_marking) {128 if (fresh_marking) {
100 fresh_marking = false;129 fresh_marking = false;
101 if (!SuccessorGenerator::next(state, tindex)) {130 if (!SuccessorGenerator::next(state)) {
102 // This is a fresh marking, so if there is no more successors for the state the state is deadlocked.131 // This is a fresh marking, so if there are no more successors for the state the state is deadlocked.
103 // The semantics for deadlock is to just loop the marking so return true without changing the value of state.132 // The semantics for deadlock is to just loop the marking so return true without changing the value of state.
104 // This assumes SuccessorGenerator::next only modifies &state if there is a successor.133 std::copy(_parent->marking(), _parent->marking() + state.buchi_state_idx + 1, state.marking());
105 }134 }
106 }135 }
107 if (next_buchi_succ(state)) {136 if (next_buchi_succ(state)) {
137 update_sucinfo();
108 return true;138 return true;
109 }139 }
110 // No valid transition in Büchi automaton for current marking;140 // No valid transition in Büchi automaton for current marking;
111 // Try next marking(s) and see if we find a successor.141 // Try next marking(s) and see if we find a successor.
112 else {142 else {
113 while (SuccessorGenerator::next(state, tindex)) {143 while (SuccessorGenerator::next(state)) {
144 // reset buchi successors
145 buchi.prepare(buchi_parent);
114 if (next_buchi_succ(state)) {146 if (next_buchi_succ(state)) {
147 update_sucinfo();
115 return true;148 return true;
116 }149 }
117 }150 }
118151
=== modified file 'src/LTL/LTL_algorithm/TarjanModelChecker.cpp'
--- src/LTL/LTL_algorithm/TarjanModelChecker.cpp 2020-10-19 12:35:11 +0000
+++ src/LTL/LTL_algorithm/TarjanModelChecker.cpp 2020-11-09 13:59:57 +0000
@@ -7,72 +7,123 @@
77
8#include "LTL/LTL_algorithm/TarjanModelChecker.h"8#include "LTL/LTL_algorithm/TarjanModelChecker.h"
99
10#undef PRINTF_DEBUG
10namespace LTL {11namespace LTL {
1112
1213 inline void _dump_state(const LTL::Structures::ProductState &state) {
13#ifdef PRINTF_DEBUG
14
15 inline void _dump_state(const LTL::Structures::ProductState &state, int nplaces = -1) {
16 if (nplaces == -1) nplaces = state.buchi_state_idx;
17 std::cerr << "marking: ";14 std::cerr << "marking: ";
18 std::cerr << state.marking()[0];15 std::cerr << state.marking()[0];
19 for (int i = 1; i <= nplaces; ++i) {16 for (int i = 1; i < state.size(); ++i) {
20 std::cerr << ", " << state.marking()[i];17 std::cerr << ", " << state.marking()[i];
21 }18 }
22 std::cerr << std::endl;19 std::cerr << std::endl;
23 }20 }
2421
25#endif22 template<bool SaveTrace>
2623 bool TarjanModelChecker<SaveTrace>::isSatisfied() {
27 bool LTL::TarjanModelChecker::isSatisfied() {24 std::vector<State> initial_states;
28 {25 successorGenerator->makeInitialState(initial_states);
29 std::vector<State> initial_states;26 State working = factory.newState();
30 successorGenerator.makeInitialState(initial_states);27 State parent = factory.newState();
31 for (auto &state : initial_states) {28 for (auto &state : initial_states) {
32 seen.add(state);29 auto res = seen.add(state);
30 if (res.first) {
33 push(state);31 push(state);
34 }32 }
35 }33 while (!dstack.empty() && !violation) {
36 State working = factory.newState();34 DEntry &dtop = dstack.top();
37 while (!dstack.empty() && !violation) {35 if (!nexttrans(working, parent, dtop)) {
38 DStack &dtop = dstack.top();36 pop();
39 if (!nexttrans(working, dtop)) {37 continue;
40 pop();38 }
41 continue;39 idx_t stateid = seen.add(working).second;
42 }40 dtop.sucinfo.last_state = stateid;
43 // get ID of transition taken (nexttrans = lasttrans + 1)41
44 idx_t stateid = (*dtop.neighbors)[dtop.nexttrans - 1];42 // lookup successor in 'hash' table
4543 auto p = chash[hash(stateid)];
46 // lookup successor in 'hash' table44 while (p != std::numeric_limits<idx_t>::max() && cstack[p].stateid != stateid) {
47 auto p = chash[hash(stateid)];45 p = cstack[p].next;
48 while (p != std::numeric_limits<idx_t>::max() && cstack[p].stateid != stateid) {46 }
49 p = cstack[p].next;47 if (p != std::numeric_limits<idx_t>::max()) {
50 }48 // we found the successor, i.e. there's a loop!
51 if (p != std::numeric_limits<idx_t>::max()) {49 // now update lowlinks and check whether the loop contains an accepting state
52 // we found the successor! update lowlinks etc50 update(p);
53 update(p);51 continue;
54 continue;52 }
55 }53 if (store.find(stateid) == std::end(store)) {
56 if (store.find(stateid) == std::end(store)) {54 push(working);
57 push(working);55 }
56 }
57 if constexpr (SaveTrace) {
58 if (violation) {
59 State next = factory.newState();
60 std::cerr << "Printing trace: " << std::endl;
61 std::vector<DEntry> rev;
62 auto sz = dstack.size();
63 // dump stack to vector to allow iteration
64 for (int i = 0; i < sz; ++i) {
65 rev.push_back(dstack.top());
66 dstack.pop();
67 }
68 idx_t pos = 0;
69 // print dstack in-order. rev[0] is dstack.top(), so loop vector in reverse
70 for (int i = rev.size() - 1; i >= 0; --i) {
71 pos = rev[i].pos;
72 seen.decode(parent, cstack[pos].stateid);
73 _dump_state(parent);
74 cstack[pos].lowlink = std::numeric_limits<idx_t>::max();
75 if (i > 0) {
76 // print transition to next state
77 seen.decode(next, cstack[rev[i - 1].pos].stateid);
78 successorGenerator->prepare(&parent);
79 while (successorGenerator->next(working)) {
80 if (working == next) {
81 std::cerr << net.transitionNames()[successorGenerator->last_transition()]
82 << std::endl;
83 break;
84 }
85 }
86 }
87 }
88
89 // follow lowsource until back in dstack
90 pos = cstack[pos].lowsource;
91 if (cstack[pos].lowlink != std::numeric_limits<idx_t>::max()) {
92 std::cerr << "Printing looping part\n";
93 }
94 while (cstack[pos].lowlink != std::numeric_limits<idx_t>::max()) {
95 seen.decode(parent, cstack[pos].stateid);
96 _dump_state(parent);
97 pos = cstack[pos].lowsource;
98 }
99 }
58 }100 }
59 }101 }
60 return !violation;102 return !violation;
61 }103 }
62104
63 void TarjanModelChecker::push(State &state) {105 /**
106 * Push a state to the various stacks.
107 * @param state
108 */
109 template<bool SaveTrace>
110 void TarjanModelChecker<SaveTrace>::push(State &state) {
64 const auto res = seen.add(state);111 const auto res = seen.add(state);
65 const auto ctop = static_cast<idx_t>(cstack.size());112 const auto ctop = static_cast<idx_t>(cstack.size());
66 const auto h = hash(res.second);113 const auto h = hash(res.second);
67 cstack.emplace_back(ctop, res.second, chash[h]);114 cstack.emplace_back(ctop, res.second, chash[h]);
115 if constexpr (SaveTrace) {
116 cstack.back().lowsource = ctop;
117 }
68 chash[h] = ctop;118 chash[h] = ctop;
69 dstack.push({ctop});119 dstack.push(DEntry{ctop, initial_suc_info});
70 if (successorGenerator.isAccepting(state)) {120 if (successorGenerator->isAccepting(state)) {
71 astack.push(ctop);121 astack.push(ctop);
72 }122 }
73 }123 }
74124
75 void TarjanModelChecker::pop() {125 template<bool SaveTrace>
126 void TarjanModelChecker<SaveTrace>::pop() {
76 const size_t p = dstack.top().pos;127 const size_t p = dstack.top().pos;
77 dstack.pop();128 dstack.pop();
78 if (cstack[p].lowlink == p) {129 if (cstack[p].lowlink == p) {
@@ -91,42 +142,45 @@
91 }142 }
92 }143 }
93144
94 void TarjanModelChecker::update(idx_t to) {145 template<bool SaveTrace>
146 void TarjanModelChecker<SaveTrace>::update(idx_t to) {
95 const auto from = dstack.top().pos;147 const auto from = dstack.top().pos;
96 if (cstack[to].lowlink <= cstack[from].lowlink) {148 if (cstack[to].lowlink <= cstack[from].lowlink) {
149 // we have found a loop into earlier seen component cstack[to].lowlink.
150 // if this earlier component was found before an accepting state,
151 // we have found an accepting loop and thus a violation.
97 violation = (!astack.empty() && to <= astack.top());152 violation = (!astack.empty() && to <= astack.top());
98 cstack[from].lowlink = cstack[to].lowlink;153 cstack[from].lowlink = cstack[to].lowlink;
154 if constexpr (SaveTrace) {
155 cstack[from].lowsource = to;
156 }
99 }157 }
100 }158 }
101159
102 bool TarjanModelChecker::nexttrans(State &state, TarjanModelChecker::DStack &delem) {160 template<bool SaveTrace>
103 if (!delem.neighbors) {161 bool TarjanModelChecker<SaveTrace>::nexttrans(State &state, State &parent, TarjanModelChecker::DEntry &delem) {
104 delem.neighbors = std::vector<idx_t>();162 seen.decode(parent, cstack[delem.pos].stateid);
105 delem.nexttrans = 0;
106 State src = factory.newState();
107 State dst = factory.newState();
108 seen.decode(src, cstack[delem.pos].stateid);
109 successorGenerator.prepare(&src);
110 while (successorGenerator.next(dst)) {
111 auto res = seen.add(dst);
112#ifdef PRINTF_DEBUG163#ifdef PRINTF_DEBUG
113 std::cerr << "adding state\n";164 std::cerr << "loaded parent\n ";
114 _dump_state(dst);165 _dump_state(parent);
115#endif166#endif
116 delem.neighbors->push_back(res.second);167 successorGenerator->prepare(&parent, delem.sucinfo);
117 }168 if (delem.sucinfo.has_prev_state()) {
169 seen.decode(state, delem.sucinfo.last_state);
118 }170 }
119 if (delem.nexttrans == delem.neighbors->size()) {171 auto res = successorGenerator->next(state, delem.sucinfo);
120 return false;
121 } else {
122 seen.decode(state, (*delem.neighbors)[delem.nexttrans]);
123#ifdef PRINTF_DEBUG172#ifdef PRINTF_DEBUG
124 std::cerr << "loaded state\n";173 if (res) {
174 std::cerr << "going to state\n";
125 _dump_state(state);175 _dump_state(state);
176 }
126#endif177#endif
127 delem.nexttrans++;178 return res;
128 return true;
129 }
130 }179 }
131180
181 template
182 class TarjanModelChecker<true>;
183
184 template
185 class TarjanModelChecker<false>;
132}186}
133\ No newline at end of file187\ No newline at end of file
134188
=== modified file 'src/LTLMain.cpp'
--- src/LTLMain.cpp 2020-10-16 11:40:41 +0000
+++ src/LTLMain.cpp 2020-11-09 13:59:57 +0000
@@ -32,10 +32,8 @@
3232
33#include "CTL/CTLEngine.h"33#include "CTL/CTLEngine.h"
34#include "PetriEngine/PQL/Expressions.h"34#include "PetriEngine/PQL/Expressions.h"
35#include "LTL/LTLToBuchi.h"
36#include "LTL/LTLValidator.h"35#include "LTL/LTLValidator.h"
37#include "LTL/LTL_algorithm/NestedDepthFirstSearch.h"36#include "LTL/LTL_algorithm/NestedDepthFirstSearch.h"
38#include "LTL/LTL_algorithm/ProductPrinter.h"
39#include "LTL/LTL_algorithm/TarjanModelChecker.h"37#include "LTL/LTL_algorithm/TarjanModelChecker.h"
40#include "LTL/LTL.h"38#include "LTL/LTL.h"
4139
@@ -43,7 +41,6 @@
43using namespace PetriEngine::PQL;41using namespace PetriEngine::PQL;
44using namespace PetriEngine::Reachability;42using namespace PetriEngine::Reachability;
4543
46
47std::vector<std::string> explode(std::string const & s)44std::vector<std::string> explode(std::string const & s)
48{45{
49 std::vector<std::string> result;46 std::vector<std::string> result;
@@ -502,7 +499,10 @@
502 modelChecker = std::make_unique<LTL::NestedDepthFirstSearch>(*net, negated_formula);499 modelChecker = std::make_unique<LTL::NestedDepthFirstSearch>(*net, negated_formula);
503 break;500 break;
504 case LTL::Algorithm::Tarjan:501 case LTL::Algorithm::Tarjan:
505 modelChecker = std::make_unique<LTL::TarjanModelChecker>(*net, negated_formula);502 if (options.trace)
503 modelChecker = std::make_unique<LTL::TarjanModelChecker<true>>(*net, negated_formula);
504 else
505 modelChecker = std::make_unique<LTL::TarjanModelChecker<false>>(*net, negated_formula);
506 break;506 break;
507 }507 }
508508
509509
=== modified file 'src/PetriEngine/SuccessorGenerator.cpp'
--- src/PetriEngine/SuccessorGenerator.cpp 2020-10-16 13:38:03 +0000
+++ src/PetriEngine/SuccessorGenerator.cpp 2020-11-09 13:59:57 +0000
@@ -97,7 +97,7 @@
97 for (; _suc_tcounter != last; ++_suc_tcounter) {97 for (; _suc_tcounter != last; ++_suc_tcounter) {
9898
99 if (!checkPreset(_suc_tcounter)) continue;99 if (!checkPreset(_suc_tcounter)) continue;
100#ifdef PRINTF_DEBUG100#ifdef _PRINTF_DEBUG
101 std::cerr << "trace: " << _net.transitionNames()[_suc_tcounter] << std::endl;101 std::cerr << "trace: " << _net.transitionNames()[_suc_tcounter] << std::endl;
102#endif102#endif
103 memcpy(write.marking(), (*_parent).marking(), _net._nplaces * sizeof (MarkVal));103 memcpy(write.marking(), (*_parent).marking(), _net._nplaces * sizeof (MarkVal));

Subscribers

People subscribed via source and target branches

to all changes: