Merge lp:~tapaal-ltl/verifypn/stubborn-set-refactor into lp:verifypn
- stubborn-set-refactor
- Merge into new-trunk
Proposed by
Nikolaj Jensen Ulrik
Status: | Merged |
---|---|
Merged at revision: | 231 |
Proposed branch: | lp:~tapaal-ltl/verifypn/stubborn-set-refactor |
Merge into: | lp:verifypn |
Diff against target: |
2482 lines (+1242/-747) 23 files modified
include/PetriEngine/PQL/Contexts.h (+6/-6) include/PetriEngine/PQL/Expressions.h (+51/-36) include/PetriEngine/PQL/PQL.h (+2/-7) include/PetriEngine/PQL/Visitor.h (+87/-3) include/PetriEngine/PetriNet.h (+1/-0) include/PetriEngine/Reachability/ReachabilityResult.h (+2/-2) include/PetriEngine/Reachability/ReachabilitySearch.h (+12/-2) include/PetriEngine/ReducingSuccessorGenerator.h (+25/-54) include/PetriEngine/Stubborn/InterestingTransitionVisitor.h (+163/-0) include/PetriEngine/Stubborn/ReachabilityStubbornSet.h (+40/-0) include/PetriEngine/Stubborn/StubbornSet.h (+146/-0) include/PetriEngine/TAR/Solver.h (+1/-0) include/PetriParse/QueryParser.h (+2/-3) include/PetriParse/QueryXMLParser.h (+1/-1) src/CTL/PetriNets/OnTheFlyDG.cpp (+2/-1) src/PetriEngine/CMakeLists.txt (+2/-1) src/PetriEngine/PQL/Expressions.cpp (+10/-328) src/PetriEngine/ReducingSuccessorGenerator.cpp (+31/-302) src/PetriEngine/Stubborn/CMakeLists.txt (+3/-0) src/PetriEngine/Stubborn/InterestingTransitionVisitor.cpp (+311/-0) src/PetriEngine/Stubborn/ReachabilityStubbornSet.cpp (+41/-0) src/PetriEngine/Stubborn/StubbornSet.cpp (+302/-0) src/PetriParse/QueryXMLParser.cpp (+1/-1) |
To merge this branch: | bzr merge lp:~tapaal-ltl/verifypn/stubborn-set-refactor |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
VerifyPN Maintainers | Pending | ||
Review via email:
|
Commit message
Description of the change
Refactor stubborn set generation out of ReducingSuccess
This merge should be independent from the LTL engine merge proposal, although there may be conflicts wrt. PQL.h and Expressions.
To post a comment you must log in.
- 232. By Nikolaj Jensen Ulrik
-
Remove commented code, fix one indent
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'include/PetriEngine/PQL/Contexts.h' |
2 | --- include/PetriEngine/PQL/Contexts.h 2020-04-27 14:47:10 +0000 |
3 | +++ include/PetriEngine/PQL/Contexts.h 2021-03-04 07:47:28 +0000 |
4 | @@ -38,8 +38,8 @@ |
5 | /** Context provided for context analysis */ |
6 | class AnalysisContext { |
7 | protected: |
8 | - const unordered_map<std::string, uint32_t>& _placeNames; |
9 | - const unordered_map<std::string, uint32_t>& _transitionNames; |
10 | + const std::unordered_map<std::string, uint32_t>& _placeNames; |
11 | + const std::unordered_map<std::string, uint32_t>& _transitionNames; |
12 | const PetriNet* _net; |
13 | std::vector<ExprError> _errors; |
14 | public: |
15 | @@ -176,7 +176,7 @@ |
16 | |
17 | SimplificationContext(const MarkVal* marking, |
18 | const PetriNet* net, uint32_t queryTimeout, uint32_t lpTimeout, |
19 | - LPCache* cache) |
20 | + Simplification::LPCache* cache) |
21 | : _queryTimeout(queryTimeout), _lpTimeout(lpTimeout) { |
22 | _negated = false; |
23 | _marking = marking; |
24 | @@ -222,8 +222,8 @@ |
25 | } |
26 | |
27 | uint32_t getLpTimeout() const; |
28 | - |
29 | - LPCache* cache() const |
30 | + |
31 | + Simplification::LPCache* cache() const |
32 | { |
33 | return _cache; |
34 | } |
35 | @@ -237,7 +237,7 @@ |
36 | const PetriNet* _net; |
37 | uint32_t _queryTimeout, _lpTimeout; |
38 | std::chrono::high_resolution_clock::time_point _start; |
39 | - LPCache* _cache; |
40 | + Simplification::LPCache* _cache; |
41 | mutable glp_prob* _base_lp = nullptr; |
42 | |
43 | glp_prob* buildBase() const; |
44 | |
45 | === modified file 'include/PetriEngine/PQL/Expressions.h' |
46 | --- include/PetriEngine/PQL/Expressions.h 2020-06-02 16:20:24 +0000 |
47 | +++ include/PetriEngine/PQL/Expressions.h 2021-03-04 07:47:28 +0000 |
48 | @@ -103,8 +103,7 @@ |
49 | Member constraint(SimplificationContext& context) const override; |
50 | void toXML(std::ostream&, uint32_t tabs, bool tokencount = false) const override; |
51 | bool tk = false; |
52 | - void incr(ReducingSuccessorGenerator& generator) const override; |
53 | - void decr(ReducingSuccessorGenerator& generator) const override; |
54 | + |
55 | void visit(Visitor& visitor) const override; |
56 | protected: |
57 | int apply(int v1, int v2) const override; |
58 | @@ -122,8 +121,7 @@ |
59 | Expr::Types type() const override; |
60 | Member constraint(SimplificationContext& context) const override; |
61 | void toXML(std::ostream&, uint32_t tabs, bool tokencount = false) const override; |
62 | - void incr(ReducingSuccessorGenerator& generator) const override; |
63 | - void decr(ReducingSuccessorGenerator& generator) const override; |
64 | + |
65 | void toBinary(std::ostream&) const override; |
66 | void visit(Visitor& visitor) const override; |
67 | protected: |
68 | @@ -140,8 +138,7 @@ |
69 | Expr::Types type() const override; |
70 | Member constraint(SimplificationContext& context) const override; |
71 | void toXML(std::ostream&, uint32_t tabs, bool tokencount = false) const override; |
72 | - void incr(ReducingSuccessorGenerator& generator) const override; |
73 | - void decr(ReducingSuccessorGenerator& generator) const override; |
74 | + |
75 | void visit(Visitor& visitor) const override; |
76 | protected: |
77 | int apply(int v1, int v2) const override; |
78 | @@ -163,8 +160,7 @@ |
79 | Member constraint(SimplificationContext& context) const override; |
80 | void toXML(std::ostream&, uint32_t tabs, bool tokencount = false) const override; |
81 | void toBinary(std::ostream&) const override; |
82 | - void incr(ReducingSuccessorGenerator& generator) const override; |
83 | - void decr(ReducingSuccessorGenerator& generator) const override; |
84 | + |
85 | void visit(Visitor& visitor) const override; |
86 | int formulaSize() const override{ |
87 | return _expr->formulaSize() + 1; |
88 | @@ -187,8 +183,7 @@ |
89 | Expr::Types type() const override; |
90 | void toXML(std::ostream&, uint32_t tabs, bool tokencount = false) const override; |
91 | void toBinary(std::ostream&) const override; |
92 | - void incr(ReducingSuccessorGenerator& generator) const override; |
93 | - void decr(ReducingSuccessorGenerator& generator) const override; |
94 | + |
95 | void visit(Visitor& visitor) const override; |
96 | int formulaSize() const override{ |
97 | return 1; |
98 | @@ -223,12 +218,6 @@ |
99 | void toXML(std::ostream& os, uint32_t tabs, bool tokencount = false) const override { |
100 | _compiled->toXML(os, tabs, tokencount); |
101 | } |
102 | - void incr(ReducingSuccessorGenerator& generator) const override { |
103 | - _compiled->incr(generator); |
104 | - } |
105 | - void decr(ReducingSuccessorGenerator& generator) const override { |
106 | - _compiled->decr(generator); |
107 | - } |
108 | int formulaSize() const override { |
109 | if(_compiled) return _compiled->formulaSize(); |
110 | return 1; |
111 | @@ -245,7 +234,13 @@ |
112 | void toBinary(std::ostream& s) const override { |
113 | _compiled->toBinary(s); |
114 | } |
115 | - void visit(Visitor& visitor) const override; |
116 | + void visit(Visitor& visitor) const override; |
117 | + |
118 | + [[nodiscard]] const Expr_ptr &compiled() const |
119 | + { |
120 | + return _compiled; |
121 | + } |
122 | + |
123 | private: |
124 | std::string _name; |
125 | Expr_ptr _compiled; |
126 | @@ -267,8 +262,6 @@ |
127 | Expr::Types type() const override; |
128 | void toXML(std::ostream&, uint32_t tabs, bool tokencount = false) const override; |
129 | void toBinary(std::ostream&) const override; |
130 | - void incr(ReducingSuccessorGenerator& generator) const override; |
131 | - void decr(ReducingSuccessorGenerator& generator) const override; |
132 | int formulaSize() const override{ |
133 | return 1; |
134 | } |
135 | @@ -311,8 +304,8 @@ |
136 | |
137 | void toXML(std::ostream& out, uint32_t tabs) const override |
138 | { _compiled->toXML(out, tabs); } |
139 | - void findInteresting(ReducingSuccessorGenerator& generator, bool negated) const override |
140 | - { _compiled->findInteresting(generator, negated);} |
141 | + |
142 | + |
143 | Quantifier getQuantifier() const override |
144 | { return _compiled->getQuantifier(); } |
145 | Path getPath() const override { return _compiled->getPath(); } |
146 | @@ -381,7 +374,7 @@ |
147 | Condition_ptr pushNegation(negstat_t&, const EvaluationContext& context, bool nested, bool negated, bool initrw) override; |
148 | void toXML(std::ostream&, uint32_t tabs) const override; |
149 | void toBinary(std::ostream&) const override; |
150 | - void findInteresting(ReducingSuccessorGenerator& generator, bool negated) const override; |
151 | + |
152 | Quantifier getQuantifier() const override { return Quantifier::NEG; } |
153 | Path getPath() const override { return Path::pError; } |
154 | CTLType getQueryType() const override { return CTLType::LOPERATOR; } |
155 | @@ -421,7 +414,7 @@ |
156 | void toString(std::ostream&) const override; |
157 | void toTAPAALQuery(std::ostream&,TAPAALConditionExportContext& context) const override; |
158 | void toBinary(std::ostream& out) const override; |
159 | - void findInteresting(ReducingSuccessorGenerator& generator, bool negated) const override; |
160 | + |
161 | virtual const Condition_ptr& operator[] (size_t i) const override { return _cond;} |
162 | virtual bool containsNext() const override { return _cond->containsNext(); } |
163 | bool nestedDeadlock() const override { return _cond->nestedDeadlock(); } |
164 | @@ -562,7 +555,7 @@ |
165 | void toBinary(std::ostream& out) const override; |
166 | bool isReachability(uint32_t depth) const override; |
167 | Condition_ptr prepareForReachability(bool negated) const override; |
168 | - void findInteresting(ReducingSuccessorGenerator& generator, bool negated) const override; |
169 | + |
170 | Result evalAndSet(const EvaluationContext& context) override; |
171 | |
172 | virtual const Condition_ptr& operator[] (size_t i) const override |
173 | @@ -571,6 +564,17 @@ |
174 | { return Path::U; } |
175 | bool containsNext() const override { return _cond1->containsNext() || _cond2->containsNext(); } |
176 | bool nestedDeadlock() const override { return _cond1->nestedDeadlock() || _cond2->nestedDeadlock(); } |
177 | + |
178 | + const Condition_ptr &getCond1() const |
179 | + { |
180 | + return _cond1; |
181 | + } |
182 | + |
183 | + const Condition_ptr &getCond2() const |
184 | + { |
185 | + return _cond2; |
186 | + } |
187 | + |
188 | private: |
189 | virtual std::string op() const = 0; |
190 | |
191 | @@ -702,7 +706,7 @@ |
192 | Result evalAndSet(const EvaluationContext& context) override; |
193 | void visit(Visitor&) const override; |
194 | void toXML(std::ostream&, uint32_t tabs) const override; |
195 | - void findInteresting(ReducingSuccessorGenerator& generator, bool negated) const override; |
196 | + |
197 | Quantifier getQuantifier() const override { return Quantifier::AND; } |
198 | Condition_ptr pushNegation(negstat_t&, const EvaluationContext& context, bool nested, bool negated, bool initrw) override; |
199 | private: |
200 | @@ -726,7 +730,7 @@ |
201 | Result evalAndSet(const EvaluationContext& context) override; |
202 | void visit(Visitor&) const override; |
203 | void toXML(std::ostream&, uint32_t tabs) const override; |
204 | - void findInteresting(ReducingSuccessorGenerator& generator, bool negated) const override; |
205 | + |
206 | Quantifier getQuantifier() const override { return Quantifier::OR; } |
207 | Condition_ptr pushNegation(negstat_t&, const EvaluationContext& context, bool nested, bool negated, bool initrw) override; |
208 | private: |
209 | @@ -818,7 +822,7 @@ |
210 | Result evaluate(const EvaluationContext& context) override; |
211 | Result evalAndSet(const EvaluationContext& context) override; |
212 | void visit(Visitor&) const override; |
213 | - void findInteresting(ReducingSuccessorGenerator& generator, bool negated) const override; |
214 | + |
215 | Quantifier getQuantifier() const override { return _negated ? Quantifier::OR : Quantifier::AND; } |
216 | Condition_ptr pushNegation(negstat_t&, const EvaluationContext& context, bool nested, bool negated, bool initrw) override; |
217 | bool isNegated() const { return _negated; } |
218 | @@ -868,6 +872,17 @@ |
219 | bool containsNext() const override { return false; } |
220 | bool nestedDeadlock() const override { return false; } |
221 | bool isTrivial() const; |
222 | + |
223 | + const Expr_ptr &getExpr1() const |
224 | + { |
225 | + return _expr1; |
226 | + } |
227 | + |
228 | + const Expr_ptr &getExpr2() const |
229 | + { |
230 | + return _expr2; |
231 | + } |
232 | + |
233 | protected: |
234 | uint32_t _distance(DistanceContext& c, |
235 | std::function<uint32_t(uint32_t, uint32_t, bool)> d) const |
236 | @@ -898,7 +913,7 @@ |
237 | using CompareCondition::CompareCondition; |
238 | Retval simplify(SimplificationContext& context) const override; |
239 | void toXML(std::ostream&, uint32_t tabs) const override; |
240 | - void findInteresting(ReducingSuccessorGenerator& generator, bool negated) const override; |
241 | + |
242 | uint32_t distance(DistanceContext& context) const override; |
243 | Condition_ptr pushNegation(negstat_t&, const EvaluationContext& context, bool nested, bool negated, bool initrw) override; |
244 | void visit(Visitor&) const override; |
245 | @@ -917,7 +932,7 @@ |
246 | void toTAPAALQuery(std::ostream&,TAPAALConditionExportContext& context) const override; |
247 | Retval simplify(SimplificationContext& context) const override; |
248 | void toXML(std::ostream&, uint32_t tabs) const override; |
249 | - void findInteresting(ReducingSuccessorGenerator& generator, bool negated) const override; |
250 | + |
251 | uint32_t distance(DistanceContext& context) const override; |
252 | Condition_ptr pushNegation(negstat_t&, const EvaluationContext& context, bool nested, bool negated, bool initrw) override; |
253 | void visit(Visitor&) const override; |
254 | @@ -935,7 +950,7 @@ |
255 | using CompareCondition::CompareCondition; |
256 | Retval simplify(SimplificationContext& context) const override; |
257 | void toXML(std::ostream&, uint32_t tabs) const override; |
258 | - void findInteresting(ReducingSuccessorGenerator& generator, bool negated) const override; |
259 | + |
260 | uint32_t distance(DistanceContext& context) const override; |
261 | Condition_ptr pushNegation(negstat_t&, const EvaluationContext& context, bool nested, bool negated, bool initrw) override; |
262 | void visit(Visitor&) const override; |
263 | @@ -953,7 +968,7 @@ |
264 | using CompareCondition::CompareCondition; |
265 | Retval simplify(SimplificationContext& context) const override; |
266 | void toXML(std::ostream&, uint32_t tabs) const override; |
267 | - void findInteresting(ReducingSuccessorGenerator& generator, bool negated) const override; |
268 | + |
269 | uint32_t distance(DistanceContext& context) const override; |
270 | Condition_ptr pushNegation(negstat_t&, const EvaluationContext& context, bool nested, bool negated, bool initrw) override; |
271 | void visit(Visitor&) const override; |
272 | @@ -971,7 +986,7 @@ |
273 | using CompareCondition::CompareCondition; |
274 | Retval simplify(SimplificationContext& context) const override; |
275 | void toXML(std::ostream&, uint32_t tabs) const override; |
276 | - void findInteresting(ReducingSuccessorGenerator& generator, bool negated) const override; |
277 | + |
278 | uint32_t distance(DistanceContext& context) const override; |
279 | Condition_ptr pushNegation(negstat_t&, const EvaluationContext& context, bool nested, bool negated, bool initrw) override; |
280 | void visit(Visitor&) const override; |
281 | @@ -988,7 +1003,7 @@ |
282 | using CompareCondition::CompareCondition; |
283 | Retval simplify(SimplificationContext& context) const override; |
284 | void toXML(std::ostream&, uint32_t tabs) const override; |
285 | - void findInteresting(ReducingSuccessorGenerator& generator, bool negated) const override; |
286 | + |
287 | uint32_t distance(DistanceContext& context) const override; |
288 | Condition_ptr pushNegation(negstat_t&, const EvaluationContext& context, bool nested, bool negated, bool initrw) override; |
289 | void visit(Visitor&) const override; |
290 | @@ -1029,7 +1044,7 @@ |
291 | Condition_ptr pushNegation(negstat_t&, const EvaluationContext& context, bool nested, bool negated, bool initrw) override; |
292 | void toXML(std::ostream&, uint32_t tabs) const override; |
293 | void toBinary(std::ostream&) const override; |
294 | - void findInteresting(ReducingSuccessorGenerator& generator, bool negated) const override; |
295 | + |
296 | Quantifier getQuantifier() const override { return Quantifier::EMPTY; } |
297 | Path getPath() const override { return Path::pError; } |
298 | CTLType getQueryType() const override { return CTLType::EVAL; } |
299 | @@ -1062,7 +1077,7 @@ |
300 | Condition_ptr pushNegation(negstat_t&, const EvaluationContext& context, bool nested, bool negated, bool initrw) override; |
301 | void toXML(std::ostream&, uint32_t tabs) const override; |
302 | void toBinary(std::ostream&) const override; |
303 | - void findInteresting(ReducingSuccessorGenerator& generator, bool negated) const override; |
304 | + |
305 | static Condition_ptr DEADLOCK; |
306 | Quantifier getQuantifier() const override { return Quantifier::DEADLOCK; } |
307 | Path getPath() const override { return Path::pError; } |
308 | @@ -1188,7 +1203,7 @@ |
309 | Condition_ptr prepareForReachability(bool negated) const override; |
310 | Condition_ptr pushNegation(negstat_t&, const EvaluationContext& context, bool nested, bool negated, bool initrw) override; |
311 | void toXML(std::ostream&, uint32_t tabs) const override; |
312 | - void findInteresting(ReducingSuccessorGenerator& generator, bool negated) const override; |
313 | + |
314 | Quantifier getQuantifier() const override { return Quantifier::UPPERBOUNDS; } |
315 | Path getPath() const override { return Path::pError; } |
316 | CTLType getQueryType() const override { return CTLType::EVAL; } |
317 | |
318 | === modified file 'include/PetriEngine/PQL/PQL.h' |
319 | --- include/PetriEngine/PQL/PQL.h 2020-04-22 07:57:20 +0000 |
320 | +++ include/PetriEngine/PQL/PQL.h 2021-03-04 07:47:28 +0000 |
321 | @@ -26,8 +26,8 @@ |
322 | #include <memory> |
323 | |
324 | #include "../PetriNet.h" |
325 | -#include "../Structures/State.h" |
326 | -#include "../ReducingSuccessorGenerator.h" |
327 | +//#include "../Structures/State.h" |
328 | +//#include "../ReducingSuccessorGenerator.h" |
329 | #include "../Simplification/LPCache.h" |
330 | |
331 | namespace PetriEngine { |
332 | @@ -120,9 +120,6 @@ |
333 | /** Output the expression as it currently is to a file in XML */ |
334 | virtual void toXML(std::ostream&, uint32_t tabs, bool tokencount = false) const = 0; |
335 | virtual void toBinary(std::ostream&) const = 0; |
336 | - /** Stubborn reduction: increasing and decreasing sets */ |
337 | - virtual void incr(ReducingSuccessorGenerator& generator) const = 0; |
338 | - virtual void decr(ReducingSuccessorGenerator& generator) const = 0; |
339 | /** Count size of the entire formula in number of nodes */ |
340 | virtual int formulaSize() const = 0; |
341 | |
342 | @@ -230,8 +227,6 @@ |
343 | virtual void toXML(std::ostream&, uint32_t tabs) const = 0; |
344 | virtual void toBinary(std::ostream& out) const = 0; |
345 | |
346 | - /** Find interesting transitions in stubborn reduction*/ |
347 | - virtual void findInteresting(ReducingSuccessorGenerator& generator, bool negated) const = 0; |
348 | /** Checks if the condition is trivially true */ |
349 | bool isTriviallyTrue(); |
350 | /*** Checks if the condition is trivially false */ |
351 | |
352 | === modified file 'include/PetriEngine/PQL/Visitor.h' |
353 | --- include/PetriEngine/PQL/Visitor.h 2020-06-02 16:20:24 +0000 |
354 | +++ include/PetriEngine/PQL/Visitor.h 2021-03-04 07:47:28 +0000 |
355 | @@ -62,8 +62,14 @@ |
356 | virtual void _accept(const EUCondition*) |
357 | { assert(false); std::cerr << "No accept for EUCondition" << std::endl; exit(0);}; |
358 | virtual void _accept(const AUCondition*) |
359 | - { assert(false); std::cerr << "No accept for AUCondition" << std::endl; exit(0);}; |
360 | - |
361 | + { assert(false); std::cerr << "No accept for AUCondition" << std::endl; exit(0);}; |
362 | + |
363 | + virtual void _accept(const UntilCondition *) { |
364 | + assert(false); |
365 | + std::cerr << "No accept for UntilCondition" << std::endl; |
366 | + exit(0); |
367 | + }; |
368 | + |
369 | // shallow elements, neither of these should exist in a compiled expression |
370 | virtual void _accept(const UnfoldedFireableCondition* element) |
371 | { assert(false); std::cerr << "No accept for UnfoldedFireableCondition" << std::endl; exit(0);}; |
372 | @@ -93,7 +99,85 @@ |
373 | // shallow expression, default to error |
374 | virtual void _accept(const IdentifierExpr* element) |
375 | { assert(false); std::cerr << "No accept for IdentifierExpr" << std::endl; exit(0);}; |
376 | - }; |
377 | + }; |
378 | + |
379 | + class ExpressionVisitor : public Visitor { |
380 | + public: |
381 | + |
382 | + private: |
383 | + void _accept(const NotCondition *element) override { |
384 | + assert(false); |
385 | + std::cerr << "No accept for NotCondition" << std::endl; |
386 | + exit(0); |
387 | + }; |
388 | + |
389 | + void _accept(const AndCondition *element) override { |
390 | + assert(false); |
391 | + std::cerr << "No accept for AndCondition" << std::endl; |
392 | + exit(0); |
393 | + }; |
394 | + |
395 | + void _accept(const OrCondition *element) override { |
396 | + assert(false); |
397 | + std::cerr << "No accept for OrCondition" << std::endl; |
398 | + exit(0); |
399 | + }; |
400 | + |
401 | + void _accept(const LessThanCondition *element) override { |
402 | + assert(false); |
403 | + std::cerr << "No accept for LessThanCondition" << std::endl; |
404 | + exit(0); |
405 | + }; |
406 | + |
407 | + void _accept(const LessThanOrEqualCondition *element) override { |
408 | + assert(false); |
409 | + std::cerr << "No accept for LessThanOrEqualCondition" << std::endl; |
410 | + exit(0); |
411 | + }; |
412 | + |
413 | + void _accept(const GreaterThanCondition *element) override { |
414 | + assert(false); |
415 | + std::cerr << "No accept for GreaterThanCondition" << std::endl; |
416 | + exit(0); |
417 | + }; |
418 | + |
419 | + void _accept(const GreaterThanOrEqualCondition *element) override { |
420 | + assert(false); |
421 | + std::cerr << "No accept for GreaterThanOrEqualCondition" << std::endl; |
422 | + exit(0); |
423 | + }; |
424 | + |
425 | + void _accept(const EqualCondition *element) override { |
426 | + assert(false); |
427 | + std::cerr << "No accept for EqualCondition" << std::endl; |
428 | + exit(0); |
429 | + }; |
430 | + |
431 | + void _accept(const NotEqualCondition *element) override { |
432 | + assert(false); |
433 | + std::cerr << "No accept for NotEqualCondition" << std::endl; |
434 | + exit(0); |
435 | + }; |
436 | + |
437 | + void _accept(const DeadlockCondition *element) override { |
438 | + assert(false); |
439 | + std::cerr << "No accept for DeadlockCondition" << std::endl; |
440 | + exit(0); |
441 | + }; |
442 | + |
443 | + void _accept(const CompareConjunction *element) override { |
444 | + assert(false); |
445 | + std::cerr << "No accept for CompareConjunction" << std::endl; |
446 | + exit(0); |
447 | + }; |
448 | + |
449 | + void _accept(const UnfoldedUpperBoundsCondition *element) override { |
450 | + assert(false); |
451 | + std::cerr << "No accept for UnfoldedUpperBoundsCondition" << std::endl; |
452 | + exit(0); |
453 | + }; |
454 | + }; |
455 | + |
456 | } |
457 | } |
458 | |
459 | |
460 | === modified file 'include/PetriEngine/PetriNet.h' |
461 | --- include/PetriEngine/PetriNet.h 2020-09-18 07:35:03 +0000 |
462 | +++ include/PetriEngine/PetriNet.h 2021-03-04 07:47:28 +0000 |
463 | @@ -132,6 +132,7 @@ |
464 | friend class SuccessorGenerator; |
465 | friend class ReducingSuccessorGenerator; |
466 | friend class STSolver; |
467 | + friend class StubbornSet; |
468 | }; |
469 | |
470 | } // PetriEngine |
471 | |
472 | === modified file 'include/PetriEngine/Reachability/ReachabilityResult.h' |
473 | --- include/PetriEngine/Reachability/ReachabilityResult.h 2020-04-23 15:26:52 +0000 |
474 | +++ include/PetriEngine/Reachability/ReachabilityResult.h 2021-03-04 07:47:28 +0000 |
475 | @@ -66,8 +66,8 @@ |
476 | std::vector<std::string>& querynames; |
477 | Reducer* reducer; |
478 | public: |
479 | - const string techniques = "TECHNIQUES COLLATERAL_PROCESSING STRUCTURAL_REDUCTION QUERY_REDUCTION SAT_SMT "; |
480 | - const string techniquesStateSpace = "TECHNIQUES EXPLICIT STATE_COMPRESSION"; |
481 | + const std::string techniques = "TECHNIQUES COLLATERAL_PROCESSING STRUCTURAL_REDUCTION QUERY_REDUCTION SAT_SMT "; |
482 | + const std::string techniquesStateSpace = "TECHNIQUES EXPLICIT STATE_COMPRESSION"; |
483 | |
484 | ResultPrinter(PetriNetBuilder* b, options_t* o, std::vector<std::string>& querynames) |
485 | : builder(b), options(o), querynames(querynames), reducer(NULL) |
486 | |
487 | === modified file 'include/PetriEngine/Reachability/ReachabilitySearch.h' |
488 | --- include/PetriEngine/Reachability/ReachabilitySearch.h 2020-04-23 15:26:52 +0000 |
489 | +++ include/PetriEngine/Reachability/ReachabilitySearch.h 2021-03-04 07:47:28 +0000 |
490 | @@ -28,6 +28,7 @@ |
491 | #include "../Structures/Queue.h" |
492 | #include "../SuccessorGenerator.h" |
493 | #include "../ReducingSuccessorGenerator.h" |
494 | +#include "PetriEngine/Stubborn/ReachabilityStubbornSet.h" |
495 | |
496 | #include <memory> |
497 | #include <vector> |
498 | @@ -93,7 +94,16 @@ |
499 | Structures::State _initial; |
500 | AbstractHandler& _callback; |
501 | }; |
502 | - |
503 | + |
504 | + template <typename G> |
505 | + inline G _makeSucGen(PetriNet &net, std::vector<PQL::Condition_ptr> &queries) { |
506 | + return G{net, queries}; |
507 | + } |
508 | + template <> |
509 | + inline ReducingSuccessorGenerator _makeSucGen(PetriNet &net, std::vector<PQL::Condition_ptr> &queries) { |
510 | + return ReducingSuccessorGenerator{net, queries, std::make_shared<ReachabilityStubbornSet>(net, queries)}; |
511 | + } |
512 | + |
513 | template<typename Q, typename W, typename G> |
514 | bool ReachabilitySearch::tryReach( std::vector<std::shared_ptr<PQL::Condition> >& queries, |
515 | std::vector<ResultPrinter::Result>& results, bool usequeries, |
516 | @@ -117,7 +127,7 @@ |
517 | |
518 | W states(_net, _kbound); // stateset |
519 | Q queue(&states); // working queue |
520 | - G generator(_net, queries); // successor generator |
521 | + G generator = _makeSucGen<G>(_net, queries); // successor generator |
522 | auto r = states.add(state); |
523 | // this can fail due to reductions; we push tokens around and violate K |
524 | if(r.first){ |
525 | |
526 | === modified file 'include/PetriEngine/ReducingSuccessorGenerator.h' |
527 | --- include/PetriEngine/ReducingSuccessorGenerator.h 2020-03-02 21:03:24 +0000 |
528 | +++ include/PetriEngine/ReducingSuccessorGenerator.h 2021-03-04 07:47:28 +0000 |
529 | @@ -6,63 +6,34 @@ |
530 | #include "Structures/light_deque.h" |
531 | #include "PQL/PQL.h" |
532 | #include <memory> |
533 | +#include "PetriEngine/Stubborn/StubbornSet.h" |
534 | |
535 | namespace PetriEngine { |
536 | |
537 | -class ReducingSuccessorGenerator : public SuccessorGenerator { |
538 | - |
539 | -public: |
540 | - struct place_t { |
541 | - uint32_t pre, post; |
542 | - }; |
543 | - struct trans_t { |
544 | - uint32_t index; |
545 | - int8_t direction; |
546 | - trans_t() = default; |
547 | - trans_t(uint32_t id, int8_t dir) : index(id), direction(dir) {}; |
548 | - bool operator<(const trans_t& t) const |
549 | - { |
550 | - return index < t.index; |
551 | - } |
552 | - }; |
553 | - ReducingSuccessorGenerator(const PetriNet& net); |
554 | - ReducingSuccessorGenerator(const PetriNet& net, std::vector<std::shared_ptr<PQL::Condition> >& queries); |
555 | - virtual ~ReducingSuccessorGenerator(); |
556 | - void prepare(const Structures::State* state); |
557 | - bool next(Structures::State& write); |
558 | - void presetOf(uint32_t place, bool make_closure = false); |
559 | - void postsetOf(uint32_t place, bool make_closure = false); |
560 | - void postPresetOf(uint32_t t, bool make_closure = false); |
561 | - void inhibitorPostsetOf(uint32_t place); |
562 | - bool seenPre(uint32_t place) const; |
563 | - bool seenPost(uint32_t place) const; |
564 | - uint32_t leastDependentEnabled(); |
565 | - uint32_t fired() |
566 | - { |
567 | - return _current; |
568 | - } |
569 | - void setQuery(PQL::Condition* ptr) { _queries.clear(); _queries = {ptr};} |
570 | - void reset(); |
571 | - |
572 | -private: |
573 | - inline void addToStub(uint32_t t); |
574 | - void closure(); |
575 | - std::unique_ptr<bool[]> _enabled, _stubborn; |
576 | - std::unique_ptr<uint8_t[]> _places_seen; |
577 | - std::unique_ptr<place_t[]> _places; |
578 | - std::unique_ptr<trans_t[]> _transitions; |
579 | - light_deque<uint32_t> _unprocessed, _ordering; |
580 | - std::unique_ptr<uint32_t[]> _dependency; |
581 | - uint32_t _current; |
582 | - bool _netContainsInhibitorArcs; |
583 | - std::vector<std::vector<uint32_t>> _inhibpost; |
584 | - |
585 | - std::vector<PQL::Condition* > _queries; |
586 | - void constructEnabled(); |
587 | - void constructPrePost(); |
588 | - void constructDependency(); |
589 | - void checkForInhibitor(); |
590 | -}; |
591 | + class ReducingSuccessorGenerator : public SuccessorGenerator { |
592 | + |
593 | + public: |
594 | + ReducingSuccessorGenerator(const PetriNet &net, std::shared_ptr<StubbornSet> stubbornSet); |
595 | + |
596 | + ReducingSuccessorGenerator(const PetriNet &net, std::vector<std::shared_ptr<PQL::Condition> > &queries, |
597 | + std::shared_ptr<StubbornSet> stubbornSet); |
598 | + |
599 | + void reset(); |
600 | + |
601 | + void setQuery(PQL::Condition *ptr) { _stubSet->setQuery(ptr); } |
602 | + |
603 | + void prepare(const Structures::State *state); |
604 | + |
605 | + bool next(Structures::State &write); |
606 | + |
607 | + auto fired() const { return _current; } |
608 | + private: |
609 | + std::shared_ptr<StubbornSet> _stubSet; |
610 | + uint32_t _current; |
611 | + |
612 | + std::vector<PQL::Condition *> _queries; |
613 | + |
614 | + }; |
615 | } |
616 | |
617 | #endif /* PETRIENGINE_REDUCINGSUCCESSORGENERATOR_H_ */ |
618 | |
619 | === added directory 'include/PetriEngine/Stubborn' |
620 | === added file 'include/PetriEngine/Stubborn/InterestingTransitionVisitor.h' |
621 | --- include/PetriEngine/Stubborn/InterestingTransitionVisitor.h 1970-01-01 00:00:00 +0000 |
622 | +++ include/PetriEngine/Stubborn/InterestingTransitionVisitor.h 2021-03-04 07:47:28 +0000 |
623 | @@ -0,0 +1,163 @@ |
624 | +/* |
625 | + * File: InterestingTransitionVisitor.h |
626 | + * Author: Nikolaj J. Ulrik <nikolaj@njulrik.dk> |
627 | + * |
628 | + * Created on 03/02/2021 |
629 | + */ |
630 | + |
631 | +#ifndef VERIFYPN_INTERESTINGTRANSITIONVISITOR_H |
632 | +#define VERIFYPN_INTERESTINGTRANSITIONVISITOR_H |
633 | + |
634 | +#include "PetriEngine/PQL/Visitor.h" |
635 | +#include "PetriEngine/Stubborn/StubbornSet.h" |
636 | + |
637 | +namespace PetriEngine { |
638 | + class InterestingTransitionVisitor : public PQL::Visitor { |
639 | + public: |
640 | + InterestingTransitionVisitor(PetriEngine::StubbornSet &stubbornSet) |
641 | + : _stubborn(stubbornSet), incr(stubbornSet), decr(stubbornSet) { |
642 | + incr.decr = &decr; |
643 | + decr.incr = &incr; |
644 | + } |
645 | + |
646 | + private: |
647 | + PetriEngine::StubbornSet &_stubborn; |
648 | + bool negated = false; |
649 | + |
650 | + void negate() { negated = !negated; } |
651 | + |
652 | + protected: |
653 | + void _accept(const PQL::NotCondition *element) override; |
654 | + |
655 | + void _accept(const PQL::AndCondition *element) override; |
656 | + |
657 | + void _accept(const PQL::OrCondition *element) override; |
658 | + |
659 | + void _accept(const PQL::LessThanCondition *element) override; |
660 | + |
661 | + void _accept(const PQL::LessThanOrEqualCondition *element) override; |
662 | + |
663 | + void _accept(const PQL::GreaterThanCondition *element) override; |
664 | + |
665 | + void _accept(const PQL::GreaterThanOrEqualCondition *element) override; |
666 | + |
667 | + void _accept(const PQL::EqualCondition *element) override; |
668 | + |
669 | + void _accept(const PQL::NotEqualCondition *element) override; |
670 | + |
671 | + void _accept(const PQL::DeadlockCondition *element) override; |
672 | + |
673 | + void _accept(const PQL::CompareConjunction *element) override; |
674 | + |
675 | + void _accept(const PQL::UnfoldedUpperBoundsCondition *element) override; |
676 | + |
677 | + void _accept(const PQL::UnfoldedIdentifierExpr *element) override { |
678 | + assert(false); |
679 | + std::cerr << "No accept for UnfoldedIdentifierExpr" << std::endl; |
680 | + exit(0); |
681 | + }; |
682 | + |
683 | + void _accept(const PQL::LiteralExpr *element) override { |
684 | + assert(false); |
685 | + std::cerr << "No accept for LiteralExpr" << std::endl; |
686 | + exit(0); |
687 | + }; |
688 | + |
689 | + void _accept(const PQL::PlusExpr *element) override { |
690 | + assert(false); |
691 | + std::cerr << "No accept for PlusExpr" << std::endl; |
692 | + exit(0); |
693 | + }; |
694 | + |
695 | + void _accept(const PQL::MultiplyExpr *element) override { |
696 | + assert(false); |
697 | + std::cerr << "No accept for MultiplyExpr" << std::endl; |
698 | + exit(0); |
699 | + }; |
700 | + |
701 | + void _accept(const PQL::MinusExpr *element) override { |
702 | + assert(false); |
703 | + std::cerr << "No accept for MinusExpr" << std::endl; |
704 | + exit(0); |
705 | + }; |
706 | + |
707 | + void _accept(const PQL::SubtractExpr *element) override { |
708 | + assert(false); |
709 | + std::cerr << "No accept for SubtractExpr" << std::endl; |
710 | + exit(0); |
711 | + }; |
712 | + |
713 | + void _accept(const PQL::SimpleQuantifierCondition *element); |
714 | + |
715 | + void _accept(const PQL::UntilCondition *element) override; |
716 | + |
717 | + void _accept(const PQL::BooleanCondition *element) override; |
718 | + |
719 | + private: |
720 | + |
721 | + /* |
722 | + * Mutually recursive visitors for incrementing/decrementing of places. |
723 | + */ |
724 | + |
725 | + class DecrVisitor; |
726 | + class IncrVisitor : public PQL::ExpressionVisitor { |
727 | + public: |
728 | + IncrVisitor(StubbornSet &stubbornSet) |
729 | + : _stubborn(stubbornSet) {} |
730 | + |
731 | + DecrVisitor *decr; |
732 | + private: |
733 | + StubbornSet &_stubborn; |
734 | + |
735 | + void _accept(const PQL::IdentifierExpr *element) override { |
736 | + element->compiled()->visit(*this); |
737 | + } |
738 | + |
739 | + void _accept(const PQL::UnfoldedIdentifierExpr *element) override; |
740 | + |
741 | + void _accept(const PQL::LiteralExpr *element) override; |
742 | + |
743 | + void _accept(const PQL::PlusExpr *element) override; |
744 | + |
745 | + void _accept(const PQL::MultiplyExpr *element) override; |
746 | + |
747 | + void _accept(const PQL::MinusExpr *element) override; |
748 | + |
749 | + void _accept(const PQL::SubtractExpr *element) override; |
750 | + }; |
751 | + |
752 | + class DecrVisitor : public PQL::ExpressionVisitor { |
753 | + public: |
754 | + DecrVisitor(StubbornSet &stubbornSet) |
755 | + : _stubborn(stubbornSet) {} |
756 | + |
757 | + IncrVisitor *incr; |
758 | + |
759 | + private: |
760 | + StubbornSet &_stubborn; |
761 | + |
762 | + void _accept(const PQL::IdentifierExpr *element) override { |
763 | + element->compiled()->visit(*this); |
764 | + } |
765 | + |
766 | + void _accept(const PQL::UnfoldedIdentifierExpr *element) override; |
767 | + |
768 | + void _accept(const PQL::LiteralExpr *element) override; |
769 | + |
770 | + void _accept(const PQL::PlusExpr *element) override; |
771 | + |
772 | + void _accept(const PQL::MultiplyExpr *element) override; |
773 | + |
774 | + void _accept(const PQL::MinusExpr *element) override; |
775 | + |
776 | + void _accept(const PQL::SubtractExpr *element) override; |
777 | + }; |
778 | + |
779 | + IncrVisitor incr; |
780 | + DecrVisitor decr; |
781 | + }; |
782 | + |
783 | +} |
784 | + |
785 | + |
786 | +#endif //VERIFYPN_INTERESTINGTRANSITIONVISITOR_H |
787 | |
788 | === added file 'include/PetriEngine/Stubborn/ReachabilityStubbornSet.h' |
789 | --- include/PetriEngine/Stubborn/ReachabilityStubbornSet.h 1970-01-01 00:00:00 +0000 |
790 | +++ include/PetriEngine/Stubborn/ReachabilityStubbornSet.h 2021-03-04 07:47:28 +0000 |
791 | @@ -0,0 +1,40 @@ |
792 | +/* Copyright (C) 2021 Nikolaj J. Ulrik <nikolaj@njulrik.dk>, |
793 | + * Simon M. Virenfeldt <simon@simwir.dk> |
794 | + * |
795 | + * This program is free software: you can redistribute it and/or modify |
796 | + * it under the terms of the GNU General Public License as published by |
797 | + * the Free Software Foundation, either version 3 of the License, or |
798 | + * (at your option) any later version. |
799 | + * |
800 | + * This program is distributed in the hope that it will be useful, |
801 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
802 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
803 | + * GNU General Public License for more details. |
804 | + * |
805 | + * You should have received a copy of the GNU General Public License |
806 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
807 | + */ |
808 | + |
809 | +#ifndef VERIFYPN_REACHABILITYSTUBBORNSET_H |
810 | +#define VERIFYPN_REACHABILITYSTUBBORNSET_H |
811 | + |
812 | + |
813 | +#include "PetriEngine/Stubborn/StubbornSet.h" |
814 | + |
815 | +namespace PetriEngine { |
816 | + class ReachabilityStubbornSet : public StubbornSet { |
817 | + public: |
818 | + ReachabilityStubbornSet(const PetriNet &net, const vector<PQL::Condition_ptr> &queries) |
819 | + : StubbornSet(net, queries) {} |
820 | + |
821 | + ReachabilityStubbornSet(const PetriNet &net) |
822 | + : StubbornSet(net) {} |
823 | + |
824 | + void prepare(const Structures::State *state) override; |
825 | + |
826 | + |
827 | + private: |
828 | + }; |
829 | +} |
830 | + |
831 | +#endif //VERIFYPN_REACHABILITYSTUBBORNSET_H |
832 | |
833 | === added file 'include/PetriEngine/Stubborn/StubbornSet.h' |
834 | --- include/PetriEngine/Stubborn/StubbornSet.h 1970-01-01 00:00:00 +0000 |
835 | +++ include/PetriEngine/Stubborn/StubbornSet.h 2021-03-04 07:47:28 +0000 |
836 | @@ -0,0 +1,146 @@ |
837 | +/* Copyright (C) 2021 Nikolaj J. Ulrik <nikolaj@njulrik.dk>, |
838 | + * Simon M. Virenfeldt <simon@simwir.dk> |
839 | + * |
840 | + * This program is free software: you can redistribute it and/or modify |
841 | + * it under the terms of the GNU General Public License as published by |
842 | + * the Free Software Foundation, either version 3 of the License, or |
843 | + * (at your option) any later version. |
844 | + * |
845 | + * This program is distributed in the hope that it will be useful, |
846 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
847 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
848 | + * GNU General Public License for more details. |
849 | + * |
850 | + * You should have received a copy of the GNU General Public License |
851 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
852 | + */ |
853 | + |
854 | +#ifndef VERIFYPN_STUBBORNSET_H |
855 | +#define VERIFYPN_STUBBORNSET_H |
856 | + |
857 | +#include "PetriEngine/PetriNet.h" |
858 | +#include "PetriEngine/Structures/State.h" |
859 | +#include "PetriEngine/Structures/light_deque.h" |
860 | +#include "PetriEngine/PQL/PQL.h" |
861 | + |
862 | +#include <memory> |
863 | +#include <vector> |
864 | + |
865 | +namespace PetriEngine { |
866 | + class StubbornSet { |
867 | + public: |
868 | + StubbornSet(const PetriEngine::PetriNet &net) |
869 | + : _net(net), _inhibpost(net._nplaces) { |
870 | + _current = 0; |
871 | + _enabled = std::make_unique<bool[]>(net._ntransitions); |
872 | + _stubborn = std::make_unique<bool[]>(net._ntransitions); |
873 | + _dependency = std::make_unique<uint32_t[]>(net._ntransitions); |
874 | + _places_seen = std::make_unique<uint8_t[]>(_net.numberOfPlaces()); |
875 | + StubbornSet::reset(); |
876 | + constructPrePost(); |
877 | + constructDependency(); |
878 | + checkForInhibitor(); |
879 | + |
880 | + } |
881 | + |
882 | + StubbornSet(const PetriEngine::PetriNet &net, const std::vector<PQL::Condition_ptr> &queries) |
883 | + : StubbornSet(net) { |
884 | + for (auto &q: queries) { |
885 | + _queries.push_back(q.get()); |
886 | + } |
887 | + } |
888 | + |
889 | + virtual void prepare(const Structures::State *marking) = 0; |
890 | + |
891 | + uint32_t next(); |
892 | + |
893 | + virtual ~StubbornSet() = default; |
894 | + |
895 | + virtual void reset(); |
896 | + |
897 | + [[nodiscard]] const MarkVal *getParent() const { |
898 | + return _parent->marking(); |
899 | + } |
900 | + |
901 | + uint32_t _current; |
902 | + |
903 | + void presetOf(uint32_t place, bool make_closure = false); |
904 | + |
905 | + void postsetOf(uint32_t place, bool make_closure = false); |
906 | + |
907 | + void postPresetOf(uint32_t t, bool make_closure = false); |
908 | + |
909 | + void inhibitorPostsetOf(uint32_t place); |
910 | + |
911 | + bool seenPre(uint32_t place) const; |
912 | + |
913 | + bool seenPost(uint32_t place) const; |
914 | + |
915 | + uint32_t leastDependentEnabled(); |
916 | + |
917 | + uint32_t fired() { |
918 | + return _current; |
919 | + } |
920 | + |
921 | + void setQuery(PQL::Condition *ptr) { |
922 | + _queries.clear(); |
923 | + _queries = {ptr}; |
924 | + } |
925 | + |
926 | + protected: |
927 | + const PetriEngine::PetriNet &_net; |
928 | + const Structures::State *_parent; |
929 | + |
930 | + struct place_t { |
931 | + uint32_t pre, post; |
932 | + }; |
933 | + |
934 | + struct trans_t { |
935 | + uint32_t index; |
936 | + int8_t direction; |
937 | + |
938 | + trans_t() = default; |
939 | + |
940 | + trans_t(uint32_t id, int8_t dir) : index(id), direction(dir) {}; |
941 | + |
942 | + bool operator<(const trans_t &t) const { |
943 | + return index < t.index; |
944 | + } |
945 | + }; |
946 | + |
947 | + size_t _tid = 0; |
948 | + |
949 | + const std::vector<TransPtr> &transitions() { return _net._transitions; } |
950 | + |
951 | + const std::vector<Invariant> &invariants() { return _net._invariants; } |
952 | + |
953 | + const std::vector<uint32_t> &placeToPtrs() { return _net._placeToPtrs; } |
954 | + |
955 | + bool checkPreset(uint32_t t); |
956 | + |
957 | + inline void addToStub(uint32_t t); |
958 | + |
959 | + void closure(); |
960 | + |
961 | + std::unique_ptr<bool[]> _enabled, _stubborn; |
962 | + std::unique_ptr<uint8_t[]> _places_seen; |
963 | + std::unique_ptr<place_t[]> _places; |
964 | + std::unique_ptr<trans_t[]> _transitions; |
965 | + light_deque<uint32_t> _unprocessed, _ordering; |
966 | + std::unique_ptr<uint32_t[]> _dependency; |
967 | + bool _netContainsInhibitorArcs; |
968 | + std::vector<std::vector<uint32_t>> _inhibpost; |
969 | + |
970 | + std::vector<PQL::Condition *> _queries; |
971 | + |
972 | + void constructEnabled(); |
973 | + |
974 | + void constructPrePost(); |
975 | + |
976 | + void constructDependency(); |
977 | + |
978 | + void checkForInhibitor(); |
979 | + }; |
980 | +} |
981 | + |
982 | +#endif //VERIFYPN_STUBBORNSET_H |
983 | |
984 | === modified file 'include/PetriEngine/TAR/Solver.h' |
985 | --- include/PetriEngine/TAR/Solver.h 2020-04-21 21:01:42 +0000 |
986 | +++ include/PetriEngine/TAR/Solver.h 2021-03-04 07:47:28 +0000 |
987 | @@ -16,6 +16,7 @@ |
988 | #include "range.h" |
989 | #include "PetriEngine/PQL/PQL.h" |
990 | #include "TraceSet.h" |
991 | +#include "PetriEngine/SuccessorGenerator.h" |
992 | |
993 | #include <utility> |
994 | #include <cinttypes> |
995 | |
996 | === modified file 'include/PetriParse/QueryParser.h' |
997 | --- include/PetriParse/QueryParser.h 2020-03-02 21:03:24 +0000 |
998 | +++ include/PetriParse/QueryParser.h 2021-03-04 07:47:28 +0000 |
999 | @@ -4,11 +4,10 @@ |
1000 | |
1001 | |
1002 | #include "PetriEngine/PQL/PQL.h" |
1003 | -using namespace PetriEngine::PQL; |
1004 | |
1005 | struct QueryItem { |
1006 | - string id; // query name |
1007 | - Condition_ptr query; |
1008 | + std::string id; // query name |
1009 | + PetriEngine::PQL::Condition_ptr query; |
1010 | |
1011 | enum { |
1012 | PARSING_OK, |
1013 | |
1014 | === modified file 'include/PetriParse/QueryXMLParser.h' |
1015 | --- include/PetriParse/QueryXMLParser.h 2020-03-13 13:35:25 +0000 |
1016 | +++ include/PetriParse/QueryXMLParser.h 2021-03-04 07:47:28 +0000 |
1017 | @@ -50,7 +50,7 @@ |
1018 | Condition_ptr parseFormula(rapidxml::xml_node<>* element); |
1019 | Condition_ptr parseBooleanFormula(rapidxml::xml_node<>* element); |
1020 | Expr_ptr parseIntegerExpression(rapidxml::xml_node<>* element); |
1021 | - string parsePlace(rapidxml::xml_node<>* element); |
1022 | + std::string parsePlace(rapidxml::xml_node<>* element); |
1023 | void fatal_error(const std::string& token); |
1024 | }; |
1025 | |
1026 | |
1027 | === modified file 'src/CTL/PetriNets/OnTheFlyDG.cpp' |
1028 | --- src/CTL/PetriNets/OnTheFlyDG.cpp 2020-03-02 22:05:53 +0000 |
1029 | +++ src/CTL/PetriNets/OnTheFlyDG.cpp 2021-03-04 07:47:28 +0000 |
1030 | @@ -7,6 +7,7 @@ |
1031 | #include <limits> |
1032 | |
1033 | #include "PetriEngine/SuccessorGenerator.h" |
1034 | +#include "PetriEngine/Stubborn/ReachabilityStubbornSet.h" |
1035 | #include "PetriEngine/PQL/Expressions.h" |
1036 | #include "CTL/SearchStrategy/SearchStrategy.h" |
1037 | |
1038 | @@ -19,7 +20,7 @@ |
1039 | OnTheFlyDG::OnTheFlyDG(PetriEngine::PetriNet *t_net, bool partial_order) : encoder(t_net->numberOfPlaces(), 0), |
1040 | edge_alloc(new linked_bucket_t<DependencyGraph::Edge,1024*10>(1)), |
1041 | conf_alloc(new linked_bucket_t<char[sizeof(PetriConfig)], 1024*1024>(1)), |
1042 | - _redgen(*t_net), _partial_order(partial_order) { |
1043 | + _redgen(*t_net, std::make_shared<PetriEngine::ReachabilityStubbornSet>(*t_net)), _partial_order(partial_order) { |
1044 | net = t_net; |
1045 | n_places = t_net->numberOfPlaces(); |
1046 | n_transitions = t_net->numberOfTransitions(); |
1047 | |
1048 | === modified file 'src/PetriEngine/CMakeLists.txt' |
1049 | --- src/PetriEngine/CMakeLists.txt 2020-04-04 14:48:55 +0000 |
1050 | +++ src/PetriEngine/CMakeLists.txt 2021-03-04 07:47:28 +0000 |
1051 | @@ -3,6 +3,7 @@ |
1052 | add_subdirectory(Colored) |
1053 | add_subdirectory(Structures) |
1054 | add_subdirectory(Simplification) |
1055 | +add_subdirectory(Stubborn) |
1056 | add_subdirectory(Reachability) |
1057 | add_subdirectory(PQL) |
1058 | add_subdirectory(TAR) |
1059 | @@ -16,4 +17,4 @@ |
1060 | SuccessorGenerator.cpp |
1061 | ) |
1062 | |
1063 | -target_link_libraries(PetriEngine PRIVATE Colored Structures Simplification Reachability PQL TAR) |
1064 | +target_link_libraries(PetriEngine PRIVATE Colored Structures Simplification Stubborn Reachability PQL TAR) |
1065 | |
1066 | === modified file 'src/PetriEngine/PQL/Expressions.cpp' |
1067 | --- src/PetriEngine/PQL/Expressions.cpp 2020-07-02 13:57:17 +0000 |
1068 | +++ src/PetriEngine/PQL/Expressions.cpp 2021-03-04 07:47:28 +0000 |
1069 | @@ -500,8 +500,8 @@ |
1070 | std::sort(_ids.begin(), _ids.end(), [](auto& a, auto& b){ return a.first < b.first; }); |
1071 | std::sort(_exprs.begin(), _exprs.end(), [](auto& a, auto& b) |
1072 | { |
1073 | - auto ida = dynamic_pointer_cast<PQL::UnfoldedIdentifierExpr>(a); |
1074 | - auto idb = dynamic_pointer_cast<PQL::UnfoldedIdentifierExpr>(b); |
1075 | + auto ida = std::dynamic_pointer_cast<PQL::UnfoldedIdentifierExpr>(a); |
1076 | + auto idb = std::dynamic_pointer_cast<PQL::UnfoldedIdentifierExpr>(b); |
1077 | if(ida == NULL) return false; |
1078 | if(ida && !idb) return true; |
1079 | return ida->offset() < idb->offset(); |
1080 | @@ -3557,16 +3557,16 @@ |
1081 | if(bi == b->_ids.end() || ai == a->_ids.end()) break; |
1082 | } |
1083 | }; |
1084 | - if(auto p1 = dynamic_pointer_cast<PlusExpr>(_expr1)) |
1085 | - if(auto p2 = dynamic_pointer_cast<PlusExpr>(_expr2)) |
1086 | + if(auto p1 = std::dynamic_pointer_cast<PlusExpr>(_expr1)) |
1087 | + if(auto p2 = std::dynamic_pointer_cast<PlusExpr>(_expr2)) |
1088 | remdup(p1, p2); |
1089 | |
1090 | - if(auto m1 = dynamic_pointer_cast<MultiplyExpr>(_expr1)) |
1091 | - if(auto m2 = dynamic_pointer_cast<MultiplyExpr>(_expr2)) |
1092 | + if(auto m1 = std::dynamic_pointer_cast<MultiplyExpr>(_expr1)) |
1093 | + if(auto m2 = std::dynamic_pointer_cast<MultiplyExpr>(_expr2)) |
1094 | remdup(m1, m2); |
1095 | |
1096 | - if(auto p1 = dynamic_pointer_cast<CommutativeExpr>(_expr1)) |
1097 | - if(auto p2 = dynamic_pointer_cast<CommutativeExpr>(_expr2)) |
1098 | + if(auto p1 = std::dynamic_pointer_cast<CommutativeExpr>(_expr1)) |
1099 | + if(auto p2 = std::dynamic_pointer_cast<CommutativeExpr>(_expr2)) |
1100 | return p1->_exprs.size() + p1->_ids.size() + p2->_exprs.size() + p2->_ids.size() == 0; |
1101 | return _expr1->placeFree() && _expr2->placeFree(); |
1102 | } |
1103 | @@ -3658,324 +3658,6 @@ |
1104 | } |
1105 | |
1106 | |
1107 | - /******************** Stubborn reduction interesting transitions ********************/ |
1108 | - |
1109 | - void PlusExpr::incr(ReducingSuccessorGenerator& generator) const { |
1110 | - for(auto& i : _ids) generator.presetOf(i.first, true); |
1111 | - for(auto& e : _exprs) e->incr(generator); |
1112 | - } |
1113 | - |
1114 | - void PlusExpr::decr(ReducingSuccessorGenerator& generator) const { |
1115 | - for(auto& i : _ids) generator.postsetOf(i.first, true); |
1116 | - for(auto& e : _exprs) e->decr(generator); |
1117 | - } |
1118 | - |
1119 | - void SubtractExpr::incr(ReducingSuccessorGenerator& generator) const { |
1120 | - bool first = true; |
1121 | - for(auto& e : _exprs) |
1122 | - { |
1123 | - if(first) |
1124 | - e->incr(generator); |
1125 | - else |
1126 | - e->decr(generator); |
1127 | - first = false; |
1128 | - } |
1129 | - } |
1130 | - |
1131 | - void SubtractExpr::decr(ReducingSuccessorGenerator& generator) const { |
1132 | - bool first = true; |
1133 | - for(auto& e : _exprs) |
1134 | - { |
1135 | - if(first) |
1136 | - e->decr(generator); |
1137 | - else |
1138 | - e->incr(generator); |
1139 | - first = false; |
1140 | - } |
1141 | - } |
1142 | - |
1143 | - void MultiplyExpr::incr(ReducingSuccessorGenerator& generator) const { |
1144 | - if((_ids.size() + _exprs.size()) == 1) |
1145 | - { |
1146 | - for(auto& i : _ids) generator.presetOf(i.first, true); |
1147 | - for(auto& e : _exprs) e->incr(generator); |
1148 | - } |
1149 | - else |
1150 | - { |
1151 | - for(auto& i : _ids) |
1152 | - { |
1153 | - generator.presetOf(i.first, true); |
1154 | - generator.postsetOf(i.first, true); |
1155 | - } |
1156 | - for(auto& e : _exprs) |
1157 | - { |
1158 | - e->incr(generator); |
1159 | - e->decr(generator); |
1160 | - } |
1161 | - } |
1162 | - } |
1163 | - |
1164 | - void MultiplyExpr::decr(ReducingSuccessorGenerator& generator) const { |
1165 | - if((_ids.size() + _exprs.size()) == 1) |
1166 | - { |
1167 | - for(auto& i : _ids) generator.postsetOf(i.first, true); |
1168 | - for(auto& e : _exprs) e->decr(generator); |
1169 | - } |
1170 | - else |
1171 | - incr(generator); |
1172 | - } |
1173 | - |
1174 | - void MinusExpr::incr(ReducingSuccessorGenerator& generator) const { |
1175 | - // TODO not implemented |
1176 | - } |
1177 | - |
1178 | - void MinusExpr::decr(ReducingSuccessorGenerator& generator) const { |
1179 | - // TODO not implemented |
1180 | - } |
1181 | - |
1182 | - void LiteralExpr::incr(ReducingSuccessorGenerator& generator) const { |
1183 | - // Add nothing |
1184 | - } |
1185 | - |
1186 | - void LiteralExpr::decr(ReducingSuccessorGenerator& generator) const { |
1187 | - // Add nothing |
1188 | - } |
1189 | - |
1190 | - void UnfoldedIdentifierExpr::incr(ReducingSuccessorGenerator& generator) const { |
1191 | - generator.presetOf(_offsetInMarking, true); |
1192 | - } |
1193 | - |
1194 | - void UnfoldedIdentifierExpr::decr(ReducingSuccessorGenerator& generator) const { |
1195 | - generator.postsetOf(_offsetInMarking, true); |
1196 | - } |
1197 | - |
1198 | - void SimpleQuantifierCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const{ |
1199 | - _cond->findInteresting(generator, negated); |
1200 | - } |
1201 | - |
1202 | - void UntilCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const{ |
1203 | - _cond1->findInteresting(generator, negated); |
1204 | - _cond1->findInteresting(generator, !negated); |
1205 | - _cond2->findInteresting(generator, negated); |
1206 | - } |
1207 | - |
1208 | - void AndCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const { |
1209 | - if(!negated){ // and |
1210 | - for(auto& c : _conds) |
1211 | - { |
1212 | - if(!c->isSatisfied()) |
1213 | - { |
1214 | - c->findInteresting(generator, negated); |
1215 | - break; |
1216 | - } |
1217 | - } |
1218 | - } else { // or |
1219 | - for(auto& c : _conds) c->findInteresting(generator, negated); |
1220 | - } |
1221 | - } |
1222 | - |
1223 | - void OrCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const { |
1224 | - if(!negated){ // or |
1225 | - for(auto& c : _conds) c->findInteresting(generator, negated); |
1226 | - } else { // and |
1227 | - for(auto& c : _conds) |
1228 | - { |
1229 | - if(c->isSatisfied()) |
1230 | - { |
1231 | - c->findInteresting(generator, negated); |
1232 | - break; |
1233 | - } |
1234 | - } |
1235 | - } |
1236 | - } |
1237 | - |
1238 | - void CompareConjunction::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const{ |
1239 | - |
1240 | - auto neg = negated != _negated; |
1241 | - int32_t cand = std::numeric_limits<int32_t>::max(); |
1242 | - bool pre = false; |
1243 | - for(auto& c : _constraints) |
1244 | - { |
1245 | - auto val = generator.parent()[c._place]; |
1246 | - if(c._lower == c._upper) |
1247 | - { |
1248 | - if(neg) |
1249 | - { |
1250 | - if(val != c._lower) continue; |
1251 | - generator.postsetOf(c._place, true); |
1252 | - generator.presetOf(c._place, true); |
1253 | - } |
1254 | - else |
1255 | - { |
1256 | - if(val == c._lower) continue; |
1257 | - if(val > c._lower) { |
1258 | - cand = c._place; |
1259 | - pre = false; |
1260 | - } else { |
1261 | - cand = c._place; |
1262 | - pre = true; |
1263 | - } |
1264 | - } |
1265 | - } |
1266 | - else |
1267 | - { |
1268 | - if(!neg) |
1269 | - { |
1270 | - if(val < c._lower && c._lower != 0) |
1271 | - { |
1272 | - assert(!neg); |
1273 | - cand = c._place; |
1274 | - pre = true; |
1275 | - } |
1276 | - |
1277 | - if(val > c._upper && c._upper != std::numeric_limits<uint32_t>::max()) |
1278 | - { |
1279 | - assert(!neg); |
1280 | - cand = c._place; |
1281 | - pre = false; |
1282 | - } |
1283 | - } |
1284 | - else |
1285 | - { |
1286 | - if(val >= c._lower && c._lower != 0) |
1287 | - { |
1288 | - generator.postsetOf(c._place, true); |
1289 | - } |
1290 | - |
1291 | - if(val <= c._upper && c._upper != std::numeric_limits<uint32_t>::max()) |
1292 | - { |
1293 | - generator.presetOf(c._place, true); |
1294 | - } |
1295 | - } |
1296 | - } |
1297 | - if(cand != std::numeric_limits<int32_t>::max()) |
1298 | - { |
1299 | - if(pre && generator.seenPre(cand)) |
1300 | - return; |
1301 | - else if(!pre && generator.seenPost(cand)) |
1302 | - return; |
1303 | - } |
1304 | - } |
1305 | - if(cand != std::numeric_limits<int32_t>::max()) |
1306 | - { |
1307 | - if(pre) |
1308 | - { |
1309 | - generator.presetOf(cand, true); |
1310 | - } |
1311 | - else if(!pre) |
1312 | - { |
1313 | - generator.postsetOf(cand, true); |
1314 | - } |
1315 | - } |
1316 | - } |
1317 | - |
1318 | - void EqualCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const { |
1319 | - if(!negated){ // equal |
1320 | - if(_expr1->getEval() == _expr2->getEval()) { return; } |
1321 | - if(_expr1->getEval() > _expr2->getEval()){ |
1322 | - _expr1->decr(generator); |
1323 | - _expr2->incr(generator); |
1324 | - } else { |
1325 | - _expr1->incr(generator); |
1326 | - _expr2->decr(generator); |
1327 | - } |
1328 | - } else { // not equal |
1329 | - if(_expr1->getEval() != _expr2->getEval()) { return; } |
1330 | - _expr1->incr(generator); |
1331 | - _expr1->decr(generator); |
1332 | - _expr2->incr(generator); |
1333 | - _expr2->decr(generator); |
1334 | - } |
1335 | - } |
1336 | - |
1337 | - void NotEqualCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const { |
1338 | - if(!negated){ // not equal |
1339 | - if(_expr1->getEval() != _expr2->getEval()) { return; } |
1340 | - _expr1->incr(generator); |
1341 | - _expr1->decr(generator); |
1342 | - _expr2->incr(generator); |
1343 | - _expr2->decr(generator); |
1344 | - } else { // equal |
1345 | - if(_expr1->getEval() == _expr2->getEval()) { return; } |
1346 | - if(_expr1->getEval() > _expr2->getEval()){ |
1347 | - _expr1->decr(generator); |
1348 | - _expr2->incr(generator); |
1349 | - } else { |
1350 | - _expr1->incr(generator); |
1351 | - _expr2->decr(generator); |
1352 | - } |
1353 | - } |
1354 | - } |
1355 | - |
1356 | - void LessThanCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const { |
1357 | - if(!negated){ // less than |
1358 | - if(_expr1->getEval() < _expr2->getEval()) { return; } |
1359 | - _expr1->decr(generator); |
1360 | - _expr2->incr(generator); |
1361 | - } else { // greater than or equal |
1362 | - if(_expr1->getEval() >= _expr2->getEval()) { return; } |
1363 | - _expr1->incr(generator); |
1364 | - _expr2->decr(generator); |
1365 | - } |
1366 | - } |
1367 | - |
1368 | - void LessThanOrEqualCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const { |
1369 | - if(!negated){ // less than or equal |
1370 | - if(_expr1->getEval() <= _expr2->getEval()) { return; } |
1371 | - _expr1->decr(generator); |
1372 | - _expr2->incr(generator); |
1373 | - } else { // greater than |
1374 | - if(_expr1->getEval() > _expr2->getEval()) { return; } |
1375 | - _expr1->incr(generator); |
1376 | - _expr2->decr(generator); |
1377 | - } |
1378 | - } |
1379 | - |
1380 | - void GreaterThanCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const { |
1381 | - if(!negated){ // greater than |
1382 | - if(_expr1->getEval() > _expr2->getEval()) { return; } |
1383 | - _expr1->incr(generator); |
1384 | - _expr2->decr(generator); |
1385 | - } else { // less than or equal |
1386 | - if(_expr1->getEval() <= _expr2->getEval()) { return; } |
1387 | - _expr1->decr(generator); |
1388 | - _expr2->incr(generator); |
1389 | - } |
1390 | - } |
1391 | - |
1392 | - void GreaterThanOrEqualCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const { |
1393 | - if(!negated){ // greater than or equal |
1394 | - if(_expr1->getEval() >= _expr2->getEval()) { return; } |
1395 | - _expr1->incr(generator); |
1396 | - _expr2->decr(generator); |
1397 | - } else { // less than |
1398 | - if(_expr1->getEval() < _expr2->getEval()) { return; } |
1399 | - _expr1->decr(generator); |
1400 | - _expr2->incr(generator); |
1401 | - } |
1402 | - } |
1403 | - |
1404 | - void NotCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const { |
1405 | - _cond->findInteresting(generator, !negated); |
1406 | - } |
1407 | - |
1408 | - void BooleanCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const { |
1409 | - // Add nothing |
1410 | - } |
1411 | - |
1412 | - void DeadlockCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const { |
1413 | - if(!isSatisfied()){ |
1414 | - generator.postPresetOf(generator.leastDependentEnabled(), true); |
1415 | - } // else add nothing |
1416 | - } |
1417 | - |
1418 | - void UnfoldedUpperBoundsCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const { |
1419 | - for(auto& p : _places) |
1420 | - if(!p._maxed_out) |
1421 | - generator.presetOf(p._place); |
1422 | - } |
1423 | - |
1424 | - |
1425 | /********************** CONSTRUCTORS *********************************/ |
1426 | |
1427 | template<typename T> |
1428 | @@ -4156,10 +3838,10 @@ |
1429 | EvaluationContext c; |
1430 | _constant = apply(_constant, e->evaluate(c)); |
1431 | } |
1432 | - else if (auto id = dynamic_pointer_cast<PQL::UnfoldedIdentifierExpr>(e)) { |
1433 | + else if (auto id = std::dynamic_pointer_cast<PQL::UnfoldedIdentifierExpr>(e)) { |
1434 | _ids.emplace_back(id->offset(), id->name()); |
1435 | } |
1436 | - else if(auto c = dynamic_pointer_cast<CommutativeExpr>(e)) |
1437 | + else if(auto c = std::dynamic_pointer_cast<CommutativeExpr>(e)) |
1438 | { |
1439 | // we should move up plus/multiply here when possible; |
1440 | if(c->_ids.size() == 0 && c->_exprs.size() == 0) |
1441 | |
1442 | === modified file 'src/PetriEngine/ReducingSuccessorGenerator.cpp' |
1443 | --- src/PetriEngine/ReducingSuccessorGenerator.cpp 2020-03-02 21:03:24 +0000 |
1444 | +++ src/PetriEngine/ReducingSuccessorGenerator.cpp 2021-03-04 07:47:28 +0000 |
1445 | @@ -5,314 +5,43 @@ |
1446 | |
1447 | namespace PetriEngine { |
1448 | |
1449 | - ReducingSuccessorGenerator::ReducingSuccessorGenerator(const PetriNet& net) : SuccessorGenerator(net), _inhibpost(net._nplaces){ |
1450 | - _current = 0; |
1451 | - _enabled = std::make_unique<bool[]>(net._ntransitions); |
1452 | - _stubborn = std::make_unique<bool[]>(net._ntransitions); |
1453 | - _dependency = std::make_unique<uint32_t[]>(net._ntransitions); |
1454 | - _places_seen = std::make_unique<uint8_t[]>(_net.numberOfPlaces()); |
1455 | - reset(); |
1456 | - constructPrePost(); |
1457 | - constructDependency(); |
1458 | - checkForInhibitor(); |
1459 | + ReducingSuccessorGenerator::ReducingSuccessorGenerator(const PetriNet &net, |
1460 | + std::shared_ptr<StubbornSet> stubbornSet) |
1461 | + : SuccessorGenerator(net), _stubSet(stubbornSet) { |
1462 | + |
1463 | } |
1464 | |
1465 | - ReducingSuccessorGenerator::ReducingSuccessorGenerator(const PetriNet& net, std::vector<std::shared_ptr<PQL::Condition> >& queries) : ReducingSuccessorGenerator(net) { |
1466 | + ReducingSuccessorGenerator::ReducingSuccessorGenerator(const PetriNet &net, |
1467 | + std::vector<std::shared_ptr<PQL::Condition> > &queries, |
1468 | + std::shared_ptr<StubbornSet> stubbornSet) |
1469 | + : ReducingSuccessorGenerator(net, stubbornSet) { |
1470 | _queries.reserve(queries.size()); |
1471 | - for(auto& q : queries) |
1472 | + for (auto &q : queries) |
1473 | _queries.push_back(q.get()); |
1474 | } |
1475 | |
1476 | - ReducingSuccessorGenerator::~ReducingSuccessorGenerator() { |
1477 | - } |
1478 | - |
1479 | - void ReducingSuccessorGenerator::checkForInhibitor(){ |
1480 | - _netContainsInhibitorArcs=false; |
1481 | - for (uint32_t t = 0; t < _net._ntransitions; t++) { |
1482 | - const TransPtr& ptr = _net._transitions[t]; |
1483 | - uint32_t finv = ptr.inputs; |
1484 | - uint32_t linv = ptr.outputs; |
1485 | - for (; finv < linv; finv++) { // Post set of places |
1486 | - if (_net._invariants[finv].inhibitor) { |
1487 | - _netContainsInhibitorArcs=true; |
1488 | - return; |
1489 | - } |
1490 | - } |
1491 | - } |
1492 | - } |
1493 | - |
1494 | - void ReducingSuccessorGenerator::constructPrePost() { |
1495 | - std::vector<std::pair<std::vector<trans_t>, std::vector < trans_t>>> tmp_places(_net._nplaces); |
1496 | - |
1497 | - for (uint32_t t = 0; t < _net._ntransitions; t++) { |
1498 | - const TransPtr& ptr = _net._transitions[t]; |
1499 | - uint32_t finv = ptr.inputs; |
1500 | - uint32_t linv = ptr.outputs; |
1501 | - for (; finv < linv; finv++) { // Post set of places |
1502 | - if (_net._invariants[finv].inhibitor) { |
1503 | - _inhibpost[_net._invariants[finv].place].push_back(t); |
1504 | - _netContainsInhibitorArcs=true; |
1505 | - } else { |
1506 | - tmp_places[_net._invariants[finv].place].second.emplace_back(t, _net._invariants[finv].direction); |
1507 | - } |
1508 | - } |
1509 | - |
1510 | - finv = linv; |
1511 | - linv = _net._transitions[t + 1].inputs; |
1512 | - for (; finv < linv; finv++) { // Pre set of places |
1513 | - if(_net._invariants[finv].direction > 0) |
1514 | - tmp_places[_net._invariants[finv].place].first.emplace_back(t, _net._invariants[finv].direction); |
1515 | - } |
1516 | - } |
1517 | - |
1518 | - // flatten |
1519 | - size_t ntrans = 0; |
1520 | - for (auto p : tmp_places) { |
1521 | - ntrans += p.first.size() + p.second.size(); |
1522 | - } |
1523 | - _transitions.reset(new trans_t[ntrans]); |
1524 | - |
1525 | - _places.reset(new place_t[_net._nplaces + 1]); |
1526 | - uint32_t offset = 0; |
1527 | - uint32_t p = 0; |
1528 | - for (; p < _net._nplaces; ++p) { |
1529 | - auto& pre = tmp_places[p].first; |
1530 | - auto& post = tmp_places[p].second; |
1531 | - |
1532 | - // keep things nice for caches |
1533 | - std::sort(pre.begin(), pre.end()); |
1534 | - std::sort(post.begin(), post.end()); |
1535 | - |
1536 | - _places.get()[p].pre = offset; |
1537 | - offset += pre.size(); |
1538 | - _places.get()[p].post = offset; |
1539 | - offset += post.size(); |
1540 | - for (size_t tn = 0; tn < pre.size(); ++tn) { |
1541 | - _transitions.get()[tn + _places.get()[p].pre] = pre[tn]; |
1542 | - } |
1543 | - |
1544 | - for (size_t tn = 0; tn < post.size(); ++tn) { |
1545 | - _transitions.get()[tn + _places.get()[p].post] = post[tn]; |
1546 | - } |
1547 | - |
1548 | - } |
1549 | - assert(offset == ntrans); |
1550 | - _places.get()[p].pre = offset; |
1551 | - _places.get()[p].post = offset; |
1552 | - } |
1553 | - |
1554 | - void ReducingSuccessorGenerator::constructDependency() { |
1555 | - memset(_dependency.get(), 0, sizeof(uint32_t) * _net._ntransitions); |
1556 | - |
1557 | - for (uint32_t t = 0; t < _net._ntransitions; t++) { |
1558 | - uint32_t finv = _net._transitions[t].inputs; |
1559 | - uint32_t linv = _net._transitions[t].outputs; |
1560 | - |
1561 | - for (; finv < linv; finv++) { |
1562 | - const Invariant& inv = _net._invariants[finv]; |
1563 | - uint32_t p = inv.place; |
1564 | - uint32_t ntrans = (_places.get()[p + 1].pre - _places.get()[p].post); |
1565 | - |
1566 | - for (uint32_t tIndex = 0; tIndex < ntrans; tIndex++) { |
1567 | - ++_dependency[t]; |
1568 | - } |
1569 | - } |
1570 | - } |
1571 | - } |
1572 | - |
1573 | - void ReducingSuccessorGenerator::constructEnabled() { |
1574 | - _ordering.clear(); |
1575 | - for (uint32_t p = 0; p < _net._nplaces; ++p) { |
1576 | - // orphans are currently under "place 0" as a special case |
1577 | - if (p == 0 || (*_parent).marking()[p] > 0) { |
1578 | - uint32_t t = _net._placeToPtrs[p]; |
1579 | - uint32_t last = _net._placeToPtrs[p + 1]; |
1580 | - |
1581 | - for (; t != last; ++t) { |
1582 | - if (!checkPreset(t)) continue; |
1583 | - _enabled[t] = true; |
1584 | - _ordering.push_back(t); |
1585 | - } |
1586 | - } |
1587 | - } |
1588 | - } |
1589 | - |
1590 | - bool ReducingSuccessorGenerator::seenPre(uint32_t place) const |
1591 | - { |
1592 | - return (_places_seen.get()[place] & 1) != 0; |
1593 | - } |
1594 | - |
1595 | - bool ReducingSuccessorGenerator::seenPost(uint32_t place) const |
1596 | - { |
1597 | - return (_places_seen.get()[place] & 2) != 0; |
1598 | - } |
1599 | - |
1600 | - void ReducingSuccessorGenerator::presetOf(uint32_t place, bool make_closure) { |
1601 | - if((_places_seen.get()[place] & 1) != 0) return; |
1602 | - _places_seen.get()[place] = _places_seen.get()[place] | 1; |
1603 | - for (uint32_t t = _places.get()[place].pre; t < _places.get()[place].post; t++) |
1604 | - { |
1605 | - auto& tr = _transitions.get()[t]; |
1606 | - addToStub(tr.index); |
1607 | - } |
1608 | - if(make_closure) closure(); |
1609 | - } |
1610 | - |
1611 | - void ReducingSuccessorGenerator::postsetOf(uint32_t place, bool make_closure) { |
1612 | - if((_places_seen.get()[place] & 2) != 0) return; |
1613 | - _places_seen.get()[place] = _places_seen.get()[place] | 2; |
1614 | - for (uint32_t t = _places.get()[place].post; t < _places.get()[place + 1].pre; t++) { |
1615 | - auto tr = _transitions.get()[t]; |
1616 | - if(tr.direction < 0) |
1617 | - addToStub(tr.index); |
1618 | - } |
1619 | - if(make_closure) closure(); |
1620 | - } |
1621 | - |
1622 | - void ReducingSuccessorGenerator::addToStub(uint32_t t) |
1623 | - { |
1624 | - if(!_stubborn[t]) |
1625 | - { |
1626 | - _stubborn[t] = true; |
1627 | - _unprocessed.push_back(t); |
1628 | - } |
1629 | - } |
1630 | - |
1631 | - void ReducingSuccessorGenerator::inhibitorPostsetOf(uint32_t place){ |
1632 | - if((_places_seen.get()[place] & 4) != 0) return; |
1633 | - _places_seen.get()[place] = _places_seen.get()[place] | 4; |
1634 | - for(uint32_t& newstub : _inhibpost[place]) |
1635 | - addToStub(newstub); |
1636 | - } |
1637 | - |
1638 | - void ReducingSuccessorGenerator::postPresetOf(uint32_t t, bool make_closure) { |
1639 | - const TransPtr& ptr = _net._transitions[t]; |
1640 | - uint32_t finv = ptr.inputs; |
1641 | - uint32_t linv = ptr.outputs; |
1642 | - for (; finv < linv; finv++) { // pre-set of t |
1643 | - if(_net._invariants[finv].inhibitor){ |
1644 | - presetOf(_net._invariants[finv].place, make_closure); |
1645 | - } else { |
1646 | - postsetOf(_net._invariants[finv].place, make_closure); |
1647 | - } |
1648 | - } |
1649 | - } |
1650 | - |
1651 | - |
1652 | - void ReducingSuccessorGenerator::prepare(const Structures::State* state) { |
1653 | - _parent = state; |
1654 | - memset(_places_seen.get(), 0, _net.numberOfPlaces()); |
1655 | - constructEnabled(); |
1656 | - if(_ordering.size() == 0) return; |
1657 | - if(_ordering.size() == 1) |
1658 | - { |
1659 | - _stubborn[_ordering.front()] = true; |
1660 | - return; |
1661 | - } |
1662 | - for (auto &q : _queries) { |
1663 | - q->evalAndSet(PQL::EvaluationContext((*_parent).marking(), &_net)); |
1664 | - q->findInteresting(*this, false); |
1665 | - } |
1666 | - |
1667 | - closure(); |
1668 | - } |
1669 | - |
1670 | - void ReducingSuccessorGenerator::closure() |
1671 | - { |
1672 | - while (!_unprocessed.empty()) { |
1673 | - uint32_t tr = _unprocessed.front(); |
1674 | - _unprocessed.pop_front(); |
1675 | - const TransPtr& ptr = _net._transitions[tr]; |
1676 | - uint32_t finv = ptr.inputs; |
1677 | - uint32_t linv = ptr.outputs; |
1678 | - if(_enabled[tr]){ |
1679 | - for (; finv < linv; finv++) { |
1680 | - if(_net._invariants[finv].direction < 0) |
1681 | - { |
1682 | - auto place = _net._invariants[finv].place; |
1683 | - for (uint32_t t = _places.get()[place].post; t < _places.get()[place + 1].pre; t++) |
1684 | - addToStub(_transitions.get()[t].index); |
1685 | - } |
1686 | - } |
1687 | - if(_netContainsInhibitorArcs){ |
1688 | - uint32_t next_finv = _net._transitions[tr+1].inputs; |
1689 | - for (; linv < next_finv; linv++) |
1690 | - { |
1691 | - if(_net._invariants[linv].direction > 0) |
1692 | - inhibitorPostsetOf(_net._invariants[linv].place); |
1693 | - } |
1694 | - } |
1695 | - } else { |
1696 | - bool ok = false; |
1697 | - bool inhib = false; |
1698 | - uint32_t cand = std::numeric_limits<uint32_t>::max(); |
1699 | - |
1700 | - // Lets try to see if we havent already added sufficient pre/post |
1701 | - // for this transition. |
1702 | - for (; finv < linv; ++finv) { |
1703 | - const Invariant& inv = _net._invariants[finv]; |
1704 | - if ((*_parent).marking()[inv.place] < inv.tokens && !inv.inhibitor) { |
1705 | - inhib = false; |
1706 | - ok = (_places_seen.get()[inv.place] & 1) != 0; |
1707 | - cand = inv.place; |
1708 | - } else if ((*_parent).marking()[inv.place] >= inv.tokens && inv.inhibitor) { |
1709 | - inhib = true; |
1710 | - ok = (_places_seen.get()[inv.place] & 2) != 0; |
1711 | - cand = inv.place; |
1712 | - } |
1713 | - if(ok) break; |
1714 | - |
1715 | - } |
1716 | - |
1717 | - // OK, we didnt have sufficient, we just pick whatever is left |
1718 | - // in cand. |
1719 | - assert(cand != std::numeric_limits<uint32_t>::max()); |
1720 | - if(!ok && cand != std::numeric_limits<uint32_t>::max()) |
1721 | - { |
1722 | - if(!inhib) presetOf(cand); |
1723 | - else postsetOf(cand); |
1724 | - } |
1725 | - } |
1726 | - } |
1727 | - } |
1728 | - |
1729 | - bool ReducingSuccessorGenerator::next(Structures::State& write) { |
1730 | - while (!_ordering.empty()) { |
1731 | - _current = _ordering.front(); |
1732 | - _ordering.pop_front(); |
1733 | - if (_stubborn[_current]) { |
1734 | - assert(_enabled[_current]); |
1735 | - memcpy(write.marking(), (*_parent).marking(), _net._nplaces*sizeof(MarkVal)); |
1736 | - consumePreset(write, _current); |
1737 | - producePostset(write, _current); |
1738 | - return true; |
1739 | - } |
1740 | - } |
1741 | - reset(); |
1742 | - return false; |
1743 | - } |
1744 | - |
1745 | - uint32_t ReducingSuccessorGenerator::leastDependentEnabled() { |
1746 | - uint32_t tLeast = -1; |
1747 | - bool foundLeast = false; |
1748 | - for (uint32_t t = 0; t < _net._ntransitions; t++) { |
1749 | - if (_enabled[t]) { |
1750 | - if (!foundLeast) { |
1751 | - tLeast = t; |
1752 | - foundLeast = true; |
1753 | - } else { |
1754 | - if (_dependency[t] < _dependency[tLeast]) { |
1755 | - tLeast = t; |
1756 | - } |
1757 | - } |
1758 | - } |
1759 | - } |
1760 | - return tLeast; |
1761 | - } |
1762 | - |
1763 | void ReducingSuccessorGenerator::reset() { |
1764 | SuccessorGenerator::reset(); |
1765 | - memset(_enabled.get(), false, sizeof(bool) * _net._ntransitions); |
1766 | - memset(_stubborn.get(), false, sizeof(bool) * _net._ntransitions); |
1767 | - } |
1768 | + _stubSet->reset(); |
1769 | + } |
1770 | + |
1771 | + |
1772 | + bool ReducingSuccessorGenerator::next(Structures::State &write) { |
1773 | + _current = _stubSet->next(); |
1774 | + if (_current == std::numeric_limits<uint32_t>::max()) { |
1775 | + reset(); |
1776 | + return false; |
1777 | + } |
1778 | + memcpy(write.marking(), (*_parent).marking(), _net._nplaces * sizeof(MarkVal)); |
1779 | + consumePreset(write, _current); |
1780 | + producePostset(write, _current); |
1781 | + return true; |
1782 | + } |
1783 | + |
1784 | + void ReducingSuccessorGenerator::prepare(const Structures::State *state) { |
1785 | + _parent = state; |
1786 | + _stubSet->prepare(state); |
1787 | + } |
1788 | + |
1789 | + |
1790 | } |
1791 | |
1792 | === added directory 'src/PetriEngine/Stubborn' |
1793 | === added file 'src/PetriEngine/Stubborn/CMakeLists.txt' |
1794 | --- src/PetriEngine/Stubborn/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1795 | +++ src/PetriEngine/Stubborn/CMakeLists.txt 2021-03-04 07:47:28 +0000 |
1796 | @@ -0,0 +1,3 @@ |
1797 | +set(CMAKE_INCLUDE_CURRENT_DIR ON) |
1798 | + |
1799 | +add_library(Stubborn ReachabilityStubbornSet.cpp InterestingTransitionVisitor.cpp StubbornSet.cpp) |
1800 | |
1801 | === added file 'src/PetriEngine/Stubborn/InterestingTransitionVisitor.cpp' |
1802 | --- src/PetriEngine/Stubborn/InterestingTransitionVisitor.cpp 1970-01-01 00:00:00 +0000 |
1803 | +++ src/PetriEngine/Stubborn/InterestingTransitionVisitor.cpp 2021-03-04 07:47:28 +0000 |
1804 | @@ -0,0 +1,311 @@ |
1805 | +/* |
1806 | + * File: InterestingTransitionVisitor.cpp.cc |
1807 | + * Author: Nikolaj J. Ulrik <nikolaj@njulrik.dk> |
1808 | + * |
1809 | + * Created on 03/02/2021 |
1810 | + */ |
1811 | + |
1812 | +#include "PetriEngine/Stubborn/InterestingTransitionVisitor.h" |
1813 | + |
1814 | +namespace PetriEngine { |
1815 | + |
1816 | + void InterestingTransitionVisitor::_accept(const PQL::SimpleQuantifierCondition *element) { |
1817 | + (*element)[0]->visit(*this); |
1818 | + } |
1819 | + |
1820 | + void InterestingTransitionVisitor::_accept(const PQL::UntilCondition *element) { |
1821 | + element->getCond1()->visit(*this); |
1822 | + negate(); |
1823 | + element->getCond1()->visit(*this); |
1824 | + negate(); |
1825 | + element->getCond2()->visit(*this); |
1826 | + } |
1827 | + |
1828 | + |
1829 | + void InterestingTransitionVisitor::_accept(const PQL::AndCondition *element) { |
1830 | + if (!negated) { // and |
1831 | + for (auto &c : *element) { |
1832 | + if (!c->isSatisfied()) { |
1833 | + c->visit(*this); |
1834 | + break; |
1835 | + } |
1836 | + } |
1837 | + } else { // or |
1838 | + for (auto &c : *element) c->visit(*this); |
1839 | + } |
1840 | + } |
1841 | + |
1842 | + void InterestingTransitionVisitor::_accept(const PQL::OrCondition *element) { |
1843 | + if (!negated) { // or |
1844 | + for (auto &c : *element) c->visit(*this); |
1845 | + } else { // and |
1846 | + for (auto &c : *element) { |
1847 | + if (c->isSatisfied()) { |
1848 | + c->visit(*this); |
1849 | + break; |
1850 | + } |
1851 | + } |
1852 | + } |
1853 | + } |
1854 | + |
1855 | + void InterestingTransitionVisitor::_accept(const PQL::CompareConjunction *element) { |
1856 | + |
1857 | + auto neg = negated != element->isNegated(); |
1858 | + int32_t cand = std::numeric_limits<int32_t>::max(); |
1859 | + bool pre = false; |
1860 | + for (auto &c : *element) { |
1861 | + auto val = _stubborn.getParent()[c._place]; |
1862 | + if (c._lower == c._upper) { |
1863 | + if (neg) { |
1864 | + if (val != c._lower) continue; |
1865 | + _stubborn.postsetOf(c._place, true); |
1866 | + _stubborn.presetOf(c._place, true); |
1867 | + } else { |
1868 | + if (val == c._lower) continue; |
1869 | + if (val > c._lower) { |
1870 | + cand = c._place; |
1871 | + pre = false; |
1872 | + } else { |
1873 | + cand = c._place; |
1874 | + pre = true; |
1875 | + } |
1876 | + } |
1877 | + } else { |
1878 | + if (!neg) { |
1879 | + if (val < c._lower && c._lower != 0) { |
1880 | + assert(!neg); |
1881 | + cand = c._place; |
1882 | + pre = true; |
1883 | + } |
1884 | + |
1885 | + if (val > c._upper && c._upper != std::numeric_limits<uint32_t>::max()) { |
1886 | + assert(!neg); |
1887 | + cand = c._place; |
1888 | + pre = false; |
1889 | + } |
1890 | + } else { |
1891 | + if (val >= c._lower && c._lower != 0) { |
1892 | + _stubborn.postsetOf(c._place, true); |
1893 | + } |
1894 | + |
1895 | + if (val <= c._upper && c._upper != std::numeric_limits<uint32_t>::max()) { |
1896 | + _stubborn.presetOf(c._place, true); |
1897 | + } |
1898 | + } |
1899 | + } |
1900 | + if (cand != std::numeric_limits<int32_t>::max()) { |
1901 | + if (pre && _stubborn.seenPre(cand)) |
1902 | + return; |
1903 | + else if (!pre && _stubborn.seenPost(cand)) |
1904 | + return; |
1905 | + } |
1906 | + } |
1907 | + if (cand != std::numeric_limits<int32_t>::max()) { |
1908 | + if (pre) { |
1909 | + _stubborn.presetOf(cand, true); |
1910 | + } else if (!pre) { |
1911 | + _stubborn.postsetOf(cand, true); |
1912 | + } |
1913 | + } |
1914 | + } |
1915 | + |
1916 | + void InterestingTransitionVisitor::_accept(const PQL::EqualCondition *element) { |
1917 | + if (!negated) { // equal |
1918 | + if (element->getExpr1()->getEval() == element->getExpr2()->getEval()) { return; } |
1919 | + if (element->getExpr1()->getEval() > element->getExpr2()->getEval()) { |
1920 | + element->getExpr1()->visit(decr); |
1921 | + element->getExpr2()->visit(incr); |
1922 | + } else { |
1923 | + element->getExpr1()->visit(incr); |
1924 | + element->getExpr2()->visit(decr); |
1925 | + } |
1926 | + } else { // not equal |
1927 | + if (element->getExpr1()->getEval() != element->getExpr2()->getEval()) { return; } |
1928 | + element->getExpr1()->visit(incr); |
1929 | + element->getExpr1()->visit(decr); |
1930 | + element->getExpr2()->visit(incr); |
1931 | + element->getExpr2()->visit(decr); |
1932 | + } |
1933 | + } |
1934 | + |
1935 | + void InterestingTransitionVisitor::_accept(const PQL::NotEqualCondition *element) { |
1936 | + if (!negated) { // not equal |
1937 | + if (element->getExpr1()->getEval() != element->getExpr2()->getEval()) { return; } |
1938 | + element->getExpr1()->visit(incr); |
1939 | + element->getExpr1()->visit(decr); |
1940 | + element->getExpr2()->visit(incr); |
1941 | + element->getExpr2()->visit(decr); |
1942 | + } else { // equal |
1943 | + if (element->getExpr1()->getEval() == element->getExpr2()->getEval()) { return; } |
1944 | + if (element->getExpr1()->getEval() > element->getExpr2()->getEval()) { |
1945 | + element->getExpr1()->visit(decr); |
1946 | + element->getExpr2()->visit(incr); |
1947 | + } else { |
1948 | + element->getExpr1()->visit(incr); |
1949 | + element->getExpr2()->visit(decr); |
1950 | + } |
1951 | + } |
1952 | + } |
1953 | + |
1954 | + void InterestingTransitionVisitor::_accept(const PQL::LessThanCondition *element) { |
1955 | + if (!negated) { // less than |
1956 | + if (element->getExpr1()->getEval() < element->getExpr2()->getEval()) { return; } |
1957 | + element->getExpr1()->visit(decr); |
1958 | + element->getExpr2()->visit(incr); |
1959 | + } else { // greater than or equal |
1960 | + if (element->getExpr1()->getEval() >= element->getExpr2()->getEval()) { return; } |
1961 | + element->getExpr1()->visit(incr); |
1962 | + element->getExpr2()->visit(decr); |
1963 | + } |
1964 | + } |
1965 | + |
1966 | + void InterestingTransitionVisitor::_accept(const PQL::LessThanOrEqualCondition *element) { |
1967 | + if (!negated) { // less than or equal |
1968 | + if (element->getExpr1()->getEval() <= element->getExpr2()->getEval()) { return; } |
1969 | + element->getExpr1()->visit(decr); |
1970 | + element->getExpr2()->visit(incr); |
1971 | + } else { // greater than |
1972 | + if (element->getExpr1()->getEval() > element->getExpr2()->getEval()) { return; } |
1973 | + element->getExpr1()->visit(incr); |
1974 | + element->getExpr2()->visit(decr); |
1975 | + } |
1976 | + } |
1977 | + |
1978 | + void InterestingTransitionVisitor::_accept(const PQL::GreaterThanCondition *element) { |
1979 | + if (!negated) { // greater than |
1980 | + if (element->getExpr1()->getEval() > element->getExpr2()->getEval()) { return; } |
1981 | + element->getExpr1()->visit(incr); |
1982 | + element->getExpr2()->visit(decr); |
1983 | + } else { // less than or equal |
1984 | + if (element->getExpr1()->getEval() <= element->getExpr2()->getEval()) { return; } |
1985 | + element->getExpr1()->visit(decr); |
1986 | + element->getExpr2()->visit(incr); |
1987 | + } |
1988 | + } |
1989 | + |
1990 | + void |
1991 | + InterestingTransitionVisitor::_accept(const PQL::GreaterThanOrEqualCondition *element) { |
1992 | + if (!negated) { // greater than or equal |
1993 | + if (element->getExpr1()->getEval() >= element->getExpr2()->getEval()) { return; } |
1994 | + element->getExpr1()->visit(incr); |
1995 | + element->getExpr2()->visit(decr); |
1996 | + } else { // less than |
1997 | + if (element->getExpr1()->getEval() < element->getExpr2()->getEval()) { return; } |
1998 | + element->getExpr1()->visit(decr); |
1999 | + element->getExpr2()->visit(incr); |
2000 | + } |
2001 | + } |
2002 | + |
2003 | + void InterestingTransitionVisitor::_accept(const PQL::NotCondition *element) { |
2004 | + negate(); |
2005 | + element->visit(*this); |
2006 | + negate(); |
2007 | + } |
2008 | + |
2009 | + void InterestingTransitionVisitor::_accept(const PQL::BooleanCondition *element) { |
2010 | + // Add nothing |
2011 | + } |
2012 | + |
2013 | + void InterestingTransitionVisitor::_accept(const PQL::DeadlockCondition *element) { |
2014 | + if (!element->isSatisfied()) { |
2015 | + _stubborn.postPresetOf(_stubborn.leastDependentEnabled(), true); |
2016 | + } // else add nothing |
2017 | + } |
2018 | + |
2019 | + void |
2020 | + InterestingTransitionVisitor::_accept(const PQL::UnfoldedUpperBoundsCondition *element) { |
2021 | + for (auto &p : element->places()) |
2022 | + if (!p._maxed_out) |
2023 | + _stubborn.presetOf(p._place); |
2024 | + } |
2025 | + |
2026 | + void InterestingTransitionVisitor::IncrVisitor::_accept(const PQL::PlusExpr *element) { |
2027 | + for(auto& i : element->places()) _stubborn.presetOf(i.first, true); |
2028 | + for(auto& e : element->expressions()) e->visit(*this); |
2029 | + } |
2030 | + |
2031 | + void InterestingTransitionVisitor::DecrVisitor::_accept(const PQL::PlusExpr *element) { |
2032 | + for(auto& i : element->places()) _stubborn.postsetOf(i.first, true); |
2033 | + for(auto& e : element->expressions()) e->visit(*this); |
2034 | + } |
2035 | + |
2036 | + void InterestingTransitionVisitor::IncrVisitor::_accept(const PQL::SubtractExpr *element) { |
2037 | + bool first = true; |
2038 | + for(auto& e : element->expressions()) |
2039 | + { |
2040 | + if(first) |
2041 | + e->visit(*this); |
2042 | + else |
2043 | + e->visit(*decr); |
2044 | + first = false; |
2045 | + } |
2046 | + } |
2047 | + |
2048 | + void InterestingTransitionVisitor::DecrVisitor::_accept(const PQL::SubtractExpr *element) { |
2049 | + bool first = true; |
2050 | + for(auto& e : element->expressions()) |
2051 | + { |
2052 | + if(first) |
2053 | + e->visit(*this); |
2054 | + else |
2055 | + e->visit(*incr); |
2056 | + first = false; |
2057 | + } |
2058 | + } |
2059 | + |
2060 | + void InterestingTransitionVisitor::IncrVisitor::_accept(const PQL::MultiplyExpr *element) { |
2061 | + if((element->places().size() + element->expressions().size()) == 1) |
2062 | + { |
2063 | + for(auto& i : element->places()) _stubborn.presetOf(i.first, true); |
2064 | + for(auto& e : element->expressions()) e->visit(*this); |
2065 | + } |
2066 | + else |
2067 | + { |
2068 | + for(auto& i : element->places()) |
2069 | + { |
2070 | + _stubborn.presetOf(i.first, true); |
2071 | + _stubborn.postsetOf(i.first, true); |
2072 | + } |
2073 | + for(auto& e : element->expressions()) |
2074 | + { |
2075 | + e->visit(*this); |
2076 | + e->visit(*decr); |
2077 | + } |
2078 | + } |
2079 | + } |
2080 | + |
2081 | + void InterestingTransitionVisitor::DecrVisitor::_accept(const PQL::MultiplyExpr *element) { |
2082 | + if((element->places().size() + element->expressions().size()) == 1) |
2083 | + { |
2084 | + for(auto& i : element->places()) _stubborn.postsetOf(i.first, true); |
2085 | + for(auto& e : element->expressions()) e->visit(*this); |
2086 | + } |
2087 | + else |
2088 | + element->visit(*incr); |
2089 | + } |
2090 | + |
2091 | + void InterestingTransitionVisitor::IncrVisitor::_accept(const PQL::MinusExpr *element) { |
2092 | + // TODO not implemented |
2093 | + } |
2094 | + |
2095 | + void InterestingTransitionVisitor::DecrVisitor::_accept(const PQL::MinusExpr *element) { |
2096 | + // TODO not implemented |
2097 | + } |
2098 | + |
2099 | + void InterestingTransitionVisitor::IncrVisitor::_accept(const PQL::LiteralExpr *element) { |
2100 | + // Add nothing |
2101 | + } |
2102 | + |
2103 | + void InterestingTransitionVisitor::DecrVisitor::_accept(const PQL::LiteralExpr *element) { |
2104 | + // Add nothing |
2105 | + } |
2106 | + |
2107 | + void InterestingTransitionVisitor::IncrVisitor::_accept(const PQL::UnfoldedIdentifierExpr *element) { |
2108 | + _stubborn.presetOf(element->offset(), true); |
2109 | + } |
2110 | + |
2111 | + void InterestingTransitionVisitor::DecrVisitor::_accept(const PQL::UnfoldedIdentifierExpr *element) { |
2112 | + _stubborn.postsetOf(element->offset(), true); |
2113 | + } |
2114 | + |
2115 | +} |
2116 | \ No newline at end of file |
2117 | |
2118 | === added file 'src/PetriEngine/Stubborn/ReachabilityStubbornSet.cpp' |
2119 | --- src/PetriEngine/Stubborn/ReachabilityStubbornSet.cpp 1970-01-01 00:00:00 +0000 |
2120 | +++ src/PetriEngine/Stubborn/ReachabilityStubbornSet.cpp 2021-03-04 07:47:28 +0000 |
2121 | @@ -0,0 +1,41 @@ |
2122 | +/* Copyright (C) 2021 Nikolaj J. Ulrik <nikolaj@njulrik.dk>, |
2123 | + * Simon M. Virenfeldt <simon@simwir.dk> |
2124 | + * |
2125 | + * This program is free software: you can redistribute it and/or modify |
2126 | + * it under the terms of the GNU General Public License as published by |
2127 | + * the Free Software Foundation, either version 3 of the License, or |
2128 | + * (at your option) any later version. |
2129 | + * |
2130 | + * This program is distributed in the hope that it will be useful, |
2131 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2132 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2133 | + * GNU General Public License for more details. |
2134 | + * |
2135 | + * You should have received a copy of the GNU General Public License |
2136 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2137 | + */ |
2138 | + |
2139 | +#include "PetriEngine/Stubborn/ReachabilityStubbornSet.h" |
2140 | +#include "PetriEngine/Stubborn/InterestingTransitionVisitor.h" |
2141 | +#include "PetriEngine/PQL/Contexts.h" |
2142 | + |
2143 | +namespace PetriEngine { |
2144 | + void ReachabilityStubbornSet::prepare(const Structures::State *state) { |
2145 | + _parent = state; |
2146 | + memset(_places_seen.get(), 0, _net.numberOfPlaces()); |
2147 | + constructEnabled(); |
2148 | + if (_ordering.size() == 0) return; |
2149 | + if (_ordering.size() == 1) { |
2150 | + _stubborn[_ordering.front()] = true; |
2151 | + return; |
2152 | + } |
2153 | + for (auto &q : _queries) { |
2154 | + q->evalAndSet(PQL::EvaluationContext((*_parent).marking(), &_net)); |
2155 | + InterestingTransitionVisitor interesting{*this}; |
2156 | + |
2157 | + q->visit(interesting); |
2158 | + } |
2159 | + |
2160 | + closure(); |
2161 | + } |
2162 | +} |
2163 | |
2164 | === added file 'src/PetriEngine/Stubborn/StubbornSet.cpp' |
2165 | --- src/PetriEngine/Stubborn/StubbornSet.cpp 1970-01-01 00:00:00 +0000 |
2166 | +++ src/PetriEngine/Stubborn/StubbornSet.cpp 2021-03-04 07:47:28 +0000 |
2167 | @@ -0,0 +1,302 @@ |
2168 | +/* Copyright (C) 2021 Nikolaj J. Ulrik <nikolaj@njulrik.dk>, |
2169 | + * Simon M. Virenfeldt <simon@simwir.dk> |
2170 | + * |
2171 | + * This program is free software: you can redistribute it and/or modify |
2172 | + * it under the terms of the GNU General Public License as published by |
2173 | + * the Free Software Foundation, either version 3 of the License, or |
2174 | + * (at your option) any later version. |
2175 | + * |
2176 | + * This program is distributed in the hope that it will be useful, |
2177 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2178 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2179 | + * GNU General Public License for more details. |
2180 | + * |
2181 | + * You should have received a copy of the GNU General Public License |
2182 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2183 | + */ |
2184 | + |
2185 | + |
2186 | +#include <PetriEngine/Stubborn/InterestingTransitionVisitor.h> |
2187 | +#include "PetriEngine/Stubborn/StubbornSet.h" |
2188 | +#include "PetriEngine/PQL/Contexts.h" |
2189 | + |
2190 | +namespace PetriEngine { |
2191 | + uint32_t StubbornSet::next() { |
2192 | + while (!_ordering.empty()) { |
2193 | + _current = _ordering.front(); |
2194 | + _ordering.pop_front(); |
2195 | + if (_stubborn[_current] && _enabled[_current]) { |
2196 | + return _current; |
2197 | + } |
2198 | + } |
2199 | + reset(); |
2200 | + return std::numeric_limits<uint32_t>::max(); |
2201 | + } |
2202 | + |
2203 | + bool StubbornSet::checkPreset(uint32_t t) { |
2204 | + const TransPtr &ptr = transitions()[t]; |
2205 | + uint32_t finv = ptr.inputs; |
2206 | + uint32_t linv = ptr.outputs; |
2207 | + |
2208 | + for (; finv < linv; ++finv) { |
2209 | + const Invariant &inv = _net._invariants[finv]; |
2210 | + if (_parent->marking()[inv.place] < inv.tokens) { |
2211 | + if (!inv.inhibitor) { |
2212 | + return false; |
2213 | + } |
2214 | + } else { |
2215 | + if (inv.inhibitor) { |
2216 | + return false; |
2217 | + } |
2218 | + } |
2219 | + } |
2220 | + return true; |
2221 | + } |
2222 | + |
2223 | + bool StubbornSet::seenPre(uint32_t place) const { |
2224 | + return (_places_seen.get()[place] & 1) != 0; |
2225 | + } |
2226 | + |
2227 | + bool StubbornSet::seenPost(uint32_t place) const { |
2228 | + return (_places_seen.get()[place] & 2) != 0; |
2229 | + } |
2230 | + |
2231 | + void StubbornSet::presetOf(uint32_t place, bool make_closure) { |
2232 | + if ((_places_seen.get()[place] & 1) != 0) return; |
2233 | + _places_seen.get()[place] = _places_seen.get()[place] | 1; |
2234 | + for (uint32_t t = _places.get()[place].pre; t < _places.get()[place].post; t++) { |
2235 | + auto &tr = _transitions.get()[t]; |
2236 | + addToStub(tr.index); |
2237 | + } |
2238 | + if (make_closure) closure(); |
2239 | + } |
2240 | + |
2241 | + void StubbornSet::postsetOf(uint32_t place, bool make_closure) { |
2242 | + if ((_places_seen.get()[place] & 2) != 0) return; |
2243 | + _places_seen.get()[place] = _places_seen.get()[place] | 2; |
2244 | + for (uint32_t t = _places.get()[place].post; t < _places.get()[place + 1].pre; t++) { |
2245 | + auto tr = _transitions.get()[t]; |
2246 | + if (tr.direction < 0) |
2247 | + addToStub(tr.index); |
2248 | + } |
2249 | + if (make_closure) closure(); |
2250 | + } |
2251 | + |
2252 | + void StubbornSet::inhibitorPostsetOf(uint32_t place) { |
2253 | + if ((_places_seen.get()[place] & 4) != 0) return; |
2254 | + _places_seen.get()[place] = _places_seen.get()[place] | 4; |
2255 | + for (uint32_t &newstub : _inhibpost[place]) |
2256 | + addToStub(newstub); |
2257 | + } |
2258 | + |
2259 | + void StubbornSet::postPresetOf(uint32_t t, bool make_closure) { |
2260 | + const TransPtr &ptr = transitions()[t]; |
2261 | + uint32_t finv = ptr.inputs; |
2262 | + uint32_t linv = ptr.outputs; |
2263 | + for (; finv < linv; finv++) { // pre-set of t |
2264 | + if (invariants()[finv].inhibitor) { |
2265 | + presetOf(invariants()[finv].place, make_closure); |
2266 | + } else { |
2267 | + postsetOf(invariants()[finv].place, make_closure); |
2268 | + } |
2269 | + } |
2270 | + } |
2271 | + |
2272 | + void StubbornSet::constructEnabled() { |
2273 | + _ordering.clear(); |
2274 | + for (uint32_t p = 0; p < _net.numberOfPlaces(); ++p) { |
2275 | + // orphans are currently under "place 0" as a special case |
2276 | + if (p == 0 || _parent->marking()[p] > 0) { |
2277 | + uint32_t t = placeToPtrs()[p]; |
2278 | + uint32_t last = placeToPtrs()[p + 1]; |
2279 | + |
2280 | + for (; t != last; ++t) { |
2281 | + if (!checkPreset(t)) continue; |
2282 | + _enabled[t] = true; |
2283 | + _ordering.push_back(t); |
2284 | + } |
2285 | + } |
2286 | + } |
2287 | + } |
2288 | + |
2289 | + void StubbornSet::checkForInhibitor() { |
2290 | + _netContainsInhibitorArcs = false; |
2291 | + for (uint32_t t = 0; t < _net._ntransitions; t++) { |
2292 | + const TransPtr &ptr = _net._transitions[t]; |
2293 | + uint32_t finv = ptr.inputs; |
2294 | + uint32_t linv = ptr.outputs; |
2295 | + for (; finv < linv; finv++) { // Post set of places |
2296 | + if (_net._invariants[finv].inhibitor) { |
2297 | + _netContainsInhibitorArcs = true; |
2298 | + return; |
2299 | + } |
2300 | + } |
2301 | + } |
2302 | + } |
2303 | + |
2304 | + void StubbornSet::constructPrePost() { |
2305 | + std::vector<std::pair<std::vector<trans_t>, std::vector<trans_t>>> tmp_places(_net._nplaces); |
2306 | + |
2307 | + for (uint32_t t = 0; t < _net._ntransitions; t++) { |
2308 | + const TransPtr &ptr = _net._transitions[t]; |
2309 | + uint32_t finv = ptr.inputs; |
2310 | + uint32_t linv = ptr.outputs; |
2311 | + for (; finv < linv; finv++) { // Post set of places |
2312 | + if (_net._invariants[finv].inhibitor) { |
2313 | + _inhibpost[_net._invariants[finv].place].push_back(t); |
2314 | + _netContainsInhibitorArcs = true; |
2315 | + } else { |
2316 | + tmp_places[_net._invariants[finv].place].second.emplace_back(t, _net._invariants[finv].direction); |
2317 | + } |
2318 | + } |
2319 | + |
2320 | + finv = linv; |
2321 | + linv = _net._transitions[t + 1].inputs; |
2322 | + for (; finv < linv; finv++) { // Pre set of places |
2323 | + if (_net._invariants[finv].direction > 0) |
2324 | + tmp_places[_net._invariants[finv].place].first.emplace_back(t, _net._invariants[finv].direction); |
2325 | + } |
2326 | + } |
2327 | + |
2328 | + // flatten |
2329 | + size_t ntrans = 0; |
2330 | + for (auto p : tmp_places) { |
2331 | + ntrans += p.first.size() + p.second.size(); |
2332 | + } |
2333 | + _transitions.reset(new trans_t[ntrans]); |
2334 | + |
2335 | + _places.reset(new place_t[_net._nplaces + 1]); |
2336 | + uint32_t offset = 0; |
2337 | + uint32_t p = 0; |
2338 | + for (; p < _net._nplaces; ++p) { |
2339 | + auto &pre = tmp_places[p].first; |
2340 | + auto &post = tmp_places[p].second; |
2341 | + |
2342 | + // keep things nice for caches |
2343 | + std::sort(pre.begin(), pre.end()); |
2344 | + std::sort(post.begin(), post.end()); |
2345 | + |
2346 | + _places.get()[p].pre = offset; |
2347 | + offset += pre.size(); |
2348 | + _places.get()[p].post = offset; |
2349 | + offset += post.size(); |
2350 | + for (size_t tn = 0; tn < pre.size(); ++tn) { |
2351 | + _transitions.get()[tn + _places.get()[p].pre] = pre[tn]; |
2352 | + } |
2353 | + |
2354 | + for (size_t tn = 0; tn < post.size(); ++tn) { |
2355 | + _transitions.get()[tn + _places.get()[p].post] = post[tn]; |
2356 | + } |
2357 | + |
2358 | + } |
2359 | + assert(offset == ntrans); |
2360 | + _places.get()[p].pre = offset; |
2361 | + _places.get()[p].post = offset; |
2362 | + } |
2363 | + |
2364 | + void StubbornSet::constructDependency() { |
2365 | + memset(_dependency.get(), 0, sizeof(uint32_t) * _net._ntransitions); |
2366 | + |
2367 | + for (uint32_t t = 0; t < _net._ntransitions; t++) { |
2368 | + uint32_t finv = _net._transitions[t].inputs; |
2369 | + uint32_t linv = _net._transitions[t].outputs; |
2370 | + |
2371 | + for (; finv < linv; finv++) { |
2372 | + const Invariant &inv = _net._invariants[finv]; |
2373 | + uint32_t p = inv.place; |
2374 | + uint32_t ntrans = (_places.get()[p + 1].pre - _places.get()[p].post); |
2375 | + |
2376 | + for (uint32_t tIndex = 0; tIndex < ntrans; tIndex++) { |
2377 | + ++_dependency[t]; |
2378 | + } |
2379 | + } |
2380 | + } |
2381 | + } |
2382 | + |
2383 | + |
2384 | + void StubbornSet::addToStub(uint32_t t) { |
2385 | + if (!_stubborn[t]) { |
2386 | + _stubborn[t] = true; |
2387 | + _unprocessed.push_back(t); |
2388 | + } |
2389 | + } |
2390 | + |
2391 | + void StubbornSet::closure() { |
2392 | + while (!_unprocessed.empty()) { |
2393 | + uint32_t tr = _unprocessed.front(); |
2394 | + _unprocessed.pop_front(); |
2395 | + const TransPtr &ptr = transitions()[tr]; |
2396 | + uint32_t finv = ptr.inputs; |
2397 | + uint32_t linv = ptr.outputs; |
2398 | + if (_enabled[tr]) { |
2399 | + for (; finv < linv; finv++) { |
2400 | + if (invariants()[finv].direction < 0) { |
2401 | + auto place = invariants()[finv].place; |
2402 | + for (uint32_t t = _places.get()[place].post; t < _places.get()[place + 1].pre; t++) |
2403 | + addToStub(_transitions.get()[t].index); |
2404 | + } |
2405 | + } |
2406 | + if (_netContainsInhibitorArcs) { |
2407 | + uint32_t next_finv = transitions()[tr + 1].inputs; |
2408 | + for (; linv < next_finv; linv++) { |
2409 | + if (invariants()[linv].direction > 0) |
2410 | + inhibitorPostsetOf(invariants()[linv].place); |
2411 | + } |
2412 | + } |
2413 | + } else { |
2414 | + bool ok = false; |
2415 | + bool inhib = false; |
2416 | + uint32_t cand = std::numeric_limits<uint32_t>::max(); |
2417 | + |
2418 | + // Lets try to see if we havent already added sufficient pre/post |
2419 | + // for this transition. |
2420 | + for (; finv < linv; ++finv) { |
2421 | + const Invariant &inv = invariants()[finv]; |
2422 | + if ((*_parent).marking()[inv.place] < inv.tokens && !inv.inhibitor) { |
2423 | + inhib = false; |
2424 | + ok = (_places_seen.get()[inv.place] & 1) != 0; |
2425 | + cand = inv.place; |
2426 | + } else if ((*_parent).marking()[inv.place] >= inv.tokens && inv.inhibitor) { |
2427 | + inhib = true; |
2428 | + ok = (_places_seen.get()[inv.place] & 2) != 0; |
2429 | + cand = inv.place; |
2430 | + } |
2431 | + if (ok) break; |
2432 | + |
2433 | + } |
2434 | + |
2435 | + // OK, we didnt have sufficient, we just pick whatever is left |
2436 | + // in cand. |
2437 | + assert(cand != std::numeric_limits<uint32_t>::max()); |
2438 | + if (!ok && cand != std::numeric_limits<uint32_t>::max()) { |
2439 | + if (!inhib) presetOf(cand); |
2440 | + else postsetOf(cand); |
2441 | + } |
2442 | + } |
2443 | + } |
2444 | + } |
2445 | + |
2446 | + uint32_t StubbornSet::leastDependentEnabled() { |
2447 | + uint32_t tLeast = -1; |
2448 | + bool foundLeast = false; |
2449 | + for (uint32_t t = 0; t < _net.numberOfTransitions(); t++) { |
2450 | + if (_enabled[t]) { |
2451 | + if (!foundLeast) { |
2452 | + tLeast = t; |
2453 | + foundLeast = true; |
2454 | + } else { |
2455 | + if (_dependency[t] < _dependency[tLeast]) { |
2456 | + tLeast = t; |
2457 | + } |
2458 | + } |
2459 | + } |
2460 | + } |
2461 | + return tLeast; |
2462 | + } |
2463 | + |
2464 | + void StubbornSet::reset() { |
2465 | + memset(_enabled.get(), false, sizeof(bool) * _net.numberOfTransitions()); |
2466 | + memset(_stubborn.get(), false, sizeof(bool) * _net.numberOfTransitions()); |
2467 | + _tid = 0; |
2468 | + } |
2469 | +} |
2470 | |
2471 | === modified file 'src/PetriParse/QueryXMLParser.cpp' |
2472 | --- src/PetriParse/QueryXMLParser.cpp 2020-03-13 13:36:32 +0000 |
2473 | +++ src/PetriParse/QueryXMLParser.cpp 2021-03-04 07:47:28 +0000 |
2474 | @@ -569,7 +569,7 @@ |
2475 | return nullptr; |
2476 | } |
2477 | |
2478 | -string QueryXMLParser::parsePlace(rapidxml::xml_node<>* element) { |
2479 | +std::string QueryXMLParser::parsePlace(rapidxml::xml_node<>* element) { |
2480 | if (strcmp(element->name(), "place") != 0) return ""; // missing place tag |
2481 | string placeName = element->value(); |
2482 | placeName.erase(std::remove_if(placeName.begin(), placeName.end(), ::isspace), placeName.end()); |