Merge lp:~tapaal-ltl/verifypn/reach-stub-new into lp:verifypn

Proposed by Peter Gjøl Jensen
Status: Merged
Approved by: Jiri Srba
Approved revision: 284
Merged at revision: 252
Proposed branch: lp:~tapaal-ltl/verifypn/reach-stub-new
Merge into: lp:verifypn
Diff against target: 6145 lines (+1333/-1200)
29 files modified
CMakeLists.txt (+1/-1)
include/LTL/Algorithm/ModelChecker.h (+37/-33)
include/LTL/Algorithm/NestedDepthFirstSearch.h (+29/-34)
include/LTL/Algorithm/TarjanModelChecker.h (+32/-34)
include/LTL/LTLMain.h (+5/-4)
include/LTL/Structures/BitProductStateSet.h (+4/-4)
include/LTL/Structures/ProductState.h (+9/-1)
include/LTL/Structures/ProductStateFactory.h (+4/-3)
include/LTL/Stubborn/SafeAutStubbornSet.h (+22/-5)
include/LTL/SuccessorGeneration/BuchiSuccessorGenerator.h (+1/-1)
include/LTL/SuccessorGeneration/ProductSuccessorGenerator.h (+8/-6)
include/LTL/SuccessorGeneration/ReachStubProductSuccessorGenerator.h (+27/-9)
include/LTL/SuccessorGeneration/ResumingSuccessorGenerator.h (+74/-81)
include/LTL/SuccessorGeneration/SpoolingSuccessorGenerator.h (+27/-16)
include/PetriEngine/Reducer.h (+21/-21)
include/PetriEngine/Structures/StateSet.h (+5/-33)
include/PetriEngine/Structures/light_deque.h (+83/-24)
include/PetriEngine/SuccessorGenerator.h (+4/-4)
src/LTL/Algorithm/NestedDepthFirstSearch.cpp (+124/-124)
src/LTL/Algorithm/TarjanModelChecker.cpp (+107/-86)
src/LTL/LTLMain.cpp (+29/-63)
src/LTL/Stubborn/AutomatonStubbornSet.cpp (+1/-1)
src/LTL/Stubborn/SafeAutStubbornSet.cpp (+57/-9)
src/LTL/SuccessorGeneration/ResumingSuccessorGenerator.cpp (+2/-2)
src/PetriEngine/PQL/Expressions.cpp (+403/-414)
src/PetriEngine/Reducer.cpp (+160/-157)
src/PetriEngine/Stubborn/InterestingTransitionVisitor.cpp (+23/-1)
src/PetriEngine/TraceReplay.cpp (+4/-4)
src/VerifyPN.cpp (+30/-25)
To merge this branch: bzr merge lp:~tapaal-ltl/verifypn/reach-stub-new
Reviewer Review Type Date Requested Status
Jiri Srba Approve
Review via email: mp+409596@code.launchpad.net

Commit message

Adds POR for LTL, improves performance of NDFS.

Passes regression on MCC21 models using competition script.

To post a comment you must log in.
279. By Nikolaj Jensen Ulrik

Probably properly fixed k-bounds in NDFS. Fixes https://bugs.launchpad.net/tapaal/+bug/1947036

280. By Nikolaj Jensen Ulrik

LTL Query simplification more robust against queries without leading A/E quantifier.

281. By Nikolaj Jensen Ulrik

Fixing infinite loop in Tarjan trace generation

282. By Peter G. Jensen <email address hidden>

avoiding double-addition of extra-consume during ruleB trace reconstruction

283. By Nikolaj Jensen Ulrik

extraConsume in the right place

284. By <email address hidden>

increased version number to 4.2.0

Revision history for this message
Jiri Srba (srba) wrote :

Merging to trunk now - small issue with loop at the end in once case but let's address this in 3.9.1 release.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2021-08-11 09:06:51 +0000
3+++ CMakeLists.txt 2021-10-17 18:21:15 +0000
4@@ -15,7 +15,7 @@
5 set(CMAKE_POSITION_INDEPENDENT_CODE ON)
6
7
8-set(VERIFYPN_VERSION 4.1.0)
9+set(VERIFYPN_VERSION 4.2.0)
10 add_compile_definitions(VERIFYPN_VERSION=\"${VERIFYPN_VERSION}\")
11
12 project(verifypn VERSION ${VERIFYPN_VERSION} LANGUAGES CXX C)
13
14=== modified file 'include/LTL/Algorithm/ModelChecker.h'
15--- include/LTL/Algorithm/ModelChecker.h 2021-08-06 09:34:01 +0000
16+++ include/LTL/Algorithm/ModelChecker.h 2021-10-17 18:21:15 +0000
17@@ -25,7 +25,9 @@
18 #include "LTL/SuccessorGeneration/SpoolingSuccessorGenerator.h"
19 #include "LTL/Structures/BitProductStateSet.h"
20 #include "LTL/SuccessorGeneration/ReachStubProductSuccessorGenerator.h"
21+#include "LTL/Structures/ProductStateFactory.h"
22 #include "PetriEngine/options.h"
23+#include "PetriEngine/Reducer.h"
24
25 #include <iomanip>
26 #include <algorithm>
27@@ -37,11 +39,14 @@
28 ModelChecker(const PetriEngine::PetriNet *net,
29 const PetriEngine::PQL::Condition_ptr &condition,
30 const Structures::BuchiAutomaton &buchi,
31- SuccessorGen *successorGen,
32+ SuccessorGen *successorGen, const PetriEngine::Reducer* reducer,
33 std::unique_ptr<Spooler> &&...spooler)
34- : net(net), formula(condition)
35+ : net(net), formula(condition), _reducer(reducer), successorGenerator(
36+ std::make_unique<ProductSucGen<SuccessorGen, Spooler...>>(net, buchi, successorGen,
37+ std::move(spooler)...)),
38+ _factory(net, buchi, this->successorGenerator->initial_buchi_state())
39 {
40- successorGenerator = std::make_unique<ProductSucGen<SuccessorGen, Spooler...>>(net, buchi, successorGen, std::move(spooler)...);
41+// successorGenerator = std::make_unique<ProductSucGen<SuccessorGen, Spooler...>>(net, buchi, successorGen, std::move(spooler)...);
42 }
43
44 void setOptions(const options_t &options) {
45@@ -81,11 +86,14 @@
46 << "\tmax tokens: " << stateSet.max_tokens() << std::endl;
47 }
48
49+ const PetriEngine::Reducer* _reducer;
50 std::unique_ptr<ProductSucGen<SuccessorGen, Spooler...>> successorGenerator;
51
52 const PetriEngine::PetriNet *net;
53 PetriEngine::PQL::Condition_ptr formula;
54+ //const Structures::BuchiAutomaton *_aut;
55 TraceLevel traceLevel;
56+ LTL::Structures::ProductStateFactory _factory;
57
58 size_t _discovered = 0;
59 bool shortcircuitweak;
60@@ -102,41 +110,37 @@
61 }
62
63 std::ostream &
64- printTransition(size_t transition, LTL::Structures::ProductState &state, std::ostream &os)
65+ printTransition(size_t transition, std::ostream &os, const LTL::Structures::ProductState* state = nullptr)
66 {
67 if (transition >= std::numeric_limits<ptrie::uint>::max() - 1) {
68 os << indent << "<deadlock/>";
69 return os;
70 }
71- os << indent << "<transition id="
72- // field width stuff obsolete without büchi state printing.
73- //<< std::setw(maxTransName + 2) << std::left
74- << std::quoted(net->transitionNames()[transition]);
75- if (traceLevel == TraceLevel::Full) {
76- os << ">";
77- os << std::endl;
78- auto [fpre, lpre] = net->preset(transition);
79- for(; fpre < lpre; ++fpre) {
80- if (fpre->inhibitor) {
81- assert(state.marking()[fpre->place] < fpre->tokens);
82- continue;
83- }
84- for (size_t i = 0; i < fpre->tokens; ++i) {
85- assert(state.marking()[fpre->place] >= fpre->tokens);
86- os << tokenIndent << R"(<token age="0" place=")" << net->placeNames()[fpre->place] << "\"/>\n";
87- }
88- }
89- /*for (size_t i = 0; i < net->numberOfPlaces(); ++i) {
90- for (size_t j = 0; j < state.marking()[i]; ++j) {
91- os << tokenIndent << R"(<token age="0" place=")" << net->placeNames()[i] << "\"/>\n";
92- }
93- }*/
94- os << indent << "</transition>";
95- }
96- else {
97- os << "/>";
98- }
99- return os;
100+ os << indent << "<transition id="
101+ // field width stuff obsolete without büchi state printing.
102+ << std::quoted(net->transitionNames()[transition]);
103+ os << ">";
104+ if(_reducer) {
105+ _reducer->extraConsume(os, net->transitionNames()[transition]);
106+ }
107+ os << std::endl;
108+ auto [fpre, lpre] = net->preset(transition);
109+ for(; fpre < lpre; ++fpre) {
110+ if (fpre->inhibitor) {
111+ assert(state == nullptr || state->marking()[fpre->place] < fpre->tokens);
112+ continue;
113+ }
114+ for (size_t i = 0; i < fpre->tokens; ++i) {
115+ assert(state == nullptr || state->marking()[fpre->place] >= fpre->tokens);
116+ os << tokenIndent << R"(<token age="0" place=")" << net->placeNames()[fpre->place] << "\"/>\n";
117+ }
118+ }
119+ os << indent << "</transition>\n";
120+ if(_reducer)
121+ {
122+ _reducer->postFire(os, net->transitionNames()[transition]);
123+ }
124+ return os;
125 }
126 };
127 }
128
129=== modified file 'include/LTL/Algorithm/NestedDepthFirstSearch.h'
130--- include/LTL/Algorithm/NestedDepthFirstSearch.h 2021-08-10 13:44:22 +0000
131+++ include/LTL/Algorithm/NestedDepthFirstSearch.h 2021-10-17 18:21:15 +0000
132@@ -22,12 +22,11 @@
133 #include "PetriEngine/Structures/StateSet.h"
134 #include "PetriEngine/Structures/State.h"
135 #include "PetriEngine/Structures/Queue.h"
136+#include "PetriEngine/Structures/light_deque.h"
137 #include "LTL/Structures/ProductStateFactory.h"
138
139-#include <ptrie/ptrie_stable.h>
140-#include <unordered_set>
141-
142 namespace LTL {
143+
144 /**
145 * Implement the nested DFS algorithm for LTL model checking. Roughly based on versions given in
146 * <p>
147@@ -45,14 +44,13 @@
148 * @tparam W type used for state storage. Use <code>PetriEngine::Structures::TracableStateSet</code> if you want traces,
149 * <code>PetriEngine::Structures::StateSet</code> if you don't care (as it is faster).
150 */
151- template<typename SucGen, typename W>
152-class NestedDepthFirstSearch : public ModelChecker<ProductSuccessorGenerator, SucGen> {
153+ template<typename SucGen>
154+ class NestedDepthFirstSearch : public ModelChecker<ProductSuccessorGenerator, SucGen> {
155 public:
156 NestedDepthFirstSearch(const PetriEngine::PetriNet *net, const PetriEngine::PQL::Condition_ptr &query,
157- const Structures::BuchiAutomaton &buchi, SucGen *gen, int kbound)
158- : ModelChecker<ProductSuccessorGenerator, SucGen>(net, query, buchi, gen),
159- factory{net, this->successorGenerator->initial_buchi_state()},
160- states(net, kbound) {}
161+ const Structures::BuchiAutomaton &buchi, SucGen *gen, const bool print_trace, int kbound, const PetriEngine::Reducer* reducer)
162+ : ModelChecker<ProductSuccessorGenerator, SucGen>(net, query, buchi, gen, reducer),
163+ _states(net, kbound), _print_trace(print_trace) {}
164
165 bool isSatisfied() override;
166
167@@ -60,43 +58,40 @@
168
169 private:
170 using State = LTL::Structures::ProductState;
171-
172- Structures::ProductStateFactory factory;
173- W states; //StateSet
174- std::set<size_t> mark1;
175- std::set<size_t> mark2;
176+ std::pair<bool,size_t> mark(State& state, uint8_t);
177+
178+
179+ LTL::Structures::BitProductStateSet<> _states;
180+
181+ std::unordered_map<size_t, uint8_t> _markers;
182+ //std::vector<uint8_t> _markers;
183+ static constexpr uint8_t MARKER1 = 1;
184+ static constexpr uint8_t MARKER2 = 2;
185+ size_t _mark_count[3] = {0,0,0};
186
187 struct StackEntry {
188- size_t id;
189- typename SucGen::sucinfo sucinfo;
190+ size_t _id;
191+ typename SucGen::successor_info_t _sucinfo;
192 };
193
194- State *seed;
195- bool violation = false;
196+ bool _violation = false;
197+ const bool _print_trace = false;
198
199 //Used for printing the trace
200- std::stack<std::pair<size_t, size_t>> nested_transitions;
201+ std::stack<std::pair<size_t, size_t>> _nested_transitions;
202
203 void dfs();
204
205- void ndfs(State &state);
206-
207- void printTrace(std::stack<std::pair<size_t, size_t>> &transitions, std::ostream &os = std::cout);
208-
209- static constexpr bool SaveTrace = std::is_same_v<W, PetriEngine::Structures::TracableStateSet>;
210+ void ndfs(const State &state, light_deque<StackEntry>& nested_todo);
211+
212+ void print_trace(light_deque<StackEntry>& todo, light_deque<StackEntry>& nested_todo, std::ostream &os = std::cout);
213 };
214
215 extern template
216- class NestedDepthFirstSearch<LTL::ResumingSuccessorGenerator, LTL::Structures::BitProductStateSet<>>;
217-
218- extern template
219- class NestedDepthFirstSearch<LTL::ResumingSuccessorGenerator, LTL::Structures::TraceableBitProductStateSet<>>;
220-
221- extern template
222- class NestedDepthFirstSearch<LTL::SpoolingSuccessorGenerator, LTL::Structures::BitProductStateSet<>>;
223-
224- extern template
225- class NestedDepthFirstSearch<LTL::SpoolingSuccessorGenerator, LTL::Structures::TraceableBitProductStateSet<>>;
226+ class NestedDepthFirstSearch<LTL::ResumingSuccessorGenerator>;
227+
228+ extern template
229+ class NestedDepthFirstSearch<LTL::SpoolingSuccessorGenerator>;
230 }
231
232 #endif //VERIFYPN_NESTEDDEPTHFIRSTSEARCH_H
233
234=== modified file 'include/LTL/Algorithm/TarjanModelChecker.h'
235--- include/LTL/Algorithm/TarjanModelChecker.h 2021-08-10 13:44:22 +0000
236+++ include/LTL/Algorithm/TarjanModelChecker.h 2021-10-17 18:21:15 +0000
237@@ -49,62 +49,60 @@
238 TarjanModelChecker(const PetriEngine::PetriNet *net, const PetriEngine::PQL::Condition_ptr &cond,
239 const Structures::BuchiAutomaton &buchi,
240 SuccessorGen *successorGen,
241- int kbound,
242+ int kbound, const PetriEngine::Reducer* reducer,
243 std::unique_ptr<Spooler> &&...spooler)
244- : ModelChecker<ProductSucGen, SuccessorGen, Spooler...>(net, cond, buchi, successorGen, std::move(spooler)...),
245- factory(net, this->successorGenerator->initial_buchi_state()),
246- seen(net, kbound)
247+ : ModelChecker<ProductSucGen, SuccessorGen, Spooler...>(net, cond, buchi, successorGen, reducer, std::move(spooler)...),
248+ _seen(net, kbound)
249 {
250 if (buchi._buchi->num_states() > 65535) {
251 std::cerr << "Fatal error: cannot handle Büchi automata larger than 2^16 states\n";
252 exit(1);
253 }
254- chash.fill(std::numeric_limits<idx_t>::max());
255+ _chash.fill(std::numeric_limits<idx_t>::max());
256 }
257
258 bool isSatisfied() override;
259
260 void printStats(std::ostream &os) override
261 {
262- this->_printStats(os, seen);
263+ this->_printStats(os, _seen);
264 }
265
266 private:
267 using State = LTL::Structures::ProductState;
268 using idx_t = size_t;
269 // 64 MB hash table
270- static constexpr idx_t HashSz = 16777216;
271+ static constexpr idx_t _hash_sz = 16777216;
272
273- LTL::Structures::ProductStateFactory factory;
274
275 using StateSet = std::conditional_t<SaveTrace, LTL::Structures::TraceableBitProductStateSet<>, LTL::Structures::BitProductStateSet<>>;
276- static constexpr bool IsSpooling = std::is_same_v<SuccessorGen, SpoolingSuccessorGenerator>;
277+ static constexpr bool _is_spooling = std::is_same_v<SuccessorGen, SpoolingSuccessorGenerator>;
278
279- StateSet seen;
280- std::unordered_set<idx_t> store;
281+ StateSet _seen;
282+ std::unordered_set<idx_t> _store;
283
284 // rudimentary hash table of state IDs. chash[hash(state)] is the top index in cstack
285 // corresponding to state. Collisions are resolved using linked list via CEntry::next.
286- std::array<idx_t, HashSz> chash;
287- static_assert(sizeof(chash) == (1U << 27U));
288+ std::array<idx_t, _hash_sz> _chash;
289+ static_assert(sizeof(_chash) == (1U << 27U));
290
291 static inline idx_t hash(idx_t id)
292 {
293- return id % HashSz;
294+ return id % _hash_sz;
295 }
296
297 struct PlainCEntry {
298- idx_t lowlink;
299- idx_t stateid;
300- idx_t next = std::numeric_limits<idx_t>::max();
301- bool dstack = true;
302+ idx_t _lowlink;
303+ idx_t _stateid;
304+ idx_t _next = std::numeric_limits<idx_t>::max();
305+ bool _dstack = true;
306
307- PlainCEntry(idx_t lowlink, idx_t stateid, idx_t next) : lowlink(lowlink), stateid(stateid), next(next) {}
308+ PlainCEntry(idx_t lowlink, idx_t stateid, idx_t next) : _lowlink(lowlink), _stateid(stateid), _next(next) {}
309 };
310
311 struct TracableCEntry : PlainCEntry {
312- idx_t lowsource = std::numeric_limits<idx_t>::max();
313- idx_t sourcetrans;
314+ idx_t _lowsource = std::numeric_limits<idx_t>::max();
315+ idx_t _sourcetrans;
316
317 TracableCEntry(idx_t lowlink, idx_t stateid, idx_t next) : PlainCEntry(lowlink, stateid, next) {}
318 };
319@@ -114,24 +112,24 @@
320 PlainCEntry>;
321
322 struct DEntry {
323- idx_t pos; // position in cstack.
324-
325- typename SuccessorGen::sucinfo sucinfo;
326-
327- explicit DEntry(idx_t pos) : pos(pos), sucinfo(SuccessorGen::initial_suc_info()) {}
328+ idx_t _pos; // position in cstack.
329+
330+ typename SuccessorGen::successor_info_t _sucinfo;
331+
332+ explicit DEntry(idx_t pos) : _pos(pos), _sucinfo(SuccessorGen::initial_suc_info()) {}
333 };
334
335 // master list of state information.
336- std::vector<CEntry> cstack;
337+ std::vector<CEntry> _cstack;
338 // depth-first search stack, contains current search path.
339- std::stack<DEntry> dstack;
340+ std::stack<DEntry> _dstack;
341 // cstack positions of accepting states in current search path, for quick access.
342- std::stack<idx_t> astack;
343+ std::stack<idx_t> _astack;
344
345- bool violation = false;
346- bool invariant_loop = true;
347- size_t loopstate = std::numeric_limits<size_t>::max();
348- size_t looptrans = std::numeric_limits<size_t>::max();
349+ bool _violation = false;
350+ bool _invariant_loop = true;
351+ size_t _loop_state = std::numeric_limits<size_t>::max();
352+ size_t _loop_trans = std::numeric_limits<size_t>::max();
353
354 void push(State &state, size_t stateid);
355
356@@ -144,8 +142,8 @@
357 void popCStack();
358
359 void printTrace(std::stack<DEntry> &&dstack, std::ostream &os = std::cout);
360-
361 };
362+
363 extern template
364 class TarjanModelChecker<ProductSuccessorGenerator, LTL::ResumingSuccessorGenerator, true>;
365
366
367=== modified file 'include/LTL/LTLMain.h'
368--- include/LTL/LTLMain.h 2021-08-03 12:00:44 +0000
369+++ include/LTL/LTLMain.h 2021-10-17 18:21:15 +0000
370@@ -1,16 +1,16 @@
371 /* Copyright (C) 2021 Nikolaj J. Ulrik <nikolaj@njulrik.dk>,
372 * Simon M. Virenfeldt <simon@simwir.dk>
373- *
374+ *
375 * This program is free software: you can redistribute it and/or modify
376 * it under the terms of the GNU General Public License as published by
377 * the Free Software Foundation, either version 3 of the License, or
378 * (at your option) any later version.
379- *
380+ *
381 * This program is distributed in the hope that it will be useful,
382 * but WITHOUT ANY WARRANTY; without even the implied warranty of
383 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
384 * GNU General Public License for more details.
385- *
386+ *
387 * You should have received a copy of the GNU General Public License
388 * along with this program. If not, see <http://www.gnu.org/licenses/>.
389 */
390@@ -26,7 +26,8 @@
391 bool LTLMain(const PetriEngine::PetriNet *net,
392 const PetriEngine::PQL::Condition_ptr &query,
393 const std::string &queryName,
394- options_t &options);
395+ options_t &options,
396+ const PetriEngine::Reducer* reducer);
397 }
398
399 #endif //VERIFYPN_LTLMAIN_H
400
401=== modified file 'include/LTL/Structures/BitProductStateSet.h'
402--- include/LTL/Structures/BitProductStateSet.h 2021-08-10 13:44:22 +0000
403+++ include/LTL/Structures/BitProductStateSet.h 2021-10-17 18:21:15 +0000
404@@ -1,16 +1,16 @@
405 /* Copyright (C) 2021 Nikolaj J. Ulrik <nikolaj@njulrik.dk>,
406 * Simon M. Virenfeldt <simon@simwir.dk>
407- *
408+ *
409 * This program is free software: you can redistribute it and/or modify
410 * it under the terms of the GNU General Public License as published by
411 * the Free Software Foundation, either version 3 of the License, or
412 * (at your option) any later version.
413- *
414+ *
415 * This program is distributed in the hope that it will be useful,
416 * but WITHOUT ANY WARRANTY; without even the implied warranty of
417 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
418 * GNU General Public License for more details.
419- *
420+ *
421 * You should have received a copy of the GNU General Public License
422 * along with this program. If not, see <http://www.gnu.org/licenses/>.
423 */
424@@ -64,7 +64,7 @@
425 template<uint8_t nbits = 16>
426 class BitProductStateSet : public ProductStateSetInterface {
427 public:
428- explicit BitProductStateSet(const PetriEngine::PetriNet *net, int kbound = 0, size_t nplaces = -1)
429+ explicit BitProductStateSet(const PetriEngine::PetriNet *net, int kbound = 0)
430 : markings(*net, kbound, net->numberOfPlaces())
431 {
432 }
433
434=== modified file 'include/LTL/Structures/ProductState.h'
435--- include/LTL/Structures/ProductState.h 2021-04-29 13:19:53 +0000
436+++ include/LTL/Structures/ProductState.h 2021-10-17 18:21:15 +0000
437@@ -19,6 +19,7 @@
438 #define VERIFYPN_PRODUCTSTATE_H
439
440 #include "PetriEngine/Structures/State.h"
441+#include "LTL/Structures/BuchiAutomaton.h"
442
443 namespace LTL {
444 template <class SuccessorGen>
445@@ -32,7 +33,7 @@
446 */
447 class ProductState : public PetriEngine::Structures::State {
448 public:
449- ProductState() : PetriEngine::Structures::State() {}
450+ explicit ProductState(const BuchiAutomaton* aut = nullptr) : PetriEngine::Structures::State(), _aut(aut) {}
451
452 void setMarking(PetriEngine::MarkVal* marking, size_t nplaces)
453 {
454@@ -74,10 +75,17 @@
455 bool operator!=(const ProductState &rhs) const {
456 return !(rhs == *this);
457 }
458+
459+ [[nodiscard]] bool is_accepting() const {
460+ assert(_aut);
461+ return _aut->_buchi->state_is_accepting(getBuchiState());
462+ }
463+
464 private:
465 template <typename T>
466 friend class LTL::ProductSuccessorGenerator;
467 size_t buchi_state_idx;
468+ const LTL::Structures::BuchiAutomaton *_aut = nullptr;
469 };
470 }
471
472
473=== modified file 'include/LTL/Structures/ProductStateFactory.h'
474--- include/LTL/Structures/ProductStateFactory.h 2021-04-29 07:47:52 +0000
475+++ include/LTL/Structures/ProductStateFactory.h 2021-10-17 18:21:15 +0000
476@@ -25,14 +25,14 @@
477 namespace LTL::Structures{
478 class ProductStateFactory {
479 public:
480- ProductStateFactory(const PetriEngine::PetriNet *net, size_t initial_buchi_state)
481- : net(net), buchi_init(initial_buchi_state) {}
482+ ProductStateFactory(const PetriEngine::PetriNet *net, const BuchiAutomaton& aut, size_t initial_buchi_state)
483+ : net(net), _aut(aut), buchi_init(initial_buchi_state) {}
484
485 ProductState newState() {
486 auto buf = new PetriEngine::MarkVal[net->numberOfPlaces()+1];
487 std::copy(net->initial(), net->initial() + net->numberOfPlaces(), buf);
488 buf[net->numberOfPlaces()] = 0;
489- ProductState state;
490+ ProductState state{&_aut};
491 state.setMarking(buf, net->numberOfPlaces());
492 state.setBuchiState(buchi_init);
493 return state;
494@@ -40,6 +40,7 @@
495
496 private:
497 const PetriEngine::PetriNet *net;
498+ const LTL::Structures::BuchiAutomaton _aut;
499 const size_t buchi_init;
500 };
501 }
502
503=== modified file 'include/LTL/Stubborn/SafeAutStubbornSet.h'
504--- include/LTL/Stubborn/SafeAutStubbornSet.h 2021-05-13 09:19:31 +0000
505+++ include/LTL/Stubborn/SafeAutStubbornSet.h 2021-10-17 18:21:15 +0000
506@@ -48,23 +48,40 @@
507 StubbornSet::reset();
508 memset(_unsafe.get(), false, sizeof(bool) * _net.numberOfTransitions());
509 _bad = false;
510+ _has_enabled_stubborn = false;
511+ }
512+
513+ void set_buchi_conds(PetriEngine::PQL::Condition_ptr ret_cond,
514+ PetriEngine::PQL::Condition_ptr prog_cond,
515+ PetriEngine::PQL::Condition_ptr sink_cond) {
516+ _ret_cond = ret_cond;
517+ _prog_cond = prog_cond;
518+ _sink_cond = sink_cond;
519 }
520
521 protected:
522 void addToStub(uint32_t t) override
523 {
524- //refinement of bad: can manually check whether firing t would violate some progressing formula.
525- if (_unsafe[t] && _enabled[t]) {
526- _bad = true;
527- return;
528+ // potential refinement of bad: can manually check whether firing t would violate some progressing formula.
529+ if (_enabled[t]) {
530+ _has_enabled_stubborn = true;
531+ if (_unsafe[t]) {
532+ _bad = true;
533+ return;
534+ }
535 }
536- //TODO check safe-ness
537 StubbornSet::addToStub(t);
538 }
539
540 private:
541 std::unique_ptr<bool[]> _unsafe;
542 bool _bad = false;
543+ bool _has_enabled_stubborn = false;
544+ PetriEngine::PQL::Condition_ptr _ret_cond;
545+ PetriEngine::PQL::Condition_ptr _prog_cond;
546+ PetriEngine::PQL::Condition_ptr _sink_cond;
547+
548+ void _print_debug();
549 };
550 }
551
552
553=== modified file 'include/LTL/SuccessorGeneration/BuchiSuccessorGenerator.h'
554--- include/LTL/SuccessorGeneration/BuchiSuccessorGenerator.h 2021-04-14 09:38:34 +0000
555+++ include/LTL/SuccessorGeneration/BuchiSuccessorGenerator.h 2021-10-17 18:21:15 +0000
556@@ -78,6 +78,7 @@
557 {
558 return (bool) aut._buchi->prop_weak();
559 }
560+
561 size_t buchiStates() { return aut._buchi->num_states(); }
562
563 Structures::BuchiAutomaton aut;
564@@ -91,7 +92,6 @@
565 }
566 };
567
568-
569 bool has_invariant_self_loop(size_t state) {
570 if (self_loops[state] != InvariantSelfLoop::UNKNOWN)
571 return self_loops[state] == InvariantSelfLoop::TRUE;
572
573=== modified file 'include/LTL/SuccessorGeneration/ProductSuccessorGenerator.h'
574--- include/LTL/SuccessorGeneration/ProductSuccessorGenerator.h 2021-04-29 13:19:53 +0000
575+++ include/LTL/SuccessorGeneration/ProductSuccessorGenerator.h 2021-10-17 18:21:15 +0000
576@@ -48,6 +48,8 @@
577
578 }
579
580+ const PetriEngine::PetriNet& net() const { return *_net; }
581+
582 [[nodiscard]] size_t initial_buchi_state() const { return buchi.initial_state_number(); };
583
584 bool next(LTL::Structures::ProductState &state)
585@@ -89,12 +91,12 @@
586 auto buf = new PetriEngine::MarkVal[_net->numberOfPlaces() + 1];
587 std::copy(_net->initial(), _net->initial() + _net->numberOfPlaces(), buf);
588 buf[_net->numberOfPlaces()] = initial_buchi_state();
589- LTL::Structures::ProductState state;
590+ LTL::Structures::ProductState state{&buchi.aut};
591 state.setMarking(buf, _net->numberOfPlaces());
592 //state.setBuchiState(initial_buchi_state());
593 buchi.prepare(state.getBuchiState());
594 while (next_buchi_succ(state)) {
595- states.emplace_back();
596+ states.emplace_back(&buchi.aut);
597 states.back().setMarking(new PetriEngine::MarkVal[_net->numberOfPlaces() + 1], _net->numberOfPlaces());
598 std::copy(state.marking(), state.marking() + _net->numberOfPlaces(), states.back().marking());
599 states.back().setBuchiState(state.getBuchiState());
600@@ -112,7 +114,7 @@
601 * @param state the source state to generate successors from
602 * @param sucinfo the point in the iteration to start from, as returned by `next`.
603 */
604- virtual void prepare(const LTL::Structures::ProductState *state, typename SuccessorGen::sucinfo &sucinfo)
605+ virtual void prepare(const LTL::Structures::ProductState *state, typename SuccessorGen::successor_info_t &sucinfo)
606 {
607 _successor_generator->prepare(state, sucinfo);
608 fresh_marking = sucinfo.fresh();
609@@ -139,7 +141,7 @@
610 * @return `true` if a successor was successfully generated, `false` otherwise.
611 * @warning do not use the same State for both prepare and next, this will cause wildly incorrect behaviour!
612 */
613- bool next(Structures::ProductState &state, typename SuccessorGen::sucinfo &sucinfo)
614+ bool next(Structures::ProductState &state, typename SuccessorGen::successor_info_t &sucinfo)
615 {
616 if (fresh_marking) {
617 fresh_marking = false;
618@@ -182,7 +184,7 @@
619 size_t fired() const { return _successor_generator->fired(); }
620
621 //template<typename T = std::enable_if_t<std::is_same_v<SuccessorGen, PetriEngine::ReducingSuccessorGenerator>, void>>
622- void generateAll(LTL::Structures::ProductState *parent, typename SuccessorGen::sucinfo &sucinfo)
623+ void generateAll(LTL::Structures::ProductState *parent, typename SuccessorGen::successor_info_t &sucinfo)
624 {
625 if constexpr (std::is_same_v<SuccessorGen, LTL::SpoolingSuccessorGenerator>) {
626 _successor_generator->generate_all(parent, sucinfo);
627@@ -221,7 +223,7 @@
628 }
629 }
630
631- void pop(const typename SuccessorGen::sucinfo &sucinfo) {
632+ void pop(const typename SuccessorGen::successor_info_t &sucinfo) {
633 if constexpr (std::is_same_v<SuccessorGen, LTL::SpoolingSuccessorGenerator>) {
634 _successor_generator->pop(sucinfo);
635 }
636
637=== modified file 'include/LTL/SuccessorGeneration/ReachStubProductSuccessorGenerator.h'
638--- include/LTL/SuccessorGeneration/ReachStubProductSuccessorGenerator.h 2021-08-04 08:13:25 +0000
639+++ include/LTL/SuccessorGeneration/ReachStubProductSuccessorGenerator.h 2021-10-17 18:21:15 +0000
640@@ -49,7 +49,7 @@
641 std::transform(std::begin(buchi.ap_info), std::end(buchi.ap_info), std::begin(aps),
642 [](const std::pair<int, AtomicProposition> &pair) { return pair.second; });
643 for (unsigned state = 0; state < buchi._buchi->num_states(); ++state) {
644- if (buchi._buchi->state_is_accepting(state)) continue;
645+ //if (buchi._buchi->state_is_accepting(state)) continue;
646
647 bdd retarding = bddfalse;
648 bdd progressing = bddfalse;
649@@ -61,16 +61,32 @@
650 progressing |= e.cond;
651 }
652 }
653- if ((retarding | progressing) == bddtrue) {
654- _reach_states.insert(std::make_pair(state, BuchiEdge{progressing, toPQL(spot::bdd_to_formula(progressing, buchi.dict), aps)}));
655- }
656+ bdd sink_prop = bdd_not(retarding | progressing);
657+ auto prog_cond = toPQL(spot::bdd_to_formula(progressing, buchi.dict), aps);
658+ auto ret_cond = toPQL(spot::bdd_to_formula(retarding, buchi.dict), aps);
659+ auto sink_cond = sink_prop == bdd_false()
660+ ? PetriEngine::PQL::BooleanCondition::FALSE_CONSTANT
661+ : std::make_shared<PetriEngine::PQL::NotCondition>(
662+ std::make_shared<PetriEngine::PQL::OrCondition>(prog_cond, ret_cond)
663+ );
664+ _reach_states.insert(std::make_pair(
665+ state,
666+ BuchiEdge{progressing | sink_prop,
667+ ret_cond,
668+ prog_cond,
669+ sink_cond}));
670 }
671 }
672
673- void prepare(const LTL::Structures::ProductState *state, typename S::sucinfo &sucinfo) override
674+ void prepare(const LTL::Structures::ProductState *state, typename S::successor_info_t &sucinfo) override
675 {
676- if (auto suc = _reach_states.find(state->getBuchiState()); suc != std::end(_reach_states) && !this->guard_valid(*state, suc->second.bddCond)) {
677- (dynamic_cast<PetriEngine::StubbornSet*>(_reach.get()))->setQuery(suc->second.cond.get());
678+ auto suc = _reach_states.find(state->getBuchiState());
679+ // assert valid since all states are reducible when considering
680+ // the sink progressing formula and key transitions in accepting states.
681+ assert(suc != std::end(_reach_states));
682+ if (suc != std::end(_reach_states) && !this->guard_valid(*state, suc->second.bddCond)) {
683+ //_reach->setQuery(suc->second.prog_cond.get());
684+ _reach->set_buchi_conds(suc->second.ret_cond, suc->second.prog_cond, suc->second.pseudo_sink_cond);
685 set_spooler(_reach.get());
686 }
687 else {
688@@ -92,11 +108,13 @@
689
690 struct BuchiEdge{
691 bdd bddCond;
692- PetriEngine::PQL::Condition_ptr cond;
693+ PetriEngine::PQL::Condition_ptr ret_cond;
694+ PetriEngine::PQL::Condition_ptr prog_cond;
695+ PetriEngine::PQL::Condition_ptr pseudo_sink_cond;
696 };
697
698 std::unique_ptr<Spooler> _fallback_spooler;
699- std::unique_ptr<LTL::SuccessorSpooler> _reach;
700+ std::unique_ptr<LTL::SafeAutStubbornSet> _reach;
701 std::unordered_map<size_t, BuchiEdge> _reach_states;
702 std::vector<PetriEngine::PQL::Condition_ptr> _progressing_formulae;
703
704
705=== modified file 'include/LTL/SuccessorGeneration/ResumingSuccessorGenerator.h'
706--- include/LTL/SuccessorGeneration/ResumingSuccessorGenerator.h 2021-04-29 07:47:52 +0000
707+++ include/LTL/SuccessorGeneration/ResumingSuccessorGenerator.h 2021-10-17 18:21:15 +0000
708@@ -25,114 +25,107 @@
709 #include "PetriEngine/Stubborn/StubbornSet.h"
710
711 namespace LTL {
712- /**
713- * type holding sufficient information to resume successor generation for a state from a given point.
714- */
715- struct successor_info {
716- uint32_t pcounter;
717- uint32_t tcounter;
718- size_t buchi_state;
719- size_t last_state;
720-
721- friend bool operator==(const successor_info &lhs, const successor_info &rhs)
722- {
723- return lhs.pcounter == rhs.pcounter &&
724- lhs.tcounter == rhs.tcounter &&
725- lhs.buchi_state == rhs.buchi_state &&
726- lhs.last_state == rhs.last_state;
727- }
728-
729- friend bool operator!=(const successor_info &lhs, const successor_info &rhs)
730- {
731- return !(rhs == lhs);
732- }
733-
734- inline bool has_pcounter() const
735- {
736- return pcounter != NoPCounter;
737- }
738-
739- inline bool has_tcounter() const
740- {
741- return tcounter != NoTCounter;
742- }
743-
744- inline bool has_buchistate() const
745- {
746- return buchi_state != NoBuchiState;
747- }
748-
749- inline bool has_prev_state() const
750- {
751- return last_state != NoLastState;
752- }
753-
754- [[nodiscard]] inline bool fresh() const
755- {
756- return pcounter == NoPCounter && tcounter == NoTCounter;
757- }
758-
759- static constexpr auto NoPCounter = 0;
760- static constexpr auto NoTCounter = std::numeric_limits<uint32_t>::max();
761- static constexpr auto NoBuchiState = std::numeric_limits<size_t>::max();
762- static constexpr auto NoLastState = std::numeric_limits<size_t>::max();
763- };
764
765 class ResumingSuccessorGenerator : public PetriEngine::SuccessorGenerator {
766 public:
767
768+ struct successor_info_t {
769+ uint32_t pcounter;
770+ uint32_t tcounter;
771+ size_t buchi_state;
772+ size_t last_state;
773+
774+ friend bool operator==(const successor_info_t &lhs, const successor_info_t &rhs) {
775+ return lhs.pcounter == rhs.pcounter &&
776+ lhs.tcounter == rhs.tcounter &&
777+ lhs.buchi_state == rhs.buchi_state &&
778+ lhs.last_state == rhs.last_state;
779+ }
780+
781+ friend bool operator!=(const successor_info_t &lhs, const successor_info_t &rhs) {
782+ return !(rhs == lhs);
783+ }
784+
785+ bool has_pcounter() const {
786+ return pcounter != NoPCounter;
787+ }
788+
789+ bool has_tcounter() const {
790+ return tcounter != NoTCounter;
791+ }
792+
793+ bool has_buchistate() const {
794+ return buchi_state != NoBuchiState;
795+ }
796+
797+ bool has_prev_state() const {
798+ return last_state != NoLastState;
799+ }
800+
801+ size_t state() const {
802+ return last_state;
803+ }
804+
805+ size_t transition() const {
806+ return tcounter - 1;
807+ }
808+
809+ [[nodiscard]] bool fresh() const {
810+ return pcounter == NoPCounter && tcounter == NoTCounter;
811+ }
812+
813+ static constexpr auto NoPCounter = 0;
814+ static constexpr auto NoTCounter = std::numeric_limits<uint32_t>::max();
815+ static constexpr auto NoBuchiState = std::numeric_limits<size_t>::max();
816+ static constexpr auto NoLastState = std::numeric_limits<size_t>::max();
817+ };
818+ public:
819+
820 ResumingSuccessorGenerator(const PetriEngine::PetriNet *net);
821
822 ResumingSuccessorGenerator(const PetriEngine::PetriNet *net, const std::shared_ptr<PetriEngine::StubbornSet> &);
823
824 ResumingSuccessorGenerator(const PetriEngine::PetriNet *net,
825- std::vector<std::shared_ptr<PetriEngine::PQL::Condition> > &queries);
826+ std::vector<std::shared_ptr<PetriEngine::PQL::Condition> > &queries);
827
828 ResumingSuccessorGenerator(const PetriEngine::PetriNet *net,
829- const std::shared_ptr<PetriEngine::PQL::Condition> &query);
830+ const std::shared_ptr<PetriEngine::PQL::Condition> &query);
831
832 ~ResumingSuccessorGenerator() override = default;
833
834- void prepare(const PetriEngine::Structures::State *state, const successor_info &sucinfo);
835-
836-
837- bool next(PetriEngine::Structures::State &write, successor_info &sucinfo)
838- {
839+ void prepare(const PetriEngine::Structures::State *state, const successor_info_t &sucinfo);
840+
841+ bool next(PetriEngine::Structures::State &write, successor_info_t &sucinfo) {
842 bool has_suc = PetriEngine::SuccessorGenerator::next(write);
843- getSuccInfo(sucinfo);
844+ get_succ_info(sucinfo);
845 return has_suc;
846 }
847
848- uint32_t fired() const
849- {
850+ uint32_t fired() const {
851 return _suc_tcounter - 1;
852 }
853
854- const PetriEngine::MarkVal *getParent() const
855- {
856+ const PetriEngine::MarkVal *get_parent() const {
857 return _parent->marking();
858 }
859
860-
861- size_t last_transition() const
862- {
863+ size_t last_transition() const {
864 return _suc_tcounter == std::numeric_limits<uint32_t>::max() ? std::numeric_limits<uint32_t>::max() :
865- _suc_tcounter - 1;
866- }
867-
868- using sucinfo = successor_info;
869-
870- static constexpr sucinfo _initial_suc_info{
871- successor_info::NoPCounter,
872- successor_info::NoTCounter,
873- successor_info::NoBuchiState,
874- successor_info::NoLastState
875- };
876-
877- static constexpr auto initial_suc_info() { return _initial_suc_info; }
878+ _suc_tcounter - 1;
879+ }
880+
881+ static constexpr successor_info_t _initial_suc_info{
882+ successor_info_t::NoPCounter,
883+ successor_info_t::NoTCounter,
884+ successor_info_t::NoBuchiState,
885+ successor_info_t::NoLastState};
886+
887+ static constexpr auto initial_suc_info() {
888+ return _initial_suc_info;
889+ }
890
891 private:
892- void getSuccInfo(successor_info &sucinfo) const;
893+ void get_succ_info(successor_info_t &sucinfo) const;
894
895 //friend class ReducingSuccessorGenerator;
896 };
897
898=== modified file 'include/LTL/SuccessorGeneration/SpoolingSuccessorGenerator.h'
899--- include/LTL/SuccessorGeneration/SpoolingSuccessorGenerator.h 2021-04-30 07:02:31 +0000
900+++ include/LTL/SuccessorGeneration/SpoolingSuccessorGenerator.h 2021-10-17 18:21:15 +0000
901@@ -1,16 +1,16 @@
902 /* Copyright (C) 2021 Nikolaj J. Ulrik <nikolaj@njulrik.dk>,
903 * Simon M. Virenfeldt <simon@simwir.dk>
904- *
905+ *
906 * This program is free software: you can redistribute it and/or modify
907 * it under the terms of the GNU General Public License as published by
908 * the Free Software Foundation, either version 3 of the License, or
909 * (at your option) any later version.
910- *
911+ *
912 * This program is distributed in the hope that it will be useful,
913 * but WITHOUT ANY WARRANTY; without even the implied warranty of
914 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
915 * GNU General Public License for more details.
916- *
917+ *
918 * You should have received a copy of the GNU General Public License
919 * along with this program. If not, see <http://www.gnu.org/licenses/>.
920 */
921@@ -34,18 +34,27 @@
922 _statebuf.setMarking(new PetriEngine::MarkVal[net->numberOfPlaces() + 1], net->numberOfPlaces());
923 }
924
925- struct sucinfo {
926+ struct successor_info_t {
927 SuccessorQueue<> successors;
928 size_t buchi_state;
929 size_t last_state;
930-
931- sucinfo(size_t buchiState, size_t lastState) : buchi_state(buchiState), last_state(lastState) {}
932-
933- [[nodiscard]] inline bool has_prev_state() const
934+ size_t _transition;
935+
936+ successor_info_t(size_t buchiState, size_t lastState) : buchi_state(buchiState), last_state(lastState) {}
937+
938+ [[nodiscard]] bool has_prev_state() const
939 {
940 return last_state != NoLastState;
941 }
942
943+ size_t state() const {
944+ return last_state;
945+ }
946+
947+ size_t transition() const {
948+ return _transition;
949+ }
950+
951 [[nodiscard]] bool fresh() const { return buchi_state == NoBuchiState && last_state == NoLastState; }
952
953 static constexpr auto NoBuchiState = std::numeric_limits<size_t>::max();
954@@ -62,9 +71,9 @@
955 _heuristic = heuristic;
956 }
957
958- [[nodiscard]] static sucinfo initial_suc_info()
959+ [[nodiscard]] static successor_info_t initial_suc_info()
960 {
961- return sucinfo{sucinfo::NoBuchiState, sucinfo::NoLastState};
962+ return successor_info_t{successor_info_t::NoBuchiState, successor_info_t::NoLastState};
963 }
964
965 bool prepare(const PetriEngine::Structures::State *state)
966@@ -78,14 +87,15 @@
967 }
968
969
970- void prepare(const Structures::ProductState *state, sucinfo &sucinfo)
971+ void prepare(const Structures::ProductState *state, successor_info_t &sucinfo)
972 {
973 assert(_spooler != nullptr);
974
975 PetriEngine::SuccessorGenerator::prepare(state);
976 if (sucinfo.successors == nullptr) {
977 uint32_t tid;
978- _spooler->prepare(state);
979+ bool res = _spooler->prepare(state);
980+ //assert(!res/* || !_net.deadlocked(state->marking())*/);
981 if (!_heuristic || !_heuristic->has_heuristic(*state)) {
982 uint32_t nsuc = 0;
983 // generate list of transitions that generate a successor.
984@@ -95,7 +105,7 @@
985 assert(nsuc <= _net.numberOfTransitions());
986 }
987 sucinfo.successors = SuccessorQueue(_transbuf.get(), nsuc);
988-
989+ assert((res && !sucinfo.successors.empty()) || !res);
990 } else {
991 // list of (transition, weight)
992 _heuristic->prepare(*state);
993@@ -113,7 +123,7 @@
994 }
995 }
996 }
997- bool next(Structures::ProductState &state, sucinfo &sucinfo)
998+ bool next(Structures::ProductState &state, successor_info_t &sucinfo)
999 {
1000 assert(sucinfo.successors != nullptr);
1001 if (sucinfo.successors.empty()) {
1002@@ -124,6 +134,7 @@
1003 return false;
1004 }
1005 _last = sucinfo.successors.front();
1006+ sucinfo._transition = _last;
1007 #ifndef NDEBUG
1008 //std::cerr << "Firing " << _net.transitionNames()[_last] << std::endl;
1009 #endif
1010@@ -134,7 +145,7 @@
1011
1012 [[nodiscard]] uint32_t fired() const { return _last; }
1013
1014- void generate_all(LTL::Structures::ProductState *parent, sucinfo &sucinfo)
1015+ void generate_all(LTL::Structures::ProductState *parent, successor_info_t &sucinfo)
1016 {
1017 assert(_spooler != nullptr);
1018 assert(sucinfo.successors != nullptr);
1019@@ -200,7 +211,7 @@
1020 _heuristic->push(fired());
1021 }
1022
1023- void pop(const sucinfo &sc) {
1024+ void pop(const successor_info_t &sc) {
1025 if (_heuristic && sc.successors.has_consumed())
1026 _heuristic->pop(sc.successors.last_pop());
1027 }
1028
1029=== modified file 'include/PetriEngine/Reducer.h'
1030--- include/PetriEngine/Reducer.h 2021-07-07 13:19:23 +0000
1031+++ include/PetriEngine/Reducer.h 2021-10-17 18:21:15 +0000
1032@@ -1,4 +1,4 @@
1033-/*
1034+/*
1035 * File: Reducer.h
1036 * Author: srba
1037 *
1038@@ -19,34 +19,34 @@
1039 namespace PetriEngine {
1040
1041 using ArcIter = std::vector<Arc>::iterator;
1042-
1043+
1044 class PetriNetBuilder;
1045-
1046+
1047 class QueryPlaceAnalysisContext : public PQL::AnalysisContext {
1048 std::vector<uint32_t> _placeInQuery;
1049 bool _deadlock;
1050 public:
1051
1052- QueryPlaceAnalysisContext(const std::unordered_map<std::string, uint32_t>& pnames, const std::unordered_map<std::string, uint32_t>& tnames, const PetriNet* net)
1053+ QueryPlaceAnalysisContext(const std::unordered_map<std::string, uint32_t>& pnames, const std::unordered_map<std::string, uint32_t>& tnames, const PetriNet* net)
1054 : PQL::AnalysisContext(pnames, tnames, net) {
1055 _placeInQuery.resize(_placeNames.size(), 0);
1056 _deadlock = false;
1057 };
1058-
1059+
1060 virtual ~QueryPlaceAnalysisContext()
1061 {
1062 }
1063-
1064+
1065 uint32_t* getQueryPlaceCount(){
1066 return _placeInQuery.data();
1067 }
1068
1069 bool hasDeadlock() { return _deadlock; }
1070-
1071+
1072 virtual void setHasDeadlock() override {
1073 _deadlock = true;
1074 };
1075-
1076+
1077 ResolutionResult resolve(const std::string& identifier, bool place) override {
1078 if(!place) return PQL::AnalysisContext::resolve(identifier, false);
1079 ResolutionResult result;
1080@@ -61,7 +61,7 @@
1081 _placeInQuery[i]++;
1082 return result;
1083 }
1084-
1085+
1086 return result;
1087 }
1088
1089@@ -70,7 +70,7 @@
1090 struct ExpandedArc
1091 {
1092 ExpandedArc(std::string place, size_t weight) : place(place), weight(weight) {}
1093-
1094+
1095 friend std::ostream& operator<<(std::ostream& os, ExpandedArc const & ea) {
1096 for(size_t i = 0; i < ea.weight; ++i)
1097 {
1098@@ -78,18 +78,18 @@
1099 }
1100 return os;
1101 }
1102-
1103- std::string place;
1104+
1105+ std::string place;
1106 size_t weight;
1107 };
1108-
1109+
1110 class Reducer {
1111 public:
1112 Reducer(PetriNetBuilder*);
1113 ~Reducer();
1114 void Print(QueryPlaceAnalysisContext& context); // prints the net, just for debugging
1115 void Reduce(QueryPlaceAnalysisContext& context, int enablereduction, bool reconstructTrace, int timeout, bool remove_loops, bool remove_consumers, bool next_safe, std::vector<uint32_t>& reductions);
1116-
1117+
1118 size_t RemovedTransitions() const {
1119 return _removedTransitions;
1120 }
1121@@ -115,9 +115,9 @@
1122 << "Applications of rule K: " << _ruleK << std::endl;
1123 }
1124
1125- void postFire(std::ostream&, const std::string& transition);
1126- void extraConsume(std::ostream&, const std::string& transition);
1127- void initFire(std::ostream&);
1128+ void postFire(std::ostream&, const std::string& transition) const;
1129+ void extraConsume(std::ostream&, const std::string& transition) const;
1130+ void initFire(std::ostream&) const;
1131
1132 private:
1133 size_t _removedTransitions = 0;
1134@@ -146,7 +146,7 @@
1135
1136 std::string getTransitionName(uint32_t transition);
1137 std::string getPlaceName(uint32_t place);
1138-
1139+
1140 PetriEngine::Transition& getTransition(uint32_t transition);
1141 ArcIter getOutArc(PetriEngine::Transition&, uint32_t place);
1142 ArcIter getInArc(uint32_t place, PetriEngine::Transition&);
1143@@ -154,14 +154,14 @@
1144 void skipTransition(uint32_t);
1145 void skipPlace(uint32_t);
1146 std::string newTransName();
1147-
1148+
1149 bool consistent();
1150 bool hasTimedout() const {
1151 auto end = std::chrono::high_resolution_clock::now();
1152 auto diff = std::chrono::duration_cast<std::chrono::seconds>(end - _timer);
1153 return (diff.count() >= _timeout);
1154 }
1155-
1156+
1157 std::vector<std::string> _initfire;
1158 std::unordered_map<std::string, std::vector<std::string>> _postfire;
1159 std::unordered_map<std::string, std::vector<ExpandedArc>> _extraconsume;
1160@@ -171,7 +171,7 @@
1161 std::vector<uint32_t> _skipped_trans;
1162 };
1163
1164-
1165+
1166
1167
1168 }
1169
1170=== modified file 'include/PetriEngine/Structures/StateSet.h'
1171--- include/PetriEngine/Structures/StateSet.h 2021-04-29 07:47:52 +0000
1172+++ include/PetriEngine/Structures/StateSet.h 2021-10-17 18:21:15 +0000
1173@@ -42,10 +42,11 @@
1174 _maxPlaceBound = std::vector<uint32_t>(net.numberOfPlaces(), 0);
1175 _sp = binarywrapper_t(sizeof(uint32_t) * _nplaces * 8);
1176 }
1177- virtual ~StateSetInterface()
1178- {
1179- _sp.release();
1180- }
1181+
1182+ virtual ~StateSetInterface()
1183+ {
1184+ _sp.release();
1185+ }
1186
1187 virtual std::pair<bool, size_t> add(const State& state) = 0;
1188
1189@@ -59,10 +60,6 @@
1190
1191 virtual std::pair<size_t, size_t> getHistory(size_t markingid) = 0;
1192
1193- virtual void setHistory2(size_t id, size_t transition) = 0;
1194-
1195- virtual std::pair<size_t, size_t> getHistory2(size_t markingid) = 0;
1196-
1197 protected:
1198 size_t _discovered;
1199 uint32_t _kbound;
1200@@ -235,14 +232,6 @@
1201 return std::make_pair(0,0);
1202 }
1203
1204- virtual void setHistory2(size_t id, size_t transition) override {}
1205-
1206- virtual std::pair<size_t, size_t> getHistory2(size_t markingid) override
1207- {
1208- assert(false);
1209- return std::make_pair(std::numeric_limits<std::size_t>::max(), std::numeric_limits<std::size_t>::max());
1210- }
1211-
1212 private:
1213 ptrie_t _trie;
1214 };
1215@@ -254,8 +243,6 @@
1216 {
1217 ptrie::uint parent;
1218 ptrie::uint transition = std::numeric_limits<ptrie::uint>::max();
1219- ptrie::uint parent2;
1220- ptrie::uint transition2 = std::numeric_limits<ptrie::uint>::max();
1221 };
1222
1223 private:
1224@@ -301,21 +288,6 @@
1225 return std::pair<size_t, size_t>(t.parent, t.transition);
1226 }
1227
1228- virtual void setHistory2(size_t id, size_t transition) override {
1229- traceable_t &t = _trie.get_data(id);
1230- t.parent2 = _parent;
1231- t.transition2 = transition;
1232- }
1233-
1234- virtual std::pair<size_t, size_t> getHistory2(size_t markingid) override {
1235- traceable_t &t = _trie.get_data(markingid);
1236- return std::pair<size_t, size_t>(t.parent2, t.transition2);
1237- }
1238-
1239- void setParent(size_t id) {
1240- _parent = id;
1241- }
1242-
1243 private:
1244 ptrie_t _trie;
1245 size_t _parent = 0;
1246
1247=== modified file 'include/PetriEngine/Structures/light_deque.h'
1248--- include/PetriEngine/Structures/light_deque.h 2021-03-23 14:10:04 +0000
1249+++ include/PetriEngine/Structures/light_deque.h 2021-10-17 18:21:15 +0000
1250@@ -1,4 +1,4 @@
1251-/*
1252+/*
1253 * File: light_deque.h
1254 * Author: Peter G. Jensen <pgj@cs.aau.dk>
1255 *
1256@@ -18,30 +18,40 @@
1257 size_t _front = 0;
1258 size_t _back = 0;
1259 size_t _size = 0;
1260- std::unique_ptr<T[]> _data;
1261+ T* _data = nullptr;
1262 public:
1263 light_deque(size_t initial_size = 64)
1264 {
1265 if(initial_size == 0) initial_size = 1;
1266- _data.reset(new T[initial_size]);
1267+ _data = (T*)new uint8_t[initial_size*sizeof(T)]; // TODO, revisit with cast and initialization
1268 _size = initial_size;
1269 }
1270
1271 light_deque<T> &operator=(const light_deque<T> &other) {
1272- _front = other._front;
1273- _back = other._back;
1274+ for(auto& e : *this)
1275+ e.~T();
1276+ delete[] (uint8_t*)_data;
1277+ _front = 0;
1278+ _back = 0;
1279 _size = other.size();
1280- _data.reset(new T[_size]);
1281- memcpy(_data.get(), other._data.get(), _size * sizeof(T));
1282+ _data = (T*)new uint8_t[_size*sizeof(T)];
1283+ for(auto& e : other)
1284+ push_back(e);
1285 return *this;
1286 }
1287
1288- light_deque(light_deque &&) noexcept = default;
1289- light_deque &operator=(light_deque &&) noexcept = default;
1290+ ~light_deque() {
1291+ for(auto& e : *this)
1292+ {
1293+ e.~T();
1294+ }
1295+ delete[] (uint8_t*)_data;
1296+ _data = nullptr;
1297+ }
1298
1299 void push_back(const T& element)
1300 {
1301- _data.get()[_back] = element;
1302+ new (&_data[_back]) T(element);
1303 ++_back;
1304 if(_back == _size)
1305 {
1306@@ -51,7 +61,7 @@
1307
1308 void push_back(T&& element)
1309 {
1310- _data.get()[_back] = element;
1311+ new (&_data[_back]) T(std::move(element));
1312 ++_back;
1313 if(_back == _size) {
1314 expand();
1315@@ -62,39 +72,88 @@
1316 {
1317 return _front == _back;
1318 }
1319-
1320+
1321 size_t size() const
1322 {
1323 return _back - _front;
1324 }
1325-
1326- T front() const
1327- {
1328- return _data.get()[_front];
1329- }
1330- const T& front() {
1331- return _data.get()[_front];
1332+
1333+ const T& front() const
1334+ {
1335+ return _data[_front];
1336+ }
1337+
1338+ T& front() {
1339+ return _data[_front];
1340+ }
1341+
1342+ const T& back() const
1343+ {
1344+ return _data[_back - 1];
1345+ }
1346+
1347+ T& back() {
1348+ return _data[_back - 1];
1349 }
1350
1351 void pop_front()
1352 {
1353+ _data[_front].~T();
1354 ++_front;
1355 if(_front >= _back)
1356 {
1357 _front = _back = 0;
1358 }
1359 }
1360-
1361+
1362+ void pop_back()
1363+ {
1364+ if(_back > _front)
1365+ {
1366+ --_back;
1367+ _data[_back].~T();
1368+ }
1369+ if(_back == _front)
1370+ clear();
1371+ }
1372+
1373 void clear()
1374 {
1375+ for(auto& e : *this)
1376+ e.~T();
1377 _front = _back = 0;
1378 }
1379- private:
1380+
1381+ T* begin() {
1382+ return &front();
1383+ }
1384+
1385+ T* end() {
1386+ return &_data[_back];
1387+ }
1388+
1389+ const T* begin() const {
1390+ return &front();
1391+ }
1392+
1393+ const T* end() const {
1394+ return &_data[_back];
1395+ }
1396+
1397+ private:
1398 void expand() {
1399- std::unique_ptr<T[]> ndata(new T[_size*2]);
1400- memcpy(ndata.get(), _data.get(), _size*sizeof(T));
1401+ T* ndata = (T*)new uint8_t[_size*2*sizeof(T)];
1402+ size_t n = 0;
1403+ for(auto& e : *this)
1404+ {
1405+ new (ndata + n) T(std::move(e));
1406+ ++n;
1407+ }
1408 _size *= 2;
1409- _data.swap(ndata);
1410+ _back = (_back - _front);
1411+ _front = 0;
1412+ std::swap(_data, ndata);
1413+ delete[] (uint8_t*)ndata;
1414 }
1415 };
1416
1417
1418=== modified file 'include/PetriEngine/SuccessorGenerator.h'
1419--- include/PetriEngine/SuccessorGenerator.h 2021-03-19 11:48:52 +0000
1420+++ include/PetriEngine/SuccessorGenerator.h 2021-10-17 18:21:15 +0000
1421@@ -4,7 +4,7 @@
1422 * and open the template in the editor.
1423 */
1424
1425-/*
1426+/*
1427 * File: SuccessorGenerator.h
1428 * Author: Peter G. Jensen
1429 *
1430@@ -32,13 +32,15 @@
1431 virtual bool next(Structures::State& write);
1432 uint32_t fired() const
1433 {
1434- return _suc_tcounter -1;
1435+ return _suc_tcounter == std::numeric_limits<uint32_t>::max() ? std::numeric_limits<uint32_t>::max() : _suc_tcounter - 1;
1436 }
1437
1438 const MarkVal* getParent() const {
1439 return _parent->marking();
1440 }
1441
1442+ const PetriNet& net() const { return _net; }
1443+
1444 void reset();
1445
1446 /**
1447@@ -64,8 +66,6 @@
1448 */
1449 void producePostset(Structures::State& write, uint32_t t);
1450
1451- size_t last_transition() const { return _suc_tcounter == std::numeric_limits<uint32_t>::max() ? std::numeric_limits<uint32_t>::max() : _suc_tcounter - 1; }
1452-
1453 protected:
1454 const PetriNet& _net;
1455
1456
1457=== modified file 'src/LTL/Algorithm/NestedDepthFirstSearch.cpp'
1458--- src/LTL/Algorithm/NestedDepthFirstSearch.cpp 2021-08-10 13:44:22 +0000
1459+++ src/LTL/Algorithm/NestedDepthFirstSearch.cpp 2021-10-17 18:21:15 +0000
1460@@ -18,186 +18,186 @@
1461 #include "LTL/Algorithm/NestedDepthFirstSearch.h"
1462
1463 namespace LTL {
1464- template<typename S, typename W>
1465- bool NestedDepthFirstSearch<S, W>::isSatisfied()
1466+ template<typename S>
1467+ bool NestedDepthFirstSearch<S>::isSatisfied()
1468 {
1469 this->is_weak = this->successorGenerator->is_weak() && this->shortcircuitweak;
1470 dfs();
1471- return !violation;
1472- }
1473-
1474- template<typename S, typename W>
1475- void NestedDepthFirstSearch<S, W>::dfs()
1476- {
1477- std::stack<size_t> call_stack;
1478- std::stack<StackEntry> todo;
1479-
1480- State working = factory.newState();
1481- State curState = factory.newState();
1482-
1483- {
1484-
1485+ return !_violation;
1486+ }
1487+
1488+ template<typename S>
1489+ std::pair<bool,size_t> NestedDepthFirstSearch<S>::mark(State& state, const uint8_t MARKER)
1490+ {
1491+ auto[_, stateid] = _states.add(state);
1492+ if (stateid == std::numeric_limits<size_t>::max()) {
1493+ return std::make_pair(false, stateid);
1494+ }
1495+
1496+ auto r = _markers[stateid];
1497+ _markers[stateid] = (MARKER | r);
1498+ const bool is_new = (r & MARKER) == 0;
1499+ if(is_new)
1500+ {
1501+ ++_mark_count[MARKER];
1502+ ++this->_discovered;
1503+ }
1504+ return std::make_pair(is_new, stateid);
1505+ }
1506+
1507+ template<typename S>
1508+ void NestedDepthFirstSearch<S>::dfs()
1509+ {
1510+
1511+ light_deque<StackEntry> todo;
1512+ light_deque<StackEntry> nested_todo;
1513+
1514+ State working = this->_factory.newState();
1515+ State curState = this->_factory.newState();
1516+
1517+ {
1518 std::vector<State> initial_states = this->successorGenerator->makeInitialState();
1519 for (auto &state : initial_states) {
1520- auto res = states.add(state);
1521+ auto res = _states.add(state);
1522 if (res.first) {
1523- assert(res.first);
1524- todo.push(StackEntry{res.second, S::initial_suc_info()});
1525- this->_discovered++;
1526+ todo.push_back(StackEntry{res.second, S::initial_suc_info()});
1527+ ++this->_discovered;
1528 }
1529 }
1530 }
1531
1532 while (!todo.empty()) {
1533- auto &top = todo.top();
1534- states.decode(curState, top.id);
1535- this->successorGenerator->prepare(&curState, top.sucinfo);
1536- if (top.sucinfo.has_prev_state()) {
1537- states.decode(working, top.sucinfo.last_state);
1538+ auto &top = todo.back();
1539+ _states.decode(curState, top._id);
1540+ this->successorGenerator->prepare(&curState, top._sucinfo);
1541+ if (top._sucinfo.has_prev_state()) {
1542+ _states.decode(working, top._sucinfo.last_state);
1543 }
1544- if (!this->successorGenerator->next(working, top.sucinfo)) {
1545+ if (!this->successorGenerator->next(working, top._sucinfo)) {
1546 // no successor
1547- todo.pop();
1548- if (this->successorGenerator->isAccepting(curState)) {
1549- seed = &curState;
1550- ndfs(curState);
1551- if (violation) {
1552- if constexpr (SaveTrace) {
1553- std::stack<std::pair<size_t, size_t>> transitions;
1554- size_t next = top.id;
1555- states.decode(working, next);
1556- while (!this->successorGenerator->isInitialState(working)) {
1557- auto[parent, transition] = states.getHistory(next);
1558- transitions.push(std::make_pair(parent, transition));
1559- next = parent;
1560- states.decode(working, next);
1561- }
1562- printTrace(transitions);
1563+ if (curState.is_accepting()) {
1564+ if(this->successorGenerator->has_invariant_self_loop(curState))
1565+ _violation = true;
1566+ else
1567+ ndfs(curState, nested_todo);
1568+ if (_violation) {
1569+ if (_print_trace) {
1570+ print_trace(todo, nested_todo);
1571 }
1572 return;
1573 }
1574 }
1575+ todo.pop_back();
1576 } else {
1577- auto[_, stateid] = states.add(working);
1578+ auto [is_new, stateid] = mark(working, MARKER1);
1579 if (stateid == std::numeric_limits<size_t>::max()) {
1580 continue;
1581 }
1582- auto[it, is_new] = mark1.insert(stateid);
1583- top.sucinfo.last_state = stateid;
1584+ top._sucinfo.last_state = stateid;
1585 if (is_new) {
1586- if constexpr (SaveTrace) {
1587- states.setParent(top.id);
1588- states.setHistory(stateid, this->successorGenerator->fired());
1589+ ++this->_discovered;
1590+ if(this->successorGenerator->isAccepting(curState) &&
1591+ this->successorGenerator->has_invariant_self_loop(curState))
1592+ {
1593+ _violation = true;
1594+ if(_print_trace)
1595+ print_trace(todo, nested_todo);
1596+ return;
1597 }
1598- this->_discovered++;
1599- todo.push(StackEntry{stateid, S::initial_suc_info()});
1600+ todo.push_back(StackEntry{stateid, S::initial_suc_info()});
1601 }
1602 }
1603 }
1604 }
1605
1606- template<typename S, typename W>
1607- void NestedDepthFirstSearch<S, W>::ndfs(State &state)
1608+ template<typename S>
1609+ void NestedDepthFirstSearch<S>::ndfs(const State &state, light_deque<StackEntry>& nested_todo)
1610 {
1611- std::stack<StackEntry> todo;
1612-
1613- State working = factory.newState();
1614- State curState = factory.newState();
1615-
1616- todo.push(StackEntry{states.add(state).second, S::initial_suc_info()});
1617-
1618- while (!todo.empty()) {
1619- auto &top = todo.top();
1620- states.decode(curState, top.id);
1621- this->successorGenerator->prepare(&curState, top.sucinfo);
1622- if (top.sucinfo.has_prev_state()) {
1623- states.decode(working, top.sucinfo.last_state);
1624+
1625+ State working = this->_factory.newState();
1626+ State curState = this->_factory.newState();
1627+
1628+ nested_todo.push_back(StackEntry{_states.add(state).second, S::initial_suc_info()});
1629+
1630+ while (!nested_todo.empty()) {
1631+ auto &top = nested_todo.back();
1632+ _states.decode(curState, top._id);
1633+ this->successorGenerator->prepare(&curState, top._sucinfo);
1634+ if (top._sucinfo.has_prev_state()) {
1635+ _states.decode(working, top._sucinfo.last_state);
1636 }
1637- if (!this->successorGenerator->next(working, top.sucinfo)) {
1638- todo.pop();
1639+ if (!this->successorGenerator->next(working, top._sucinfo)) {
1640+ nested_todo.pop_back();
1641 } else {
1642 if (this->is_weak && !this->successorGenerator->isAccepting(working)) {
1643 continue;
1644 }
1645- if (working == *seed) {
1646- violation = true;
1647- if constexpr (SaveTrace) {
1648- auto[_, stateid] = states.add(working);
1649- auto seedId = stateid;
1650- states.setHistory2(stateid, this->successorGenerator->fired());
1651- size_t next = stateid;
1652- // follow trace until back at seed state.
1653- do {
1654- auto[state, transition] = states.getHistory2(next);
1655- nested_transitions.push(std::make_pair(state, transition));
1656- next = state;
1657- } while (next != seedId);
1658- }
1659+ if (working == state) {
1660+ _violation = true;
1661 return;
1662 }
1663- auto[_, stateid] = states.add(working);
1664- if (stateid == std::numeric_limits<size_t>::max()) {
1665+ auto [is_new, stateid] = mark(working, MARKER2);
1666+ if (stateid == std::numeric_limits<size_t>::max())
1667 continue;
1668- }
1669- auto[it, is_new] = mark2.insert(stateid);
1670- top.sucinfo.last_state = stateid;
1671+ top._sucinfo.last_state = stateid;
1672 if (is_new) {
1673- if constexpr (SaveTrace) {
1674- states.setParent(top.id);
1675- states.setHistory2(stateid, this->successorGenerator->fired());
1676- }
1677- this->_discovered++;
1678- todo.push(StackEntry{stateid, S::initial_suc_info()});
1679+ nested_todo.push_back(StackEntry{stateid, S::initial_suc_info()});
1680 }
1681-
1682 }
1683 }
1684 }
1685
1686- template<typename S, typename W>
1687- void NestedDepthFirstSearch<S, W>::printStats(std::ostream &os)
1688+ template<typename S>
1689+ void NestedDepthFirstSearch<S>::printStats(std::ostream &os)
1690 {
1691 std::cout << "STATS:\n"
1692- << "\tdiscovered states: " << states.discovered() << std::endl
1693- << "\tmax tokens: " << states.max_tokens() << std::endl
1694- << "\texplored states: " << mark1.size() << std::endl
1695- << "\texplored states (nested): " << mark2.size() << std::endl;
1696+ << "\tdiscovered states: " << _states.discovered() << std::endl
1697+ << "\tmax tokens: " << _states.max_tokens() << std::endl
1698+ << "\texplored states: " << _mark_count[MARKER1] << std::endl
1699+ << "\texplored states (nested): " << _mark_count[MARKER2] << std::endl;
1700 }
1701
1702
1703- template<typename S, typename W>
1704- void NestedDepthFirstSearch<S, W>::printTrace(std::stack<std::pair<size_t, size_t>> &transitions, std::ostream &os)
1705+ template<typename S>
1706+ void NestedDepthFirstSearch<S>::print_trace(light_deque<StackEntry>& _todo, light_deque<StackEntry>& _nested_todo, std::ostream &os)
1707 {
1708- State state = factory.newState();
1709 os << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
1710 "<trace>\n";
1711- while (!transitions.empty()) {
1712- auto[stateid, transition] = transitions.top();
1713- states.decode(state, stateid);
1714- this->printTransition(transition, state, os) << std::endl;
1715- transitions.pop();
1716+ if(this->_reducer)
1717+ this->_reducer->initFire(os);
1718+ size_t loop_id = std::numeric_limits<size_t>::max();
1719+ // last element of todo-stack always has a "garbage" transition, it is the
1720+ // current working element OR first element of nested.
1721+
1722+ if(!_todo.empty())
1723+ _todo.pop_back();
1724+ if(!_nested_todo.empty()) {
1725+ // here the last state is significant
1726+ // of the successor is the check that demonstrates the violation.
1727+ loop_id = _nested_todo.back()._id;
1728+ _nested_todo.pop_back();
1729 }
1730- this->printLoop(os);
1731- while (!nested_transitions.empty()) {
1732- auto[stateid, transition] = nested_transitions.top();
1733- states.decode(state, stateid);
1734
1735- this->printTransition(transition, state, os) << std::endl;
1736- nested_transitions.pop();
1737+ for(auto* stck : {&_todo, &_nested_todo})
1738+ {
1739+ while(!(*stck).empty())
1740+ {
1741+ auto& top = (*stck).front();
1742+ if(top._id == loop_id)
1743+ {
1744+ this->printLoop(os);
1745+ loop_id = std::numeric_limits<size_t>::max();
1746+ }
1747+ this->printTransition(top._sucinfo.transition(), os) << std::endl;
1748+ (*stck).pop_front();
1749+ }
1750 }
1751 os << std::endl << "</trace>" << std::endl;
1752 }
1753
1754 template
1755- class NestedDepthFirstSearch<LTL::ResumingSuccessorGenerator, LTL::Structures::BitProductStateSet<>>;
1756-
1757- template
1758- class NestedDepthFirstSearch<LTL::ResumingSuccessorGenerator, LTL::Structures::TraceableBitProductStateSet<>>;
1759-
1760- template
1761- class NestedDepthFirstSearch<LTL::SpoolingSuccessorGenerator, LTL::Structures::BitProductStateSet<>>;
1762-
1763- template
1764- class NestedDepthFirstSearch<LTL::SpoolingSuccessorGenerator, LTL::Structures::TraceableBitProductStateSet<>>;
1765-
1766+ class NestedDepthFirstSearch<LTL::ResumingSuccessorGenerator>;
1767+
1768+ template
1769+ class NestedDepthFirstSearch<LTL::SpoolingSuccessorGenerator>;
1770 }
1771
1772=== modified file 'src/LTL/Algorithm/TarjanModelChecker.cpp'
1773--- src/LTL/Algorithm/TarjanModelChecker.cpp 2021-08-10 13:44:22 +0000
1774+++ src/LTL/Algorithm/TarjanModelChecker.cpp 2021-10-17 18:21:15 +0000
1775@@ -24,50 +24,62 @@
1776 {
1777 this->is_weak = this->successorGenerator->is_weak() && this->shortcircuitweak;
1778 std::vector<State> initial_states = this->successorGenerator->makeInitialState();
1779- State working = factory.newState();
1780- State parent = factory.newState();
1781+ State working = this->_factory.newState();
1782+ State parent = this->_factory.newState();
1783 for (auto &state : initial_states) {
1784- const auto res = seen.add(state);
1785+ const auto res = _seen.add(state);
1786 if (res.first) {
1787 push(state, res.second);
1788 }
1789- while (!dstack.empty() && !violation) {
1790- DEntry &dtop = dstack.top();
1791+ while (!_dstack.empty() && !_violation) {
1792+ DEntry &dtop = _dstack.top();
1793 // write next successor state to working.
1794 if (!nexttrans(working, parent, dtop)) {
1795 ++this->stats.expanded;
1796+#ifndef NDEBUG
1797+ std::cerr << "backtrack\n";
1798+#endif
1799 pop();
1800 continue;
1801 }
1802+ auto fired = this->successorGenerator->fired();
1803+#ifndef NDEBUG
1804+ if (fired >= std::numeric_limits<uint32_t>::max() - 3) {
1805+ std::cerr << "looping\n";
1806+ }
1807+ else {
1808+ //state.print(*this->net, std::cerr); std::cerr << ": <transition id='" << this->net->transitionNames()[fired] << "'>" << std::endl ;
1809+ }
1810+#endif
1811 ++this->stats.explored;
1812- const auto[isnew, stateid] = seen.add(working);
1813+ const auto[isnew, stateid] = _seen.add(working);
1814 if (stateid == std::numeric_limits<idx_t>::max()) {
1815 continue;
1816 }
1817
1818 if constexpr (SaveTrace) {
1819 if (isnew) {
1820- seen.setHistory(stateid, this->successorGenerator->fired());
1821+ _seen.setHistory(stateid, this->successorGenerator->fired());
1822 }
1823 }
1824
1825- dtop.sucinfo.last_state = stateid;
1826+ dtop._sucinfo.last_state = stateid;
1827
1828 // lookup successor in 'hash' table
1829- auto suc_pos = chash[hash(stateid)];
1830- auto marking = seen.getMarkingId(stateid);
1831- while (suc_pos != std::numeric_limits<idx_t>::max() && cstack[suc_pos].stateid != stateid) {
1832- if constexpr (IsSpooling) {
1833- if (cstack[suc_pos].dstack && seen.getMarkingId(cstack[suc_pos].stateid) == marking) {
1834- this->successorGenerator->generateAll(&parent, dtop.sucinfo);
1835+ auto suc_pos = _chash[hash(stateid)];
1836+ auto marking = _seen.getMarkingId(stateid);
1837+ while (suc_pos != std::numeric_limits<idx_t>::max() && _cstack[suc_pos]._stateid != stateid) {
1838+ if constexpr (_is_spooling) {
1839+ if (_cstack[suc_pos]._dstack && _seen.getMarkingId(_cstack[suc_pos]._stateid) == marking) {
1840+ this->successorGenerator->generateAll(&parent, dtop._sucinfo);
1841 }
1842 }
1843- suc_pos = cstack[suc_pos].next;
1844+ suc_pos = _cstack[suc_pos]._next;
1845 }
1846 if (suc_pos != std::numeric_limits<idx_t>::max()) {
1847- if constexpr (IsSpooling) {
1848- if (cstack[suc_pos].dstack) {
1849- this->successorGenerator->generateAll(&parent, dtop.sucinfo);
1850+ if constexpr (_is_spooling) {
1851+ if (_cstack[suc_pos]._dstack) {
1852+ this->successorGenerator->generateAll(&parent, dtop._sucinfo);
1853 }
1854 }
1855 // we found the successor, i.e. there's a loop!
1856@@ -75,24 +87,24 @@
1857 update(suc_pos);
1858 continue;
1859 }
1860- if (store.find(stateid) == std::end(store)) {
1861+ if (_store.find(stateid) == std::end(_store)) {
1862 push(working, stateid);
1863 }
1864 }
1865 if constexpr (SaveTrace) {
1866 // print counter-example if it exists.
1867- if (violation) {
1868+ if (_violation) {
1869 std::stack<DEntry> revstack;
1870- while (!dstack.empty()) {
1871- revstack.push(std::move(dstack.top()));
1872- dstack.pop();
1873+ while (!_dstack.empty()) {
1874+ revstack.push(std::move(_dstack.top()));
1875+ _dstack.pop();
1876 }
1877 printTrace(std::move(revstack));
1878 return false;
1879 }
1880 }
1881 }
1882- return !violation;
1883+ return !_violation;
1884 }
1885
1886 /**
1887@@ -101,20 +113,19 @@
1888 */
1889 template<template<typename, typename...> typename S, typename G, bool SaveTrace, typename... Spooler>
1890 void TarjanModelChecker<S, G, SaveTrace, Spooler...>::push(State &state, size_t stateid) {
1891- const auto ctop = static_cast<idx_t>(cstack.size());
1892+ const auto ctop = static_cast<idx_t>(_cstack.size());
1893 const auto h = hash(stateid);
1894- cstack.emplace_back(ctop, stateid, chash[h]);
1895- chash[h] = ctop;
1896- dstack.push(DEntry{ctop});
1897+ _cstack.emplace_back(ctop, stateid, _chash[h]);
1898+ _chash[h] = ctop;
1899+ _dstack.push(DEntry{ctop});
1900 if (this->successorGenerator->isAccepting(state)) {
1901- astack.push(ctop);
1902- if (this->successorGenerator->has_invariant_self_loop(state) && !SaveTrace){
1903- //std::cerr << "Invariant self loop found. Violation is true" << std::endl;
1904- violation = true;
1905- invariant_loop = true;
1906+ _astack.push(ctop);
1907+ if (this->successorGenerator->has_invariant_self_loop(state)){
1908+ _violation = true;
1909+ _invariant_loop = true;
1910 }
1911 }
1912- if constexpr (IsSpooling) {
1913+ if constexpr (_is_spooling) {
1914 this->successorGenerator->push();
1915 }
1916 }
1917@@ -122,27 +133,27 @@
1918 template<template<typename, typename...> typename S, typename G, bool SaveTrace, typename... Spooler>
1919 void TarjanModelChecker<S, G, SaveTrace, Spooler...>::pop()
1920 {
1921- const auto p = dstack.top().pos;
1922- dstack.pop();
1923- cstack[p].dstack = false;
1924- if (cstack[p].lowlink == p) {
1925- while (cstack.size() > p) {
1926+ const auto p = _dstack.top()._pos;
1927+ _dstack.pop();
1928+ _cstack[p]._dstack = false;
1929+ if (_cstack[p]._lowlink == p) {
1930+ while (_cstack.size() > p) {
1931 popCStack();
1932 }
1933 } else if (this->is_weak) {
1934- State state = factory.newState();
1935- seen.decode(state, cstack[p].stateid);
1936+ State state = this->_factory.newState();
1937+ _seen.decode(state, _cstack[p]._stateid);
1938 if (!this->successorGenerator->isAccepting(state)) {
1939 popCStack();
1940 }
1941 }
1942- if (!astack.empty() && p == astack.top()) {
1943- astack.pop();
1944+ if (!_astack.empty() && p == _astack.top()) {
1945+ _astack.pop();
1946 }
1947- if (!dstack.empty()) {
1948+ if (!_dstack.empty()) {
1949 update(p);
1950- if constexpr (IsSpooling) {
1951- this->successorGenerator->pop(dstack.top().sucinfo);
1952+ if constexpr (_is_spooling) {
1953+ this->successorGenerator->pop(_dstack.top()._sucinfo);
1954 }
1955 }
1956 }
1957@@ -150,28 +161,28 @@
1958 template<template<typename, typename...> typename S, typename G, bool SaveTrace, typename... Spooler>
1959 void TarjanModelChecker<S, G, SaveTrace, Spooler...>::popCStack()
1960 {
1961- auto h = hash(cstack.back().stateid);
1962- store.insert(cstack.back().stateid);
1963- chash[h] = cstack.back().next;
1964- cstack.pop_back();
1965+ auto h = hash(_cstack.back()._stateid);
1966+ _store.insert(_cstack.back()._stateid);
1967+ _chash[h] = _cstack.back()._next;
1968+ _cstack.pop_back();
1969 }
1970
1971 template<template<typename, typename...> typename S, typename G, bool SaveTrace, typename... Spooler>
1972 void TarjanModelChecker<S, G, SaveTrace, Spooler...>::update(idx_t to)
1973 {
1974- const auto from = dstack.top().pos;
1975- assert(cstack[to].lowlink != std::numeric_limits<idx_t>::max() && cstack[from].lowlink != std::numeric_limits<idx_t>::max());
1976- if (cstack[to].lowlink <= cstack[from].lowlink) {
1977+ const auto from = _dstack.top()._pos;
1978+ assert(_cstack[to]._lowlink != std::numeric_limits<idx_t>::max() && _cstack[from]._lowlink != std::numeric_limits<idx_t>::max());
1979+ if (_cstack[to]._lowlink <= _cstack[from]._lowlink) {
1980 // we have now found a loop into earlier seen component cstack[to].lowlink.
1981 // if this earlier component precedes an accepting state,
1982 // the found loop is accepting and thus a violation.
1983- violation = (!astack.empty() && to <= astack.top());
1984+ _violation = (!_astack.empty() && to <= _astack.top());
1985 // either way update the component ID of the state we came from.
1986- cstack[from].lowlink = cstack[to].lowlink;
1987+ _cstack[from]._lowlink = _cstack[to]._lowlink;
1988 if constexpr (SaveTrace) {
1989- loopstate = cstack[from].stateid;
1990- looptrans = this->successorGenerator->fired();
1991- cstack[from].lowsource = to;
1992+ _loop_state = _cstack[to]._stateid;
1993+ _loop_trans = this->successorGenerator->fired();
1994+ _cstack[from]._lowsource = to;
1995
1996 }
1997 }
1998@@ -180,13 +191,13 @@
1999 template<template<typename, typename...> typename S, typename G, bool SaveTrace, typename... Spooler>
2000 bool TarjanModelChecker<S, G, SaveTrace, Spooler...>::nexttrans(State &state, State &parent, TarjanModelChecker::DEntry &delem)
2001 {
2002- seen.decode(parent, cstack[delem.pos].stateid);
2003- this->successorGenerator->prepare(&parent, delem.sucinfo);
2004+ _seen.decode(parent, _cstack[delem._pos]._stateid);
2005+ this->successorGenerator->prepare(&parent, delem._sucinfo);
2006 // ensure that `state` buffer contains the correct state for Büchi successor generation.
2007- if (delem.sucinfo.has_prev_state()) {
2008- seen.decode(state, delem.sucinfo.last_state);
2009+ if (delem._sucinfo.has_prev_state()) {
2010+ _seen.decode(state, delem._sucinfo.last_state);
2011 }
2012- auto res = this->successorGenerator->next(state, delem.sucinfo);
2013+ auto res = this->successorGenerator->next(state, delem._sucinfo);
2014 return res;
2015 }
2016
2017@@ -196,39 +207,49 @@
2018 if constexpr (!SaveTrace) {
2019 return;
2020 } else {
2021- assert(violation);
2022- State state = factory.newState();
2023+ assert(_violation);
2024 os << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
2025 "<trace>\n";
2026- if (cstack[dstack.top().pos].stateid == loopstate) this->printLoop(os);
2027- cstack[dstack.top().pos].lowlink = std::numeric_limits<idx_t>::max();
2028+ this->_reducer->initFire(os);
2029+ if (_cstack[dstack.top()._pos]._stateid == _loop_state)
2030+ this->printLoop(os);
2031 dstack.pop();
2032 unsigned long p;
2033+ bool had_deadlock = false;
2034 // print (reverted) dstack
2035 while (!dstack.empty()) {
2036- p = dstack.top().pos;
2037- auto stateid = cstack[p].stateid;
2038- auto[parent, tid] = seen.getHistory(stateid);
2039- seen.decode(state, parent);
2040-
2041- if (stateid == loopstate) this->printLoop(os);
2042- this->printTransition(tid, state, os) << '\n';
2043-
2044- cstack[p].lowlink = std::numeric_limits<idx_t>::max();
2045+ p = dstack.top()._pos;
2046 dstack.pop();
2047+ auto stateid = _cstack[p]._stateid;
2048+ auto[parent, tid] = _seen.getHistory(stateid);
2049+ this->printTransition(tid, os) << '\n';
2050+ if(tid >= std::numeric_limits<ptrie::uint>::max() - 1)
2051+ {
2052+ had_deadlock = true;
2053+ break;
2054+ }
2055+ if(_cstack[p]._stateid == _loop_state)
2056+ this->printLoop(os);
2057+ _cstack[p]._lowlink = std::numeric_limits<idx_t>::max();
2058 }
2059 // follow previously found back edges via lowsource until back in dstack.
2060- assert(cstack[p].lowsource != std::numeric_limits<idx_t>::max());
2061- p = cstack[p].lowsource;
2062- while (cstack[p].lowlink != std::numeric_limits<idx_t>::max()) {
2063- auto[parent, tid] = seen.getHistory(cstack[p].stateid);
2064- seen.decode(state, parent);
2065- this->printTransition(tid, state, os) << '\n';
2066- assert(cstack[p].lowsource != std::numeric_limits<idx_t>::max());
2067- p = cstack[p].lowsource;
2068+ if(_cstack[p]._lowsource != std::numeric_limits<idx_t>::max() && !had_deadlock)
2069+ {
2070+ p = _cstack[p]._lowsource;
2071+ while (_cstack[p]._lowlink != std::numeric_limits<idx_t>::max()) {
2072+ auto[parent, tid] = _seen.getHistory(_cstack[p]._stateid);
2073+ this->printTransition(tid, os) << '\n';
2074+ if(tid >= std::numeric_limits<ptrie::uint>::max() - 1)
2075+ {
2076+ had_deadlock = true;
2077+ break;
2078+ }
2079+ assert(_cstack[p]._lowsource != std::numeric_limits<idx_t>::max());
2080+ p = _cstack[p]._lowsource;
2081+ }
2082+ if(!had_deadlock)
2083+ this->printTransition(_loop_trans, os) << '\n';
2084 }
2085- seen.decode(state, loopstate);
2086- this->printTransition(looptrans, state, os) << '\n';
2087
2088 os << "</trace>" << std::endl;
2089 }
2090
2091=== modified file 'src/LTL/LTLMain.cpp'
2092--- src/LTL/LTLMain.cpp 2021-08-10 13:44:22 +0000
2093+++ src/LTL/LTLMain.cpp 2021-10-17 18:21:15 +0000
2094@@ -71,9 +71,7 @@
2095 }
2096
2097 template<typename Checker>
2098- Result _verify(const PetriNet *net,
2099- Condition_ptr &negatedQuery,
2100- std::unique_ptr<Checker> checker,
2101+ Result _verify(std::unique_ptr<Checker> checker,
2102 const options_t &options)
2103 {
2104 Result result;
2105@@ -110,15 +108,14 @@
2106 bool LTLMain(const PetriNet *net,
2107 const Condition_ptr &query,
2108 const std::string &queryName,
2109- options_t &options)
2110+ options_t &options, const Reducer* reducer)
2111 {
2112- auto res = to_ltl(query);
2113- Condition_ptr negated_formula = res.first;
2114- bool negate_answer = res.second;
2115
2116 // force AP compress off for Büchi prints
2117 options.ltl_compress_aps = options.buchi_out_file.empty() ? options.ltl_compress_aps : APCompression::None;
2118
2119+ auto [negated_formula, negate_answer] = to_ltl(query);
2120+
2121 Structures::BuchiAutomaton automaton = makeBuchiAutomaton(negated_formula, options);
2122 if (!options.buchi_out_file.empty()) {
2123 automaton.output_buchi(options.buchi_out_file, options.buchi_out_type);
2124@@ -127,7 +124,7 @@
2125 bool is_visible_stub = options.stubbornreduction
2126 && (options.ltl_por == LTLPartialOrder::Visible || options.ltl_por == LTLPartialOrder::VisibleReach)
2127 && !net->has_inhibitor()
2128- && !negated_formula->containsNext();
2129+ && !negated_formula->containsNext();
2130 bool is_autreach_stub = options.stubbornreduction
2131 && (options.ltl_por == LTLPartialOrder::AutomatonReach ||
2132 options.ltl_por == LTLPartialOrder::VisibleReach)
2133@@ -149,39 +146,17 @@
2134 spooler = std::make_unique<EnabledSpooler>(net, gen);
2135 gen.setSpooler(spooler.get());
2136 gen.setHeuristic(heuristic.get());
2137+ result = _verify(
2138+ std::make_unique<NestedDepthFirstSearch<SpoolingSuccessorGenerator>>(
2139+ net, negated_formula, automaton, &gen, options.trace != TraceLevel::None, options.kbound, reducer),
2140+ options);
2141
2142- if (options.trace != TraceLevel::None) {
2143- result = _verify(
2144- net, negated_formula,
2145- std::make_unique<NestedDepthFirstSearch<SpoolingSuccessorGenerator, LTL::Structures::TraceableBitProductStateSet<> >>(
2146- net, negated_formula, automaton, &gen,
2147- options.kbound),
2148- options);
2149- } else {
2150- result = _verify(
2151- net, negated_formula,
2152- std::make_unique<NestedDepthFirstSearch<SpoolingSuccessorGenerator, LTL::Structures::BitProductStateSet<> >>(
2153- net, negated_formula, automaton, &gen,
2154- options.kbound),
2155- options);
2156- }
2157 } else {
2158 ResumingSuccessorGenerator gen{net};
2159- if (options.trace != TraceLevel::None) {
2160- result = _verify(
2161- net, negated_formula,
2162- std::make_unique<NestedDepthFirstSearch<ResumingSuccessorGenerator, LTL::Structures::TraceableBitProductStateSet<> >>(
2163- net, negated_formula, automaton, &gen,
2164- options.kbound),
2165- options);
2166- } else {
2167- result = _verify(
2168- net, negated_formula,
2169- std::make_unique<NestedDepthFirstSearch<ResumingSuccessorGenerator, LTL::Structures::BitProductStateSet<> >>(
2170- net, negated_formula, automaton, &gen,
2171- options.kbound),
2172- options);
2173- }
2174+ result = _verify(
2175+ std::make_unique<NestedDepthFirstSearch<ResumingSuccessorGenerator>>(
2176+ net, negated_formula, automaton, &gen, options.trace != TraceLevel::None, options.kbound, reducer),
2177+ options);
2178 }
2179 break;
2180
2181@@ -191,7 +166,6 @@
2182 // Running default, BestFS, or RDFS search strategy so use spooling successor generator to enable heuristics.
2183 SpoolingSuccessorGenerator gen{net, negated_formula};
2184 if (is_visible_stub) {
2185- std::cout << "Running stubborn version!" << std::endl;
2186 spooler = std::make_unique<VisibleLTLStubbornSet>(*net, negated_formula);
2187 } else if (is_buchi_stub) {
2188 spooler = std::make_unique<AutomatonStubbornSet>(*net, automaton);
2189@@ -211,68 +185,62 @@
2190
2191 if (options.trace != TraceLevel::None) {
2192 if (is_autreach_stub && is_visible_stub) {
2193- result = _verify(net, negated_formula,
2194- std::make_unique<TarjanModelChecker<ReachStubProductSuccessorGenerator, SpoolingSuccessorGenerator, true, VisibleLTLStubbornSet>>(
2195+ result = _verify(std::make_unique<TarjanModelChecker<ReachStubProductSuccessorGenerator, SpoolingSuccessorGenerator, true, VisibleLTLStubbornSet>>(
2196 net,
2197 negated_formula,
2198 automaton,
2199 &gen,
2200- options.kbound,
2201+ options.kbound, reducer,
2202 std::make_unique<VisibleLTLStubbornSet>(*net, negated_formula)),
2203 options);
2204 }
2205 else if (is_autreach_stub && !is_visible_stub) {
2206- result = _verify(net, negated_formula,
2207- std::make_unique<TarjanModelChecker<ReachStubProductSuccessorGenerator, SpoolingSuccessorGenerator, true, EnabledSpooler>>(
2208+ result = _verify(std::make_unique<TarjanModelChecker<ReachStubProductSuccessorGenerator, SpoolingSuccessorGenerator, true, EnabledSpooler>>(
2209 net,
2210 negated_formula,
2211 automaton,
2212 &gen,
2213- options.kbound,
2214+ options.kbound, reducer,
2215 std::make_unique<EnabledSpooler>(net, gen)),
2216 options);
2217 }
2218 else {
2219- result = _verify(net, negated_formula,
2220- std::make_unique<TarjanModelChecker<ProductSuccessorGenerator, SpoolingSuccessorGenerator, true>>(
2221+ result = _verify(std::make_unique<TarjanModelChecker<ProductSuccessorGenerator, SpoolingSuccessorGenerator, true>>(
2222 net,
2223 negated_formula,
2224 automaton,
2225 &gen,
2226- options.kbound),
2227+ options.kbound, reducer),
2228 options);
2229 }
2230 } else {
2231
2232 if (is_autreach_stub && is_visible_stub) {
2233- result = _verify(net, negated_formula,
2234- std::make_unique<TarjanModelChecker<ReachStubProductSuccessorGenerator, SpoolingSuccessorGenerator, false, VisibleLTLStubbornSet>>(
2235+ result = _verify(std::make_unique<TarjanModelChecker<ReachStubProductSuccessorGenerator, SpoolingSuccessorGenerator, false, VisibleLTLStubbornSet>>(
2236 net,
2237 negated_formula,
2238 automaton,
2239 &gen,
2240- options.kbound,
2241+ options.kbound, reducer,
2242 std::make_unique<VisibleLTLStubbornSet>(*net, negated_formula)),
2243 options);
2244 } else if (is_autreach_stub && !is_visible_stub) {
2245- result = _verify(net, negated_formula,
2246- std::make_unique<TarjanModelChecker<ReachStubProductSuccessorGenerator, SpoolingSuccessorGenerator, false, EnabledSpooler>>(
2247+ result = _verify(std::make_unique<TarjanModelChecker<ReachStubProductSuccessorGenerator, SpoolingSuccessorGenerator, false, EnabledSpooler>>(
2248 net,
2249 negated_formula,
2250 automaton,
2251 &gen,
2252- options.kbound,
2253+ options.kbound, reducer,
2254 std::make_unique<EnabledSpooler>(net, gen)),
2255 options);
2256 }
2257 else {
2258- result = _verify(net, negated_formula,
2259- std::make_unique<TarjanModelChecker<ProductSuccessorGenerator, SpoolingSuccessorGenerator, false>>(
2260+ result = _verify(std::make_unique<TarjanModelChecker<ProductSuccessorGenerator, SpoolingSuccessorGenerator, false>>(
2261 net,
2262 negated_formula,
2263 automaton,
2264 &gen,
2265- options.kbound),
2266+ options.kbound, reducer),
2267 options);
2268 }
2269 }
2270@@ -281,22 +249,20 @@
2271
2272 // no spooling needed, thus use resuming successor generation
2273 if (options.trace != TraceLevel::None) {
2274- result = _verify(net, negated_formula,
2275- std::make_unique<TarjanModelChecker<ProductSuccessorGenerator, ResumingSuccessorGenerator, true>>(
2276+ result = _verify(std::make_unique<TarjanModelChecker<ProductSuccessorGenerator, ResumingSuccessorGenerator, true>>(
2277 net,
2278 negated_formula,
2279 automaton,
2280 &gen,
2281- options.kbound),
2282+ options.kbound, reducer),
2283 options);
2284 } else {
2285- result = _verify(net, negated_formula,
2286- std::make_unique<TarjanModelChecker<ProductSuccessorGenerator, ResumingSuccessorGenerator, false>>(
2287+ result = _verify(std::make_unique<TarjanModelChecker<ProductSuccessorGenerator, ResumingSuccessorGenerator, false>>(
2288 net,
2289 negated_formula,
2290 automaton,
2291 &gen,
2292- options.kbound),
2293+ options.kbound, reducer),
2294 options);
2295 }
2296 }
2297
2298=== modified file 'src/LTL/Stubborn/AutomatonStubbornSet.cpp'
2299--- src/LTL/Stubborn/AutomatonStubbornSet.cpp 2021-04-29 13:19:53 +0000
2300+++ src/LTL/Stubborn/AutomatonStubbornSet.cpp 2021-10-17 18:21:15 +0000
2301@@ -28,7 +28,7 @@
2302 public:
2303 NondeterministicConjunctionVisitor(AutomatonStubbornSet &stubbornSet) :
2304 InterestingLTLTransitionVisitor(stubbornSet, false),
2305- _stubborn(stubbornSet), _net(stubbornSet._net) {}
2306+ _net(stubbornSet._net), _stubborn(stubbornSet){}
2307
2308 protected:
2309 static constexpr auto PresetBad = StubbornSet::PresetBad;
2310
2311=== modified file 'src/LTL/Stubborn/SafeAutStubbornSet.cpp'
2312--- src/LTL/Stubborn/SafeAutStubbornSet.cpp 2021-05-13 09:19:31 +0000
2313+++ src/LTL/Stubborn/SafeAutStubbornSet.cpp 2021-10-17 18:21:15 +0000
2314@@ -16,6 +16,7 @@
2315 */
2316
2317 #include "LTL/Stubborn/SafeAutStubbornSet.h"
2318+#include "LTL/Stubborn/VisibleTransitionVisitor.h"
2319
2320 namespace LTL {
2321 using namespace PetriEngine;
2322@@ -28,37 +29,84 @@
2323
2324 constructEnabled();
2325 if (_ordering.empty()) {
2326+ _print_debug();
2327 return false;
2328 }
2329 if (_ordering.size() == 1) {
2330 _stubborn[_ordering.front()] = true;
2331+ _print_debug();
2332 return true;
2333 }
2334
2335+ InterestingLTLTransitionVisitor unsafe{*this, false};
2336 InterestingTransitionVisitor interesting{*this, false};
2337
2338- for (auto &q : _queries) {
2339- q->evalAndSet(PQL::EvaluationContext((*_parent).marking(), &_net));
2340- q->visit(interesting);
2341- }
2342+ PQL::EvaluationContext ctx((*_parent).marking(), &_net);
2343+ _prog_cond->evalAndSet(ctx);
2344+ _sink_cond->evalAndSet(ctx);
2345+ _prog_cond->visit(unsafe);
2346+ _sink_cond->visit(unsafe);
2347+
2348+ //_ret_cond->evalAndSet(ctx);
2349+ //(std::make_shared<PetriEngine::PQL::NotCondition>(_ret_cond))->visit(interesting);
2350+
2351 assert(!_bad);
2352
2353 _unsafe.swap(_stubborn);
2354+ _has_enabled_stubborn = false;
2355 //memset(_stubborn.get(), false, sizeof(bool) * _net.numberOfTransitions());
2356 _unprocessed.clear();
2357 memset(_places_seen.get(), 0, _net.numberOfPlaces());
2358
2359 assert(_unprocessed.empty());
2360
2361- for (auto &q : _queries) {
2362- q->visit(interesting);
2363+
2364+
2365+ // sink condition is not interesting, just unsafe.
2366+ _prog_cond->visit(interesting);
2367+ //_sink_cond->visit(interesting);
2368+ closure();
2369+ if (_bad) {
2370+ // abort
2371+ set_all_stubborn();
2372+ _print_debug();
2373+ return true;
2374+ }
2375+ // accepting states need key transition. add firs t enabled by index.
2376+ if (state->is_accepting() && !_has_enabled_stubborn) {
2377+ //set_all_stubborn();
2378+ //_print_debug();
2379+ //return true;
2380+ addToStub(_ordering.front());
2381 closure();
2382+/* for (int i = 0; i < _net.numberOfPlaces(); ++i) {
2383+ if (_enabled[i]) {
2384+ addToStub(i);
2385+ closure();
2386+ break;
2387+ }
2388+ }*/
2389 if (_bad) {
2390- // abort
2391 set_all_stubborn();
2392- return true;
2393 }
2394 }
2395+ _print_debug();
2396 return true;
2397 }
2398-}
2399\ No newline at end of file
2400+
2401+ void SafeAutStubbornSet::_print_debug() {
2402+#ifndef NDEBUG
2403+ float num_stubborn = 0;
2404+ float num_enabled = 0;
2405+ float num_enabled_stubborn = 0;
2406+ for (int i = 0; i < _net.numberOfTransitions(); ++i) {
2407+ if (_stubborn[i]) ++num_stubborn;
2408+ if (_enabled[i]) ++num_enabled;
2409+ if (_stubborn[i] && _enabled[i]) ++num_enabled_stubborn;
2410+ }
2411+ std::cerr << "Enabled: " << num_enabled << "/" << _net.numberOfTransitions() << " (" << num_enabled/_net.numberOfTransitions()*100.0 << "%),\t\t "
2412+ << "Stubborn: " << num_stubborn << "/" << _net.numberOfTransitions() << " (" << num_stubborn/_net.numberOfTransitions()*100.0 << "%),\t\t "
2413+ << "Enabled stubborn: " << num_enabled_stubborn << "/" << num_enabled << " (" << num_enabled_stubborn/num_enabled*100.0 << "%)" << std::endl;
2414+#endif
2415+ }
2416+}
2417
2418=== modified file 'src/LTL/SuccessorGeneration/ResumingSuccessorGenerator.cpp'
2419--- src/LTL/SuccessorGeneration/ResumingSuccessorGenerator.cpp 2021-04-29 07:47:52 +0000
2420+++ src/LTL/SuccessorGeneration/ResumingSuccessorGenerator.cpp 2021-10-17 18:21:15 +0000
2421@@ -34,13 +34,13 @@
2422 }
2423
2424
2425- void ResumingSuccessorGenerator::prepare(const Structures::State* state, const successor_info &sucinfo) {
2426+ void ResumingSuccessorGenerator::prepare(const Structures::State* state, const successor_info_t &sucinfo) {
2427 SuccessorGenerator::prepare(state);
2428 _suc_pcounter = sucinfo.pcounter;
2429 _suc_tcounter = sucinfo.tcounter;
2430 }
2431
2432- void ResumingSuccessorGenerator::getSuccInfo(successor_info &sucinfo) const {
2433+ void ResumingSuccessorGenerator::get_succ_info(successor_info_t &sucinfo) const {
2434 sucinfo.pcounter = _suc_pcounter;
2435 sucinfo.tcounter = _suc_tcounter;
2436 }
2437
2438=== modified file 'src/PetriEngine/PQL/Expressions.cpp'
2439--- src/PetriEngine/PQL/Expressions.cpp 2021-08-21 10:20:38 +0000
2440+++ src/PetriEngine/PQL/Expressions.cpp 2021-10-17 18:21:15 +0000
2441@@ -3,17 +3,17 @@
2442 * Thomas Søndersø Nielsen <primogens@gmail.com>,
2443 * Lars Kærlund Østergaard <larsko@gmail.com>,
2444 * Peter Gjøl Jensen <root@petergjoel.dk>
2445- *
2446+ *
2447 * This program is free software: you can redistribute it and/or modify
2448 * it under the terms of the GNU General Public License as published by
2449 * the Free Software Foundation, either version 3 of the License, or
2450 * (at your option) any later version.
2451- *
2452+ *
2453 * This program is distributed in the hope that it will be useful,
2454 * but WITHOUT ANY WARRANTY; without even the implied warranty of
2455 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2456 * GNU General Public License for more details.
2457- *
2458+ *
2459 * You should have received a copy of the GNU General Public License
2460 * along with this program. If not, see <http://www.gnu.org/licenses/>.
2461 */
2462@@ -38,7 +38,7 @@
2463
2464 namespace PetriEngine {
2465 namespace PQL {
2466-
2467+
2468 std::ostream& generateTabs(std::ostream& out, uint32_t tabs) {
2469
2470 for(uint32_t i = 0; i < tabs; i++) {
2471@@ -46,7 +46,7 @@
2472 }
2473 return out;
2474 }
2475-
2476+
2477 /** FOR COMPILING AND CONSTRUCTING LOGICAL OPERATORS **/
2478
2479 template<typename T>
2480@@ -61,7 +61,7 @@
2481 _conds.emplace_back(ptr);
2482 }
2483 else if (auto comp = std::dynamic_pointer_cast<CompareCondition>(ptr))
2484- {
2485+ {
2486 if((std::is_same<T, AndCondition>::value && std::dynamic_pointer_cast<NotEqualCondition>(ptr)) ||
2487 (std::is_same<T, OrCondition>::value && std::dynamic_pointer_cast<EqualCondition>(ptr)))
2488 {
2489@@ -113,7 +113,7 @@
2490 }
2491 else
2492 {
2493- _conds.emplace_back(ptr);
2494+ _conds.emplace_back(ptr);
2495 }
2496 }
2497 else
2498@@ -122,7 +122,7 @@
2499 }
2500
2501 }
2502-
2503+
2504 template<typename T, bool K>
2505 Condition_ptr makeLog(const std::vector<Condition_ptr>& conds, bool aggressive)
2506 {
2507@@ -138,28 +138,28 @@
2508 return BooleanCondition::getShared(K);
2509 return res;
2510 }
2511-
2512- Condition_ptr makeOr(const std::vector<Condition_ptr>& cptr)
2513+
2514+ Condition_ptr makeOr(const std::vector<Condition_ptr>& cptr)
2515 { return makeLog<OrCondition,false>(cptr, true); }
2516- Condition_ptr makeAnd(const std::vector<Condition_ptr>& cptr)
2517+ Condition_ptr makeAnd(const std::vector<Condition_ptr>& cptr)
2518 { return makeLog<AndCondition,true>(cptr, true); }
2519- Condition_ptr makeOr(const Condition_ptr& a, const Condition_ptr& b) {
2520- std::vector<Condition_ptr> cnds{a,b};
2521- return makeLog<OrCondition,false>(cnds, true);
2522- }
2523- Condition_ptr makeAnd(const Condition_ptr& a, const Condition_ptr& b)
2524- {
2525- std::vector<Condition_ptr> cnds{a,b};
2526- return makeLog<AndCondition,true>(cnds, true);
2527- }
2528-
2529-
2530+ Condition_ptr makeOr(const Condition_ptr& a, const Condition_ptr& b) {
2531+ std::vector<Condition_ptr> cnds{a,b};
2532+ return makeLog<OrCondition,false>(cnds, true);
2533+ }
2534+ Condition_ptr makeAnd(const Condition_ptr& a, const Condition_ptr& b)
2535+ {
2536+ std::vector<Condition_ptr> cnds{a,b};
2537+ return makeLog<AndCondition,true>(cnds, true);
2538+ }
2539+
2540+
2541 // CONSTANTS
2542 Condition_ptr BooleanCondition::FALSE_CONSTANT = std::make_shared<BooleanCondition>(false);
2543 Condition_ptr BooleanCondition::TRUE_CONSTANT = std::make_shared<BooleanCondition>(true);
2544 Condition_ptr DeadlockCondition::DEADLOCK = std::make_shared<DeadlockCondition>();
2545-
2546-
2547+
2548+
2549 Condition_ptr BooleanCondition::getShared(bool val)
2550 {
2551 if(val)
2552@@ -178,7 +178,7 @@
2553 out << op() << " ";
2554 _cond->toTAPAALQuery(out,context);
2555 }
2556-
2557+
2558 void UntilCondition::toTAPAALQuery(std::ostream& out,TAPAALConditionExportContext& context) const {
2559 out << op() << " (";
2560 _cond1->toTAPAALQuery(out, context);
2561@@ -186,7 +186,7 @@
2562 _cond2->toTAPAALQuery(out,context);
2563 out << ")";
2564 }
2565-
2566+
2567 void LogicalCondition::toTAPAALQuery(std::ostream& out,TAPAALConditionExportContext& context) const {
2568 out << "(";
2569 _conds[0]->toTAPAALQuery(out, context);
2570@@ -197,7 +197,7 @@
2571 }
2572 out << ")";
2573 }
2574-
2575+
2576 void CompareConjunction::toTAPAALQuery(std::ostream& out,TAPAALConditionExportContext& context) const {
2577 out << "(";
2578 if(_negated) out << "!";
2579@@ -205,11 +205,11 @@
2580 for(auto& c : _constraints)
2581 {
2582 if(!first) out << " and ";
2583- if(c._lower != 0)
2584+ if(c._lower != 0)
2585 out << "(" << c._lower << " <= " << context.netName << "." << c._name << ")";
2586- if(c._lower != 0 && c._upper != std::numeric_limits<uint32_t>::max())
2587+ if(c._lower != 0 && c._upper != std::numeric_limits<uint32_t>::max())
2588 out << " and ";
2589- if(c._lower != 0)
2590+ if(c._lower != 0)
2591 out << "(" << c._upper << " >= " << context.netName << "." << c._name << ")";
2592 first = false;
2593 }
2594@@ -270,7 +270,7 @@
2595 }
2596 out << ")";
2597 }
2598-
2599+
2600 /******************** opTAPAAL ********************/
2601
2602 std::string EqualCondition::opTAPAAL() const {
2603@@ -405,16 +405,16 @@
2604 void SimpleQuantifierCondition::analyze(AnalysisContext& context) {
2605 _cond->analyze(context);
2606 }
2607-
2608+
2609 void UntilCondition::analyze(AnalysisContext& context) {
2610 _cond1->analyze(context);
2611 _cond2->analyze(context);
2612 }
2613-
2614+
2615 void LogicalCondition::analyze(AnalysisContext& context) {
2616 for(auto& c : _conds) c->analyze(context);
2617 }
2618-
2619+
2620 void UnfoldedFireableCondition::_analyze(AnalysisContext& context)
2621 {
2622 std::vector<Condition_ptr> conds;
2623@@ -425,7 +425,7 @@
2624 _name.length());
2625 context.reportError(error);
2626 return;
2627- }
2628+ }
2629
2630 assert(_name.compare(context.net()->transitionNames()[result.offset]) == 0);
2631 auto preset = context.net()->preset(result.offset);
2632@@ -462,9 +462,9 @@
2633 ExprError error("Unable to resolve colored identifier \"" + _name + "\"", _name.length());
2634 coloredContext->reportError(error);
2635 return;
2636- }
2637+ }
2638 if(names.size() < 1){
2639- //If the transition points to empty vector we know that it has
2640+ //If the transition points to empty vector we know that it has
2641 //no legal bindings and can never fire
2642 _compiled = std::make_shared<BooleanCondition>(false);
2643 _compiled->analyze(context);
2644@@ -497,7 +497,7 @@
2645 _expr1->analyze(context);
2646 _expr2->analyze(context);
2647 }
2648-
2649+
2650 void NotCondition::analyze(AnalysisContext& context) {
2651 _cond->analyze(context);
2652 }
2653@@ -639,7 +639,7 @@
2654 }
2655 _compiled->analyze(context);
2656 }
2657-
2658+
2659 void UnfoldedUpperBoundsCondition::analyze(AnalysisContext& c)
2660 {
2661 for(auto& p : _places)
2662@@ -833,7 +833,7 @@
2663 setUpperBound(value(context.marking()));
2664 return _max <= _bound ? RTRUE : RUNKNOWN;
2665 }
2666-
2667+
2668 /******************** Evaluation - save result ********************/
2669 Condition::Result SimpleQuantifierCondition::evalAndSet(const EvaluationContext& context) {
2670 return RUNKNOWN;
2671@@ -880,14 +880,14 @@
2672 setSatisfied(res);
2673 return res;
2674 }
2675-
2676+
2677 Condition::Result UntilCondition::evalAndSet(const EvaluationContext& context) {
2678 auto r2 = _cond2->evalAndSet(context);
2679 if(r2 != RFALSE) return r2;
2680 auto r1 = _cond1->evalAndSet(context);
2681 if(r1 == RFALSE) return RFALSE;
2682 return RUNKNOWN;
2683- }
2684+ }
2685
2686 int Expr::evalAndSet(const EvaluationContext& context) {
2687 int r = evaluate(context);
2688@@ -939,7 +939,7 @@
2689 setSatisfied(res);
2690 return res;
2691 }
2692-
2693+
2694 Condition::Result CompareCondition::evalAndSet(const EvaluationContext& context) {
2695 int v1 = _expr1->evalAndSet(context);
2696 int v2 = _expr2->evalAndSet(context);
2697@@ -966,7 +966,7 @@
2698 setSatisfied(context.net()->deadlocked(context.marking()));
2699 return isSatisfied() ? RTRUE : RFALSE;
2700 }
2701-
2702+
2703 Condition::Result UnfoldedUpperBoundsCondition::evalAndSet(const EvaluationContext& context)
2704 {
2705 auto res = evaluate(context);
2706@@ -990,12 +990,12 @@
2707 {
2708 ctx.accept<decltype(this)>(this);
2709 }
2710-
2711+
2712 void EXCondition::visit(Visitor& ctx) const
2713 {
2714 ctx.accept<decltype(this)>(this);
2715 }
2716-
2717+
2718 void EFCondition::visit(Visitor& ctx) const
2719 {
2720 ctx.accept<decltype(this)>(this);
2721@@ -1004,7 +1004,7 @@
2722 void AUCondition::visit(Visitor& ctx) const
2723 {
2724 ctx.accept<decltype(this)>(this);
2725- }
2726+ }
2727
2728 void AXCondition::visit(Visitor& ctx) const
2729 {
2730@@ -1014,7 +1014,7 @@
2731 void AFCondition::visit(Visitor& ctx) const
2732 {
2733 ctx.accept<decltype(this)>(this);
2734- }
2735+ }
2736
2737 void AGCondition::visit(Visitor& ctx) const
2738 {
2739@@ -1060,7 +1060,7 @@
2740 {
2741 ctx.accept<decltype(this)>(this);
2742 }
2743-
2744+
2745 void EqualCondition::visit(Visitor& ctx) const
2746 {
2747 ctx.accept<decltype(this)>(this);
2748@@ -1075,22 +1075,22 @@
2749 {
2750 ctx.accept<decltype(this)>(this);
2751 }
2752-
2753+
2754 void LessThanOrEqualCondition::visit(Visitor& ctx) const
2755 {
2756 ctx.accept<decltype(this)>(this);
2757 }
2758-
2759+
2760 void LessThanCondition::visit(Visitor& ctx) const
2761 {
2762 ctx.accept<decltype(this)>(this);
2763 }
2764-
2765+
2766 void BooleanCondition::visit(Visitor& ctx) const
2767 {
2768 ctx.accept<decltype(this)>(this);
2769 }
2770-
2771+
2772 void DeadlockCondition::visit(Visitor& ctx) const
2773 {
2774 ctx.accept<decltype(this)>(this);
2775@@ -1143,7 +1143,7 @@
2776 else
2777 ctx.accept<decltype(this)>(this);
2778 }
2779-
2780+
2781 void UnfoldedFireableCondition::visit(Visitor& ctx) const
2782 {
2783 if(_compiled)
2784@@ -1152,12 +1152,12 @@
2785 ctx.accept<decltype(this)>(this);
2786 }
2787
2788-
2789+
2790 void UnfoldedUpperBoundsCondition::visit(Visitor& ctx) const
2791 {
2792 ctx.accept<decltype(this)>(this);
2793 }
2794-
2795+
2796 void LiteralExpr::visit(Visitor& ctx) const
2797 {
2798 ctx.accept<decltype(this)>(this);
2799@@ -1393,7 +1393,7 @@
2800 int MultiplyExpr::apply(int v1, int v2) const {
2801 return v1 * v2;
2802 }
2803-
2804+
2805 /******************** Apply (CompareCondition subclasses) ********************/
2806
2807 bool EqualCondition::apply(int v1, int v2) const {
2808@@ -1425,7 +1425,7 @@
2809 std::string MultiplyExpr::op() const {
2810 return "*";
2811 }
2812-
2813+
2814 /******************** Op (QuantifierCondition subclasses) ********************/
2815
2816 std::string ACondition::op() const {
2817@@ -1447,27 +1447,27 @@
2818 std::string XCondition::op() const {
2819 return "X";
2820 }
2821-
2822+
2823 std::string EXCondition::op() const {
2824 return "EX";
2825 }
2826-
2827+
2828 std::string EGCondition::op() const {
2829 return "EG";
2830 }
2831-
2832+
2833 std::string EFCondition::op() const {
2834 return "EF";
2835 }
2836-
2837+
2838 std::string AXCondition::op() const {
2839 return "AX";
2840 }
2841-
2842+
2843 std::string AGCondition::op() const {
2844 return "AG";
2845 }
2846-
2847+
2848 std::string AFCondition::op() const {
2849 return "AF";
2850 }
2851@@ -1481,11 +1481,11 @@
2852 std::string EUCondition::op() const {
2853 return "E";
2854 }
2855-
2856+
2857 std::string AUCondition::op() const {
2858 return "A";
2859 }
2860-
2861+
2862 /******************** Op (LogicalCondition subclasses) ********************/
2863
2864 std::string AndCondition::op() const {
2865@@ -1514,7 +1514,7 @@
2866 return "<=";
2867 }
2868
2869- /******************** free of places ********************/
2870+ /******************** free of places ********************/
2871
2872 bool NaryExpr::placeFree() const
2873 {
2874@@ -1523,18 +1523,18 @@
2875 return false;
2876 return true;
2877 }
2878-
2879+
2880 bool CommutativeExpr::placeFree() const
2881 {
2882 if(_ids.size() > 0) return false;
2883 return NaryExpr::placeFree();
2884 }
2885-
2886+
2887 bool MinusExpr::placeFree() const
2888 {
2889 return _expr->placeFree();
2890 }
2891-
2892+
2893 /******************** Expr::type() implementation ********************/
2894
2895 Expr::Types PlusExpr::type() const {
2896@@ -1610,17 +1610,17 @@
2897 return 0;
2898 }
2899
2900- uint32_t UnfoldedUpperBoundsCondition::distance(DistanceContext& context) const
2901+ uint32_t UnfoldedUpperBoundsCondition::distance(DistanceContext& context) const
2902 {
2903 size_t tmp = 0;
2904 for(auto& p : _places)
2905 {
2906 tmp += context.marking()[p._place];
2907 }
2908-
2909+
2910 return _max - tmp;
2911 }
2912-
2913+
2914 uint32_t EFCondition::distance(DistanceContext& context) const {
2915 return _cond->distance(context);
2916 }
2917@@ -1636,14 +1636,14 @@
2918 uint32_t EUCondition::distance(DistanceContext& context) const {
2919 return _cond2->distance(context);
2920 }
2921-
2922+
2923 uint32_t AFCondition::distance(DistanceContext& context) const {
2924 context.negate();
2925 uint32_t retval = _cond->distance(context);
2926 context.negate();
2927 return retval;
2928 }
2929-
2930+
2931 uint32_t AXCondition::distance(DistanceContext& context) const {
2932 context.negate();
2933 uint32_t retval = _cond->distance(context);
2934@@ -1665,7 +1665,7 @@
2935 context.negate();
2936 return r1 + r2;
2937 }
2938-
2939+
2940 uint32_t CompareConjunction::distance(DistanceContext& context) const {
2941 uint32_t d = 0;
2942 auto neg = context.negated() != _negated;
2943@@ -1691,7 +1691,7 @@
2944 else d = std::min(d, d2);
2945 first = false;
2946 }
2947-
2948+
2949 if(c._lower != 0)
2950 {
2951 auto d2 = delta<LessThanOrEqualCondition>(c._upper, pv, neg);
2952@@ -1739,35 +1739,35 @@
2953 int d;
2954 unsigned int p;
2955 };
2956-
2957+
2958 uint32_t LessThanOrEqualCondition::distance(DistanceContext& context) const {
2959 return _distance(context, delta<LessThanOrEqualCondition>);
2960 }
2961-
2962+
2963 uint32_t LessThanCondition::distance(DistanceContext& context) const {
2964 return _distance(context, delta<LessThanCondition>);
2965 }
2966-
2967+
2968 uint32_t NotEqualCondition::distance(DistanceContext& context) const {
2969 return _distance(context, delta<NotEqualCondition>);
2970 }
2971-
2972+
2973 uint32_t EqualCondition::distance(DistanceContext& context) const {
2974 return _distance(context, delta<EqualCondition>);
2975 }
2976
2977 /******************** BIN output ********************/
2978-
2979+
2980 void LiteralExpr::toBinary(std::ostream& out) const {
2981 out.write("l", sizeof(char));
2982 out.write(reinterpret_cast<const char*>(&_value), sizeof(int));
2983 }
2984-
2985+
2986 void UnfoldedIdentifierExpr::toBinary(std::ostream& out) const {
2987 out.write("i", sizeof(char));
2988- out.write(reinterpret_cast<const char*>(&_offsetInMarking), sizeof(int));
2989+ out.write(reinterpret_cast<const char*>(&_offsetInMarking), sizeof(int));
2990 }
2991-
2992+
2993 void MinusExpr::toBinary(std::ostream& out) const
2994 {
2995 auto e1 = std::make_shared<PQL::LiteralExpr>(0);
2996@@ -1776,7 +1776,7 @@
2997 exprs.push_back(_expr);
2998 PQL::SubtractExpr(std::move(exprs)).toBinary(out);
2999 }
3000-
3001+
3002 void SubtractExpr::toBinary(std::ostream& out) const {
3003 out.write("-", sizeof(char));
3004 uint32_t size = _exprs.size();
3005@@ -1799,7 +1799,7 @@
3006 for(auto& e : _exprs)
3007 e->toBinary(out);
3008 }
3009-
3010+
3011 void SimpleQuantifierCondition::toBinary(std::ostream& out) const
3012 {
3013 auto path = getPath();
3014@@ -1818,7 +1818,7 @@
3015 _cond1->toBinary(out);
3016 _cond2->toBinary(out);
3017 }
3018-
3019+
3020 void LogicalCondition::toBinary(std::ostream& out) const
3021 {
3022 auto path = getPath();
3023@@ -1829,7 +1829,7 @@
3024 out.write(reinterpret_cast<const char*>(&size), sizeof(uint32_t));
3025 for(auto& c : _conds) c->toBinary(out);
3026 }
3027-
3028+
3029 void CompareConjunction::toBinary(std::ostream& out) const
3030 {
3031 auto path = getPath();
3032@@ -1841,12 +1841,12 @@
3033 out.write(reinterpret_cast<const char*>(&size), sizeof(uint32_t));
3034 for(auto& c : _constraints)
3035 {
3036- out.write(reinterpret_cast<const char*>(&c._place), sizeof(int32_t));
3037+ out.write(reinterpret_cast<const char*>(&c._place), sizeof(int32_t));
3038 out.write(reinterpret_cast<const char*>(&c._lower), sizeof(uint32_t));
3039 out.write(reinterpret_cast<const char*>(&c._upper), sizeof(uint32_t));
3040 }
3041 }
3042-
3043+
3044 void CompareCondition::toBinary(std::ostream& out) const
3045 {
3046 auto path = getPath();
3047@@ -1859,7 +1859,7 @@
3048 _expr1->toBinary(out);
3049 _expr2->toBinary(out);
3050 }
3051-
3052+
3053 void DeadlockCondition::toBinary(std::ostream& out) const
3054 {
3055 auto path = getPath();
3056@@ -1867,7 +1867,7 @@
3057 out.write(reinterpret_cast<const char*>(&path), sizeof(Path));
3058 out.write(reinterpret_cast<const char*>(&quant), sizeof(Quantifier));
3059 }
3060-
3061+
3062 void BooleanCondition::toBinary(std::ostream& out) const
3063 {
3064 auto path = getPath();
3065@@ -1876,24 +1876,24 @@
3066 out.write(reinterpret_cast<const char*>(&quant), sizeof(Quantifier));
3067 out.write(reinterpret_cast<const char*>(&value), sizeof(bool));
3068 }
3069-
3070+
3071 void UnfoldedUpperBoundsCondition::toBinary(std::ostream& out) const
3072 {
3073 auto path = getPath();
3074 auto quant = Quantifier::UPPERBOUNDS;
3075 out.write(reinterpret_cast<const char*>(&path), sizeof(Path));
3076- out.write(reinterpret_cast<const char*>(&quant), sizeof(Quantifier));
3077+ out.write(reinterpret_cast<const char*>(&quant), sizeof(Quantifier));
3078 uint32_t size = _places.size();
3079- out.write(reinterpret_cast<const char*>(&size), sizeof(uint32_t));
3080- out.write(reinterpret_cast<const char*>(&_max), sizeof(double));
3081- out.write(reinterpret_cast<const char*>(&_offset), sizeof(double));
3082+ out.write(reinterpret_cast<const char*>(&size), sizeof(uint32_t));
3083+ out.write(reinterpret_cast<const char*>(&_max), sizeof(double));
3084+ out.write(reinterpret_cast<const char*>(&_offset), sizeof(double));
3085 for(auto& b : _places)
3086 {
3087- out.write(reinterpret_cast<const char*>(&b._place), sizeof(uint32_t));
3088+ out.write(reinterpret_cast<const char*>(&b._place), sizeof(uint32_t));
3089 out.write(reinterpret_cast<const char*>(&b._max), sizeof(double));
3090 }
3091 }
3092-
3093+
3094 void NotCondition::toBinary(std::ostream& out) const
3095 {
3096 auto path = getPath();
3097@@ -1902,9 +1902,9 @@
3098 out.write(reinterpret_cast<const char*>(&quant), sizeof(Quantifier));
3099 _cond->toBinary(out);
3100 }
3101-
3102- /******************** CTL Output ********************/
3103-
3104+
3105+ /******************** CTL Output ********************/
3106+
3107 void LiteralExpr::toXML(std::ostream& out,uint32_t tabs, bool tokencount) const {
3108 generateTabs(out,tabs) << "<integer-constant>" + std::to_string(_value) + "</integer-constant>\n";
3109 }
3110@@ -1929,14 +1929,14 @@
3111 ExprError error("Unable to resolve colored identifier \"" + _name + "\"", _name.length());
3112 coloredContext->reportError(error);
3113 return;
3114- }
3115+ }
3116 if(names.size() < 1){
3117- //If the transition points to empty vector we know that it has
3118+ //If the transition points to empty vector we know that it has
3119 //no legal bindings and can never fire
3120 out << "<false/>";
3121 return;
3122 }
3123-
3124+
3125 out << "<is-fireable>";
3126 for (auto& unfoldedName : names) {
3127 out << "<transition>" + unfoldedName << "</transition>";
3128@@ -1944,14 +1944,14 @@
3129 out << "</is-fireable>";
3130 }
3131 }
3132-
3133+
3134 void UnfoldedIdentifierExpr::toXML(std::ostream& out,uint32_t tabs, bool tokencount) const {
3135 if (tokencount) {
3136 generateTabs(out,tabs) << "<place>" << _name << "</place>\n";
3137 }
3138 else
3139 {
3140- generateTabs(out,tabs) << "<tokens-count>\n";
3141+ generateTabs(out,tabs) << "<tokens-count>\n";
3142 generateTabs(out,tabs+1) << "<place>" << _name << "</place>\n";
3143 generateTabs(out,tabs) << "</tokens-count>\n";
3144 }
3145@@ -1963,7 +1963,7 @@
3146 }
3147 else
3148 {
3149- out << "<tokens-count>\n";
3150+ out << "<tokens-count>\n";
3151 out << "<place>" << _name << "</place>\n";
3152 out << "</tokens-count>\n";
3153 }
3154@@ -1977,9 +1977,9 @@
3155 ExprError error("Unable to resolve colored identifier \"" + _name + "\"", _name.length());
3156 coloredContext->reportError(error);
3157 return;
3158- }
3159-
3160-
3161+ }
3162+
3163+
3164 out << "<tokens-count>\n";
3165 for (auto& unfoldedName : names) {
3166 out << "<place>" << unfoldedName.second << "</place>\n";
3167@@ -1991,19 +1991,19 @@
3168 }
3169 else
3170 {
3171- out << "<tokens-count>\n";
3172+ out << "<tokens-count>\n";
3173 out << "<place>" << _name << "</place>\n";
3174 out << "</tokens-count>\n";
3175 }
3176 }
3177 }
3178-
3179+
3180 void PlusExpr::toXML(std::ostream& ss,uint32_t tabs, bool tokencount) const {
3181 if (tokencount) {
3182 for(auto& e : _exprs) e->toXML(ss,tabs, tokencount);
3183 return;
3184 }
3185-
3186+
3187 if(tk) {
3188 generateTabs(ss,tabs) << "<tokens-count>\n";
3189 for(auto& e : _ids) generateTabs(ss,tabs+1) << "<place>" << e.second << "</place>\n";
3190@@ -2015,9 +2015,9 @@
3191 generateTabs(ss,tabs+1) << "<integer-constant>" + std::to_string(_constant) + "</integer-constant>\n";
3192 for(auto& i : _ids)
3193 {
3194- generateTabs(ss,tabs+1) << "<tokens-count>\n";
3195+ generateTabs(ss,tabs+1) << "<tokens-count>\n";
3196 generateTabs(ss,tabs+2) << "<place>" << i.second << "</place>\n";
3197- generateTabs(ss,tabs+1) << "</tokens-count>\n";
3198+ generateTabs(ss,tabs+1) << "</tokens-count>\n";
3199 }
3200 for(auto& e : _exprs) e->toXML(ss,tabs+1, tokencount);
3201 generateTabs(ss,tabs) << "</integer-sum>\n";
3202@@ -2028,7 +2028,7 @@
3203 for(auto& e : _exprs) e->toCompactXML(out,tabs, context, tokencount);
3204 return;
3205 }
3206-
3207+
3208 if(tk) {
3209 out << "<tokens-count>\n";
3210 for(auto& e : _ids) out << "<place>" << e.second << "</place>\n";
3211@@ -2040,14 +2040,14 @@
3212 out << "<integer-constant>" + std::to_string(_constant) + "</integer-constant>\n";
3213 for(auto& i : _ids)
3214 {
3215- out << "<tokens-count>\n";
3216+ out << "<tokens-count>\n";
3217 out << "<place>" << i.second << "</place>\n";
3218- out << "</tokens-count>\n";
3219+ out << "</tokens-count>\n";
3220 }
3221 for(auto& e : _exprs) e->toCompactXML(out,tabs, context, tokencount);
3222 out << "</integer-sum>\n";
3223 }
3224-
3225+
3226 void SubtractExpr::toXML(std::ostream& ss,uint32_t tabs, bool tokencount) const {
3227 generateTabs(ss,tabs) << "<integer-difference>\n";
3228 for(auto& e : _exprs) e->toXML(ss,tabs+1);
3229@@ -2059,7 +2059,7 @@
3230 for(auto& e : _exprs) e->toCompactXML(out,tabs, context);
3231 out << "</integer-difference>\n";
3232 }
3233-
3234+
3235 void MultiplyExpr::toXML(std::ostream& ss,uint32_t tabs, bool tokencount) const {
3236 generateTabs(ss,tabs) << "<integer-product>\n";
3237 for(auto& e : _exprs) e->toXML(ss,tabs+1);
3238@@ -2071,13 +2071,13 @@
3239 for(auto& e : _exprs) e->toCompactXML(out,tabs, context);
3240 out << "</integer-product>\n";
3241 }
3242-
3243+
3244 void MinusExpr::toXML(std::ostream& out,uint32_t tabs, bool tokencount) const {
3245-
3246+
3247 generateTabs(out,tabs) << "<integer-product>\n";
3248 _expr->toXML(out,tabs+1);
3249 generateTabs(out,tabs+1) << "<integer-difference>\n" ; generateTabs(out,tabs+2) <<
3250- "<integer-constant>0</integer-constant>\n" ; generateTabs(out,tabs+2) <<
3251+ "<integer-constant>0</integer-constant>\n" ; generateTabs(out,tabs+2) <<
3252 "<integer-constant>1</integer-constant>\n" ; generateTabs(out,tabs+1) <<
3253 "</integer-difference>\n" ; generateTabs(out,tabs) << "</integer-product>\n";
3254 }
3255@@ -2086,11 +2086,11 @@
3256 out << "<integer-product>\n";
3257 _expr->toCompactXML(out,tabs, context);
3258 out << "<integer-difference>\n" ; out <<
3259- "<integer-constant>0</integer-constant>\n" ; out <<
3260+ "<integer-constant>0</integer-constant>\n" ; out <<
3261 "<integer-constant>1</integer-constant>\n" ; out <<
3262 "</integer-difference>\n" ; out << "</integer-product>\n";
3263 }
3264-
3265+
3266 void EXCondition::toXML(std::ostream& out,uint32_t tabs) const {
3267 generateTabs(out,tabs) << "<exists-path>\n" ; generateTabs(out,tabs+1) << "<next>\n";
3268 _cond->toXML(out,tabs+2);
3269@@ -2103,66 +2103,66 @@
3270 out << "</next>\n" ; out << "</exists-path>\n";
3271 }
3272
3273- void AXCondition::toXML(std::ostream& out,uint32_t tabs) const {
3274+ void AXCondition::toXML(std::ostream& out,uint32_t tabs) const {
3275 generateTabs(out,tabs) << "<all-paths>\n"; generateTabs(out,tabs+1) << "<next>\n";
3276- _cond->toXML(out,tabs+2);
3277+ _cond->toXML(out,tabs+2);
3278 generateTabs(out,tabs+1) << "</next>\n"; generateTabs(out,tabs) << "</all-paths>\n";
3279 }
3280
3281- void AXCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3282+ void AXCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3283 out << "<all-paths>\n" ;out << "<next>\n";
3284 _cond->toCompactXML(out,tabs+2, context);
3285 out << "</next>\n" ; out << "</all-paths>\n";
3286 }
3287-
3288+
3289 void EFCondition::toXML(std::ostream& out,uint32_t tabs) const {
3290 generateTabs(out,tabs) << "<exists-path>\n" ; generateTabs(out,tabs+1) << "<finally>\n";
3291 _cond->toXML(out,tabs+2);
3292 generateTabs(out,tabs+1) << "</finally>\n" ; generateTabs(out,tabs) << "</exists-path>\n";
3293 }
3294
3295- void EFCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3296+ void EFCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3297 out << "<exists-path>\n" ;out << "<finally>\n";
3298 _cond->toCompactXML(out,tabs+2, context);
3299 out << "</finally>\n" ; out << "</exists-path>\n";
3300 }
3301-
3302+
3303 void AFCondition::toXML(std::ostream& out,uint32_t tabs) const {
3304 generateTabs(out,tabs) << "<all-paths>\n" ; generateTabs(out,tabs+1) << "<finally>\n";
3305 _cond->toXML(out,tabs+2);
3306 generateTabs(out,tabs+1) << "</finally>\n" ; generateTabs(out,tabs) << "</all-paths>\n";
3307 }
3308
3309- void AFCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3310+ void AFCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3311 out << "<all-paths>\n" ;out << "<finally>\n";
3312 _cond->toCompactXML(out,tabs+2, context);
3313 out << "</finally>\n" ; out << "</all-paths>\n";
3314 }
3315-
3316- void EGCondition::toXML(std::ostream& out,uint32_t tabs) const {
3317+
3318+ void EGCondition::toXML(std::ostream& out,uint32_t tabs) const {
3319 generateTabs(out,tabs) << "<exists-path>\n" ; generateTabs(out,tabs+1) << "<globally>\n";
3320- _cond->toXML(out,tabs+2);
3321+ _cond->toXML(out,tabs+2);
3322 generateTabs(out,tabs+1) << "</globally>\n" ; generateTabs(out,tabs) << "</exists-path>\n";
3323 }
3324
3325- void EGCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3326+ void EGCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3327 out << "<exists-path>\n" ;out << "<globally>\n";
3328 _cond->toCompactXML(out,tabs+2, context);
3329 out << "</globally>\n" ; out << "</exists-path>\n";
3330 }
3331-
3332- void AGCondition::toXML(std::ostream& out,uint32_t tabs) const {
3333+
3334+ void AGCondition::toXML(std::ostream& out,uint32_t tabs) const {
3335 generateTabs(out,tabs) << "<all-paths>\n" ; generateTabs(out,tabs+1) << "<globally>\n";
3336 _cond->toXML(out,tabs+2);
3337 generateTabs(out,tabs+1) << "</globally>\n" ; generateTabs(out,tabs) << "</all-paths>\n";
3338 }
3339
3340- void AGCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3341+ void AGCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3342 out << "<all-paths>\n" ;out << "<globally>\n";
3343 _cond->toCompactXML(out,tabs+2, context);
3344 out << "</globally>\n" ; out << "</all-paths>\n";
3345 }
3346-
3347+
3348 void EUCondition::toXML(std::ostream& out,uint32_t tabs) const {
3349 generateTabs(out,tabs) << "<exists-path>\n" ; generateTabs(out,tabs+1) << "<until>\n" ; generateTabs(out,tabs+2) << "<before>\n";
3350 _cond1->toXML(out,tabs+3);
3351@@ -2171,14 +2171,14 @@
3352 generateTabs(out,tabs+2) << "</reach>\n" ; generateTabs(out,tabs+1) << "</until>\n" ; generateTabs(out,tabs) << "</exists-path>\n";
3353 }
3354
3355- void EUCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3356+ void EUCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3357 out << "<exists-path>\n" ; out << "<until>\n" ; out << "<before>\n";
3358 _cond1->toCompactXML(out,tabs+2, context);
3359 out << "</before>\n" ; out << "<reach>\n";
3360 _cond2->toCompactXML(out,tabs+2, context);
3361 out << "</reach>\n" ; out << "</until>\n" ; out << "</exists-path>\n";
3362 }
3363-
3364+
3365 void AUCondition::toXML(std::ostream& out,uint32_t tabs) const {
3366 generateTabs(out,tabs) << "<all-paths>\n" ; generateTabs(out,tabs+1) << "<until>\n" ; generateTabs(out,tabs+2) << "<before>\n";
3367 _cond1->toXML(out,tabs+3);
3368@@ -2187,7 +2187,7 @@
3369 generateTabs(out,tabs+2) << "</reach>\n" ; generateTabs(out,tabs+1) << "</until>\n" ; generateTabs(out,tabs) << "</all-paths>\n";
3370 }
3371
3372- void AUCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3373+ void AUCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3374 out << "<all-paths>\n" ; out << "<until>\n" ; out << "<before>\n";
3375 _cond1->toCompactXML(out,tabs+2, context);
3376 out << "</before>\n" ; out << "<reach>\n";
3377@@ -2201,7 +2201,7 @@
3378 generateTabs(out, tabs) << "</all-paths>\n";
3379 }
3380
3381- void ACondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3382+ void ACondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3383 out << "<all-paths>\n" ;
3384 _cond->toCompactXML(out,tabs+2, context);
3385 out << "</all-paths>\n";
3386@@ -2213,7 +2213,7 @@
3387 generateTabs(out, tabs) << "</exists-path>\n";
3388 }
3389
3390- void ECondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3391+ void ECondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3392 out << "<exists-path>\n" ;
3393 _cond->toCompactXML(out,tabs+2, context);
3394 out << "</exists-path>\n";
3395@@ -2225,7 +2225,7 @@
3396 generateTabs(out, tabs) << "</finally>\n";
3397 }
3398
3399- void FCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3400+ void FCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3401 out << "<finally>\n" ;
3402 _cond->toCompactXML(out,tabs+2, context);
3403 out << "</finally>\n";
3404@@ -2237,7 +2237,7 @@
3405 generateTabs(out, tabs) << "</globally>\n";
3406 }
3407
3408- void GCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3409+ void GCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3410 out << "<globally>\n" ;
3411 _cond->toCompactXML(out,tabs+2, context);
3412 out << "</globally>\n";
3413@@ -2249,7 +2249,7 @@
3414 generateTabs(out, tabs) << "</next>\n";
3415 }
3416
3417- void XCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3418+ void XCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3419 out << "<next>\n" ;
3420 _cond->toCompactXML(out,tabs+2, context);
3421 out << "</next>\n";
3422@@ -2263,7 +2263,7 @@
3423 generateTabs(out,tabs+1) << "</reach>\n" ; generateTabs(out,tabs) << "</until>\n" ;
3424 }
3425
3426- void UntilCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3427+ void UntilCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3428 out << "<until>\n" ; out << "<before>\n";
3429 _cond1->toCompactXML(out,tabs+2, context);
3430 out << "</before>\n" ; out << "<reach>\n";
3431@@ -2298,12 +2298,12 @@
3432 }
3433 for(size_t i = _conds.size() - 1; i > 1; --i)
3434 {
3435- generateTabs(out,tabs + i) << "</conjunction>\n";
3436+ generateTabs(out,tabs + i) << "</conjunction>\n";
3437 }
3438- generateTabs(out,tabs) << "</conjunction>\n";
3439+ generateTabs(out,tabs) << "</conjunction>\n";
3440 }
3441
3442- void AndCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3443+ void AndCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3444 if(_conds.size() == 0)
3445 {
3446 BooleanCondition::TRUE_CONSTANT->toCompactXML(out,tabs, context);
3447@@ -2330,11 +2330,11 @@
3448 }
3449 for(size_t i = _conds.size() - 1; i > 1; --i)
3450 {
3451- out << "</conjunction>\n";
3452+ out << "</conjunction>\n";
3453 }
3454- out << "</conjunction>\n";
3455+ out << "</conjunction>\n";
3456 }
3457-
3458+
3459 void OrCondition::toXML(std::ostream& out,uint32_t tabs) const {
3460 if(_conds.size() == 0)
3461 {
3462@@ -2362,12 +2362,12 @@
3463 }
3464 for(size_t i = _conds.size() - 1; i > 1; --i)
3465 {
3466- generateTabs(out,tabs + i) << "</disjunction>\n";
3467+ generateTabs(out,tabs + i) << "</disjunction>\n";
3468 }
3469- generateTabs(out,tabs) << "</disjunction>\n";
3470+ generateTabs(out,tabs) << "</disjunction>\n";
3471 }
3472
3473- void OrCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3474+ void OrCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3475 if(_conds.size() == 0)
3476 {
3477 BooleanCondition::FALSE_CONSTANT->toCompactXML(out,tabs, context);
3478@@ -2394,9 +2394,9 @@
3479 }
3480 for(size_t i = _conds.size() - 1; i > 1; --i)
3481 {
3482- out << "</disjunction>\n";
3483+ out << "</disjunction>\n";
3484 }
3485- out << "</disjunction>\n";
3486+ out << "</disjunction>\n";
3487 }
3488
3489 void CompareConjunction::toXML(std::ostream& out, uint32_t tabs) const
3490@@ -2405,10 +2405,10 @@
3491 if(_constraints.size() == 0) BooleanCondition::TRUE_CONSTANT->toXML(out, tabs);
3492 else
3493 {
3494- bool single = _constraints.size() == 1 &&
3495+ bool single = _constraints.size() == 1 &&
3496 (_constraints[0]._lower == 0 ||
3497 _constraints[0]._upper == std::numeric_limits<uint32_t>::max());
3498- if(!single)
3499+ if(!single)
3500 generateTabs(out,tabs) << "<conjunction>\n";
3501 for(auto& c : _constraints)
3502 {
3503@@ -2419,7 +2419,7 @@
3504 generateTabs(out,tabs+3) << "<place>" << c._name << "</place>\n";
3505 generateTabs(out,tabs+2) << "</tokens-count>\n";
3506 generateTabs(out,tabs+2) << "<integer-constant>" << c._lower << "</integer-constant>\n";
3507- generateTabs(out,tabs+1) << "</integer-ge>\n";
3508+ generateTabs(out,tabs+1) << "</integer-ge>\n";
3509 }
3510 if(c._upper != std::numeric_limits<uint32_t>::max())
3511 {
3512@@ -2428,7 +2428,7 @@
3513 generateTabs(out,tabs+3) << "<place>" << c._name << "</place>\n";
3514 generateTabs(out,tabs+2) << "</tokens-count>\n";
3515 generateTabs(out,tabs+2) << "<integer-constant>" << c._upper << "</integer-constant>\n";
3516- generateTabs(out,tabs+1) << "</integer-le>\n";
3517+ generateTabs(out,tabs+1) << "</integer-le>\n";
3518 }
3519 }
3520 if(!single)
3521@@ -2437,15 +2437,15 @@
3522 if(_negated) generateTabs(out,--tabs) << "</negation>";
3523 }
3524
3525- void CompareConjunction::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3526+ void CompareConjunction::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3527 if(_negated) out << "<negation>";
3528 if(_constraints.size() == 0) BooleanCondition::TRUE_CONSTANT->toCompactXML(out,tabs, context);
3529 else
3530 {
3531- bool single = _constraints.size() == 1 &&
3532+ bool single = _constraints.size() == 1 &&
3533 (_constraints[0]._lower == 0 ||
3534 _constraints[0]._upper == std::numeric_limits<uint32_t>::max());
3535- if(!single)
3536+ if(!single)
3537 out << "<conjunction>\n";
3538 for(auto& c : _constraints)
3539 {
3540@@ -2456,7 +2456,7 @@
3541 out << "<place>" << c._name << "</place>\n";
3542 out << "</tokens-count>\n";
3543 out << "<integer-constant>" << c._lower << "</integer-constant>\n";
3544- out << "</integer-ge>\n";
3545+ out << "</integer-ge>\n";
3546 }
3547 if(c._upper != std::numeric_limits<uint32_t>::max())
3548 {
3549@@ -2465,104 +2465,104 @@
3550 out << "<place>" << c._name << "</place>\n";
3551 out << "</tokens-count>\n";
3552 out << "<integer-constant>" << c._upper << "</integer-constant>\n";
3553- out << "</integer-le>\n";
3554+ out << "</integer-le>\n";
3555 }
3556 }
3557 if(!single)
3558 out << "</conjunction>\n";
3559 }
3560- if(_negated) out << "</negation>";
3561+ if(_negated) out << "</negation>";
3562 }
3563
3564 void EqualCondition::toXML(std::ostream& out,uint32_t tabs) const {
3565 generateTabs(out,tabs) << "<integer-eq>\n";
3566 _expr1->toXML(out,tabs+1);
3567 _expr2->toXML(out,tabs+1);
3568- generateTabs(out,tabs) << "</integer-eq>\n";
3569+ generateTabs(out,tabs) << "</integer-eq>\n";
3570 }
3571
3572- void EqualCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3573+ void EqualCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3574 out << "<integer-eq>\n";
3575 _expr1->toCompactXML(out,tabs, context);
3576 _expr2->toCompactXML(out,tabs, context);
3577 out << "</integer-eq>\n";
3578 }
3579-
3580+
3581 void NotEqualCondition::toXML(std::ostream& out,uint32_t tabs) const {
3582 generateTabs(out,tabs) << "<integer-ne>\n";
3583 _expr1->toXML(out,tabs+1);
3584 _expr2->toXML(out,tabs+1);
3585- generateTabs(out,tabs) << "</integer-ne>\n";
3586+ generateTabs(out,tabs) << "</integer-ne>\n";
3587 }
3588
3589- void NotEqualCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3590+ void NotEqualCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3591 out << "<integer-ne>\n";
3592 _expr1->toCompactXML(out,tabs, context);
3593 _expr2->toCompactXML(out,tabs, context);
3594 out << "</integer-ne>\n";
3595 }
3596-
3597+
3598 void LessThanCondition::toXML(std::ostream& out,uint32_t tabs) const {
3599 generateTabs(out,tabs) << "<integer-lt>\n";
3600 _expr1->toXML(out,tabs+1);
3601 _expr2->toXML(out,tabs+1);
3602- generateTabs(out,tabs) << "</integer-lt>\n";
3603+ generateTabs(out,tabs) << "</integer-lt>\n";
3604 }
3605
3606- void LessThanCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3607+ void LessThanCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3608 out << "<integer-lt>\n";
3609 _expr1->toCompactXML(out,tabs, context);
3610 _expr2->toCompactXML(out,tabs, context);
3611 out << "</integer-lt>\n";
3612 }
3613-
3614+
3615 void LessThanOrEqualCondition::toXML(std::ostream& out,uint32_t tabs) const {
3616 generateTabs(out,tabs) << "<integer-le>\n";
3617 _expr1->toXML(out,tabs+1);
3618 _expr2->toXML(out,tabs+1);
3619- generateTabs(out,tabs) << "</integer-le>\n";
3620+ generateTabs(out,tabs) << "</integer-le>\n";
3621 }
3622
3623- void LessThanOrEqualCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3624+ void LessThanOrEqualCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3625 out << "<integer-le>\n";
3626 _expr1->toCompactXML(out,tabs, context);
3627 _expr2->toCompactXML(out,tabs, context);
3628 out << "</integer-le>\n";
3629 }
3630-
3631+
3632 void NotCondition::toXML(std::ostream& out,uint32_t tabs) const {
3633-
3634+
3635 generateTabs(out,tabs) << "<negation>\n";
3636 _cond->toXML(out,tabs+1);
3637- generateTabs(out,tabs) << "</negation>\n";
3638+ generateTabs(out,tabs) << "</negation>\n";
3639 }
3640
3641- void NotCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3642+ void NotCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3643 out << "<negation>\n";
3644 _cond->toCompactXML(out,tabs, context);
3645 out << "</negation>\n";
3646 }
3647-
3648- void BooleanCondition::toXML(std::ostream& out,uint32_t tabs) const {
3649- generateTabs(out,tabs) << "<" <<
3650- (value ? "true" : "false")
3651- << "/>\n";
3652- }
3653-
3654- void BooleanCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3655- out << "<" <<
3656- (value ? "true" : "false")
3657- << "/>\n";
3658- }
3659-
3660+
3661+ void BooleanCondition::toXML(std::ostream& out,uint32_t tabs) const {
3662+ generateTabs(out,tabs) << "<" <<
3663+ (value ? "true" : "false")
3664+ << "/>\n";
3665+ }
3666+
3667+ void BooleanCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3668+ out << "<" <<
3669+ (value ? "true" : "false")
3670+ << "/>\n";
3671+ }
3672+
3673 void DeadlockCondition::toXML(std::ostream& out,uint32_t tabs) const {
3674- generateTabs(out,tabs) << "<deadlock/>\n";
3675+ generateTabs(out,tabs) << "<deadlock/>\n";
3676 }
3677
3678- void DeadlockCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3679+ void DeadlockCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3680 out << "<deadlock/>\n";
3681 }
3682-
3683+
3684 void UnfoldedUpperBoundsCondition::toXML(std::ostream& out, uint32_t tabs) const {
3685 generateTabs(out, tabs) << "<place-bound>\n";
3686 for(auto& p : _places)
3687@@ -2570,33 +2570,33 @@
3688 generateTabs(out, tabs) << "</place-bound>\n";
3689 }
3690
3691- void UnfoldedUpperBoundsCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3692+ void UnfoldedUpperBoundsCondition::toCompactXML(std::ostream& out, uint32_t tabs, AnalysisContext& context) const{
3693 out << "<place-bound>\n";
3694 for(auto& p : _places)
3695 out << "<place>" << p._name << "</place>\n";
3696- out << "</place-bound>\n";
3697+ out << "</place-bound>\n";
3698 }
3699-
3700- /******************** Query Simplification ********************/
3701-
3702+
3703+ /******************** Query Simplification ********************/
3704+
3705 Member LiteralExpr::constraint(SimplificationContext& context) const {
3706 return Member(_value);
3707 }
3708-
3709- Member memberForPlace(size_t p, SimplificationContext& context)
3710+
3711+ Member memberForPlace(size_t p, SimplificationContext& context)
3712 {
3713 std::vector<int> row(context.net()->numberOfTransitions(), 0);
3714 row.shrink_to_fit();
3715 for (size_t t = 0; t < context.net()->numberOfTransitions(); t++) {
3716 row[t] = context.net()->outArc(t, p) - context.net()->inArc(p, t);
3717 }
3718- return Member(std::move(row), context.marking()[p]);
3719+ return Member(std::move(row), context.marking()[p]);
3720 }
3721-
3722+
3723 Member UnfoldedIdentifierExpr::constraint(SimplificationContext& context) const {
3724 return memberForPlace(_offsetInMarking, context);
3725 }
3726-
3727+
3728 Member CommutativeExpr::commutativeCons(int constant, SimplificationContext& context, std::function<void(Member& a, Member b)> op) const
3729 {
3730 Member res;
3731@@ -2606,7 +2606,7 @@
3732 first = false;
3733 res = Member(_constant);
3734 }
3735-
3736+
3737 for(auto& i : _ids)
3738 {
3739 if(first) res = memberForPlace(i.first, context);
3740@@ -2620,28 +2620,28 @@
3741 else op(res, e->constraint(context));
3742 first = false;
3743 }
3744- return res;
3745+ return res;
3746 }
3747-
3748+
3749 Member PlusExpr::constraint(SimplificationContext& context) const {
3750 return commutativeCons(0, context, [](auto& a , auto b){ a += b;});
3751 }
3752-
3753+
3754 Member SubtractExpr::constraint(SimplificationContext& context) const {
3755 Member res = _exprs[0]->constraint(context);
3756 for(size_t i = 1; i < _exprs.size(); ++i) res -= _exprs[i]->constraint(context);
3757 return res;
3758 }
3759-
3760+
3761 Member MultiplyExpr::constraint(SimplificationContext& context) const {
3762 return commutativeCons(1, context, [](auto& a , auto b){ a *= b;});
3763 }
3764-
3765+
3766 Member MinusExpr::constraint(SimplificationContext& context) const {
3767 Member neg(-1);
3768 return _expr->constraint(context) *= neg;
3769 }
3770-
3771+
3772 Retval simplifyEX(Retval& r, SimplificationContext& context) {
3773 if(r.formula->isTriviallyTrue() || !r.neglps->satisfiable(context)) {
3774 return Retval(std::make_shared<NotCondition>(
3775@@ -2652,7 +2652,7 @@
3776 return Retval(std::make_shared<EXCondition>(r.formula));
3777 }
3778 }
3779-
3780+
3781 Retval simplifyAX(Retval& r, SimplificationContext& context) {
3782 if(r.formula->isTriviallyTrue() || !r.neglps->satisfiable(context)){
3783 return Retval(BooleanCondition::TRUE_CONSTANT);
3784@@ -2672,7 +2672,7 @@
3785 return Retval(std::make_shared<EFCondition>(r.formula));
3786 }
3787 }
3788-
3789+
3790 Retval simplifyAF(Retval& r, SimplificationContext& context){
3791 if(r.formula->isTriviallyTrue() || !r.neglps->satisfiable(context)){
3792 return Retval(BooleanCondition::TRUE_CONSTANT);
3793@@ -2682,7 +2682,7 @@
3794 return Retval(std::make_shared<AFCondition>(r.formula));
3795 }
3796 }
3797-
3798+
3799 Retval simplifyEG(Retval& r, SimplificationContext& context){
3800 if(r.formula->isTriviallyTrue() || !r.neglps->satisfiable(context)){
3801 return Retval(BooleanCondition::TRUE_CONSTANT);
3802@@ -2692,7 +2692,7 @@
3803 return Retval(std::make_shared<EGCondition>(r.formula));
3804 }
3805 }
3806-
3807+
3808 Retval simplifyAG(Retval& r, SimplificationContext& context){
3809 if(r.formula->isTriviallyTrue() || !r.neglps->satisfiable(context)){
3810 return Retval(BooleanCondition::TRUE_CONSTANT);
3811@@ -2720,32 +2720,32 @@
3812 Retval r = _cond->simplify(context);
3813 return context.negated() ? simplifyAX(r, context) : simplifyEX(r, context);
3814 }
3815-
3816+
3817 Retval AXCondition::simplify(SimplificationContext& context) const {
3818 Retval r = _cond->simplify(context);
3819 return context.negated() ? simplifyEX(r, context) : simplifyAX(r, context);
3820- }
3821-
3822+ }
3823+
3824 Retval EFCondition::simplify(SimplificationContext& context) const {
3825 Retval r = _cond->simplify(context);
3826- return context.negated() ? simplifyAG(r, context) : simplifyEF(r, context);
3827+ return context.negated() ? simplifyAG(r, context) : simplifyEF(r, context);
3828 }
3829-
3830+
3831 Retval AFCondition::simplify(SimplificationContext& context) const {
3832 Retval r = _cond->simplify(context);
3833- return context.negated() ? simplifyEG(r, context) : simplifyAF(r, context);
3834+ return context.negated() ? simplifyEG(r, context) : simplifyAF(r, context);
3835 }
3836-
3837+
3838 Retval EGCondition::simplify(SimplificationContext& context) const {
3839 Retval r = _cond->simplify(context);
3840- return context.negated() ? simplifyAF(r, context) : simplifyEG(r, context);
3841+ return context.negated() ? simplifyAF(r, context) : simplifyEG(r, context);
3842 }
3843-
3844+
3845 Retval AGCondition::simplify(SimplificationContext& context) const {
3846 Retval r = _cond->simplify(context);
3847- return context.negated() ? simplifyEF(r, context) : simplifyAG(r, context);
3848+ return context.negated() ? simplifyEF(r, context) : simplifyAG(r, context);
3849 }
3850-
3851+
3852 Retval EUCondition::simplify(SimplificationContext& context) const {
3853 // cannot push negation any further
3854 bool neg = context.negated();
3855@@ -2754,20 +2754,20 @@
3856 if(r2.formula->isTriviallyTrue() || !r2.neglps->satisfiable(context))
3857 {
3858 context.setNegate(neg);
3859- return neg ?
3860+ return neg ?
3861 Retval(BooleanCondition::FALSE_CONSTANT) :
3862 Retval(BooleanCondition::TRUE_CONSTANT);
3863 }
3864 else if(r2.formula->isTriviallyFalse() || !r2.lps->satisfiable(context))
3865 {
3866 context.setNegate(neg);
3867- return neg ?
3868+ return neg ?
3869 Retval(BooleanCondition::TRUE_CONSTANT) :
3870- Retval(BooleanCondition::FALSE_CONSTANT);
3871+ Retval(BooleanCondition::FALSE_CONSTANT);
3872 }
3873 Retval r1 = _cond1->simplify(context);
3874 context.setNegate(neg);
3875-
3876+
3877 if(context.negated()){
3878 if(r1.formula->isTriviallyTrue() || !r1.neglps->satisfiable(context)){
3879 return Retval(std::make_shared<NotCondition>(
3880@@ -2788,7 +2788,7 @@
3881 }
3882 }
3883 }
3884-
3885+
3886 Retval AUCondition::simplify(SimplificationContext& context) const {
3887 // cannot push negation any further
3888 bool neg = context.negated();
3889@@ -2797,20 +2797,20 @@
3890 if(r2.formula->isTriviallyTrue() || !r2.neglps->satisfiable(context))
3891 {
3892 context.setNegate(neg);
3893- return neg ?
3894+ return neg ?
3895 Retval(BooleanCondition::FALSE_CONSTANT) :
3896 Retval(BooleanCondition::TRUE_CONSTANT);
3897 }
3898 else if(r2.formula->isTriviallyFalse() || !r2.lps->satisfiable(context))
3899 {
3900 context.setNegate(neg);
3901- return neg ?
3902+ return neg ?
3903 Retval(BooleanCondition::TRUE_CONSTANT) :
3904 Retval(BooleanCondition::FALSE_CONSTANT);
3905 }
3906 Retval r1 = _cond1->simplify(context);
3907 context.setNegate(neg);
3908-
3909+
3910 if(context.negated()){
3911 if(r1.formula->isTriviallyTrue() || !r1.neglps->satisfiable(context)){
3912 return Retval(std::make_shared<NotCondition>(
3913@@ -2919,7 +2919,7 @@
3914 }
3915 return lps[0];
3916 }
3917-
3918+
3919 Retval LogicalCondition::simplifyAnd(SimplificationContext& context) const {
3920
3921 std::vector<Condition_ptr> conditions;
3922@@ -2936,12 +2936,12 @@
3923 {
3924 continue;
3925 }
3926-
3927+
3928 conditions.push_back(r.formula);
3929 lpsv.emplace_back(r.lps);
3930 neglps.emplace_back(r.neglps);
3931 }
3932-
3933+
3934 if(conditions.size() == 0)
3935 {
3936 return Retval(BooleanCondition::TRUE_CONSTANT);
3937@@ -2953,24 +2953,24 @@
3938 if(!context.timeout() && !lps->satisfiable(context))
3939 {
3940 return Retval(BooleanCondition::FALSE_CONSTANT);
3941- }
3942+ }
3943 }
3944 catch(std::bad_alloc& e)
3945 {
3946 // we are out of memory, deal with it.
3947 std::cout<<"Query reduction: memory exceeded during LPS merge."<<std::endl;
3948 }
3949-
3950+
3951 // Lets try to see if the r1 AND r2 can ever be false at the same time
3952 // If not, then we know that r1 || r2 must be true.
3953 // we check this by checking if !r1 && !r2 is unsat
3954-
3955+
3956 return Retval(
3957- makeAnd(conditions),
3958+ makeAnd(conditions),
3959 std::move(lps),
3960 std::make_shared<UnionCollection>(std::move(neglps)));
3961 }
3962-
3963+
3964 Retval LogicalCondition::simplifyOr(SimplificationContext& context) const {
3965
3966 std::vector<Condition_ptr> conditions;
3967@@ -2993,7 +2993,7 @@
3968 lps.push_back(r.lps);
3969 neglpsv.emplace_back(r.neglps);
3970 }
3971-
3972+
3973 AbstractProgramCollection_ptr neglps = mergeLps(std::move(neglpsv));
3974
3975 if(conditions.size() == 0)
3976@@ -3005,7 +3005,7 @@
3977 if(!context.timeout() && !neglps->satisfiable(context))
3978 {
3979 return Retval(BooleanCondition::TRUE_CONSTANT);
3980- }
3981+ }
3982 }
3983 catch(std::bad_alloc& e)
3984 {
3985@@ -3016,20 +3016,20 @@
3986 // Lets try to see if the r1 AND r2 can ever be false at the same time
3987 // If not, then we know that r1 || r2 must be true.
3988 // we check this by checking if !r1 && !r2 is unsat
3989-
3990+
3991 return Retval(
3992- makeOr(conditions),
3993- std::make_shared<UnionCollection>(std::move(lps)),
3994- std::move(neglps));
3995+ makeOr(conditions),
3996+ std::make_shared<UnionCollection>(std::move(lps)),
3997+ std::move(neglps));
3998 }
3999-
4000+
4001 Retval AndCondition::simplify(SimplificationContext& context) const {
4002 if(context.timeout())
4003 {
4004- if(context.negated())
4005+ if(context.negated())
4006 return Retval(std::make_shared<NotCondition>(
4007 makeAnd(_conds)));
4008- else
4009+ else
4010 return Retval(
4011 makeAnd(_conds));
4012 }
4013@@ -3038,16 +3038,16 @@
4014 return simplifyOr(context);
4015 else
4016 return simplifyAnd(context);
4017-
4018+
4019 }
4020-
4021- Retval OrCondition::simplify(SimplificationContext& context) const {
4022+
4023+ Retval OrCondition::simplify(SimplificationContext& context) const {
4024 if(context.timeout())
4025 {
4026- if(context.negated())
4027+ if(context.negated())
4028 return Retval(std::make_shared<NotCondition>(
4029 makeOr(_conds)));
4030- else
4031+ else
4032 return Retval(makeOr(_conds));
4033 }
4034 if(context.negated())
4035@@ -3055,7 +3055,7 @@
4036 else
4037 return simplifyOr(context);
4038 }
4039-
4040+
4041 Retval CompareConjunction::simplify(SimplificationContext& context) const {
4042 if(context.timeout())
4043 {
4044@@ -3064,7 +3064,7 @@
4045 std::vector<AbstractProgramCollection_ptr> neglps, lpsv;
4046 auto neg = context.negated() != _negated;
4047 std::vector<cons_t> nconstraints;
4048- for(auto& c : _constraints)
4049+ for(auto& c : _constraints)
4050 {
4051 nconstraints.push_back(c);
4052 if(c._lower != 0 /*&& !context.timeout()*/ )
4053@@ -3088,7 +3088,7 @@
4054 neglps.push_back(nlp);
4055 }
4056 }
4057-
4058+
4059 if(c._upper != std::numeric_limits<uint32_t>::max() /*&& !context.timeout()*/)
4060 {
4061 auto m1 = memberForPlace(c._place, context);
4062@@ -3110,26 +3110,26 @@
4063 neglps.push_back(nlp);
4064 }
4065 }
4066-
4067+
4068 assert(nconstraints.size() > 0);
4069 if(nconstraints.back()._lower == 0 && nconstraints.back()._upper == std::numeric_limits<uint32_t>::max())
4070 nconstraints.pop_back();
4071
4072 assert(nconstraints.size() <= neglps.size()*2);
4073 }
4074-
4075+
4076 auto lps = mergeLps(std::move(lpsv));
4077-
4078- if(lps == nullptr && !context.timeout())
4079+
4080+ if(lps == nullptr && !context.timeout())
4081 {
4082 return Retval(BooleanCondition::getShared(!neg));
4083 }
4084-
4085+
4086 try {
4087 if(!context.timeout() && lps && !lps->satisfiable(context))
4088 {
4089 return Retval(BooleanCondition::getShared(neg));
4090- }
4091+ }
4092 }
4093 catch(std::bad_alloc& e)
4094 {
4095@@ -3142,7 +3142,7 @@
4096 try {
4097 // remove trivial rules from neglp
4098 int ncnt = neglps.size() - 1;
4099- for(int i = nconstraints.size() - 1; i >= 0; --i)
4100+ for(int i = nconstraints.size() - 1; i >= 0; --i)
4101 {
4102 if(context.timeout()) break;
4103 assert(ncnt >= 0);
4104@@ -3161,7 +3161,7 @@
4105 c._upper = std::numeric_limits<uint32_t>::max();
4106 neglps.erase(neglps.begin() + ncnt);
4107 }
4108- if(c._upper == std::numeric_limits<uint32_t>::max() && c._lower == 0)
4109+ if(c._upper == std::numeric_limits<uint32_t>::max() && c._lower == 0)
4110 nconstraints.erase(nconstraints.begin() + i);
4111 --ncnt;
4112 }
4113@@ -3171,13 +3171,13 @@
4114 {
4115 // we are out of memory, deal with it.
4116 std::cout<<"Query reduction: memory exceeded during LPS merge."<<std::endl;
4117- }
4118+ }
4119 if(nconstraints.size() == 0)
4120 {
4121- return Retval(BooleanCondition::getShared(!neg));
4122+ return Retval(BooleanCondition::getShared(!neg));
4123 }
4124
4125-
4126+
4127 Condition_ptr rc = [&]() -> Condition_ptr {
4128 if(nconstraints.size() == 1)
4129 {
4130@@ -3209,7 +3209,7 @@
4131 else
4132 {
4133 if(neg) return std::make_shared<LessThanCondition>(lu, id);
4134- else return std::make_shared<LessThanOrEqualCondition>(id, lu);
4135+ else return std::make_shared<LessThanOrEqualCondition>(id, lu);
4136 }
4137 }
4138 }
4139@@ -3218,26 +3218,26 @@
4140 return std::make_shared<CompareConjunction>(std::move(nconstraints), context.negated() != _negated);
4141 }
4142 }();
4143-
4144+
4145
4146 if(!neg)
4147 {
4148 return Retval(
4149- rc,
4150+ rc,
4151 std::move(lps),
4152 std::make_shared<UnionCollection>(std::move(neglps)));
4153 }
4154 else
4155 {
4156 return Retval(
4157- rc,
4158+ rc,
4159 std::make_shared<UnionCollection>(std::move(neglps)),
4160- std::move(lps));
4161+ std::move(lps));
4162 }
4163 }
4164
4165 Retval EqualCondition::simplify(SimplificationContext& context) const {
4166-
4167+
4168 Member m1 = _expr1->constraint(context);
4169 Member m2 = _expr2->constraint(context);
4170 std::shared_ptr<AbstractProgramCollection> lps, neglps;
4171@@ -3249,27 +3249,27 @@
4172 int constant = m2.constant() - m1.constant();
4173 m1 -= m2;
4174 m2 = m1;
4175- neglps =
4176+ neglps =
4177 std::make_shared<UnionCollection>(
4178 std::make_shared<SingleProgram>(context.cache(), std::move(m1), constant, Simplification::OP_GT),
4179 std::make_shared<SingleProgram>(context.cache(), std::move(m2), constant, Simplification::OP_LT));
4180 Member m3 = m2;
4181 lps = std::make_shared<SingleProgram>(context.cache(), std::move(m3), constant, Simplification::OP_EQ);
4182-
4183+
4184 if(context.negated()) lps.swap(neglps);
4185 }
4186 } else {
4187 lps = std::make_shared<SingleProgram>();
4188 neglps = std::make_shared<SingleProgram>();
4189 }
4190-
4191+
4192 if (!context.timeout() && !lps->satisfiable(context)) {
4193 return Retval(BooleanCondition::FALSE_CONSTANT);
4194- }
4195+ }
4196 else if(!context.timeout() && !neglps->satisfiable(context))
4197 {
4198- return Retval(BooleanCondition::TRUE_CONSTANT);
4199- }
4200+ return Retval(BooleanCondition::TRUE_CONSTANT);
4201+ }
4202 else {
4203 if (context.negated()) {
4204 return Retval(std::make_shared<NotEqualCondition>(_expr1, _expr2), std::move(lps), std::move(neglps));
4205@@ -3278,7 +3278,7 @@
4206 }
4207 }
4208 }
4209-
4210+
4211 Retval NotEqualCondition::simplify(SimplificationContext& context) const {
4212 Member m1 = _expr1->constraint(context);
4213 Member m2 = _expr2->constraint(context);
4214@@ -3287,17 +3287,17 @@
4215 if ((m1.isZero() && m2.isZero()) || m1.substrationIsZero(m2)) {
4216 return Retval(std::make_shared<BooleanCondition>(
4217 context.negated() ? (m1.constant() == m2.constant()) : (m1.constant() != m2.constant())));
4218- } else{
4219+ } else{
4220 int constant = m2.constant() - m1.constant();
4221 m1 -= m2;
4222 m2 = m1;
4223- lps =
4224+ lps =
4225 std::make_shared<UnionCollection>(
4226 std::make_shared<SingleProgram>(context.cache(), std::move(m1), constant, Simplification::OP_GT),
4227 std::make_shared<SingleProgram>(context.cache(), std::move(m2), constant, Simplification::OP_LT));
4228 Member m3 = m2;
4229- neglps = std::make_shared<SingleProgram>(context.cache(), std::move(m3), constant, Simplification::OP_EQ);
4230-
4231+ neglps = std::make_shared<SingleProgram>(context.cache(), std::move(m3), constant, Simplification::OP_EQ);
4232+
4233 if(context.negated()) lps.swap(neglps);
4234 }
4235 } else {
4236@@ -3306,20 +3306,20 @@
4237 }
4238 if (!context.timeout() && !lps->satisfiable(context)) {
4239 return Retval(BooleanCondition::FALSE_CONSTANT);
4240- }
4241+ }
4242 else if(!context.timeout() && !neglps->satisfiable(context))
4243 {
4244- return Retval(BooleanCondition::TRUE_CONSTANT);
4245+ return Retval(BooleanCondition::TRUE_CONSTANT);
4246 }
4247 else {
4248 if (context.negated()) {
4249 return Retval(std::make_shared<EqualCondition>(_expr1, _expr2), std::move(lps), std::move(neglps));
4250 } else {
4251 return Retval(std::make_shared<NotEqualCondition>(_expr1, _expr2), std::move(lps), std::move(neglps));
4252- }
4253+ }
4254 }
4255 }
4256-
4257+
4258 Retval LessThanCondition::simplify(SimplificationContext& context) const {
4259 Member m1 = _expr1->constraint(context);
4260 Member m2 = _expr2->constraint(context);
4261@@ -3340,27 +3340,27 @@
4262 lps = std::make_shared<SingleProgram>();
4263 neglps = std::make_shared<SingleProgram>();
4264 }
4265-
4266+
4267 if (!context.timeout() && !lps->satisfiable(context)) {
4268 return Retval(BooleanCondition::FALSE_CONSTANT);
4269 }
4270 else if(!context.timeout() && !neglps->satisfiable(context))
4271 {
4272- return Retval(BooleanCondition::TRUE_CONSTANT);
4273+ return Retval(BooleanCondition::TRUE_CONSTANT);
4274 }
4275 else {
4276 if (context.negated()) {
4277 return Retval(std::make_shared<LessThanOrEqualCondition>(_expr2, _expr1), std::move(lps), std::move(neglps));
4278 } else {
4279 return Retval(std::make_shared<LessThanCondition>(_expr1, _expr2), std::move(lps), std::move(neglps));
4280- }
4281+ }
4282 }
4283- }
4284-
4285+ }
4286+
4287 Retval LessThanOrEqualCondition::simplify(SimplificationContext& context) const {
4288 Member m1 = _expr1->constraint(context);
4289 Member m2 = _expr2->constraint(context);
4290-
4291+
4292 AbstractProgramCollection_ptr lps, neglps;
4293 if (!context.timeout() && m1.canAnalyze() && m2.canAnalyze()) {
4294 // test for trivial comparison
4295@@ -3378,7 +3378,7 @@
4296 lps = std::make_shared<SingleProgram>();
4297 neglps = std::make_shared<SingleProgram>();
4298 }
4299-
4300+
4301 assert(lps);
4302 assert(neglps);
4303
4304@@ -3390,19 +3390,19 @@
4305 if (context.negated()) {
4306 return Retval(std::make_shared<LessThanCondition>(_expr2, _expr1), std::move(lps), std::move(neglps));
4307 } else {
4308- return Retval(std::make_shared<LessThanOrEqualCondition>(_expr1, _expr2),
4309+ return Retval(std::make_shared<LessThanOrEqualCondition>(_expr1, _expr2),
4310 std::move(lps), std::move(neglps));
4311- }
4312+ }
4313 }
4314 }
4315-
4316+
4317 Retval NotCondition::simplify(SimplificationContext& context) const {
4318 context.negate();
4319 Retval r = _cond->simplify(context);
4320 context.negate();
4321 return r;
4322 }
4323-
4324+
4325 Retval BooleanCondition::simplify(SimplificationContext& context) const {
4326 if (context.negated()) {
4327 return Retval(getShared(!value));
4328@@ -3410,7 +3410,7 @@
4329 return Retval(getShared(value));
4330 }
4331 }
4332-
4333+
4334 Retval DeadlockCondition::simplify(SimplificationContext& context) const {
4335 if (context.negated()) {
4336 return Retval(std::make_shared<NotCondition>(DeadlockCondition::DEADLOCK));
4337@@ -3418,8 +3418,8 @@
4338 return Retval(DeadlockCondition::DEADLOCK);
4339 }
4340 }
4341-
4342- Retval UnfoldedUpperBoundsCondition::simplify(SimplificationContext& context) const
4343+
4344+ Retval UnfoldedUpperBoundsCondition::simplify(SimplificationContext& context) const
4345 {
4346 std::vector<place_t> next;
4347 std::vector<uint32_t> places;
4348@@ -3442,29 +3442,29 @@
4349 }
4350 return Retval(std::make_shared<UnfoldedUpperBoundsCondition>(next, bounds[nplaces].first-offset, offset));
4351 }
4352-
4353+
4354 /******************** Check if query is a reachability query ********************/
4355-
4356+
4357 bool EXCondition::isReachability(uint32_t depth) const {
4358 return false;
4359 }
4360-
4361+
4362 bool EGCondition::isReachability(uint32_t depth) const {
4363 return false;
4364 }
4365-
4366+
4367 bool EFCondition::isReachability(uint32_t depth) const {
4368 return depth > 0 ? false : _cond->isReachability(depth + 1);
4369 }
4370-
4371+
4372 bool AXCondition::isReachability(uint32_t depth) const {
4373 return false;
4374 }
4375-
4376+
4377 bool AGCondition::isReachability(uint32_t depth) const {
4378 return depth > 0 ? false : _cond->isReachability(depth + 1);
4379 }
4380-
4381+
4382 bool AFCondition::isReachability(uint32_t depth) const {
4383 return false;
4384 }
4385@@ -3473,28 +3473,27 @@
4386 if (depth != 0) {
4387 return false;
4388 }
4389-
4390- if (auto cond = dynamic_cast<FCondition*>(_cond.get())) {
4391+ else if (auto cond = dynamic_cast<FCondition*>(_cond.get())) {
4392 // EF is a reachability formula so skip checking the F.
4393 return (*cond)[0]->isReachability(depth + 1);
4394 }
4395- return _cond->isReachability(depth + 1);
4396+ else return false;
4397 }
4398
4399 bool ACondition::isReachability(uint32_t depth) const {
4400 if (depth != 0) {
4401 return false;
4402 }
4403- if (auto cond = dynamic_cast<GCondition*>(_cond.get())) {
4404+ else if (auto cond = dynamic_cast<GCondition*>(_cond.get())) {
4405 return (*cond)[0]->isReachability(depth + 1);
4406 }
4407- return _cond->isReachability(depth + 1);
4408+ else return false;
4409 }
4410-
4411+
4412 bool UntilCondition::isReachability(uint32_t depth) const {
4413 return false;
4414 }
4415-
4416+
4417 bool LogicalCondition::isReachability(uint32_t depth) const {
4418 if(depth == 0) return false;
4419 bool reachability = true;
4420@@ -3505,69 +3504,59 @@
4421 }
4422 return reachability;
4423 }
4424-
4425+
4426 bool CompareCondition::isReachability(uint32_t depth) const {
4427 return depth > 0;
4428 }
4429-
4430+
4431 bool NotCondition::isReachability(uint32_t depth) const {
4432 return _cond->isReachability(depth);
4433 }
4434-
4435+
4436 bool BooleanCondition::isReachability(uint32_t depth) const {
4437 return depth > 0;
4438 }
4439-
4440+
4441 bool DeadlockCondition::isReachability(uint32_t depth) const {
4442 return depth > 0;
4443 }
4444-
4445+
4446 bool UnfoldedUpperBoundsCondition::isReachability(uint32_t depth) const {
4447 return depth > 0;
4448 }
4449-
4450+
4451 /******************** Prepare Reachability Queries ********************/
4452-
4453+
4454 Condition_ptr EXCondition::prepareForReachability(bool negated) const {
4455 return nullptr;
4456 }
4457-
4458+
4459 Condition_ptr EGCondition::prepareForReachability(bool negated) const {
4460 return nullptr;
4461 }
4462-
4463+
4464 Condition_ptr EFCondition::prepareForReachability(bool negated) const {
4465 _cond->setInvariant(negated);
4466 return _cond;
4467 }
4468-
4469+
4470 Condition_ptr AXCondition::prepareForReachability(bool negated) const {
4471 return nullptr;
4472 }
4473-
4474+
4475 Condition_ptr AGCondition::prepareForReachability(bool negated) const {
4476 Condition_ptr cond = std::make_shared<NotCondition>(_cond);
4477 cond->setInvariant(!negated);
4478 return cond;
4479 }
4480-
4481+
4482 Condition_ptr AFCondition::prepareForReachability(bool negated) const {
4483 return nullptr;
4484 }
4485
4486 Condition_ptr ACondition::prepareForReachability(bool negated) const {
4487 auto g = std::dynamic_pointer_cast<GCondition>(_cond);
4488- if (g) {
4489- return AGCondition((*g)[0]).prepareForReachability(negated);
4490- }
4491- else {
4492- // ugly hacking for `A true`.
4493- auto bcond = std::dynamic_pointer_cast<BooleanCondition>(_cond);
4494- if (bcond) {
4495- return bcond;
4496- }
4497- else return nullptr;
4498- }
4499+ return g ? AGCondition((*g)[0]).prepareForReachability(negated) : nullptr;
4500 }
4501
4502 Condition_ptr ECondition::prepareForReachability(bool negated) const {
4503@@ -3578,7 +3567,7 @@
4504 Condition_ptr UntilCondition::prepareForReachability(bool negated) const {
4505 return nullptr;
4506 }
4507-
4508+
4509 Condition_ptr LogicalCondition::prepareForReachability(bool negated) const {
4510 return nullptr;
4511 }
4512@@ -3586,19 +3575,19 @@
4513 Condition_ptr CompareConjunction::prepareForReachability(bool negated) const {
4514 return nullptr;
4515 }
4516-
4517+
4518 Condition_ptr CompareCondition::prepareForReachability(bool negated) const {
4519 return nullptr;
4520 }
4521-
4522+
4523 Condition_ptr NotCondition::prepareForReachability(bool negated) const {
4524 return _cond->prepareForReachability(!negated);
4525 }
4526-
4527+
4528 Condition_ptr BooleanCondition::prepareForReachability(bool negated) const {
4529 return nullptr;
4530 }
4531-
4532+
4533 Condition_ptr DeadlockCondition::prepareForReachability(bool negated) const {
4534 return nullptr;
4535 }
4536@@ -3606,9 +3595,9 @@
4537 Condition_ptr UnfoldedUpperBoundsCondition::prepareForReachability(bool negated) const {
4538 return nullptr;
4539 }
4540-
4541+
4542 /******************** Prepare CTL Queries ********************/
4543-
4544+
4545 Condition_ptr EGCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
4546 ++stats[0];
4547 return AFCondition(std::make_shared<NotCondition>(_cond)).pushNegation(stats, context, nested, !negated, initrw);
4548@@ -3618,7 +3607,7 @@
4549 ++stats[1];
4550 return EFCondition(std::make_shared<NotCondition>(_cond)).pushNegation(stats, context, nested, !negated, initrw);
4551 }
4552-
4553+
4554 Condition_ptr EXCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
4555 return initialMarkingRW([&]() -> Condition_ptr {
4556 auto a = _cond->pushNegation(stats, context, true, negated, initrw);
4557@@ -3629,9 +3618,9 @@
4558 }
4559 else
4560 {
4561- if(a == BooleanCondition::FALSE_CONSTANT)
4562+ if(a == BooleanCondition::FALSE_CONSTANT)
4563 { ++stats[3]; return a;}
4564- if(a == BooleanCondition::TRUE_CONSTANT)
4565+ if(a == BooleanCondition::TRUE_CONSTANT)
4566 { ++stats[4]; return std::make_shared<NotCondition>(DeadlockCondition::DEADLOCK); }
4567 a = std::make_shared<EXCondition>(a);
4568 }
4569@@ -3649,7 +3638,7 @@
4570 }
4571 else
4572 {
4573- if(a == BooleanCondition::TRUE_CONSTANT)
4574+ if(a == BooleanCondition::TRUE_CONSTANT)
4575 { ++stats[6]; return a;}
4576 if(a == BooleanCondition::FALSE_CONSTANT)
4577 { ++stats[7]; return DeadlockCondition::DEADLOCK; }
4578@@ -3659,7 +3648,7 @@
4579 }, stats, context, nested, negated, initrw);
4580 }
4581
4582-
4583+
4584 Condition_ptr EFCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
4585 return initialMarkingRW([&]() -> Condition_ptr {
4586 auto a = _cond->pushNegation(stats, context, true, false, initrw);
4587@@ -3670,7 +3659,7 @@
4588 {
4589 ++stats[8];
4590 return a->pushNegation(stats, context, nested, negated, initrw);
4591- }
4592+ }
4593 }
4594
4595 if(!a->isTemporal())
4596@@ -3679,7 +3668,7 @@
4597 if(negated) return std::make_shared<NotCondition>(res);
4598 return res;
4599 }
4600-
4601+
4602 if( dynamic_cast<EFCondition*>(a.get()))
4603 {
4604 ++stats[9];
4605@@ -3714,7 +3703,7 @@
4606 }
4607 ++stats[13];
4608 std::vector<Condition_ptr> pef, atomic;
4609- for(auto& i : *cond)
4610+ for(auto& i : *cond)
4611 {
4612 pef.push_back(std::make_shared<EFCondition>(i));
4613 }
4614@@ -3722,7 +3711,7 @@
4615 return a;
4616 }
4617 else
4618- {
4619+ {
4620 Condition_ptr b = std::make_shared<EFCondition>(a);
4621 if(negated) b = std::make_shared<NotCondition>(b);
4622 return b;
4623@@ -3740,9 +3729,9 @@
4624 {
4625 ++stats[14];
4626 return a->pushNegation(stats, context, nested, negated, initrw);
4627- }
4628+ }
4629 }
4630-
4631+
4632 if(dynamic_cast<AFCondition*>(a.get()))
4633 {
4634 ++stats[15];
4635@@ -3814,7 +3803,7 @@
4636 return AFCondition(b).pushNegation(stats, context, nested, negated, initrw);
4637 }
4638 }
4639-
4640+
4641 if(auto cond = dynamic_cast<AFCondition*>(b.get()))
4642 {
4643 ++stats[22];
4644@@ -3855,7 +3844,7 @@
4645 return makeOr(pef)->pushNegation(stats, context, nested, negated, initrw);
4646 }
4647 }
4648-
4649+
4650 auto c = std::make_shared<AUCondition>(a, b);
4651 if(negated) return std::make_shared<NotCondition>(c);
4652 return c;
4653@@ -3889,7 +3878,7 @@
4654 return EFCondition(b).pushNegation(stats, context, nested, negated, initrw);
4655 }
4656 }
4657-
4658+
4659 if(dynamic_cast<EFCondition*>(b.get()))
4660 {
4661 ++stats[28];
4662@@ -4026,7 +4015,7 @@
4663 /*Boolean connectives */
4664 Condition_ptr pushAnd(const std::vector<Condition_ptr>& _conds, negstat_t& stats, const EvaluationContext& context, bool nested, bool negate_children, bool initrw)
4665 {
4666- std::vector<Condition_ptr> nef, other;
4667+ std::vector<Condition_ptr> nef, other;
4668 for(auto& c : _conds)
4669 {
4670 auto n = c->pushNegation(stats, context, nested, negate_children, initrw);
4671@@ -4047,27 +4036,27 @@
4672 {
4673 other.emplace_back(n);
4674 }
4675- }
4676+ }
4677 if(nef.size() + other.size() == 0)
4678 return BooleanCondition::TRUE_CONSTANT;
4679- if(nef.size() + other.size() == 1)
4680- {
4681- return nef.size() == 0 ?
4682- other[0] :
4683+ if(nef.size() + other.size() == 1)
4684+ {
4685+ return nef.size() == 0 ?
4686+ other[0] :
4687 std::make_shared<NotCondition>(std::make_shared<EFCondition>(nef[0]));
4688 }
4689 if(nef.size() != 0) other.push_back(
4690 std::make_shared<NotCondition>(
4691 std::make_shared<EFCondition>(
4692- makeOr(nef))));
4693+ makeOr(nef))));
4694 if(other.size() == 1) return other[0];
4695 auto res = makeAnd(other);
4696 return res;
4697 }
4698-
4699+
4700 Condition_ptr pushOr(const std::vector<Condition_ptr>& _conds, negstat_t& stats, const EvaluationContext& context, bool nested, bool negate_children, bool initrw)
4701 {
4702- std::vector<Condition_ptr> nef, other;
4703+ std::vector<Condition_ptr> nef, other;
4704 for(auto& c : _conds)
4705 {
4706 auto n = c->pushNegation(stats, context, nested, negate_children, initrw);
4707@@ -4090,7 +4079,7 @@
4708 if(nef.size() + other.size() == 1) { return nef.size() == 0 ? other[0] : std::make_shared<EFCondition>(nef[0]);}
4709 if(nef.size() != 0) other.push_back(
4710 std::make_shared<EFCondition>(
4711- makeOr(nef)));
4712+ makeOr(nef)));
4713 if(other.size() == 1) return other[0];
4714 return makeOr(other);
4715 }
4716@@ -4102,7 +4091,7 @@
4717 }, stats, context, nested, negated, initrw);
4718 }
4719
4720-
4721+
4722 Condition_ptr AndCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
4723 return initialMarkingRW([&]() -> Condition_ptr {
4724 return negated ? pushOr (_conds, stats, context, nested, true, initrw) :
4725@@ -4110,14 +4099,14 @@
4726
4727 }, stats, context, nested, negated, initrw);
4728 }
4729-
4730+
4731 Condition_ptr CompareConjunction::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
4732 return initialMarkingRW([&]() -> Condition_ptr {
4733 return std::make_shared<CompareConjunction>(*this, negated);
4734 }, stats, context, nested, negated, initrw);
4735 }
4736
4737-
4738+
4739 Condition_ptr NotCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
4740 return initialMarkingRW([&]() -> Condition_ptr {
4741 if(negated) ++stats[30];
4742@@ -4173,11 +4162,11 @@
4743 if(auto p1 = std::dynamic_pointer_cast<PlusExpr>(_expr1))
4744 if(auto p2 = std::dynamic_pointer_cast<PlusExpr>(_expr2))
4745 remdup(p1, p2);
4746-
4747+
4748 if(auto m1 = std::dynamic_pointer_cast<MultiplyExpr>(_expr1))
4749 if(auto m2 = std::dynamic_pointer_cast<MultiplyExpr>(_expr2))
4750- remdup(m1, m2);
4751-
4752+ remdup(m1, m2);
4753+
4754 if(auto p1 = std::dynamic_pointer_cast<CommutativeExpr>(_expr1))
4755 if(auto p2 = std::dynamic_pointer_cast<CommutativeExpr>(_expr2))
4756 return p1->_exprs.size() + p1->_ids.size() + p2->_exprs.size() + p2->_ids.size() == 0;
4757@@ -4217,34 +4206,34 @@
4758 if(negated == noteq) return std::make_shared<EqualCondition>((*org)[0], (*org)[1]);
4759 else return std::make_shared<NotEqualCondition>((*org)[0], (*org)[1]);
4760 }
4761-
4762+
4763 Condition_ptr NotEqualCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
4764 return initialMarkingRW([&]() -> Condition_ptr {
4765 return pushEqual(this, negated, true, context);
4766 }, stats, context, nested, negated, initrw);
4767 }
4768
4769-
4770+
4771 Condition_ptr EqualCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
4772 return initialMarkingRW([&]() -> Condition_ptr {
4773 return pushEqual(this, negated, false, context);
4774 }, stats, context, nested, negated, initrw);
4775 }
4776-
4777+
4778 Condition_ptr BooleanCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
4779 return initialMarkingRW([&]() -> Condition_ptr {
4780 if(negated) return getShared(!value);
4781 else return getShared(value);
4782 }, stats, context, nested, negated, initrw);
4783 }
4784-
4785+
4786 Condition_ptr DeadlockCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
4787 return initialMarkingRW([&]() -> Condition_ptr {
4788 if(negated) return std::make_shared<NotCondition>(DEADLOCK);
4789 else return DEADLOCK;
4790 }, stats, context, nested, negated, initrw);
4791 }
4792-
4793+
4794 Condition_ptr UnfoldedUpperBoundsCondition::pushNegation(negstat_t&, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
4795 if(negated)
4796 {
4797@@ -4260,24 +4249,24 @@
4798 void postMerge(std::vector<Condition_ptr>& conds) {
4799 std::sort(std::begin(conds), std::end(conds),
4800 [](auto& a, auto& b) {
4801- return a->isTemporal() < b->isTemporal();
4802+ return a->isTemporal() < b->isTemporal();
4803 });
4804- }
4805-
4806+ }
4807+
4808 AndCondition::AndCondition(std::vector<Condition_ptr>&& conds) {
4809 for (auto& c : conds) tryMerge<AndCondition>(_conds, c);
4810 for (auto& c : _conds) _temporal = _temporal || c->isTemporal();
4811 for (auto& c : _conds) _loop_sensitive = _loop_sensitive || c->isLoopSensitive();
4812 postMerge(_conds);
4813 }
4814-
4815+
4816 AndCondition::AndCondition(const std::vector<Condition_ptr>& conds) {
4817 for (auto& c : conds) tryMerge<AndCondition>(_conds, c);
4818 for (auto& c : _conds) _temporal = _temporal || c->isTemporal();
4819 for (auto& c : _conds) _loop_sensitive = _loop_sensitive || c->isLoopSensitive();
4820 postMerge(_conds);
4821 }
4822-
4823+
4824 AndCondition::AndCondition(Condition_ptr left, Condition_ptr right) {
4825 tryMerge<AndCondition>(_conds, left);
4826 tryMerge<AndCondition>(_conds, right);
4827@@ -4285,21 +4274,21 @@
4828 for (auto& c : _conds) _loop_sensitive = _loop_sensitive || c->isLoopSensitive();
4829 postMerge(_conds);
4830 }
4831-
4832+
4833 OrCondition::OrCondition(std::vector<Condition_ptr>&& conds) {
4834 for (auto& c : conds) tryMerge<OrCondition>(_conds, c);
4835 for (auto& c : _conds) _temporal = _temporal || c->isTemporal();
4836 for (auto& c : _conds) _loop_sensitive = _loop_sensitive || c->isLoopSensitive();
4837 postMerge(_conds);
4838 }
4839-
4840+
4841 OrCondition::OrCondition(const std::vector<Condition_ptr>& conds) {
4842 for (auto& c : conds) tryMerge<OrCondition>(_conds, c);
4843 for (auto& c : _conds) _temporal = _temporal || c->isTemporal();
4844 for (auto& c : _conds) _loop_sensitive = _loop_sensitive || c->isLoopSensitive();
4845 postMerge(_conds);
4846 }
4847-
4848+
4849 OrCondition::OrCondition(Condition_ptr left, Condition_ptr right) {
4850 tryMerge<OrCondition>(_conds, left);
4851 tryMerge<OrCondition>(_conds, right);
4852@@ -4307,14 +4296,14 @@
4853 for (auto& c : _conds) _loop_sensitive = _loop_sensitive || c->isLoopSensitive();
4854 postMerge(_conds);
4855 }
4856-
4857+
4858
4859 CompareConjunction::CompareConjunction(const std::vector<Condition_ptr>& conditions, bool negated)
4860 {
4861 _negated = negated;
4862 merge(conditions, negated);
4863 }
4864-
4865+
4866 void CompareConjunction::merge(const CompareConjunction& other)
4867 {
4868 auto neg = _negated != other._negated;
4869@@ -4329,7 +4318,7 @@
4870 {
4871 if(neg)
4872 c.invert();
4873-
4874+
4875 if(c._upper == std::numeric_limits<uint32_t>::max() && c._lower == 0)
4876 {
4877 continue;
4878@@ -4340,7 +4329,7 @@
4879 assert(false);
4880 exit(ErrorCode);
4881 }
4882-
4883+
4884 il = std::lower_bound(_constraints.begin(), _constraints.end(), c);
4885 if(il == _constraints.end() || il->_place != c._place)
4886 {
4887@@ -4353,7 +4342,7 @@
4888 }
4889 }
4890 }
4891-
4892+
4893 void CompareConjunction::merge(const std::vector<Condition_ptr>& conditions, bool negated)
4894 {
4895 for(auto& c : conditions)
4896@@ -4405,21 +4394,21 @@
4897 }
4898 if(negated)
4899 next.invert();
4900-
4901+
4902 auto lb = std::lower_bound(std::begin(_constraints), std::end(_constraints), next);
4903 if(lb == std::end(_constraints) || lb->_place != next._place)
4904 {
4905 next._name = id->name();
4906 _constraints.insert(lb, next);
4907- }
4908+ }
4909 else
4910 {
4911 assert(id->name().compare(lb->_name) == 0);
4912 lb->intersect(next);
4913 }
4914- }
4915+ }
4916 }
4917-
4918+
4919 void CommutativeExpr::init(std::vector<Expr_ptr>&& exprs)
4920 {
4921 for (auto& e : exprs) {
4922@@ -4430,7 +4419,7 @@
4923 }
4924 else if (auto id = std::dynamic_pointer_cast<PQL::UnfoldedIdentifierExpr>(e)) {
4925 _ids.emplace_back(id->offset(), id->name());
4926- }
4927+ }
4928 else if(auto c = std::dynamic_pointer_cast<CommutativeExpr>(e))
4929 {
4930 // we should move up plus/multiply here when possible;
4931@@ -4440,19 +4429,19 @@
4932 }
4933 else
4934 {
4935- _exprs.emplace_back(std::move(e));
4936+ _exprs.emplace_back(std::move(e));
4937 }
4938 } else {
4939 _exprs.emplace_back(std::move(e));
4940 }
4941 }
4942 }
4943-
4944+
4945 PlusExpr::PlusExpr(std::vector<Expr_ptr>&& exprs, bool tk) : CommutativeExpr(0), tk(tk)
4946 {
4947 init(std::move(exprs));
4948 }
4949-
4950+
4951 MultiplyExpr::MultiplyExpr(std::vector<Expr_ptr>&& exprs) : CommutativeExpr(1)
4952 {
4953 init(std::move(exprs));
4954
4955=== modified file 'src/PetriEngine/Reducer.cpp'
4956--- src/PetriEngine/Reducer.cpp 2021-07-07 13:19:23 +0000
4957+++ src/PetriEngine/Reducer.cpp 2021-10-17 18:21:15 +0000
4958@@ -1,4 +1,4 @@
4959-/*
4960+/*
4961 * File: Reducer.cpp
4962 * Author: srba
4963 *
4964@@ -15,7 +15,7 @@
4965
4966 namespace PetriEngine {
4967
4968- Reducer::Reducer(PetriNetBuilder* p)
4969+ Reducer::Reducer(PetriNetBuilder* p)
4970 : parent(p) {
4971 }
4972
4973@@ -24,9 +24,9 @@
4974 }
4975
4976 void Reducer::Print(QueryPlaceAnalysisContext& context) {
4977- std::cout << "\nNET INFO:\n"
4978+ std::cout << "\nNET INFO:\n"
4979 << "Number of places: " << parent->numberOfPlaces() << std::endl
4980- << "Number of transitions: " << parent->numberOfTransitions()
4981+ << "Number of transitions: " << parent->numberOfTransitions()
4982 << std::endl << std::endl;
4983 for (uint32_t t = 0; t < parent->numberOfTransitions(); t++) {
4984 std::cout << "Transition " << t << " :\n";
4985@@ -36,30 +36,30 @@
4986 }
4987 for(auto& arc : parent->_transitions[t].pre)
4988 {
4989- if (arc.weight > 0)
4990- std::cout << "\tInput place " << arc.place
4991+ if (arc.weight > 0)
4992+ std::cout << "\tInput place " << arc.place
4993 << " (" << getPlaceName(arc.place) << ")"
4994 << " with arc-weight " << arc.weight << std::endl;
4995 }
4996 for(auto& arc : parent->_transitions[t].post)
4997 {
4998- if (arc.weight > 0)
4999- std::cout << "\tOutput place " << arc.place
5000- << " (" << getPlaceName(arc.place) << ")"
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches