Merge lp:~tapaal-ltl/verifypn/ruleI.5 into lp:~tapaal-ltl/verifypn/ltl-model-checker

Proposed by Simon Virenfeldt
Status: Merged
Merged at revision: 252
Proposed branch: lp:~tapaal-ltl/verifypn/ruleI.5
Merge into: lp:~tapaal-ltl/verifypn/ltl-model-checker
Diff against target: 375 lines (+171/-122)
3 files modified
include/PetriEngine/Reducer.h (+8/-3)
src/PetriEngine/Reducer.cpp (+162/-118)
src/VerifyPN.cpp (+1/-1)
To merge this branch: bzr merge lp:~tapaal-ltl/verifypn/ruleI.5
Reviewer Review Type Date Requested Status
Nikolaj Jensen Ulrik Approve
Review via email: mp+398248@code.launchpad.net

Description of the change

Implements the new structural reduction rule K which is a weaker version of rule I tailored to LTL reduction.

To post a comment you must log in.
Revision history for this message
Nikolaj Jensen Ulrik (waefwerf) :
review: Approve
lp:~tapaal-ltl/verifypn/ruleI.5 updated
252. By Simon Virenfeldt

Merge lp:~tapaal-ltl/verifypn/ruleI.5@253

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/PetriEngine/Reducer.h'
2--- include/PetriEngine/Reducer.h 2020-11-26 10:36:20 +0000
3+++ include/PetriEngine/Reducer.h 2021-02-18 12:06:25 +0000
4@@ -110,7 +110,8 @@
5 << "Applications of rule G: " << _ruleG << "\n"
6 << "Applications of rule H: " << _ruleH << "\n"
7 << "Applications of rule I: " << _ruleI << "\n"
8- << "Applications of rule J: " << _ruleJ << std::endl;
9+ << "Applications of rule J: " << _ruleJ << "\n"
10+ << "Applications of rule K: " << _ruleK << std::endl;
11 }
12
13 void postFire(std::ostream&, const std::string& transition);
14@@ -120,7 +121,7 @@
15 private:
16 size_t _removedTransitions = 0;
17 size_t _removedPlaces= 0;
18- size_t _ruleA = 0, _ruleB = 0, _ruleC = 0, _ruleD = 0, _ruleE = 0, _ruleF = 0, _ruleG = 0, _ruleH = 0, _ruleI = 0, _ruleJ = 0;
19+ size_t _ruleA = 0, _ruleB = 0, _ruleC = 0, _ruleD = 0, _ruleE = 0, _ruleF = 0, _ruleG = 0, _ruleH = 0, _ruleI = 0, _ruleJ = 0, _ruleK = 0;
20 PetriNetBuilder* parent = nullptr;
21 bool reconstructTrace = false;
22 std::chrono::high_resolution_clock::time_point _timer;
23@@ -137,7 +138,11 @@
24 bool ReducebyRuleG(uint32_t* placeInQuery, bool remove_loops, bool remove_consumers);
25 bool ReducebyRuleH(uint32_t* placeInQuery);
26 bool ReducebyRuleJ(uint32_t* placeInQuery);
27-
28+ bool ReducebyRuleK(uint32_t* placeInQuery, bool remove_consumers);
29+
30+ std::optional<std::pair<std::vector<bool>, std::vector<bool>>>relevant(const uint32_t* placeInQuery, bool remove_consumers);
31+ bool remove_irrelevant(const uint32_t* placeInQuery, const std::vector<bool> &tseen, const std::vector<bool> &pseen);
32+
33 std::string getTransitionName(uint32_t transition);
34 std::string getPlaceName(uint32_t place);
35
36
37=== modified file 'src/PetriEngine/Reducer.cpp'
38--- src/PetriEngine/Reducer.cpp 2020-12-04 11:14:38 +0000
39+++ src/PetriEngine/Reducer.cpp 2021-02-18 12:06:25 +0000
40@@ -903,131 +903,24 @@
41
42 if(skipplace)
43 skipPlace(p);
44-
45+
46 }
47 assert(consistent());
48 return continueReductions;
49 }
50-
51+
52 bool Reducer::ReducebyRuleI(uint32_t* placeInQuery, bool remove_loops, bool remove_consumers) {
53 bool reduced = false;
54 if(remove_loops)
55 {
56- std::vector<uint32_t> wtrans;
57- std::vector<bool> tseen(parent->numberOfTransitions(), false);
58-
59- for(uint32_t p = 0; p < parent->numberOfPlaces(); ++p)
60- {
61- if(hasTimedout()) return false;
62- if(placeInQuery[p] > 0)
63- {
64- const Place& place = parent->_places[p];
65- for(auto t : place.consumers)
66- {
67- if(!tseen[t])
68- {
69- wtrans.push_back(t);
70- tseen[t] = true;
71- }
72- }
73- for(auto t : place.producers)
74- {
75- if(!tseen[t])
76- {
77- wtrans.push_back(t);
78- tseen[t] = true;
79- }
80- }
81- }
82- }
83-
84- std::vector<bool> pseen(parent->numberOfPlaces(), false);
85- while(!wtrans.empty())
86- {
87- if(hasTimedout()) return false;
88- auto t = wtrans.back();
89- wtrans.pop_back();
90- const Transition& trans = parent->_transitions[t];
91- for(const Arc& arc : trans.pre)
92- {
93- const Place& place = parent->_places[arc.place];
94- if(arc.inhib)
95- {
96- for(auto pt : place.consumers)
97- {
98- if(!tseen[pt])
99- {
100- Transition& trans = parent->_transitions[pt];
101- auto it = trans.post.begin();
102- for(; it != trans.post.end(); ++it)
103- if(it->place >= arc.place) break;
104- if(it != trans.post.end() && it->place == arc.place)
105- {
106- auto it2 = trans.pre.begin();
107- for(; it2 != trans.pre.end(); ++it2)
108- if(it2->place >= arc.place || it2->inhib) break;
109- if(it->weight <= it2->weight) continue;
110- }
111- tseen[pt] = true;
112- wtrans.push_back(pt);
113- }
114- }
115- }
116- else
117- {
118- for(auto pt : place.producers)
119- {
120- if(!tseen[pt])
121- {
122- Transition& trans = parent->_transitions[pt];
123- auto it = trans.pre.begin();
124- for(; it != trans.pre.end(); ++it)
125- if(it->place >= arc.place) break;
126-
127- if(it != trans.pre.end() && it->place == arc.place && !it->inhib)
128- {
129- auto it2 = trans.post.begin();
130- for(; it2 != trans.post.end(); ++it2)
131- if(it2->place >= arc.place) break;
132- if(it->weight >= it2->weight) continue;
133- }
134-
135- tseen[pt] = true;
136- wtrans.push_back(pt);
137- }
138- }
139-
140- for(auto pt : place.consumers)
141- {
142- if(!tseen[pt] && (!remove_consumers || placeInQuery[arc.place] > 0))
143- {
144- tseen[pt] = true;
145- wtrans.push_back(pt);
146- }
147- }
148- }
149- pseen[arc.place] = true;
150- }
151- }
152-
153- for(size_t t = 0; t < parent->numberOfTransitions(); ++t)
154- {
155- if(!tseen[t] && !parent->_transitions[t].skip)
156- {
157- skipTransition(t);
158- reduced = true;
159- }
160- }
161-
162- for(size_t p = 0; p < parent->numberOfPlaces(); ++p)
163- {
164- if(!pseen[p] && !parent->_places[p].skip && placeInQuery[p] == 0)
165- {
166- assert(placeInQuery[p] == 0);
167- skipPlace(p);
168- reduced = true;
169- }
170- }
171+
172+ auto result = relevant(placeInQuery, remove_consumers);
173+ if (!result) {
174+ return false;
175+ }
176+ auto[tseen, pseen] = result.value();
177+
178+ reduced |= remove_irrelevant(placeInQuery, tseen, pseen);
179
180 if(reduced)
181 ++_ruleI;
182@@ -1565,6 +1458,153 @@
183 }
184 return continueReductions;
185 }
186+
187+ bool Reducer::ReducebyRuleK(uint32_t *placeInQuery, bool remove_consumers) {
188+ bool reduced = false;
189+ auto opt = relevant(placeInQuery, remove_consumers);
190+ if (!opt)
191+ return false;
192+ auto[tseen, pseen] = opt.value();
193+ for (std::size_t p = 0; p < parent->numberOfPlaces(); ++p) {
194+ if (placeInQuery[p] != 0)
195+ pseen[p] = true;
196+ }
197+
198+ for (std::size_t t = 0; t < parent->numberOfTransitions(); ++t) {
199+ auto transition = parent->_transitions[t];
200+ if (!tseen[t] && !transition.skip && !transition.inhib && transition.pre.size() == 1 &&
201+ transition.post.size() == 1
202+ && transition.pre[0].place == transition.post[0].place) {
203+ auto p = transition.pre[0].place;
204+ if (!pseen[p] && !parent->_places[p].inhib) {
205+ if (parent->initialMarking[p] >= transition.pre[0].weight){
206+ //Mark the initially marked self loop as relevant.
207+ tseen[t] = true;
208+ pseen[p] = true;
209+ reduced |= remove_irrelevant(placeInQuery, tseen, pseen);
210+ _ruleK++;
211+ return reduced;
212+ }
213+ if (transition.pre[0].weight == 1){
214+ for (auto t2 : parent->_places[p].consumers) {
215+ auto transition2 = parent->_transitions[t2];
216+ if (t != t2 && !tseen[t2] && !transition2.skip) {
217+ skipTransition(t2);
218+ reduced = true;
219+ _ruleK++;
220+ }
221+ }
222+ }
223+ }
224+ }
225+ }
226+ return reduced;
227+ }
228+
229+ std::optional<std::pair<std::vector<bool>, std::vector<bool>>>
230+ Reducer::relevant(const uint32_t *placeInQuery, bool remove_consumers) {
231+ std::vector<uint32_t> wtrans;
232+ std::vector<bool> tseen(parent->numberOfTransitions(), false);
233+ for (uint32_t p = 0; p < parent->numberOfPlaces(); ++p) {
234+ if (hasTimedout()) return std::nullopt;
235+ if (placeInQuery[p] > 0) {
236+ const Place &place = parent->_places[p];
237+ for (auto t : place.consumers) {
238+ if (!tseen[t]) {
239+ wtrans.push_back(t);
240+ tseen[t] = true;
241+ }
242+ }
243+ for (auto t : place.producers) {
244+ if (!tseen[t]) {
245+ wtrans.push_back(t);
246+ tseen[t] = true;
247+ }
248+ }
249+ }
250+ }
251+ std::vector<bool> pseen(parent->numberOfPlaces(), false);
252+
253+ while (!wtrans.empty()) {
254+ if (hasTimedout()) return std::nullopt;
255+ auto t = wtrans.back();
256+ wtrans.pop_back();
257+ const Transition &trans = parent->_transitions[t];
258+ for (const Arc &arc : trans.pre) {
259+ const Place &place = parent->_places[arc.place];
260+ if (arc.inhib) {
261+ for (auto pt : place.consumers) {
262+ if (!tseen[pt]) {
263+ Transition &trans = parent->_transitions[pt];
264+ auto it = trans.post.begin();
265+ for (; it != trans.post.end(); ++it)
266+ if (it->place >= arc.place) break;
267+ if (it != trans.post.end() && it->place == arc.place) {
268+ auto it2 = trans.pre.begin();
269+ for (; it2 != trans.pre.end(); ++it2)
270+ if (it2->place >= arc.place || it2->inhib) break;
271+ if (it->weight <= it2->weight) continue;
272+ }
273+ tseen[pt] = true;
274+ wtrans.push_back(pt);
275+ }
276+ }
277+ } else {
278+ for (auto pt : place.producers) {
279+ if (!tseen[pt]) {
280+ Transition &trans = parent->_transitions[pt];
281+ auto it = trans.pre.begin();
282+ for (; it != trans.pre.end(); ++it)
283+ if (it->place >= arc.place) break;
284+
285+ if (it != trans.pre.end() && it->place == arc.place && !it->inhib) {
286+ auto it2 = trans.post.begin();
287+ for (; it2 != trans.post.end(); ++it2)
288+ if (it2->place >= arc.place) break;
289+ if (it->weight >= it2->weight) continue;
290+ }
291+
292+ tseen[pt] = true;
293+ wtrans.push_back(pt);
294+ }
295+ }
296+
297+ for (auto pt : place.consumers) {
298+ if (!tseen[pt] && (!remove_consumers || placeInQuery[arc.place] > 0)) {
299+ tseen[pt] = true;
300+ wtrans.push_back(pt);
301+ }
302+ }
303+ }
304+ pseen[arc.place] = true;
305+ }
306+ }
307+ return std::make_optional(std::pair(tseen, pseen));
308+ }
309+
310+ bool Reducer::remove_irrelevant(const uint32_t* placeInQuery, const std::vector<bool> &tseen, const std::vector<bool> &pseen) {
311+ bool reduced = false;
312+ for(size_t t = 0; t < parent->numberOfTransitions(); ++t)
313+ {
314+ if(!tseen[t] && !parent->_transitions[t].skip)
315+ {
316+ skipTransition(t);
317+ reduced = true;
318+ }
319+ }
320+
321+ for(size_t p = 0; p < parent->numberOfPlaces(); ++p)
322+ {
323+ if(!pseen[p] && !parent->_places[p].skip && placeInQuery[p] == 0)
324+ {
325+ assert(placeInQuery[p] == 0);
326+ skipPlace(p);
327+ reduced = true;
328+ }
329+ }
330+ return reduced;
331+ }
332+
333 void Reducer::Reduce(QueryPlaceAnalysisContext& context, int enablereduction, bool reconstructTrace, int timeout, bool remove_loops, bool remove_consumers, bool next_safe, std::vector<uint32_t>& reduction) {
334
335 this->_timeout = timeout;
336@@ -1603,6 +1643,7 @@
337 if(!remove_loops)
338 while(ReducebyRuleI(context.getQueryPlaceCount(), remove_loops, remove_consumers)) changed = true;
339 while(ReducebyRuleD(context.getQueryPlaceCount())) changed = true;
340+ changed |= ReducebyRuleK(context.getQueryPlaceCount(), remove_consumers);
341 }
342 } while(changed && !hasTimedout());
343 if(!next_safe)
344@@ -1622,7 +1663,7 @@
345 }
346 else
347 {
348- const char* rnames = "ABCDEFGHIJ";
349+ const char* rnames = "ABCDEFGHIJK";
350 for(int i = reduction.size() - 1; i >= 0; --i)
351 {
352 if(next_safe)
353@@ -1683,6 +1724,9 @@
354 case 9:
355 while(ReducebyRuleJ(context.getQueryPlaceCount())) changed = true;
356 break;
357+ case 10:
358+ if (ReducebyRuleK(context.getQueryPlaceCount(), remove_consumers)) changed = true;
359+ break;
360 }
361 #ifndef NDEBUG
362 auto end = std::chrono::high_resolution_clock::now();
363
364=== modified file 'src/VerifyPN.cpp'
365--- src/VerifyPN.cpp 2021-02-04 11:16:09 +0000
366+++ src/VerifyPN.cpp 2021-02-18 12:06:25 +0000
367@@ -204,7 +204,7 @@
368 for(auto& qn : q)
369 {
370 int32_t n;
371- if(sscanf(qn.c_str(), "%d", &n) != 1 || n < 0 || n > 9)
372+ if(sscanf(qn.c_str(), "%d", &n) != 1 || n < 0 || n > 10)
373 {
374 std::cerr << "Error in reduction rule choice : " << qn << std::endl;
375 return ErrorCode;

Subscribers

People subscribed via source and target branches

to all changes: