Merge lp:~tapaal-ltl/verifypn/ruleI.5 into lp:~tapaal-ltl/verifypn/ltl-model-checker
- ruleI.5
- Merge into 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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Nikolaj Jensen Ulrik | Approve | ||
Review via email:
|
Commit message
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
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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; |