Merge lp:~verifypn-stub/verifypn/ctl-structural into lp:verifypn

Proposed by Peter Gjøl Jensen
Status: Merged
Approved by: Jiri Srba
Approved revision: 224
Merged at revision: 193
Proposed branch: lp:~verifypn-stub/verifypn/ctl-structural
Merge into: lp:verifypn
Diff against target: 872 lines (+240/-109)
16 files modified
CTL/CTLEngine.cpp (+2/-2)
CTL/CTLEngine.h (+1/-0)
CTL/PetriNets/OnTheFlyDG.cpp (+21/-22)
CTL/PetriNets/OnTheFlyDG.h (+26/-4)
PetriEngine/PQL/Expressions.cpp (+4/-2)
PetriEngine/PQL/Expressions.h (+15/-2)
PetriEngine/PQL/PQL.h (+1/-1)
PetriEngine/PetriNetBuilder.cpp (+2/-1)
PetriEngine/PetriNetBuilder.h (+4/-0)
PetriEngine/Reducer.cpp (+110/-45)
PetriEngine/Reducer.h (+7/-2)
PetriEngine/ReducingSuccessorGenerator.cpp (+9/-1)
PetriEngine/ReducingSuccessorGenerator.h (+4/-2)
PetriEngine/Structures/light_deque.h (+5/-0)
PetriEngine/SuccessorGenerator.h (+2/-1)
VerifyPN.cpp (+27/-24)
To merge this branch: bzr merge lp:~verifypn-stub/verifypn/ctl-structural
Reviewer Review Type Date Requested Status
Jiri Srba Approve
Review via email: mp+335697@code.launchpad.net

Description of the change

Adds structural reductions to the CTL verification -- only enabled if the formulas are next-free.
Also adds partial order reduction to EF leafs in CTL verification, although only yielding a minor speedup.

Consistent on 2017 models.
Improvements;

CTLCardinality:
r180: 3916
r187: 3922
r188: 3999
trunk: 4154
this: 4201

CTLFireability:
r180: 3111
r187: 3171
r188: 3248
trunk: 3575
this: 3655

To post a comment you must log in.
Revision history for this message
Jiri Srba (srba) wrote :

The switch that disables partial order reduction should be active also
for CTL verification for EF and AG leafs.

review: Needs Fixing
224. By Peter Gjøl Jensen

propagating switch for po-reduction to ctl-engine

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

Please, fix the warning:

CTL/PetriNets/OnTheFlyDG.cpp:24:9: warning: field '_redgen' will be initialized after field
      '_partial_order' [-Wreorder]
        _redgen(*t_net), _partial_order(partial_order) {
        ^

review: Needs Fixing
225. By Peter Gjøl Jensen

fixed reorder warning

Revision history for this message
Jiri Srba (srba) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CTL/CTLEngine.cpp'
--- CTL/CTLEngine.cpp 2017-12-04 13:45:29 +0000
+++ CTL/CTLEngine.cpp 2018-01-04 10:26:07 +0000
@@ -66,7 +66,6 @@
66 cout << " Processed Edges : " << result.processedEdges << endl;66 cout << " Processed Edges : " << result.processedEdges << endl;
67 cout << " Processed N. Edges: " << result.processedNegationEdges << endl;67 cout << " Processed N. Edges: " << result.processedNegationEdges << endl;
68 cout << " Explored Configs : " << result.exploredConfigurations << endl;68 cout << " Explored Configs : " << result.exploredConfigurations << endl;
69 if(!only_stats) result.query->toString(cout);
70 std::cout << endl;69 std::cout << endl;
71 }70 }
72}71}
@@ -77,6 +76,7 @@
77 bool gamemode,76 bool gamemode,
78 bool printstatistics,77 bool printstatistics,
79 bool mccoutput,78 bool mccoutput,
79 bool partial_order,
80 const std::vector<std::string>& querynames,80 const std::vector<std::string>& querynames,
81 const std::vector<std::shared_ptr<Condition>>& queries,81 const std::vector<std::shared_ptr<Condition>>& queries,
82 const std::vector<size_t>& querynumbers82 const std::vector<size_t>& querynumbers
@@ -90,7 +90,7 @@
9090
91 for(auto qnum : querynumbers){91 for(auto qnum : querynumbers){
92 CTLResult result(queries[qnum]);92 CTLResult result(queries[qnum]);
93 PetriNets::OnTheFlyDG graph(net); 93 PetriNets::OnTheFlyDG graph(net, partial_order);
94 graph.setQuery(result.query);94 graph.setQuery(result.query);
95 std::shared_ptr<Algorithm::FixedPointAlgorithm> alg = nullptr;95 std::shared_ptr<Algorithm::FixedPointAlgorithm> alg = nullptr;
96 bool solved = false;96 bool solved = false;
9797
=== modified file 'CTL/CTLEngine.h'
--- CTL/CTLEngine.h 2017-11-26 13:43:04 +0000
+++ CTL/CTLEngine.h 2018-01-04 10:26:07 +0000
@@ -16,6 +16,7 @@
16 bool gamemode,16 bool gamemode,
17 bool printstatistics,17 bool printstatistics,
18 bool mccoutput,18 bool mccoutput,
19 bool partial_order,
19 const std::vector<std::string>& querynames,20 const std::vector<std::string>& querynames,
20 const std::vector<std::shared_ptr<PetriEngine::PQL::Condition>>& reducedQueries,21 const std::vector<std::shared_ptr<PetriEngine::PQL::Condition>>& reducedQueries,
21 const std::vector<size_t>& ids);22 const std::vector<size_t>& ids);
2223
=== modified file 'CTL/PetriNets/OnTheFlyDG.cpp'
--- CTL/PetriNets/OnTheFlyDG.cpp 2017-11-29 21:20:21 +0000
+++ CTL/PetriNets/OnTheFlyDG.cpp 2018-01-04 10:26:07 +0000
@@ -18,9 +18,10 @@
1818
19namespace PetriNets {19namespace PetriNets {
2020
21OnTheFlyDG::OnTheFlyDG(PetriEngine::PetriNet *t_net) : encoder(t_net->numberOfPlaces(), 0), 21OnTheFlyDG::OnTheFlyDG(PetriEngine::PetriNet *t_net, bool partial_order) : encoder(t_net->numberOfPlaces(), 0),
22 edge_alloc(new linked_bucket_t<DependencyGraph::Edge,1024*10>(1)), 22 edge_alloc(new linked_bucket_t<DependencyGraph::Edge,1024*10>(1)),
23 conf_alloc(new linked_bucket_t<char[sizeof(PetriConfig)], 1024*1024>(1)) {23 conf_alloc(new linked_bucket_t<char[sizeof(PetriConfig)], 1024*1024>(1)),
24 _redgen(*t_net), _partial_order(partial_order) {
24 net = t_net;25 net = t_net;
25 n_places = t_net->numberOfPlaces();26 n_places = t_net->numberOfPlaces();
26 n_transitions = t_net->numberOfTransitions();27 n_transitions = t_net->numberOfTransitions();
@@ -37,7 +38,6 @@
37 {38 {
38 ((PetriConfig*)&(*conf_alloc)[i])->~PetriConfig();39 ((PetriConfig*)&(*conf_alloc)[i])->~PetriConfig();
39 }40 }
40 std::cout << "NEDGES " << edge_alloc->size() << std::endl;
41 delete conf_alloc;41 delete conf_alloc;
42 delete edge_alloc;42 delete edge_alloc;
43}43}
@@ -176,7 +176,7 @@
176 if (valid || left != NULL) {176 if (valid || left != NULL) {
177 //if left side is guaranteed to be not satisfied, skip successor generation177 //if left side is guaranteed to be not satisfied, skip successor generation
178 Edge* leftEdge = NULL;178 Edge* leftEdge = NULL;
179 nextStates (query_marking,179 nextStates (query_marking, cond,
180 [&](){ leftEdge = newEdge(*v, std::numeric_limits<uint32_t>::max());},180 [&](){ leftEdge = newEdge(*v, std::numeric_limits<uint32_t>::max());},
181 [&](Marking& mark){181 [&](Marking& mark){
182 auto res = fastEval(cond, &mark);182 auto res = fastEval(cond, &mark);
@@ -227,7 +227,7 @@
227 subquery->addTarget(c);227 subquery->addTarget(c);
228 }228 }
229 Edge* e1 = NULL;229 Edge* e1 = NULL;
230 nextStates(query_marking,230 nextStates(query_marking, cond,
231 [&](){e1 = newEdge(*v, std::numeric_limits<uint32_t>::max());},231 [&](){e1 = newEdge(*v, std::numeric_limits<uint32_t>::max());},
232 [&](Marking& mark)232 [&](Marking& mark)
233 {233 {
@@ -264,7 +264,7 @@
264 auto cond = static_cast<AXCondition*>(v->query);264 auto cond = static_cast<AXCondition*>(v->query);
265 Edge* e = newEdge(*v, std::numeric_limits<uint32_t>::max());265 Edge* e = newEdge(*v, std::numeric_limits<uint32_t>::max());
266 Condition::Result allValid = Condition::RTRUE;266 Condition::Result allValid = Condition::RTRUE;
267 nextStates(query_marking, 267 nextStates(query_marking, cond,
268 [](){}, 268 [](){},
269 [&](Marking& mark){269 [&](Marking& mark){
270 auto res = fastEval((*cond)[0], &mark);270 auto res = fastEval((*cond)[0], &mark);
@@ -326,7 +326,7 @@
326326
327 Configuration *left = NULL;327 Configuration *left = NULL;
328 bool valid = false;328 bool valid = false;
329 nextStates(query_marking, 329 nextStates(query_marking, cond,
330 [&](){330 [&](){
331 auto r0 = fastEval((*cond)[0], &query_marking);331 auto r0 = fastEval((*cond)[0], &query_marking);
332 if (r0 == Condition::RUNKNOWN) {332 if (r0 == Condition::RUNKNOWN) {
@@ -389,7 +389,7 @@
389 subquery->addTarget(c);389 subquery->addTarget(c);
390 }390 }
391391
392 nextStates(query_marking,392 nextStates(query_marking, cond,
393 [](){},393 [](){},
394 [&](Marking& mark){394 [&](Marking& mark){
395 auto res = fastEval(cond, &mark);395 auto res = fastEval(cond, &mark);
@@ -424,7 +424,7 @@
424 else if(v->query->getPath() == X){424 else if(v->query->getPath() == X){
425 auto cond = static_cast<EXCondition*>(v->query);425 auto cond = static_cast<EXCondition*>(v->query);
426 auto query = (*cond)[0];426 auto query = (*cond)[0];
427 nextStates(query_marking, 427 nextStates(query_marking, cond,
428 [](){}, 428 [](){},
429 [&](Marking& marking) {429 [&](Marking& marking) {
430 auto res = fastEval(query, &marking);430 auto res = fastEval(query, &marking);
@@ -478,25 +478,24 @@
478 return initial_config;478 return initial_config;
479}479}
480480
481void OnTheFlyDG::nextStates(Marking& t_marking, 481
482void OnTheFlyDG::nextStates(Marking& t_marking, Condition* ptr,
482 std::function<void ()> pre, 483 std::function<void ()> pre,
483 std::function<bool (Marking&)> foreach, 484 std::function<bool (Marking&)> foreach,
484 std::function<void ()> post)485 std::function<void ()> post)
485{486{
486
487 bool first = true;487 bool first = true;
488 PetriEngine::SuccessorGenerator PNGen(*net);
489 PNGen.prepare(&query_marking);
490 memcpy(working_marking.marking(), query_marking.marking(), n_places*sizeof(PetriEngine::MarkVal)); 488 memcpy(working_marking.marking(), query_marking.marking(), n_places*sizeof(PetriEngine::MarkVal));
491489 auto qf = static_cast<QuantifierCondition*>(ptr);
492 490 if(!_partial_order || ptr->getQuantifier() != E || ptr->getPath() != F || (*qf)[0]->isTemporal())
493 while(PNGen.next(working_marking)){491 {
494 if(first) pre();492 PetriEngine::SuccessorGenerator PNGen(*net);
495 first = false;493 dowork<PetriEngine::SuccessorGenerator>(PNGen, first, pre, foreach);
496 if(!foreach(working_marking))494 }
497 {495 else
498 break;496 {
499 }497 _redgen.setQuery(ptr);
498 dowork<PetriEngine::ReducingSuccessorGenerator>(_redgen, first, pre, foreach);
500 }499 }
501500
502 if(!first) post();501 if(!first) post();
503502
=== modified file 'CTL/PetriNets/OnTheFlyDG.h'
--- CTL/PetriNets/OnTheFlyDG.h 2017-11-26 22:46:37 +0000
+++ CTL/PetriNets/OnTheFlyDG.h 2018-01-04 10:26:07 +0000
@@ -12,6 +12,7 @@
12#include "PetriEngine/Structures/ptrie_map.h"12#include "PetriEngine/Structures/ptrie_map.h"
13#include "PetriEngine/Structures/AlignedEncoder.h"13#include "PetriEngine/Structures/AlignedEncoder.h"
14#include "PetriEngine/Structures/linked_bucket.h"14#include "PetriEngine/Structures/linked_bucket.h"
15#include "PetriEngine/ReducingSuccessorGenerator.h"
1516
16namespace PetriNets {17namespace PetriNets {
17class OnTheFlyDG : public DependencyGraph::BasicDependencyGraph18class OnTheFlyDG : public DependencyGraph::BasicDependencyGraph
@@ -20,7 +21,7 @@
20 using Condition = PetriEngine::PQL::Condition;21 using Condition = PetriEngine::PQL::Condition;
21 using Condition_ptr = PetriEngine::PQL::Condition_ptr;22 using Condition_ptr = PetriEngine::PQL::Condition_ptr;
22 using Marking = PetriEngine::Structures::State;23 using Marking = PetriEngine::Structures::State;
23 OnTheFlyDG(PetriEngine::PetriNet *t_net);24 OnTheFlyDG(PetriEngine::PetriNet *t_net, bool partial_order);
2425
25 virtual ~OnTheFlyDG();26 virtual ~OnTheFlyDG();
2627
@@ -57,7 +58,6 @@
57 uint32_t n_places = 0;58 uint32_t n_places = 0;
58 size_t _markingCount = 0;59 size_t _markingCount = 0;
59 size_t _configurationCount = 0;60 size_t _configurationCount = 0;
60
61 //used after query is set61 //used after query is set
62 Condition_ptr query = nullptr;62 Condition_ptr query = nullptr;
6363
@@ -66,10 +66,27 @@
66 {66 {
67 return fastEval(query.get(), unfolded);67 return fastEval(query.get(), unfolded);
68 }68 }
69 void nextStates(Marking& t_marking, 69 void nextStates(Marking& t_marking, Condition*,
70 std::function<void ()> pre, 70 std::function<void ()> pre,
71 std::function<bool (Marking&)> foreach, 71 std::function<bool (Marking&)> foreach,
72 std::function<void ()> post);72 std::function<void ()> post);
73 template<typename T>
74 void dowork(T& gen, bool& first,
75 std::function<void ()>& pre,
76 std::function<bool (Marking&)>& foreach)
77 {
78 gen.prepare(&query_marking);
79
80 while(gen.next(working_marking)){
81 if(first) pre();
82 first = false;
83 if(!foreach(working_marking))
84 {
85 gen.reset();
86 break;
87 }
88 }
89 }
73 PetriConfig *createConfiguration(size_t marking, size_t own, Condition* query);90 PetriConfig *createConfiguration(size_t marking, size_t own, Condition* query);
74 PetriConfig *createConfiguration(size_t marking, size_t own, const Condition_ptr& query)91 PetriConfig *createConfiguration(size_t marking, size_t own, const Condition_ptr& query)
75 {92 {
@@ -86,7 +103,12 @@
86103
87 // Problem with linked bucket and complex constructor104 // Problem with linked bucket and complex constructor
88 linked_bucket_t<char[sizeof(PetriConfig)], 1024*1024>* conf_alloc = nullptr;105 linked_bucket_t<char[sizeof(PetriConfig)], 1024*1024>* conf_alloc = nullptr;
89 106
107 PetriEngine::ReducingSuccessorGenerator _redgen;
108 bool _partial_order = false;
109
90};110};
111
112
91}113}
92#endif // ONTHEFLYDG_H114#endif // ONTHEFLYDG_H
93115
=== modified file 'PetriEngine/PQL/Expressions.cpp'
--- PetriEngine/PQL/Expressions.cpp 2017-12-14 08:59:40 +0000
+++ PetriEngine/PQL/Expressions.cpp 2018-01-04 10:26:07 +0000
@@ -2997,11 +2997,13 @@
2997 }2997 }
2998 2998
2999 void SimpleQuantifierCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const{2999 void SimpleQuantifierCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const{
3000 // Not implemented3000 _cond->findInteresting(generator, negated);
3001 }3001 }
3002 3002
3003 void UntilCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const{3003 void UntilCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const{
3004 // Not implemented3004 _cond1->findInteresting(generator, negated);
3005 _cond1->findInteresting(generator, !negated);
3006 _cond2->findInteresting(generator, negated);
3005 }3007 }
3006 3008
3007 void AndCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const {3009 void AndCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const {
30083010
=== modified file 'PetriEngine/PQL/Expressions.h'
--- PetriEngine/PQL/Expressions.h 2017-12-13 14:17:08 +0000
+++ PetriEngine/PQL/Expressions.h 2018-01-04 10:26:07 +0000
@@ -254,6 +254,7 @@
254 bool isUpperBound() override;254 bool isUpperBound() override;
255 void findInteresting(ReducingSuccessorGenerator& generator, bool negated) const override;255 void findInteresting(ReducingSuccessorGenerator& generator, bool negated) const override;
256 virtual const Condition_ptr& operator[] (size_t i) const override { return _cond;}256 virtual const Condition_ptr& operator[] (size_t i) const override { return _cond;}
257 virtual bool containsNext() const override { return _cond->containsNext(); }
257 private:258 private:
258 virtual std::string op() const = 0;259 virtual std::string op() const = 0;
259 260
@@ -272,7 +273,7 @@
272 Quantifier getQuantifier() const override { return Quantifier::E; }273 Quantifier getQuantifier() const override { return Quantifier::E; }
273 Path getPath() const override { return Path::X; }274 Path getPath() const override { return Path::X; }
274 uint32_t distance(DistanceContext& context) const override;275 uint32_t distance(DistanceContext& context) const override;
275 276 bool containsNext() const override { return true; }
276 private:277 private:
277 std::string op() const override;278 std::string op() const override;
278 };279 };
@@ -324,6 +325,7 @@
324 Quantifier getQuantifier() const override { return Quantifier::A; }325 Quantifier getQuantifier() const override { return Quantifier::A; }
325 Path getPath() const override { return Path::X; }326 Path getPath() const override { return Path::X; }
326 uint32_t distance(DistanceContext& context) const override;327 uint32_t distance(DistanceContext& context) const override;
328 bool containsNext() const override { return true; }
327 private:329 private:
328 std::string op() const override;330 std::string op() const override;
329 };331 };
@@ -385,7 +387,7 @@
385 { if(i == 0) return _cond1; return _cond2;}387 { if(i == 0) return _cond1; return _cond2;}
386 Path getPath() const override 388 Path getPath() const override
387 { return Path::U; }389 { return Path::U; }
388390 bool containsNext() const override { return _cond1->containsNext() || _cond2->containsNext(); }
389 private:391 private:
390 virtual std::string op() const = 0; 392 virtual std::string op() const = 0;
391 393
@@ -463,6 +465,9 @@
463 { return _compiled->getQueryType(); }465 { return _compiled->getQueryType(); }
464 int formulaSize() const override466 int formulaSize() const override
465 { return _compiled->formulaSize(); }467 { return _compiled->formulaSize(); }
468 bool containsNext() const override
469 { return false; }
470
466 private:471 private:
467 std::string _name;472 std::string _name;
468 Condition_ptr _compiled;473 Condition_ptr _compiled;
@@ -503,6 +508,8 @@
503 auto end() const { return _conds.end(); }508 auto end() const { return _conds.end(); }
504 bool empty() const { return _conds.size() == 0; }509 bool empty() const { return _conds.size() == 0; }
505 bool singular() const { return _conds.size() == 1; }510 bool singular() const { return _conds.size() == 1; }
511 bool containsNext() const override
512 { return std::any_of(begin(), end(), [](auto& a){return a->containsNext();}); }
506 protected:513 protected:
507 LogicalCondition() {};514 LogicalCondition() {};
508 Retval simplifyOr(SimplificationContext& context) const;515 Retval simplifyOr(SimplificationContext& context) const;
@@ -632,6 +639,8 @@
632 (_constraints[0]._lower == 0 || 639 (_constraints[0]._lower == 0 ||
633 _constraints[0]._upper == std::numeric_limits<uint32_t>::max());640 _constraints[0]._upper == std::numeric_limits<uint32_t>::max());
634 };641 };
642 bool containsNext() const override { return false;}
643
635 private:644 private:
636 std::vector<cons_t> _constraints;645 std::vector<cons_t> _constraints;
637 bool _negated = false;646 bool _negated = false;
@@ -665,6 +674,7 @@
665 if(id == 0) return _expr1;674 if(id == 0) return _expr1;
666 else return _expr2;675 else return _expr2;
667 }676 }
677 bool containsNext() const override { return false; }
668 protected:678 protected:
669 uint32_t _distance(DistanceContext& c, 679 uint32_t _distance(DistanceContext& c,
670 std::function<uint32_t(uint32_t, uint32_t, bool)> d) const680 std::function<uint32_t(uint32_t, uint32_t, bool)> d) const
@@ -825,6 +835,7 @@
825 CTLType getQueryType() const override { return CTLType::LOPERATOR; }835 CTLType getQueryType() const override { return CTLType::LOPERATOR; }
826 const Condition_ptr& operator[](size_t i) const { return _cond; };836 const Condition_ptr& operator[](size_t i) const { return _cond; };
827 virtual bool isTemporal() const override { return _temporal;}837 virtual bool isTemporal() const override { return _temporal;}
838 bool containsNext() const override { return _cond->containsNext(); }
828839
829 private:840 private:
830 Condition_ptr _cond;841 Condition_ptr _cond;
@@ -864,6 +875,7 @@
864 Quantifier getQuantifier() const override { return Quantifier::EMPTY; }875 Quantifier getQuantifier() const override { return Quantifier::EMPTY; }
865 Path getPath() const override { return Path::pError; }876 Path getPath() const override { return Path::pError; }
866 CTLType getQueryType() const override { return CTLType::EVAL; }877 CTLType getQueryType() const override { return CTLType::EVAL; }
878 bool containsNext() const override { return false; }
867 private:879 private:
868 const bool _value;880 const bool _value;
869 };881 };
@@ -894,6 +906,7 @@
894 Quantifier getQuantifier() const override { return Quantifier::EMPTY; }906 Quantifier getQuantifier() const override { return Quantifier::EMPTY; }
895 Path getPath() const override { return Path::pError; }907 Path getPath() const override { return Path::pError; }
896 CTLType getQueryType() const override { return CTLType::EVAL; }908 CTLType getQueryType() const override { return CTLType::EVAL; }
909 bool containsNext() const override { return false; }
897 };910 };
898911
899 }912 }
900913
=== modified file 'PetriEngine/PQL/PQL.h'
--- PetriEngine/PQL/PQL.h 2017-12-11 08:24:36 +0000
+++ PetriEngine/PQL/PQL.h 2018-01-04 10:26:07 +0000
@@ -289,7 +289,7 @@
289 virtual Path getPath() const = 0;289 virtual Path getPath() const = 0;
290 static std::shared_ptr<Condition> 290 static std::shared_ptr<Condition>
291 initialMarkingRW(std::function<std::shared_ptr<Condition> ()> func, negstat_t& stats, const EvaluationContext& context, bool nested, bool negated);291 initialMarkingRW(std::function<std::shared_ptr<Condition> ()> func, negstat_t& stats, const EvaluationContext& context, bool nested, bool negated);
292 292 virtual bool containsNext() const = 0;
293 protected:293 protected:
294 //Value for checking if condition is trivially true or false.294 //Value for checking if condition is trivially true or false.
295 //0 is undecided (default), 1 is true, 2 is false.295 //0 is undecided (default), 1 is true, 2 is false.
296296
=== modified file 'PetriEngine/PetriNetBuilder.cpp'
--- PetriEngine/PetriNetBuilder.cpp 2017-12-08 12:21:38 +0000
+++ PetriEngine/PetriNetBuilder.cpp 2018-01-04 10:26:07 +0000
@@ -395,7 +395,8 @@
395 QueryPlaceAnalysisContext placecontext(getPlaceNames(), getTransitionNames(), net);395 QueryPlaceAnalysisContext placecontext(getPlaceNames(), getTransitionNames(), net);
396 for(uint32_t i = 0; i < queries.size(); ++i)396 for(uint32_t i = 0; i < queries.size(); ++i)
397 {397 {
398 if(results[i] == Reachability::ResultPrinter::Unknown)398 if(results[i] == Reachability::ResultPrinter::Unknown ||
399 results[i] == Reachability::ResultPrinter::CTL )
399 {400 {
400 queries[i]->analyze(placecontext); 401 queries[i]->analyze(placecontext);
401 }402 }
402403
=== modified file 'PetriEngine/PetriNetBuilder.h'
--- PetriEngine/PetriNetBuilder.h 2017-12-08 13:28:43 +0000
+++ PetriEngine/PetriNetBuilder.h 2018-01-04 10:26:07 +0000
@@ -112,6 +112,10 @@
112 return reducer.RuleE();112 return reducer.RuleE();
113 }113 }
114 114
115 size_t RuleF() const {
116 return reducer.RuleF();
117 }
118
115 Reducer* getReducer() { return &reducer; }119 Reducer* getReducer() { return &reducer; }
116 120
117 std::vector<std::pair<std::string, uint32_t>> orphanPlaces() const {121 std::vector<std::pair<std::string, uint32_t>> orphanPlaces() const {
118122
=== modified file 'PetriEngine/Reducer.cpp'
--- PetriEngine/Reducer.cpp 2017-12-08 13:34:25 +0000
+++ PetriEngine/Reducer.cpp 2018-01-04 10:26:07 +0000
@@ -10,11 +10,12 @@
10#include "PetriNetBuilder.h"10#include "PetriNetBuilder.h"
11#include <PetriParse/PNMLParser.h>11#include <PetriParse/PNMLParser.h>
12#include <queue>12#include <queue>
13#include <set>
1314
14namespace PetriEngine {15namespace PetriEngine {
1516
16 Reducer::Reducer(PetriNetBuilder* p) 17 Reducer::Reducer(PetriNetBuilder* p)
17 : _removedTransitions(0), _removedPlaces(0), _ruleA(0), _ruleB(0), _ruleC(0), _ruleD(0), _ruleE(0), parent(p) {18 : _removedTransitions(0), _removedPlaces(0), _ruleA(0), _ruleB(0), _ruleC(0), _ruleD(0), _ruleE(0), _ruleF(0), parent(p) {
18 }19 }
1920
20 Reducer::~Reducer() {21 Reducer::~Reducer() {
@@ -180,12 +181,14 @@
180 assert(!t.skip || (t.pre.size() == 0 && t.post.size() == 0));181 assert(!t.skip || (t.pre.size() == 0 && t.post.size() == 0));
181 for(Arc& a : t.pre)182 for(Arc& a : t.pre)
182 {183 {
184 assert(a.weight > 0);
183 Place& p = parent->_places[a.place];185 Place& p = parent->_places[a.place];
184 assert(!p.skip);186 assert(!p.skip);
185 assert(std::find(p.consumers.begin(), p.consumers.end(), i) != p.consumers.end());187 assert(std::find(p.consumers.begin(), p.consumers.end(), i) != p.consumers.end());
186 }188 }
187 for(Arc& a : t.post)189 for(Arc& a : t.post)
188 {190 {
191 assert(a.weight > 0);
189 Place& p = parent->_places[a.place];192 Place& p = parent->_places[a.place];
190 assert(!p.skip);193 assert(!p.skip);
191 assert(std::find(p.producers.begin(), p.producers.end(), i) != p.producers.end());194 assert(std::find(p.producers.begin(), p.producers.end(), i) != p.producers.end());
@@ -239,14 +242,10 @@
239242
240 // A2. we have more/less than one arc in pre or post243 // A2. we have more/less than one arc in pre or post
241 // checked first to avoid out-of-bounds when looking up indexes.244 // checked first to avoid out-of-bounds when looking up indexes.
242 if(trans.pre.size() != 1 || trans.post.size() != 1) continue;245 if(trans.pre.size() != 1) continue;
243246
244 uint32_t pPre = trans.pre[0].place;247 uint32_t pPre = trans.pre[0].place;
245 uint32_t pPost = trans.post[0].place;248
246
247 // A1. continue if source and destination are the same
248 if (pPre == pPost) continue;
249
250 // A2. Check that pPre goes only to t249 // A2. Check that pPre goes only to t
251 if(parent->_places[pPre].consumers.size() != 1) continue;250 if(parent->_places[pPre].consumers.size() != 1) continue;
252 251
@@ -255,10 +254,21 @@
255 if(trans.pre[0].weight != 1 || trans.post[0].weight < 1) continue;254 if(trans.pre[0].weight != 1 || trans.post[0].weight < 1) continue;
256 255
257 // A4. Do inhibitor check, neither T, pPre or pPost can be involved with any inhibitor256 // A4. Do inhibitor check, neither T, pPre or pPost can be involved with any inhibitor
258 if(parent->_places[pPre].inhib || parent->_places[pPost].inhib || trans.inhib) continue;257 if(parent->_places[pPre].inhib|| trans.inhib) continue;
259258
260 // A5. dont mess with query!259 // A5. dont mess with query!
261 if(placeInQuery[pPre] > 0 || placeInQuery[pPost]) continue;260 if(placeInQuery[pPre] > 0) continue;
261 // check A1, A4 and A5 for post
262 bool ok = true;
263 for(auto& pPost : trans.post)
264 {
265 if(parent->_places[pPost.place].inhib || pPre == pPost.place || placeInQuery[pPost.place] > 0)
266 {
267 ok = false;
268 break;
269 }
270 }
271 if(!ok) continue;
262 272
263 continueReductions = true;273 continueReductions = true;
264 _ruleA++;274 _ruleA++;
@@ -280,40 +290,45 @@
280 } 290 }
281 }291 }
282 292
283 size_t weight = trans.post[0].weight;293 for(auto& pPost : trans.post)
284 294 {
285 // UA2. move the token for the initial marking, makes things simpler.295 // UA2. move the token for the initial marking, makes things simpler.
286 parent->initialMarking[pPost] += (parent->initialMarking[pPre] * weight);296 parent->initialMarking[pPost.place] += (parent->initialMarking[pPre] * pPost.weight);
297 }
287 parent->initialMarking[pPre] = 0;298 parent->initialMarking[pPre] = 0;
288299
289 // Remove transition t and the place that has no tokens in m0300 // Remove transition t and the place that has no tokens in m0
290 // UA1. remove transition301 // UA1. remove transition
302 auto toMove = trans.post;
291 skipTransition(t);303 skipTransition(t);
292 assert(pPost != pPre);
293304
294 // UA2. update arcs305 // UA2. update arcs
295 for(auto& _t : parent->_places[pPre].producers)306 for(auto& _t : parent->_places[pPre].producers)
296 {307 {
297 assert(pPre != pPost);
298 assert(_t != t);308 assert(_t != t);
299 // move output-arcs to post.309 // move output-arcs to post.
300 Transition& trans = getTransition(_t);310 Transition& src = getTransition(_t);
301 auto source = getOutArc(trans, pPre);311 auto source = *getOutArc(src, pPre);
302 assert(source != trans.pre.end());312 for(auto& pPost : toMove)
303 auto dest = getOutArc(trans, pPost);313 {
304 if(dest == trans.post.end())314 Arc a;
305 {315 a.place = pPost.place;
306 source->place = pPost;316 a.weight = source.weight * pPost.weight;
307 source->weight *= weight;317 assert(a.weight > 0);
308 parent->_places[pPost].producers.push_back(_t);318 a.inhib = false;
309319 auto dest = std::lower_bound(src.post.begin(), src.post.end(), a);
310 std::sort(trans.post.begin(), trans.post.end());320 if(dest == src.post.end() || dest->place != pPost.place)
311 std::sort( parent->_places[pPost].producers.begin(), 321 {
312 parent->_places[pPost].producers.end());322 dest = src.post.insert(dest, a);
313 }323 auto& prod = parent->_places[pPost.place].producers;
314 else324 auto lb = std::lower_bound(prod.begin(), prod.end(), _t);
315 {325 prod.insert(lb, _t);
316 dest->weight += (source->weight * weight);326 }
327 else
328 {
329 dest->weight += (source.weight * pPost.weight);
330 }
331 assert(dest->weight > 0);
317 }332 }
318 } 333 }
319 // UA1. remove place334 // UA1. remove place
@@ -714,7 +729,8 @@
714 if(placeInQuery[p] > 0) continue;729 if(placeInQuery[p] > 0) continue;
715 if(place.producers.size() > place.consumers.size()) continue;730 if(place.producers.size() > place.consumers.size()) continue;
716 731
717 bool ok = true;732 std::set<uint32_t> notenabled;
733 bool ok = true;
718 for(uint cons : place.consumers)734 for(uint cons : place.consumers)
719 {735 {
720 Transition& t = getTransition(cons);736 Transition& t = getTransition(cons);
@@ -723,12 +739,21 @@
723 ok = false;739 ok = false;
724 break;740 break;
725 } 741 }
742 else
743 {
744 notenabled.insert(cons);
745 }
726 }746 }
727 747
728 if(!ok) continue;748 if(!ok) continue;
729 749
730 for(uint prod : place.producers)750 for(uint prod : place.producers)
731 {751 {
752 if(notenabled.count(prod) == 0)
753 {
754 ok = false;
755 break;
756 }
732 // check that producing arcs originate from transition also 757 // check that producing arcs originate from transition also
733 // consuming. If so, we know it will never fire.758 // consuming. If so, we know it will never fire.
734 Transition& t = getTransition(prod);759 Transition& t = getTransition(prod);
@@ -741,24 +766,63 @@
741 }766 }
742 767
743 if(!ok) continue;768 if(!ok) continue;
769
770 _ruleE++;
771 continueReductions = true;
744 772
745 parent->initialMarking[p] = 0;773 parent->initialMarking[p] = 0;
746 774
747 auto torem = place.consumers;775 bool skipplace = notenabled.size() == place.consumers.size();
748 for(uint cons : torem)776 for(uint cons : notenabled)
749 {
750 skipTransition(cons);777 skipTransition(cons);
778
779 if(skipplace)
780 skipPlace(p);
781
782 }
783 assert(consistent());
784 return continueReductions;
785 }
786
787 bool Reducer::ReducebyRuleF(uint32_t* placeInQuery) {
788 bool continueReductions = false;
789 const size_t numberofplaces = parent->numberOfPlaces();
790 for(uint32_t p = 0; p < numberofplaces; ++p)
791 {
792 if(hasTimedout()) return false;
793 Place& place = parent->_places[p];
794 if(place.skip) continue;
795 if(place.inhib) continue;
796 if(placeInQuery[p] > 0) continue;
797 if(place.consumers.size() > 0) continue;
798
799 ++_ruleF;
800 continueReductions = true;
801 skipPlace(p);
802 std::vector<uint32_t> torem;
803 for(auto& t : place.producers)
804 {
805 auto& trans = parent->_transitions[t];
806 if(trans.post.size() != 0)
807 continue;
808 bool ok = true;
809 for(auto& a : trans.pre)
810 {
811 if(placeInQuery[a.place] > 0)
812 {
813 ok = false;
814 }
815 }
816 if(ok) torem.push_back(t);
751 }817 }
752818
753 skipPlace(p);819 for(auto t : torem)
754 _ruleE++;820 skipTransition(t);
755 continueReductions = true;821 assert(consistent());
756 }822 }
757 assert(consistent());
758 return continueReductions;823 return continueReductions;
759 }824 }
760825
761
762 void Reducer::Reduce(QueryPlaceAnalysisContext& context, int enablereduction, bool reconstructTrace, int timeout) {826 void Reducer::Reduce(QueryPlaceAnalysisContext& context, int enablereduction, bool reconstructTrace, int timeout) {
763 this->_timeout = timeout;827 this->_timeout = timeout;
764 _timer = std::chrono::high_resolution_clock::now();828 _timer = std::chrono::high_resolution_clock::now();
@@ -773,11 +837,12 @@
773 changed |= ReducebyRuleA(context.getQueryPlaceCount());837 changed |= ReducebyRuleA(context.getQueryPlaceCount());
774 changed |= ReducebyRuleB(context.getQueryPlaceCount());838 changed |= ReducebyRuleB(context.getQueryPlaceCount());
775 changed |= ReducebyRuleE(context.getQueryPlaceCount());839 changed |= ReducebyRuleE(context.getQueryPlaceCount());
840 changed |= ReducebyRuleF(context.getQueryPlaceCount());
776 } while(changed && !hasTimedout());841 } while(changed && !hasTimedout());
777 // RuleC and RuleD are expensive, so wait with those till nothing else changes842 // RuleC and RuleD are expensive, so wait with those till nothing else changes
778 changed |= ReducebyRuleD(context.getQueryPlaceCount());843 changed |= ReducebyRuleD(context.getQueryPlaceCount());
779 changed |= ReducebyRuleC(context.getQueryPlaceCount());844 changed |= ReducebyRuleC(context.getQueryPlaceCount());
780 } while(changed);845 } while(!hasTimedout() && changed);
781846
782 } else if (enablereduction == 2) { // for k-boundedness checking only rules A and D are applicable847 } else if (enablereduction == 2) { // for k-boundedness checking only rules A and D are applicable
783 while ( (848 while ( (
784849
=== modified file 'PetriEngine/Reducer.h'
--- PetriEngine/Reducer.h 2017-12-13 14:17:08 +0000
+++ PetriEngine/Reducer.h 2018-01-04 10:26:07 +0000
@@ -114,7 +114,11 @@
114 size_t RuleE() const {114 size_t RuleE() const {
115 return _ruleE;115 return _ruleE;
116 }116 }
117 117
118 size_t RuleF() const {
119 return _ruleF;
120 }
121
118 void postFire(std::ostream&, const std::string& transition);122 void postFire(std::ostream&, const std::string& transition);
119 void extraConsume(std::ostream&, const std::string& transition);123 void extraConsume(std::ostream&, const std::string& transition);
120 void initFire(std::ostream&);124 void initFire(std::ostream&);
@@ -122,7 +126,7 @@
122 private:126 private:
123 size_t _removedTransitions;127 size_t _removedTransitions;
124 size_t _removedPlaces;128 size_t _removedPlaces;
125 size_t _ruleA, _ruleB, _ruleC, _ruleD, _ruleE;129 size_t _ruleA, _ruleB, _ruleC, _ruleD, _ruleE, _ruleF;
126 PetriNetBuilder* parent;130 PetriNetBuilder* parent;
127 bool reconstructTrace = false;131 bool reconstructTrace = false;
128 std::chrono::high_resolution_clock::time_point _timer;132 std::chrono::high_resolution_clock::time_point _timer;
@@ -134,6 +138,7 @@
134 bool ReducebyRuleC(uint32_t* placeInQuery);138 bool ReducebyRuleC(uint32_t* placeInQuery);
135 bool ReducebyRuleD(uint32_t* placeInQuery);139 bool ReducebyRuleD(uint32_t* placeInQuery);
136 bool ReducebyRuleE(uint32_t* placeInQuery);140 bool ReducebyRuleE(uint32_t* placeInQuery);
141 bool ReducebyRuleF(uint32_t* placeInQuery);
137 142
138 std::string getTransitionName(uint32_t transition);143 std::string getTransitionName(uint32_t transition);
139 std::string getPlaceName(uint32_t place);144 std::string getPlaceName(uint32_t place);
140145
=== modified file 'PetriEngine/ReducingSuccessorGenerator.cpp'
--- PetriEngine/ReducingSuccessorGenerator.cpp 2017-12-05 15:13:40 +0000
+++ PetriEngine/ReducingSuccessorGenerator.cpp 2018-01-04 10:26:07 +0000
@@ -18,7 +18,9 @@
18 }18 }
1919
20 ReducingSuccessorGenerator::ReducingSuccessorGenerator(const PetriNet& net, std::vector<std::shared_ptr<PQL::Condition> >& queries) : ReducingSuccessorGenerator(net) {20 ReducingSuccessorGenerator::ReducingSuccessorGenerator(const PetriNet& net, std::vector<std::shared_ptr<PQL::Condition> >& queries) : ReducingSuccessorGenerator(net) {
21 _queries = queries;21 _queries.reserve(queries.size());
22 for(auto& q : queries)
23 _queries.push_back(q.get());
22 }24 }
2325
24 ReducingSuccessorGenerator::~ReducingSuccessorGenerator() {26 ReducingSuccessorGenerator::~ReducingSuccessorGenerator() {
@@ -182,6 +184,12 @@
182 void ReducingSuccessorGenerator::prepare(const Structures::State* state) {184 void ReducingSuccessorGenerator::prepare(const Structures::State* state) {
183 _parent = state;185 _parent = state;
184 constructEnabled();186 constructEnabled();
187 if(_ordering.size() == 0) return;
188 if(_ordering.size() == 1)
189 {
190 _stubborn[_ordering.front()] = true;
191 return;
192 }
185 for (auto &q : _queries) {193 for (auto &q : _queries) {
186 q->evalAndSet(PQL::EvaluationContext((*_parent).marking(), &_net));194 q->evalAndSet(PQL::EvaluationContext((*_parent).marking(), &_net));
187 q->findInteresting(*this, false);195 q->findInteresting(*this, false);
188196
=== modified file 'PetriEngine/ReducingSuccessorGenerator.h'
--- PetriEngine/ReducingSuccessorGenerator.h 2017-05-10 11:10:00 +0000
+++ PetriEngine/ReducingSuccessorGenerator.h 2018-01-04 10:26:07 +0000
@@ -29,6 +29,9 @@
29 {29 {
30 return _current;30 return _current;
31 }31 }
32 void setQuery(PQL::Condition* ptr) { _queries.clear(); _queries = {ptr};}
33 void reset();
34
32private:35private:
33 bool *_enabled, *_stubborn;36 bool *_enabled, *_stubborn;
34 std::unique_ptr<place_t[]> _places;37 std::unique_ptr<place_t[]> _places;
@@ -39,8 +42,7 @@
39 bool _netContainsInhibitorArcs;42 bool _netContainsInhibitorArcs;
40 std::vector<std::vector<uint32_t>> _inhibpost;43 std::vector<std::vector<uint32_t>> _inhibpost;
41 44
42 std::vector<std::shared_ptr<PQL::Condition> > _queries;45 std::vector<PQL::Condition* > _queries;
43 void reset();
44 void constructEnabled();46 void constructEnabled();
45 void constructPrePost();47 void constructPrePost();
46 void constructDependency();48 void constructDependency();
4749
=== modified file 'PetriEngine/Structures/light_deque.h'
--- PetriEngine/Structures/light_deque.h 2017-03-05 16:08:26 +0000
+++ PetriEngine/Structures/light_deque.h 2018-01-04 10:26:07 +0000
@@ -48,6 +48,11 @@
48 return _front == _back;48 return _front == _back;
49 }49 }
50 50
51 size_t size()
52 {
53 return _back - _front;
54 }
55
51 T front()56 T front()
52 {57 {
53 return _data.get()[_front];58 return _data.get()[_front];
5459
=== modified file 'PetriEngine/SuccessorGenerator.h'
--- PetriEngine/SuccessorGenerator.h 2017-12-05 02:09:55 +0000
+++ PetriEngine/SuccessorGenerator.h 2018-01-04 10:26:07 +0000
@@ -35,6 +35,8 @@
35 return _parent->marking();35 return _parent->marking();
36 }36 }
3737
38 void reset();
39
38protected:40protected:
39 /**41 /**
40 * Checks if the conditions are met for fireing t, if write != NULL,42 * Checks if the conditions are met for fireing t, if write != NULL,
@@ -63,7 +65,6 @@
63 const Structures::State* _parent;65 const Structures::State* _parent;
64 uint32_t _suc_pcounter;66 uint32_t _suc_pcounter;
65 uint32_t _suc_tcounter;67 uint32_t _suc_tcounter;
66 void reset();
6768
68 friend class ReducingSuccessorGenerator;69 friend class ReducingSuccessorGenerator;
69};70};
7071
=== modified file 'VerifyPN.cpp'
--- VerifyPN.cpp 2017-12-12 10:13:45 +0000
+++ VerifyPN.cpp 2018-01-04 10:26:07 +0000
@@ -478,7 +478,8 @@
478 << "Applications of rule B: " << builder.RuleB() << std::endl478 << "Applications of rule B: " << builder.RuleB() << std::endl
479 << "Applications of rule C: " << builder.RuleC() << std::endl479 << "Applications of rule C: " << builder.RuleC() << std::endl
480 << "Applications of rule D: " << builder.RuleD() << std::endl480 << "Applications of rule D: " << builder.RuleD() << std::endl
481 << "Applications of rule E: " << builder.RuleE() << std::endl;481 << "Applications of rule E: " << builder.RuleE() << std::endl
482 << "Applications of rule F: " << builder.RuleF() << std::endl;
482 }483 }
483 }484 }
484}485}
@@ -656,7 +657,26 @@
656657
657 if(alldone) return SuccessCode;658 if(alldone) return SuccessCode;
658 }659 }
659660
661 //--------------------- Apply Net Reduction ---------------//
662
663 if ( (options.enablereduction == 1 || options.enablereduction == 2)
664 && std::all_of(queries.begin(), queries.end(), [](auto& a){ return !a->containsNext(); })) {
665 // Compute how many times each place appears in the query
666 builder.startTimer();
667 builder.reduce(queries, results, options.enablereduction, options.trace, nullptr, options.reductionTimeout);
668 printer.setReducer(builder.getReducer());
669 }
670
671 printStats(builder, options);
672
673 auto net = std::unique_ptr<PetriNet>(builder.makePetriNet());
674
675 for(auto& q : queries)
676 {
677 q->indexPlaces(builder.getPlaceNames());
678 }
679
660 //----------------------- Verify CTL queries -----------------------//680 //----------------------- Verify CTL queries -----------------------//
661 std::vector<size_t> ctl_ids;681 std::vector<size_t> ctl_ids;
662 for(size_t i = 0; i < queries.size(); ++i)682 for(size_t i = 0; i < queries.size(); ++i)
@@ -670,24 +690,25 @@
670 if (ctl_ids.size() > 0) {690 if (ctl_ids.size() > 0) {
671 options.isctl=true;691 options.isctl=true;
672 PetriEngine::Reachability::Strategy reachabilityStrategy=options.strategy;692 PetriEngine::Reachability::Strategy reachabilityStrategy=options.strategy;
673 std::unique_ptr<PetriNet> ctlnet(builder.makePetriNet());693
674 // Assign indexes694 // Assign indexes
675 if(queries.size() == 0 || contextAnalysis(builder, ctlnet.get(), queries) != ContinueCode) return ErrorCode;695 if(queries.size() == 0 || contextAnalysis(builder, net.get(), queries) != ContinueCode) return ErrorCode;
676 if(options.strategy == DEFAULT) options.strategy = PetriEngine::Reachability::DFS;696 if(options.strategy == DEFAULT) options.strategy = PetriEngine::Reachability::DFS;
677 if(options.strategy != PetriEngine::Reachability::DFS){697 if(options.strategy != PetriEngine::Reachability::DFS){
678 fprintf(stdout, "Search strategy was changed to DFS as the CTL engine is called.\n");698 fprintf(stdout, "Search strategy was changed to DFS as the CTL engine is called.\n");
679 options.strategy = PetriEngine::Reachability::DFS;699 options.strategy = PetriEngine::Reachability::DFS;
680 }700 }
681 v = CTLMain(ctlnet.get(),701 v = CTLMain(net.get(),
682 options.ctlalgorithm,702 options.ctlalgorithm,
683 options.strategy,703 options.strategy,
684 options.gamemode,704 options.gamemode,
685 options.printstatistics,705 options.printstatistics,
686 true,706 true,
707 options.stubbornreduction,
687 querynames,708 querynames,
688 queries,709 queries,
689 ctl_ids);710 ctl_ids);
690 711
691 if (std::find(results.begin(), results.end(), ResultPrinter::Unknown) == results.end()) {712 if (std::find(results.begin(), results.end(), ResultPrinter::Unknown) == results.end()) {
692 return v;713 return v;
693 }714 }
@@ -695,24 +716,6 @@
695 options.strategy=reachabilityStrategy;716 options.strategy=reachabilityStrategy;
696 }717 }
697 options.isctl=false;718 options.isctl=false;
698 //--------------------- Apply Net Reduction ---------------//
699
700 if (options.enablereduction == 1 || options.enablereduction == 2) {
701 // Compute how many times each place appears in the query
702 builder.startTimer();
703 std::unique_ptr<PetriNet> net(builder.makePetriNet(false));
704 builder.reduce(queries, results, options.enablereduction, options.trace, net.get(), options.reductionTimeout);
705 printer.setReducer(builder.getReducer());
706 }
707
708 printStats(builder, options);
709
710 std::unique_ptr<PetriNet> net(builder.makePetriNet());
711
712 for(auto& q : queries)
713 {
714 q->indexPlaces(builder.getPlaceNames());
715 }
716 719
717 //----------------------- Siphon Trap ------------------------//720 //----------------------- Siphon Trap ------------------------//
718 721

Subscribers

People subscribed via source and target branches