Merge lp:~verifydtapn-contributers/verifydtapn/workflowForTrunk into lp:verifydtapn
- workflowForTrunk
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Jiri Srba |
Approved revision: | 337 |
Merged at revision: | 289 |
Proposed branch: | lp:~verifydtapn-contributers/verifydtapn/workflowForTrunk |
Merge into: | lp:verifydtapn |
Diff against target: |
1355 lines (+1009/-26) 21 files modified
src/Core/ArgsParser.cpp (+28/-1) src/Core/ArgsParser.hpp (+1/-1) src/Core/QueryParser/AST.hpp (+1/-0) src/Core/TAPN/TimedPlace.hpp (+1/-0) src/Core/VerificationOptions.hpp (+18/-3) src/DiscreteVerification/DataStructures/NonStrictMarking.hpp (+19/-4) src/DiscreteVerification/DataStructures/NonStrictMarkingBase.cpp (+2/-4) src/DiscreteVerification/DataStructures/PWList.cpp (+14/-1) src/DiscreteVerification/DataStructures/PWList.hpp (+25/-6) src/DiscreteVerification/DataStructures/WaitingList.hpp (+66/-0) src/DiscreteVerification/DataStructures/WorkflowPWList.hpp (+150/-0) src/DiscreteVerification/DiscreteVerification.cpp (+45/-3) src/DiscreteVerification/DiscreteVerification.hpp (+2/-0) src/DiscreteVerification/SearchStrategies/SearchFactory.h (+4/-1) src/DiscreteVerification/SearchStrategies/SearchStrategies.hpp (+1/-0) src/DiscreteVerification/SearchStrategies/WorkflowMinFirst.hpp (+42/-0) src/DiscreteVerification/VerificationTypes/WorkflowSoundness.cpp (+206/-0) src/DiscreteVerification/VerificationTypes/WorkflowSoundness.hpp (+180/-0) src/DiscreteVerification/VerificationTypes/WorkflowStrongSoundness.cpp (+119/-0) src/DiscreteVerification/VerificationTypes/WorkflowStrongSoundness.hpp (+83/-0) src/compile-mac-32-64.sh (+2/-2) |
To merge this branch: | bzr merge lp:~verifydtapn-contributers/verifydtapn/workflowForTrunk |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Peter Gjøl Jensen | Approve | ||
Jakob Taankvist | Approve | ||
Jiri Srba | Approve | ||
Review via email: mp+191910@code.launchpad.net |
Commit message
Description of the change
Adds workflow soundness and strong soundness verification.
Peter Gjøl Jensen (peter-gjoel) wrote : | # |
Line 701-702, why this change in access-level?
Is it reasonable to just ignore unused options, and give no warnings? (timedarts, ptries)?
The implementation of "getUnpassed" in the PW-list seems like a very inefficient waiting-list-ish thing.
"getCoveredMarking" also seems very inefficient, maybe a special hash-function would solve this problem (use only place/token-count as seed of the hash).
Also, why are these in the PWList implementation and not in WorkflowPWList?
line 984-991 and 999-1005, please make a variable instead of constantly casting to WorkflowSoundne
I am not entirely sure, but I think you need a delete marking at line 1323 (you don't add it to the PW-list and you don't use it anywhere else) - there is a delete in the original reachabilitysea
I agree with Jiri that the changes do not affect the normal verification.
Jiri Srba (srba) wrote : | # |
Agree, timedarts and Ptrie should give a error (warning). Btw. we hope Peter that
you will be able to add Ptrie to this at some point. This should not be too difficult, correct?
The other remarks make also good sense to me, Mathias, can you take a look please?
The only thing I am not sure about is the hashing on token-count. I am not sure how
this can help with discovery of covered markings on the passed/waiting list?
Mathias Grund Sørensen (mathias.grund) wrote : | # |
> Line 701-702, why this change in access-level?
> Is it reasonable to just ignore unused options, and give no warnings?
> (timedarts, ptries)?
Yes, I will add a warning in this case.
> The implementation of "getUnpassed" in the PW-list seems like a very
> inefficient waiting-list-ish thing.
Yes, this is not very elaborate, but it will only be run once ever, so the overhead of doing something elaborate would most likely outweigh the benefit IMO.
> "getCoveredMarking" also seems very inefficient, maybe a special hash-function
> would solve this problem (use only place/token-count as seed of the hash).
Yes, this appears very simple. A more elaborate method which hashes on submarkings is used as an alternative in method checkForCoverin
But yes, I considered some kind of clever hashing, but due to time constraints I didn't have time come up with one. In any ways, I am not sure this will be as easy as it sounds. And also, I am not sure you will be able to get better performance than the method hashing on submarkings anyways, but you are welcome to see if you can come up with something clever.
Anyways, I will change this so that both methods are on WorkflowPWList to keep the logic together and use a flag for which one to use.
> Also, why are these in the PWList implementation and not in WorkflowPWList?
Yes, these could be moved to WorkflowPWList, I just made them in PWList in case I needed them for strong soundness (which uses normal PWList), but I didn't so I'll just move them.
> line 984-991 and 999-1005, please make a variable instead of constantly
> casting to WorkflowSoundne
OK, will do.
> I am not entirely sure, but I think you need a delete marking at line 1323
> (you don't add it to the PW-list and you don't use it anywhere else) - there
> is a delete in the original reachabilitysea
No, it shouldn't as the marking is looked up in the passed storage and this code is only executed if there is a match, thus a delete would delete it from the passed storage. However, I think the marking used to call AddToPW could be delete on line 1292 if there is a match is found.
> I agree with Jiri that the changes do not affect the normal verification.
Good. I'll implement the comments tomorrow and you can have another look.
Mathias Grund Sørensen (mathias.grund) wrote : | # |
I have implemented Peters comments now. I also found a bug in the covering check so apparently both types of checks would be run if there was no match due to missing return (woops...) - this should increase performance on the examples where covering check was slow.
You are welcome to take a look again to see how it looks.
The change in access modifier was due to a problem I had with overriding something, but I got it to work correctly, so I have reverted it to protected.
Jiri Srba (srba) wrote : | # |
I just tested and all works fine. Peter and Jakob, please, take a quick look so that we can merge it to trunk.
Jakob Taankvist (jakob-taankvist) wrote : | # |
I just had a quick look i think it looks good, however to avoid code redundancy shouldn't the lookup function (line 308) be used in all the addToPassed functions? And do we really need this many addToPassed functions (don't they all do the same)?
- 332. By Mathias Grund Sørensen
-
Refactored addToPassed to use the lookup method.
Mathias Grund Sørensen (mathias.grund) wrote : | # |
> I just had a quick look i think it looks good, however to avoid code
> redundancy shouldn't the lookup function (line 308) be used in all the
> addToPassed functions?
Yes, this will improve code quality, I have done that now.
> And do we really need this many addToPassed functions
> (don't they all do the same)?
Yes, the workflow algorithm handles metadata manually in the algorithm so the metadata should not be set in the AddToPassed method (this will cause problems as is) - this is the only difference.
I have now implemented all your comments (Jakob and Peter), so please, reconsider your review.
Jakob Taankvist (jakob-taankvist) : | # |
Peter Gjøl Jensen (peter-gjoel) wrote : | # |
I think that the inheritance of Reachabilitysearch in Workflow is a bit unfortunate. It seems that the only methods really used from this inheritance is "getTrace" and "isDelayPossible", the rest are overwritten. Also, why is the pwList defined as a PWList instead of WorkflowPWList? And is there any reason for the new methods in PWList (they are all unused)?
I suggest to let Workflow inherit from Verification instead, define getTrace and isDelayPossible here, move pwList here also, but change the type to WorkflowPWList. This will allow you to remove the new methods from PWList and maintain a more concise inheritance model.
- 333. By Mathias Grund Sørensen
-
Changed workflow soundness PWList* to WorkflowPWList*
- 334. By Mathias Grund Sørensen
-
Removed workflow.cpp as it contained no implementations.
- 335. By Mathias Grund Sørensen
-
Removed unneeded methods for PWListBase.
- 336. By Mathias Grund Sørensen
-
Refactored to remove Workflow supertype.
Mathias Grund Sørensen (mathias.grund) wrote : | # |
> I think that the inheritance of Reachabilitysearch in Workflow is a bit
> unfortunate. It seems that the only methods really used from this inheritance
> is "getTrace" and "isDelayPossible", the rest are overwritten.
Yes, I agree the current inheritance hierarchy is not ideal. I have simplified it a little by removing the intermediate workflow class, but I think that to make the hierarchy nice, a larger refactoring has to be done, which I suggest is done in a new branch after merging.
I strongly suggest creating a DiscreteVerific
Unless you strongly feel that this branch is too messy w.r.t. inheritance hierarchy, I think we should save it for a new branch as it will touch a lot of code.
> Also, why is
> the pwList defined as a PWList instead of WorkflowPWList? And is there any
> reason for the new methods in PWList (they are all unused)?
This has now been changed. Lookup still has to be global, as it is used in strong soundness search, which uses regular PWLists
> I suggest to let Workflow inherit from Verification instead, define getTrace
> and isDelayPossible here, move pwList here also, but change the type to
> WorkflowPWList. This will allow you to remove the new methods from PWList and
> maintain a more concise inheritance model.
I have made some changes to the inheritance model (not exactly those you suggest). Please consider my comment above and let me know if you still think the model should be improved before merging.
- 337. By Mathias Grund Sørensen
-
Removed code in comments.
Peter Gjøl Jensen (peter-gjoel) wrote : | # |
> This has now been changed. Lookup still has to be global, as it is used in strong soundness search, which uses regular PWLists
No you don't. I just removed it and put it in the workflow-pw-list, it compiles just fine. (also if you search the diff, there is no "new PWList..-" anywhere)
I poked a bit around in the code and ended up doing something like this:
lp:~peter-gjoel/verifydtapn/workflowForTrunk
> Unless you strongly feel that this branch is too messy w.r.t. inheritance hierarchy, I think we should save it for a new branch as it will touch a lot of code.
Agreed. I will approve it for now, and then we can sort out the rest in the new branch.
Preview Diff
1 | === modified file 'src/Core/ArgsParser.cpp' |
2 | --- src/Core/ArgsParser.cpp 2013-05-08 11:22:45 +0000 |
3 | +++ src/Core/ArgsParser.cpp 2013-10-27 17:10:01 +0000 |
4 | @@ -17,6 +17,7 @@ |
5 | static const std::string XML_TRACE_OPTION = "xml-trace"; |
6 | static const std::string LEGACY = "legacy"; |
7 | static const std::string KEEP_DEAD = "keep-dead-tokens"; |
8 | +static const std::string WORKFLOW = "workflow"; |
9 | |
10 | std::ostream& operator<<(std::ostream& out, const Switch& flag) { |
11 | flag.print(out); |
12 | @@ -162,6 +163,12 @@ |
13 | parsers.push_back( |
14 | boost::make_shared<Switch > ("x", XML_TRACE_OPTION, |
15 | "Output trace in xml format for TAPAAL.")); |
16 | + |
17 | + parsers.push_back( |
18 | + boost::make_shared<SwitchWithArg > ("w", WORKFLOW, |
19 | + "Workflow mode.\n - 0: Disabled\n - 1: Soundness (and min)\n - 2: Strong Soundness (and max)", |
20 | + 0)); |
21 | + |
22 | }; |
23 | |
24 | void ArgsParser::printHelp() const { |
25 | @@ -309,6 +316,20 @@ |
26 | } |
27 | |
28 | |
29 | +VerificationOptions::WorkflowMode intToWorkflowTypeEnum(int i) { |
30 | + switch (i) { |
31 | + case 0: |
32 | + return VerificationOptions::NOT_WORKFLOW; |
33 | + case 1: |
34 | + return VerificationOptions::WORKFLOW_SOUNDNESS; |
35 | + case 2: |
36 | + return VerificationOptions::WORKFLOW_STRONG_SOUNDNESS; |
37 | + default: |
38 | + std::cout << "Unknown workflow option specified." << std::endl; |
39 | + exit(1); |
40 | + } |
41 | +} |
42 | + |
43 | VerificationOptions::Trace intToEnum(int i) { |
44 | switch (i) { |
45 | case 0: |
46 | @@ -370,8 +391,14 @@ |
47 | assert(map.find(XML_TRACE_OPTION) != map.end()); |
48 | bool xml_trace = boost::lexical_cast<bool>( |
49 | map.find(XML_TRACE_OPTION)->second); |
50 | + |
51 | + assert(map.find(WORKFLOW) != map.end()); |
52 | + VerificationOptions::WorkflowMode workflow = intToWorkflowTypeEnum( |
53 | + tryParseInt(*map.find(WORKFLOW))); |
54 | + |
55 | + |
56 | |
57 | return VerificationOptions(modelFile, queryFile, search, verification, memoptimization, kbound, trace, |
58 | - xml_trace, max_constant, keep_dead); |
59 | + xml_trace, max_constant, keep_dead, workflow); |
60 | } |
61 | } |
62 | |
63 | === modified file 'src/Core/ArgsParser.hpp' |
64 | --- src/Core/ArgsParser.hpp 2013-08-13 20:59:28 +0000 |
65 | +++ src/Core/ArgsParser.hpp 2013-10-27 17:10:01 +0000 |
66 | @@ -80,7 +80,7 @@ |
67 | class ArgsParser { |
68 | typedef std::vector< boost::shared_ptr<Switch> > parser_vec; |
69 | public: |
70 | - ArgsParser() : parsers(), version(2,1,0) { initialize(); }; |
71 | + ArgsParser() : parsers(), version(2,2,0) { initialize(); }; |
72 | virtual ~ArgsParser() {}; |
73 | |
74 | VerificationOptions parse(int argc, char* argv[]) const; |
75 | |
76 | === modified file 'src/Core/QueryParser/AST.hpp' |
77 | --- src/Core/QueryParser/AST.hpp 2013-08-09 21:47:22 +0000 |
78 | +++ src/Core/QueryParser/AST.hpp 2013-10-27 17:10:01 +0000 |
79 | @@ -218,6 +218,7 @@ |
80 | |
81 | Quantifier getQuantifier() const { return quantifier; } |
82 | const Expression& getChild() const { return *expr; } |
83 | + void setQuantifier(Quantifier q){ quantifier = q; } |
84 | private: |
85 | Quantifier quantifier; |
86 | Expression* expr; |
87 | |
88 | === modified file 'src/Core/TAPN/TimedPlace.hpp' |
89 | --- src/Core/TAPN/TimedPlace.hpp 2013-07-25 21:04:53 +0000 |
90 | +++ src/Core/TAPN/TimedPlace.hpp 2013-10-27 17:10:01 +0000 |
91 | @@ -62,6 +62,7 @@ |
92 | inline const TransportArc::Vector& getTransportArcs() const { return transportArcs; } |
93 | inline const InhibitorArc::Vector& getInhibitorArcs() const { return inhibitorArcs; } |
94 | inline const TimedInputArc::Vector& getInputArcs() const { return inputArcs; } |
95 | + inline const OutputArc::Vector& getOutputArcs() const { return outputArcs; } |
96 | |
97 | private: // data |
98 | PlaceType type; |
99 | |
100 | === modified file 'src/Core/VerificationOptions.hpp' |
101 | --- src/Core/VerificationOptions.hpp 2013-05-08 11:12:08 +0000 |
102 | +++ src/Core/VerificationOptions.hpp 2013-10-27 17:10:01 +0000 |
103 | @@ -26,6 +26,10 @@ |
104 | NO_MEMORY_OPTIMIZATION, PTRIE |
105 | }; |
106 | |
107 | + enum WorkflowMode{ |
108 | + NOT_WORKFLOW, WORKFLOW_SOUNDNESS, WORKFLOW_STRONG_SOUNDNESS |
109 | + }; |
110 | + |
111 | VerificationOptions() { |
112 | } |
113 | |
114 | @@ -39,8 +43,8 @@ |
115 | Trace trace, |
116 | bool xml_trace, |
117 | bool useGlobalMaxConstants, |
118 | - bool keepDeadTokens |
119 | - ) : inputFile(inputFile), |
120 | + bool keepDeadTokens, |
121 | + WorkflowMode workflow) : inputFile(inputFile), |
122 | queryFile(queryFile), |
123 | searchType(searchType), |
124 | verificationType(verificationType), |
125 | @@ -49,7 +53,8 @@ |
126 | trace(trace), |
127 | xml_trace(xml_trace), |
128 | useGlobalMaxConstants(useGlobalMaxConstants), |
129 | - keepDeadTokens(keepDeadTokens) { |
130 | + keepDeadTokens(keepDeadTokens), |
131 | + workflow(workflow){ |
132 | |
133 | }; |
134 | |
135 | @@ -94,6 +99,15 @@ |
136 | inline const bool getKeepDeadTokens() const { |
137 | return keepDeadTokens; |
138 | }; |
139 | + |
140 | + inline const WorkflowMode getWorkflowMode() const { |
141 | + return workflow; |
142 | + }; |
143 | + |
144 | + inline bool isWorkflow() const{ |
145 | + return workflow != NOT_WORKFLOW; |
146 | + } |
147 | + |
148 | private: |
149 | std::string inputFile; |
150 | std::string queryFile; |
151 | @@ -105,6 +119,7 @@ |
152 | bool xml_trace; |
153 | bool useGlobalMaxConstants; |
154 | bool keepDeadTokens; |
155 | + WorkflowMode workflow; |
156 | }; |
157 | |
158 | std::ostream& operator<<(std::ostream& out, const VerificationOptions& options); |
159 | |
160 | === modified file 'src/DiscreteVerification/DataStructures/NonStrictMarking.hpp' |
161 | --- src/DiscreteVerification/DataStructures/NonStrictMarking.hpp 2013-08-01 21:55:57 +0000 |
162 | +++ src/DiscreteVerification/DataStructures/NonStrictMarking.hpp 2013-10-27 17:10:01 +0000 |
163 | @@ -18,6 +18,8 @@ |
164 | |
165 | namespace VerifyTAPN { |
166 | namespace DiscreteVerification { |
167 | + |
168 | + class NonStrictMarking; |
169 | |
170 | struct MetaData { |
171 | public: |
172 | @@ -30,6 +32,20 @@ |
173 | const TAPN::TimedTransition* generatedBy; |
174 | }; |
175 | |
176 | + struct WorkflowSoundnessMetaData : public MetaData { |
177 | + public: |
178 | + WorkflowSoundnessMetaData() : parents(new vector<NonStrictMarking*>), min(INT_MAX) {}; |
179 | + vector<NonStrictMarking*>* parents; |
180 | + int min; |
181 | + }; |
182 | + |
183 | + struct WorkflowStrongSoundnessMetaData : public MetaData { |
184 | + public: |
185 | + WorkflowStrongSoundnessMetaData() : parents(new vector<NonStrictMarking*>) {}; |
186 | + vector<NonStrictMarking*>* parents; |
187 | + }; |
188 | + |
189 | + |
190 | // ugly forward declaration |
191 | template<class MetaData> |
192 | struct EncodingPointer; |
193 | @@ -42,17 +58,16 @@ |
194 | class NonStrictMarking : public NonStrictMarkingBase{ |
195 | public: |
196 | NonStrictMarking():NonStrictMarkingBase(), meta(new MetaData()){} |
197 | - NonStrictMarking(const TAPN::TimedArcPetriNet& tapn, const std::vector<int>& v):NonStrictMarkingBase(tapn, v){} |
198 | - NonStrictMarking(const NonStrictMarkingBase& nsm):NonStrictMarkingBase(nsm){ |
199 | + NonStrictMarking(const TAPN::TimedArcPetriNet& tapn, const std::vector<int>& v): NonStrictMarkingBase(tapn, v), meta(NULL){} |
200 | + NonStrictMarking(const NonStrictMarkingBase& nsm):NonStrictMarkingBase(nsm), meta(NULL){ |
201 | |
202 | } |
203 | - NonStrictMarking(const NonStrictMarking& nsm):NonStrictMarkingBase(nsm){ |
204 | + NonStrictMarking(const NonStrictMarking& nsm):NonStrictMarkingBase(nsm), meta(NULL){ |
205 | |
206 | } |
207 | public: |
208 | MetaData* meta; |
209 | }; |
210 | - |
211 | |
212 | } /* namespace DiscreteVerification */ |
213 | } /* namespace VerifyTAPN */ |
214 | |
215 | === modified file 'src/DiscreteVerification/DataStructures/NonStrictMarkingBase.cpp' |
216 | --- src/DiscreteVerification/DataStructures/NonStrictMarkingBase.cpp 2013-07-26 21:59:47 +0000 |
217 | +++ src/DiscreteVerification/DataStructures/NonStrictMarkingBase.cpp 2013-10-27 17:10:01 +0000 |
218 | @@ -216,14 +216,12 @@ |
219 | } |
220 | |
221 | std::ostream& operator<<(std::ostream& out, NonStrictMarkingBase& x) { |
222 | - out << "-"; |
223 | for (PlaceList::iterator iter = x.places.begin(); iter != x.places.end(); iter++) { |
224 | - out << "place " << iter->place->getId() << " has tokens (age, count): "; |
225 | for (TokenList::iterator it = iter->tokens.begin(); it != iter->tokens.end(); it++) { |
226 | - out << "(" << it->getAge() << ", " << it->getCount() << ") "; |
227 | + out << "(" << iter->place->getName() << ", "<< it->getAge() << ", " << it->getCount() << ")"; |
228 | } |
229 | if (iter != x.places.end() - 1) { |
230 | - out << endl; |
231 | + out << ", "; |
232 | } |
233 | } |
234 | |
235 | |
236 | === modified file 'src/DiscreteVerification/DataStructures/PWList.cpp' |
237 | --- src/DiscreteVerification/DataStructures/PWList.cpp 2013-08-26 14:17:55 +0000 |
238 | +++ src/DiscreteVerification/DataStructures/PWList.cpp 2013-10-27 17:10:01 +0000 |
239 | @@ -30,11 +30,24 @@ |
240 | } |
241 | stored++; |
242 | m.push_back(marking); |
243 | - marking->meta = new MetaData(); |
244 | + marking->meta = new MetaData(); |
245 | waiting_list->add(marking, marking); |
246 | return true; |
247 | } |
248 | |
249 | +NonStrictMarking* PWList::addToPassed(NonStrictMarking* marking){ |
250 | + NonStrictMarking* existing = lookup(marking); |
251 | + if(existing != NULL){ |
252 | + return existing; |
253 | + }else{ |
254 | + NonStrictMarkingList& m = markings_storage[marking->getHashKey()]; |
255 | + stored++; |
256 | + m.push_back(marking); |
257 | + marking->meta = new MetaData(); |
258 | + return marking; |
259 | + } |
260 | + } |
261 | + |
262 | NonStrictMarking* PWList::getNextUnexplored(){ |
263 | return waiting_list->pop(); |
264 | } |
265 | |
266 | === modified file 'src/DiscreteVerification/DataStructures/PWList.hpp' |
267 | --- src/DiscreteVerification/DataStructures/PWList.hpp 2013-08-10 20:30:06 +0000 |
268 | +++ src/DiscreteVerification/DataStructures/PWList.hpp 2013-10-27 17:10:01 +0000 |
269 | @@ -17,7 +17,7 @@ |
270 | |
271 | namespace VerifyTAPN { |
272 | namespace DiscreteVerification { |
273 | - |
274 | + |
275 | class PWListBase { |
276 | public: |
277 | PWListBase() : stored(0), discoveredMarkings(0), maxNumTokensInAnyMarking(-1), isLiveness(false) {}; |
278 | @@ -26,16 +26,17 @@ |
279 | int discoveredMarkings; |
280 | int maxNumTokensInAnyMarking; |
281 | bool isLiveness; |
282 | - |
283 | + |
284 | virtual bool hasWaitingStates() = 0; |
285 | virtual long long size() const = 0; |
286 | virtual bool add(NonStrictMarking* marking) = 0; |
287 | - virtual NonStrictMarking* getNextUnexplored() = 0; |
288 | + virtual NonStrictMarking* lookup(NonStrictMarking* marking){ return NULL; } |
289 | + virtual NonStrictMarking* getNextUnexplored() = 0; |
290 | virtual long long explored()= 0; |
291 | virtual ~PWListBase(){}; |
292 | - inline void setMaxNumTokensIfGreater(int i){ if(i>maxNumTokensInAnyMarking) maxNumTokensInAnyMarking = i; }; |
293 | + inline void setMaxNumTokensIfGreater(int i){ if(i>maxNumTokensInAnyMarking) maxNumTokensInAnyMarking = i; }; |
294 | }; |
295 | - |
296 | + |
297 | class PWList : public PWListBase { |
298 | public: |
299 | typedef std::vector<NonStrictMarking*> NonStrictMarkingList; |
300 | @@ -51,14 +52,32 @@ |
301 | return (waiting_list->size() > 0); |
302 | }; |
303 | |
304 | + virtual NonStrictMarking* lookup(NonStrictMarking* marking){ |
305 | + NonStrictMarkingList& m = markings_storage[marking->getHashKey()]; |
306 | + for(NonStrictMarkingList::const_iterator iter = m.begin(); |
307 | + iter != m.end(); |
308 | + iter++){ |
309 | + if((*iter)->equals(*marking)){ |
310 | + return *iter; |
311 | + } |
312 | + } |
313 | + return NULL; |
314 | + } |
315 | + |
316 | + virtual bool addToWaiting(NonStrictMarking* marking){ |
317 | + waiting_list->add(marking, marking); |
318 | + return true; |
319 | + } |
320 | + |
321 | virtual long long size() const { |
322 | return stored; |
323 | }; |
324 | |
325 | virtual long long explored() {return waiting_list->size();}; |
326 | - |
327 | + |
328 | public: // modifiers |
329 | virtual bool add(NonStrictMarking* marking); |
330 | + virtual NonStrictMarking* addToPassed(NonStrictMarking* marking); |
331 | virtual NonStrictMarking* getNextUnexplored(); |
332 | |
333 | public: |
334 | |
335 | === modified file 'src/DiscreteVerification/DataStructures/WaitingList.hpp' |
336 | --- src/DiscreteVerification/DataStructures/WaitingList.hpp 2013-08-26 14:17:55 +0000 |
337 | +++ src/DiscreteVerification/DataStructures/WaitingList.hpp 2013-10-27 17:10:01 +0000 |
338 | @@ -127,6 +127,24 @@ |
339 | }; |
340 | |
341 | template <class T> |
342 | +class WorkflowMinFirstWaitingList : public WaitingList<T>{ |
343 | +public: |
344 | + typedef std::priority_queue<WeightedItem<T>, std::vector<WeightedItem<T> >, less<T> > priority_queue; |
345 | +public: |
346 | + WorkflowMinFirstWaitingList(AST::Query* q) : queue(), query(q) { }; |
347 | + virtual ~WorkflowMinFirstWaitingList(); |
348 | +public: |
349 | + virtual void add(NonStrictMarkingBase* weight, T* payload); |
350 | + virtual T* peek(); |
351 | + virtual T* pop(); |
352 | + virtual size_t size() { return queue.size(); }; |
353 | +private: |
354 | + int calculateWeight(NonStrictMarking* payload); |
355 | + priority_queue queue; |
356 | + AST::Query* query; |
357 | +}; |
358 | + |
359 | +template <class T> |
360 | class RandomStackWaitingList : public StackWaitingList<T>{ |
361 | public: |
362 | typedef std::priority_queue<WeightedItem<T>, std::vector<WeightedItem<T> >, less<T> > priority_queue; |
363 | @@ -336,6 +354,54 @@ |
364 | } |
365 | |
366 | template <class T> |
367 | +void WorkflowMinFirstWaitingList<T>::add(NonStrictMarkingBase* weight, T* payload) |
368 | +{ |
369 | + assert(false); |
370 | + WeightedItem<T> weighted_item; |
371 | + weighted_item.item = payload; |
372 | + weighted_item.weight = 0; |
373 | + queue.push(weighted_item); |
374 | +} |
375 | + |
376 | +template <> |
377 | +inline void WorkflowMinFirstWaitingList<NonStrictMarking>::add(NonStrictMarkingBase* weight, NonStrictMarking* payload) |
378 | +{ |
379 | + WeightedItem<NonStrictMarking> weighted_item; |
380 | + weighted_item.item = payload; |
381 | + weighted_item.weight = calculateWeight(payload); |
382 | + queue.push(weighted_item); |
383 | +} |
384 | + |
385 | +template <class T> |
386 | +T* WorkflowMinFirstWaitingList<T>::pop() |
387 | +{ |
388 | + WeightedItem<T> weighted_item = queue.top(); |
389 | + T* marking = weighted_item.item; |
390 | + queue.pop(); |
391 | + return marking; |
392 | +} |
393 | + |
394 | +template <class T> |
395 | +T* WorkflowMinFirstWaitingList<T>::peek() |
396 | +{ |
397 | + WeightedItem<T> weighted_item = queue.top(); |
398 | + T* marking = weighted_item.item; |
399 | + return marking; |
400 | +} |
401 | + |
402 | +template <class T> |
403 | +int WorkflowMinFirstWaitingList<T>::calculateWeight(NonStrictMarking* payload) |
404 | +{ |
405 | + return ((WorkflowSoundnessMetaData*)payload->meta)->min; |
406 | +} |
407 | + |
408 | +template <class T> |
409 | +WorkflowMinFirstWaitingList<T>::~WorkflowMinFirstWaitingList() |
410 | +{ |
411 | +} |
412 | + |
413 | + |
414 | +template <class T> |
415 | void RandomWaitingList<T>::add(NonStrictMarkingBase* weight, T* payload) |
416 | { |
417 | WeightedItem<T> weighted_item; |
418 | |
419 | === added file 'src/DiscreteVerification/DataStructures/WorkflowPWList.hpp' |
420 | --- src/DiscreteVerification/DataStructures/WorkflowPWList.hpp 1970-01-01 00:00:00 +0000 |
421 | +++ src/DiscreteVerification/DataStructures/WorkflowPWList.hpp 2013-10-27 17:10:01 +0000 |
422 | @@ -0,0 +1,150 @@ |
423 | +/* |
424 | + * PWList.hpp |
425 | + * |
426 | + * Created on: 01/03/2012 |
427 | + * Author: MathiasGS |
428 | + */ |
429 | + |
430 | +#ifndef WORKFLOWPWLIST_HPP_ |
431 | +#define WORKFLOWPWLIST_HPP_ |
432 | + |
433 | +#include "WaitingList.hpp" |
434 | +#include <iostream> |
435 | +#include "google/sparse_hash_map" |
436 | +#include "NonStrictMarking.hpp" |
437 | +#include "NonStrictMarking.hpp" |
438 | +#include "WaitingList.hpp" |
439 | +#include "PWList.hpp" |
440 | + |
441 | +namespace VerifyTAPN { |
442 | +namespace DiscreteVerification { |
443 | + |
444 | + class WorkflowPWList : public PWList { |
445 | + public: |
446 | + NonStrictMarking* getCoveredMarking(NonStrictMarking* marking, bool useLinearSweep){ |
447 | + if(useLinearSweep){ |
448 | + for(HashMap::const_iterator iter = markings_storage.begin(); iter != markings_storage.end(); ++iter){ |
449 | + for(NonStrictMarkingList::const_iterator m_iter = iter->second.begin(); m_iter != iter->second.end(); m_iter++){ |
450 | + if((*m_iter)->size() >= marking->size()){ |
451 | + continue; |
452 | + } |
453 | + |
454 | + // Test if m_iter is covered by marking |
455 | + PlaceList::const_iterator marking_place_iter = marking->getPlaceList().begin(); |
456 | + |
457 | + bool tokensCovered = true; |
458 | + for(PlaceList::const_iterator m_place_iter = (*m_iter)->getPlaceList().begin(); m_place_iter != (*m_iter)->getPlaceList().end(); ++m_place_iter){ |
459 | + while(marking_place_iter != marking->getPlaceList().end() && marking_place_iter->place != m_place_iter->place){ |
460 | + ++marking_place_iter; |
461 | + } |
462 | + |
463 | + if(marking_place_iter == marking->getPlaceList().end()){ |
464 | + tokensCovered = false; |
465 | + break; // Place not covered in marking |
466 | + } |
467 | + |
468 | + TokenList::const_iterator marking_token_iter = marking_place_iter->tokens.begin(); |
469 | + for(TokenList::const_iterator m_token_iter = m_place_iter->tokens.begin(); m_token_iter != m_place_iter->tokens.end(); ++m_token_iter){ |
470 | + while(marking_token_iter != marking_place_iter->tokens.end() && marking_token_iter->getAge() != m_token_iter->getAge()){ |
471 | + ++marking_token_iter; |
472 | + } |
473 | + |
474 | + if(marking_token_iter == marking_place_iter->tokens.end() || marking_token_iter->getCount() < m_token_iter->getCount()){ |
475 | + tokensCovered = false; |
476 | + break; |
477 | + } |
478 | + } |
479 | + |
480 | + if(!tokensCovered) break; |
481 | + } |
482 | + |
483 | + if(tokensCovered){ |
484 | + return *m_iter; |
485 | + } |
486 | + } |
487 | + } |
488 | + }else{ |
489 | + vector<NonStrictMarking*> coveredMarkings; |
490 | + coveredMarkings.push_back(new NonStrictMarking(*marking)); |
491 | + for(PlaceList::const_iterator p_iter = marking->getPlaceList().begin(); p_iter != marking->getPlaceList().end(); ++p_iter){ |
492 | + for(TokenList::const_iterator t_iter = p_iter->tokens.begin(); t_iter != p_iter->tokens.end(); ++t_iter){ |
493 | + for(int i = 1; i <= t_iter->getCount(); ++i){ |
494 | + vector<NonStrictMarking*> toAdd; |
495 | + for(vector<NonStrictMarking*>::iterator iter = coveredMarkings.begin(); iter != coveredMarkings.end(); ++iter){ |
496 | + NonStrictMarking* new_marking = new NonStrictMarking(**iter); |
497 | + for(int ii = i; ii > 0; --ii){ |
498 | + new_marking->removeToken(p_iter->place->getIndex(), t_iter->getAge()); |
499 | + } |
500 | + toAdd.push_back(new_marking); |
501 | + } |
502 | + for(vector<NonStrictMarking*>::iterator iter = toAdd.begin(); iter != toAdd.end(); ++iter){ |
503 | + coveredMarkings.push_back(*iter); |
504 | + } |
505 | + } |
506 | + } |
507 | + } |
508 | + |
509 | + bool isFirst = true; |
510 | + for(vector<NonStrictMarking*>::iterator iter = coveredMarkings.begin(); iter != coveredMarkings.end(); ++iter){ |
511 | + if(isFirst){ |
512 | + isFirst = false; |
513 | + continue; |
514 | + } |
515 | + NonStrictMarking* covered = lookup(*iter); |
516 | + if(covered != NULL){ |
517 | + return covered; |
518 | + } |
519 | + delete *iter; |
520 | + } |
521 | + } |
522 | + return NULL; |
523 | + } |
524 | + |
525 | + NonStrictMarking* getUnpassed(){ |
526 | + for(HashMap::iterator hmiter = markings_storage.begin(); hmiter != markings_storage.end(); hmiter++){ |
527 | + for(NonStrictMarkingList::const_iterator iter = hmiter->second.begin(); |
528 | + iter != hmiter->second.end(); |
529 | + iter++){ |
530 | + if(!(*iter)->meta->passed){ |
531 | + return *iter; |
532 | + } |
533 | + } |
534 | + } |
535 | + return NULL; |
536 | + } |
537 | + |
538 | + |
539 | + WorkflowPWList(WaitingList<NonStrictMarking>* w_l) : PWList(w_l, false) {}; |
540 | + bool add(NonStrictMarking* marking){ |
541 | + discoveredMarkings++; |
542 | + NonStrictMarkingList& m = markings_storage[marking->getHashKey()]; |
543 | + for(NonStrictMarkingList::const_iterator iter = m.begin(); |
544 | + iter != m.end(); |
545 | + iter++){ |
546 | + if((*iter)->equals(*marking)){ |
547 | + return false; |
548 | + } |
549 | + } |
550 | + stored++; |
551 | + m.push_back(marking); |
552 | + waiting_list->add(marking, marking); |
553 | + return true; |
554 | + } |
555 | + |
556 | + NonStrictMarking* addToPassed(NonStrictMarking* marking){ |
557 | + NonStrictMarking* existing = lookup(marking); |
558 | + if(existing != NULL){ |
559 | + return existing; |
560 | + }else{ |
561 | + NonStrictMarkingList& m = markings_storage[marking->getHashKey()]; |
562 | + stored++; |
563 | + m.push_back(marking); |
564 | + return marking; |
565 | + } |
566 | + } |
567 | + |
568 | + }; |
569 | + |
570 | +} /* namespace DiscreteVerification */ |
571 | +} /* namespace VerifyTAPN */ |
572 | +#endif /* PWLIST_HPP_ */ |
573 | |
574 | === modified file 'src/DiscreteVerification/DiscreteVerification.cpp' |
575 | --- src/DiscreteVerification/DiscreteVerification.cpp 2013-08-10 20:30:06 +0000 |
576 | +++ src/DiscreteVerification/DiscreteVerification.cpp 2013-10-27 17:10:01 +0000 |
577 | @@ -47,7 +47,49 @@ |
578 | std::cout << options << std::endl; |
579 | |
580 | // Select verification method |
581 | - if (options.getVerificationType() == VerificationOptions::DISCRETE) { |
582 | + if(options.getWorkflowMode() != VerificationOptions::NOT_WORKFLOW){ |
583 | + if (options.getVerificationType() == VerificationOptions::TIMEDART) { |
584 | + cout << "Workflow analysis currently only supports discrete exploration (i.e. not TimeDarts)." << endl; |
585 | + exit(1); |
586 | + } |
587 | + |
588 | + if (options.getMemoryOptimization() != VerificationOptions::NO_MEMORY_OPTIMIZATION) { |
589 | + cout << "Workflow analysis currently does not support any memory optimizations (i.e. no PTries)." << endl; |
590 | + exit(1); |
591 | + } |
592 | + WaitingList<NonStrictMarking>* strategy = getWaitingList<NonStrictMarking > (query, options); |
593 | + if(options.getWorkflowMode() == VerificationOptions::WORKFLOW_SOUNDNESS){ |
594 | + WorkflowSoundness* verifier = new WorkflowSoundness(tapn, *initialMarking, query, options, strategy); |
595 | + |
596 | + if(verifier->getModelType() == verifier->NOTTAWFN){ |
597 | + std::cerr << "Model is not a TAWFN!" << std::endl; |
598 | + return -1; |
599 | + }else if(verifier->getModelType() == verifier->ETAWFN){ |
600 | + std::cout << "Model is a ETAWFN" << std::endl << std::endl; |
601 | + }else if(verifier->getModelType() == verifier->MTAWFN){ |
602 | + std::cout << "Model is a MTAWFN" << std::endl << std::endl; |
603 | + } |
604 | + VerifyAndPrint( |
605 | + *verifier, |
606 | + options, |
607 | + query); |
608 | + verifier->printExecutionTime(cout); |
609 | + verifier->printMessages(cout); |
610 | + } |
611 | + else{ |
612 | + // Assumes correct structure of net! |
613 | + WorkflowStrongSoundnessReachability* verifier = new WorkflowStrongSoundnessReachability(tapn, *initialMarking, query, options, strategy); |
614 | + VerifyAndPrint( |
615 | + *verifier, |
616 | + options, |
617 | + query); |
618 | + verifier->printExecutionTime(cout); |
619 | + } |
620 | + |
621 | + delete strategy; |
622 | + |
623 | + } |
624 | + else if (options.getVerificationType() == VerificationOptions::DISCRETE) { |
625 | |
626 | if (options.getMemoryOptimization() == VerificationOptions::PTRIE) { |
627 | //TODO fix initialization |
628 | @@ -137,7 +179,7 @@ |
629 | } |
630 | |
631 | template<typename T> void VerifyAndPrint(Verification<T>& verifier, VerificationOptions& options, AST::Query* query) { |
632 | - bool result = (query->getQuantifier() == AG || query->getQuantifier() == AF) ? !verifier.verify() : verifier.verify(); |
633 | + bool result = (!options.isWorkflow() && (query->getQuantifier() == AG || query->getQuantifier() == AF)) ? !verifier.verify() : verifier.verify(); |
634 | |
635 | verifier.printStats(); |
636 | verifier.printTransitionStatistics(); |
637 | @@ -150,7 +192,7 @@ |
638 | std::cout << verifier.maxUsedTokens() << std::endl; |
639 | |
640 | if (options.getTrace() == VerificationOptions::SOME_TRACE) { |
641 | - if ((query->getQuantifier() == EF && result) || (query->getQuantifier() == AG && !result) || (query->getQuantifier() == EG && result) || (query->getQuantifier() == AF && !result)) { |
642 | + if ((query->getQuantifier() == EF && result) || (query->getQuantifier() == AG && !result) || (query->getQuantifier() == EG && result) || (query->getQuantifier() == AF && !result) || (options.isWorkflow())) { |
643 | verifier.getTrace(); |
644 | } else { |
645 | std::cout << "A trace could not be generated due to the query result" << std::endl; |
646 | |
647 | === modified file 'src/DiscreteVerification/DiscreteVerification.hpp' |
648 | --- src/DiscreteVerification/DiscreteVerification.hpp 2013-07-26 21:59:47 +0000 |
649 | +++ src/DiscreteVerification/DiscreteVerification.hpp 2013-10-27 17:10:01 +0000 |
650 | @@ -23,6 +23,8 @@ |
651 | #include "VerificationTypes/ReachabilitySearch.hpp" |
652 | #include "VerificationTypes/TimeDartReachabilitySearch.hpp" |
653 | #include "VerificationTypes/TimeDartLiveness.hpp" |
654 | +#include "VerificationTypes/WorkflowSoundness.hpp" |
655 | +#include "VerificationTypes/WorkflowStrongSoundness.hpp" |
656 | #include "SearchStrategies/SearchFactory.h" |
657 | #include "DataStructures/PTrie.h" |
658 | |
659 | |
660 | === modified file 'src/DiscreteVerification/SearchStrategies/SearchFactory.h' |
661 | --- src/DiscreteVerification/SearchStrategies/SearchFactory.h 2013-05-08 11:43:09 +0000 |
662 | +++ src/DiscreteVerification/SearchStrategies/SearchFactory.h 2013-10-27 17:10:01 +0000 |
663 | @@ -17,7 +17,10 @@ |
664 | template <class T> |
665 | WaitingList<T>* getWaitingList(AST::Query* query, VerificationOptions& options){ |
666 | WaitingList<T>* strategy = NULL; |
667 | - if(query->getQuantifier() == EG || query->getQuantifier() == AF){ |
668 | + if(options.getWorkflowMode() == options.WORKFLOW_SOUNDNESS){ |
669 | + WorkflowMinFirst<T> s; |
670 | + strategy = s.createWaitingList(query); |
671 | + } else if(query->getQuantifier() == EG || query->getQuantifier() == AF){ |
672 | //Liveness query, force DFS |
673 | switch(options.getSearchType()){ |
674 | case VerificationOptions::DEPTHFIRST: { |
675 | |
676 | === modified file 'src/DiscreteVerification/SearchStrategies/SearchStrategies.hpp' |
677 | --- src/DiscreteVerification/SearchStrategies/SearchStrategies.hpp 2012-09-20 14:02:19 +0000 |
678 | +++ src/DiscreteVerification/SearchStrategies/SearchStrategies.hpp 2013-10-27 17:10:01 +0000 |
679 | @@ -9,5 +9,6 @@ |
680 | #include "NonStrictRandom.hpp" |
681 | #include "NonStrictDFSHeuristic.hpp" |
682 | #include "NonStrictDFSRandom.hpp" |
683 | +#include "WorkflowMinFirst.hpp" |
684 | |
685 | #endif /* TAPN_HPP_ */ |
686 | |
687 | === added file 'src/DiscreteVerification/SearchStrategies/WorkflowMinFirst.hpp' |
688 | --- src/DiscreteVerification/SearchStrategies/WorkflowMinFirst.hpp 1970-01-01 00:00:00 +0000 |
689 | +++ src/DiscreteVerification/SearchStrategies/WorkflowMinFirst.hpp 2013-10-27 17:10:01 +0000 |
690 | @@ -0,0 +1,42 @@ |
691 | +/* |
692 | + * NonStrictDFS.hpp |
693 | + * |
694 | + * Created on: 05/03/2012 |
695 | + * Author: MathiasGS |
696 | + */ |
697 | + |
698 | +#ifndef SMALLESTDELAYFIRST_HPP_ |
699 | +#define SMALLESTDELAYFIRST_HPP_ |
700 | + |
701 | +#include "../DataStructures/PWList.hpp" |
702 | +#include "../../Core/TAPN/TAPN.hpp" |
703 | +#include "../../Core/QueryParser/AST.hpp" |
704 | +#include "../../Core/VerificationOptions.hpp" |
705 | + |
706 | +#include "../../Core/TAPN/TimedPlace.hpp" |
707 | +#include "../../Core/TAPN/TimedTransition.hpp" |
708 | +#include "../../Core/TAPN/TimedInputArc.hpp" |
709 | +#include "../../Core/TAPN/TransportArc.hpp" |
710 | +#include "../../Core/TAPN/InhibitorArc.hpp" |
711 | +#include "../../Core/TAPN/OutputArc.hpp" |
712 | + |
713 | +#include "../SuccessorGenerator.hpp" |
714 | + |
715 | +#include "../QueryVisitor.hpp" |
716 | + |
717 | +#include <stack> |
718 | +#include "SearchStrategy.hpp" |
719 | + |
720 | +namespace VerifyTAPN { |
721 | + |
722 | +namespace DiscreteVerification { |
723 | + |
724 | +template <class T> |
725 | +class WorkflowMinFirst : public SearchStrategy<T> { |
726 | +public: |
727 | + virtual WaitingList<T>* createWaitingList(AST::Query* query) const { return new WorkflowMinFirstWaitingList<T>(query); }; |
728 | +}; |
729 | + |
730 | +} |
731 | +} |
732 | +#endif /* NONSTRICTDFS_HPP_ */ |
733 | |
734 | === added file 'src/DiscreteVerification/VerificationTypes/WorkflowSoundness.cpp' |
735 | --- src/DiscreteVerification/VerificationTypes/WorkflowSoundness.cpp 1970-01-01 00:00:00 +0000 |
736 | +++ src/DiscreteVerification/VerificationTypes/WorkflowSoundness.cpp 2013-10-27 17:10:01 +0000 |
737 | @@ -0,0 +1,206 @@ |
738 | +/* |
739 | + * NonStrictSearch.cpp |
740 | + * |
741 | + * Created on: 26/04/2012 |
742 | + * Author: MathiasGS |
743 | + */ |
744 | + |
745 | +#include "WorkflowSoundness.hpp" |
746 | + |
747 | +namespace VerifyTAPN { |
748 | +namespace DiscreteVerification { |
749 | + |
750 | +WorkflowSoundness::WorkflowSoundness(TAPN::TimedArcPetriNet& tapn, NonStrictMarking& initialMarking, AST::Query* query, VerificationOptions options, WaitingList<NonStrictMarking>* waiting_list) |
751 | +: ReachabilitySearch(tapn, initialMarking, query, options, waiting_list), pwList(new WorkflowPWList(waiting_list)), final_set(new vector<NonStrictMarking*>), min_exec(INT_MAX), linearSweepTreshold(3), coveredMarking(NULL), in(NULL), out(NULL), modelType(calculateModelType()){ |
752 | + for(TimedPlace::Vector::const_iterator iter = tapn.getPlaces().begin(); iter != tapn.getPlaces().end(); iter++){ |
753 | + if((*iter)->getType() == Dead){ |
754 | + (*iter)->setType(Std); |
755 | + } |
756 | + } |
757 | +} |
758 | + |
759 | +bool WorkflowSoundness::verify(){ |
760 | + if(addToPW(&initialMarking, NULL)){ |
761 | + return false; |
762 | + } |
763 | + |
764 | + // Phase 1 |
765 | + while(pwList->hasWaitingStates()){ |
766 | + NonStrictMarking& next_marking = *pwList->getNextUnexplored(); |
767 | + tmpParent = &next_marking; |
768 | + bool noDelay = false; |
769 | + Result res = successorGenerator.generateAndInsertSuccessors(next_marking); |
770 | + if(res == QUERY_SATISFIED){ |
771 | + return false; |
772 | + } else if (res == URGENT_ENABLED) { |
773 | + noDelay = true; |
774 | + } |
775 | + |
776 | + // Generate next markings |
777 | + if(!noDelay && isDelayPossible(next_marking)){ |
778 | + NonStrictMarking* marking = new NonStrictMarking(next_marking); |
779 | + marking->incrementAge(); |
780 | + marking->setGeneratedBy(NULL); |
781 | + if(addToPW(marking, &next_marking)){ |
782 | + return false; |
783 | + } |
784 | + } |
785 | + } |
786 | + |
787 | + // Phase 2 |
788 | + for(vector<NonStrictMarking*>::iterator iter = final_set->begin(); iter != final_set->end(); iter++){ |
789 | + pwList->addToWaiting(*iter); |
790 | + if(((WorkflowSoundnessMetaData*)(*iter)->meta)->min < min_exec){ |
791 | + min_exec = ((WorkflowSoundnessMetaData*)(*iter)->meta)->min; |
792 | + lastMarking = (*iter); |
793 | + } |
794 | + } |
795 | + |
796 | + while(pwList->hasWaitingStates()){ |
797 | + NonStrictMarking* next_marking = pwList->getNextUnexplored(); |
798 | + if(next_marking->meta->passed) continue; |
799 | + next_marking->meta->passed = true; |
800 | + for(vector<NonStrictMarking*>::iterator iter = ((WorkflowSoundnessMetaData*)next_marking->meta)->parents->begin(); iter != ((WorkflowSoundnessMetaData*)next_marking->meta)->parents->end(); iter++){ |
801 | + pwList->addToWaiting(*iter); |
802 | + } |
803 | + } |
804 | + |
805 | + NonStrictMarking* unpassed = pwList->getUnpassed(); |
806 | + if(unpassed == NULL){ |
807 | + return true; |
808 | + }else{ |
809 | + lastMarking = unpassed; |
810 | + return false; |
811 | + } |
812 | +} |
813 | + |
814 | +bool WorkflowSoundness::addToPW(NonStrictMarking* marking, NonStrictMarking* parent){ |
815 | + marking->cut(); |
816 | + |
817 | + unsigned int size = marking->size(); |
818 | + |
819 | + // Check K-bound |
820 | + pwList->setMaxNumTokensIfGreater(size); |
821 | + if(modelType == ETAWFN && size > options.getKBound()) { |
822 | + lastMarking = marking; |
823 | + return true; // Terminate false |
824 | + } |
825 | + |
826 | + // Map to existing marking if any |
827 | + NonStrictMarking* lookup = pwList->lookup(marking); |
828 | + if(lookup != NULL){ |
829 | + delete marking; |
830 | + marking = lookup; |
831 | + }else{ |
832 | + marking->meta = new WorkflowSoundnessMetaData(); |
833 | + } |
834 | + |
835 | + WorkflowSoundnessMetaData* marking_meta_data = ((WorkflowSoundnessMetaData*)marking->meta); |
836 | + |
837 | + // add to parents_set |
838 | + if(parent != NULL){ |
839 | + WorkflowSoundnessMetaData* parent_meta_data = ((WorkflowSoundnessMetaData*)parent->meta); |
840 | + marking_meta_data->parents->push_back(parent); |
841 | + if(marking->getGeneratedBy() == NULL){ |
842 | + marking_meta_data->min = min(marking_meta_data->min, parent_meta_data->min+1); // Delay |
843 | + }else{ |
844 | + marking_meta_data->min = min(marking_meta_data->min, parent_meta_data->min); // Transition |
845 | + } |
846 | + }else{ |
847 | + marking_meta_data->min = 0; |
848 | + } |
849 | + |
850 | + |
851 | + |
852 | + // Test if final place |
853 | + if(marking->numberOfTokensInPlace(out->getIndex()) > 0){ |
854 | + if(size == 1){ |
855 | + marking = pwList->addToPassed(marking); |
856 | + marking_meta_data = ((WorkflowSoundnessMetaData*)marking->meta); |
857 | + marking_meta_data->parents->push_back(parent); |
858 | + // Set min |
859 | + marking_meta_data->min = min(marking_meta_data->min, ((WorkflowSoundnessMetaData*)parent->meta)->min); // Transition |
860 | + final_set->push_back(marking); |
861 | + }else{ |
862 | + lastMarking = marking; |
863 | + return true; // Terminate false |
864 | + } |
865 | + }else{ |
866 | + // If new marking |
867 | + if(pwList->add(marking)){ |
868 | + if(parent != NULL && marking->canDeadlock(tapn, 0)){ |
869 | + lastMarking = marking; |
870 | + return true; |
871 | + } |
872 | + if(modelType == MTAWFN && checkForCoveredMarking(marking)){ |
873 | + lastMarking = marking; |
874 | + return true; // Terminate false |
875 | + } |
876 | + } |
877 | + } |
878 | + |
879 | + return false; |
880 | +} |
881 | + |
882 | +bool WorkflowSoundness::checkForCoveredMarking(NonStrictMarking* marking){ |
883 | + if(marking->size() <= options.getKBound()){ |
884 | + return false; // Do not run check on small markings (invoke more rarely) |
885 | + } |
886 | + |
887 | + NonStrictMarking* covered = pwList->getCoveredMarking(marking, (marking->size() > linearSweepTreshold)); |
888 | + if(covered != NULL){ |
889 | + coveredMarking = covered; |
890 | + return true; |
891 | + } |
892 | + |
893 | + return false; |
894 | +} |
895 | + |
896 | +void WorkflowSoundness::getTrace(NonStrictMarking* base){ |
897 | + stack < NonStrictMarking*> printStack; |
898 | + NonStrictMarking* next = base; |
899 | + do{ |
900 | + int min = INT_MAX; |
901 | + NonStrictMarking* parent = NULL; |
902 | + for(vector<NonStrictMarking*>::const_iterator iter = ((WorkflowSoundnessMetaData*)next->meta)->parents->begin(); iter != ((WorkflowSoundnessMetaData*)next->meta)->parents->end(); ++iter){ |
903 | + if(((WorkflowSoundnessMetaData*)(*iter)->meta)->min < min){ |
904 | + min = ((WorkflowSoundnessMetaData*)(*iter)->meta)->min; |
905 | + parent = *iter; |
906 | + } |
907 | + } |
908 | + |
909 | + if(((WorkflowSoundnessMetaData*)next->meta)->inTrace){ break; } |
910 | + ((WorkflowSoundnessMetaData*)next->meta)->inTrace = true; |
911 | + printStack.push(next); |
912 | + next = parent; |
913 | + |
914 | + }while(((WorkflowSoundnessMetaData*)next->meta)->parents != NULL && !((WorkflowSoundnessMetaData*)next->meta)->parents->empty()); |
915 | + |
916 | + if(printStack.top() != next){ |
917 | + printStack.push(next); |
918 | + } |
919 | + |
920 | + stack < NonStrictMarking*> tempStack; |
921 | + while(!printStack.empty()){ |
922 | + printStack.top()->meta->inTrace = false; |
923 | + tempStack.push(printStack.top()); |
924 | + printStack.pop(); |
925 | + } |
926 | + |
927 | + while(!tempStack.empty()){ |
928 | + printStack.push(tempStack.top()); |
929 | + tempStack.pop(); |
930 | + } |
931 | + |
932 | + if(options.getXmlTrace()){ |
933 | + printXMLTrace(lastMarking, printStack, query, tapn); |
934 | + } else { |
935 | + printHumanTrace(lastMarking, printStack, query->getQuantifier()); |
936 | + } |
937 | +} |
938 | + |
939 | +WorkflowSoundness::~WorkflowSoundness() { |
940 | +} |
941 | + |
942 | +} /* namespace DiscreteVerification */ |
943 | +} /* namespace VerifyTAPN */ |
944 | |
945 | === added file 'src/DiscreteVerification/VerificationTypes/WorkflowSoundness.hpp' |
946 | --- src/DiscreteVerification/VerificationTypes/WorkflowSoundness.hpp 1970-01-01 00:00:00 +0000 |
947 | +++ src/DiscreteVerification/VerificationTypes/WorkflowSoundness.hpp 2013-10-27 17:10:01 +0000 |
948 | @@ -0,0 +1,180 @@ |
949 | +/* |
950 | + * NonStrictSearch.hpp |
951 | + * |
952 | + * Created on: 26/04/2012 |
953 | + * Author: MathiasGS |
954 | + */ |
955 | + |
956 | +#ifndef WORKFLOWSOUNDNESS_HPP_ |
957 | +#define WORKFLOWSOUNDNESS_HPP_ |
958 | + |
959 | +#include "../DataStructures/WorkflowPWList.hpp" |
960 | +#include "../../Core/TAPN/TAPN.hpp" |
961 | +#include "../../Core/QueryParser/AST.hpp" |
962 | +#include "../../Core/VerificationOptions.hpp" |
963 | +#include "../../Core/TAPN/TimedPlace.hpp" |
964 | +#include "../../Core/TAPN/TimedTransition.hpp" |
965 | +#include "../../Core/TAPN/TimedInputArc.hpp" |
966 | +#include "../../Core/TAPN/TransportArc.hpp" |
967 | +#include "../../Core/TAPN/InhibitorArc.hpp" |
968 | +#include "../../Core/TAPN/OutputArc.hpp" |
969 | +#include "../SuccessorGenerator.hpp" |
970 | +#include "../QueryVisitor.hpp" |
971 | +#include "../DataStructures/NonStrictMarking.hpp" |
972 | +#include <stack> |
973 | +#include "ReachabilitySearch.hpp" |
974 | +#include "../DataStructures/WaitingList.hpp" |
975 | + |
976 | +namespace VerifyTAPN { |
977 | +namespace DiscreteVerification { |
978 | + |
979 | +class WorkflowSoundness : public ReachabilitySearch{ |
980 | +public: |
981 | + WorkflowSoundness(TAPN::TimedArcPetriNet& tapn, NonStrictMarking& initialMarking, AST::Query* query, VerificationOptions options, WaitingList<NonStrictMarking>* waiting_list); |
982 | + virtual ~WorkflowSoundness(); |
983 | + bool verify(); |
984 | + void printStats(){ |
985 | + std::cout << " discovered markings:\t" << pwList->discoveredMarkings << std::endl; |
986 | + std::cout << " explored markings:\t" << pwList->size()-pwList->explored() << std::endl; |
987 | + std::cout << " stored markings:\t" << pwList->size() << std::endl; |
988 | + } |
989 | + |
990 | + inline unsigned int maxUsedTokens(){ return pwList->maxNumTokensInAnyMarking; }; |
991 | +protected: |
992 | + virtual bool addToPW(NonStrictMarking* m){ |
993 | + return addToPW(m, tmpParent); |
994 | + }; |
995 | + bool addToPW(NonStrictMarking* marking, NonStrictMarking* parent); |
996 | + bool checkForCoveredMarking(NonStrictMarking* marking); |
997 | + void getTrace(NonStrictMarking* base); |
998 | +public: |
999 | + virtual void getTrace(){ |
1000 | + return getTrace(lastMarking); |
1001 | + } |
1002 | + void printExecutionTime(ostream& stream){ |
1003 | + stream << "Minimum execution time: " << min_exec << endl; |
1004 | + } |
1005 | + void printMessages(ostream& stream){ |
1006 | + if(coveredMarking != NULL){ |
1007 | + stream << "Covered marking: " << *coveredMarking << endl; |
1008 | + getTrace(coveredMarking); |
1009 | + } |
1010 | + } |
1011 | + |
1012 | + enum ModelType{ |
1013 | + MTAWFN, ETAWFN, NOTTAWFN |
1014 | + }; |
1015 | + |
1016 | + inline const ModelType getModelType() const{ return modelType; } |
1017 | + |
1018 | + ModelType calculateModelType(){ |
1019 | + bool isin, isout; |
1020 | + bool hasInvariant = false; |
1021 | + for(TimedPlace::Vector::const_iterator iter = tapn.getPlaces().begin(); iter != tapn.getPlaces().end(); iter++){ |
1022 | + isin = isout = true; |
1023 | + TimedPlace* p = (*iter); |
1024 | + if(p->getInputArcs().empty() && p->getOutputArcs().empty() && p->getTransportArcs().empty()){ |
1025 | + bool continueOuter = true; |
1026 | + // Test if really orphan place or if out place |
1027 | + for(TransportArc::Vector::const_iterator trans_i = tapn.getTransportArcs().begin(); trans_i != tapn.getTransportArcs().end(); ++trans_i){ |
1028 | + if(&((*trans_i)->getDestination()) == p){ |
1029 | + continueOuter = false; |
1030 | + break; |
1031 | + } |
1032 | + } |
1033 | + if(continueOuter) continue; // Fix orphan places |
1034 | + } |
1035 | + |
1036 | + if(!hasInvariant && p->getInvariant() != p->getInvariant().LS_INF){ |
1037 | + hasInvariant = true; |
1038 | + } |
1039 | + |
1040 | + if(p->getInputArcs().size() > 0){ |
1041 | + isout = false; |
1042 | + } |
1043 | + |
1044 | + if(p->getOutputArcs().size() > 0){ |
1045 | + isin = false; |
1046 | + } |
1047 | + |
1048 | + if(isout){ |
1049 | + for(TransportArc::Vector::const_iterator iter = p->getTransportArcs().begin(); iter != p->getTransportArcs().end(); iter++){ |
1050 | + if(&(*iter)->getSource() == p){ |
1051 | + isout = false; |
1052 | + break; |
1053 | + } |
1054 | + } |
1055 | + } |
1056 | + |
1057 | + if(isin){ |
1058 | + for(TransportArc::Vector::const_iterator iter = tapn.getTransportArcs().begin(); iter != tapn.getTransportArcs().end(); ++iter){ // TODO maybe transportArcs should contain both incoming and outgoing? Might break something though. |
1059 | + if(&(*iter)->getDestination() == p){ |
1060 | + isin = false; |
1061 | + break; |
1062 | + } |
1063 | + } |
1064 | + } |
1065 | + |
1066 | + if(isin){ |
1067 | + if(in == NULL){ |
1068 | + in = p; |
1069 | + }else{ |
1070 | + return NOTTAWFN; |
1071 | + } |
1072 | + } |
1073 | + |
1074 | + if(isout){ |
1075 | + if(out == NULL){ |
1076 | + out = p; |
1077 | + }else{ |
1078 | + return NOTTAWFN; |
1079 | + } |
1080 | + } |
1081 | + |
1082 | + } |
1083 | + |
1084 | + if(in == NULL || out == NULL || in == out){ |
1085 | + return NOTTAWFN; |
1086 | + } |
1087 | + |
1088 | + if(initialMarking.size() != 1 || initialMarking.numberOfTokensInPlace(in->getIndex()) != 1){ |
1089 | + return NOTTAWFN; |
1090 | + } |
1091 | + |
1092 | + bool hasUrgent = false; |
1093 | + bool hasInhibitor = false; |
1094 | + // All transitions must have preset |
1095 | + for(TimedTransition::Vector::const_iterator iter = tapn.getTransitions().begin(); iter != tapn.getTransitions().end(); iter++){ |
1096 | + if((*iter)->getPresetSize() == 0 && (*iter)->getNumberOfTransportArcs() == 0){ |
1097 | + return NOTTAWFN; |
1098 | + } |
1099 | + |
1100 | + if(!hasUrgent && (*iter)->isUrgent()){ |
1101 | + hasUrgent = true; |
1102 | + } |
1103 | + |
1104 | + if(!hasInhibitor && !(*iter)->getInhibitorArcs().empty()){ |
1105 | + hasInhibitor = true; |
1106 | + } |
1107 | + } |
1108 | + |
1109 | + if(hasUrgent || hasInvariant || hasInhibitor){ |
1110 | + return ETAWFN; |
1111 | + } |
1112 | + |
1113 | + return MTAWFN; |
1114 | + } |
1115 | +protected: |
1116 | + WorkflowPWList* pwList; |
1117 | + vector<NonStrictMarking*>* final_set; |
1118 | + int min_exec; |
1119 | + unsigned int linearSweepTreshold; |
1120 | + NonStrictMarking* coveredMarking; |
1121 | + TimedPlace* in; |
1122 | + TimedPlace* out; |
1123 | + ModelType modelType; |
1124 | +}; |
1125 | + |
1126 | +} /* namespace DiscreteVerification */ |
1127 | +} /* namespace VerifyTAPN */ |
1128 | +#endif /* NONSTRICTSEARCH_HPP_ */ |
1129 | |
1130 | === added file 'src/DiscreteVerification/VerificationTypes/WorkflowStrongSoundness.cpp' |
1131 | --- src/DiscreteVerification/VerificationTypes/WorkflowStrongSoundness.cpp 1970-01-01 00:00:00 +0000 |
1132 | +++ src/DiscreteVerification/VerificationTypes/WorkflowStrongSoundness.cpp 2013-10-27 17:10:01 +0000 |
1133 | @@ -0,0 +1,119 @@ |
1134 | +/* |
1135 | + * NonStrictSearch.cpp |
1136 | + * |
1137 | + * Created on: 26/04/2012 |
1138 | + * Author: MathiasGS |
1139 | + */ |
1140 | + |
1141 | +#include "WorkflowStrongSoundness.hpp" |
1142 | + |
1143 | +namespace VerifyTAPN { |
1144 | +namespace DiscreteVerification { |
1145 | + |
1146 | +bool WorkflowStrongSoundnessReachability::verify(){ |
1147 | + if(addToPW(&initialMarking, NULL)){ |
1148 | + return true; |
1149 | + } |
1150 | + |
1151 | + //Main loop |
1152 | + while(pwList->hasWaitingStates()){ |
1153 | + NonStrictMarking& next_marking = *pwList->getNextUnexplored(); |
1154 | + tmpParent = &next_marking; |
1155 | + |
1156 | + bool noDelay = false; |
1157 | + Result res = successorGenerator.generateAndInsertSuccessors(next_marking); |
1158 | + if(res == QUERY_SATISFIED){ |
1159 | + return true; |
1160 | + } else if (res == URGENT_ENABLED) { |
1161 | + noDelay = true; |
1162 | + } |
1163 | + |
1164 | + // Generate next markings |
1165 | + if(!noDelay && isDelayPossible(next_marking)){ |
1166 | + NonStrictMarking* marking = new NonStrictMarking(next_marking); |
1167 | + marking->incrementAge(); |
1168 | + marking->setGeneratedBy(NULL); |
1169 | + if(addToPW(marking, &next_marking)){ |
1170 | + return true; |
1171 | + } |
1172 | + } |
1173 | + } |
1174 | + |
1175 | + return false; |
1176 | + } |
1177 | + |
1178 | + void WorkflowStrongSoundnessReachability::getTrace(){ |
1179 | + std::stack < NonStrictMarking*> printStack; |
1180 | + NonStrictMarking* next = lastMarking; |
1181 | + do{ |
1182 | + NonStrictMarking* parent = ((WorkflowStrongSoundnessMetaData*) next->meta)->parents->at(0); |
1183 | + printStack.push(next); |
1184 | + next = parent; |
1185 | + |
1186 | + }while(((WorkflowStrongSoundnessMetaData*)next->meta)->parents != NULL && !((WorkflowStrongSoundnessMetaData*)next->meta)->parents->empty()); |
1187 | + |
1188 | + if(printStack.top() != next){ |
1189 | + printStack.push(next); |
1190 | + } |
1191 | + |
1192 | + if(options.getXmlTrace()){ |
1193 | + printXMLTrace(lastMarking, printStack, query, tapn); |
1194 | + } else { |
1195 | + printHumanTrace(lastMarking, printStack, query->getQuantifier()); |
1196 | + } |
1197 | + } |
1198 | + |
1199 | + |
1200 | + bool WorkflowStrongSoundnessReachability::addToPW(NonStrictMarking* marking, NonStrictMarking* parent){ |
1201 | + marking->cut(); |
1202 | + marking->setParent(parent); |
1203 | + |
1204 | + unsigned int size = marking->size(); |
1205 | + |
1206 | + pwList->setMaxNumTokensIfGreater(size); |
1207 | + |
1208 | + if(size > options.getKBound()) { |
1209 | + delete marking; |
1210 | + return false; |
1211 | + } |
1212 | + |
1213 | + /* Handle max */ |
1214 | + // Map to existing marking if any |
1215 | + NonStrictMarking* lookup = pwList->lookup(marking); |
1216 | + if(lookup != NULL){ |
1217 | + marking = lookup; |
1218 | + }else{ |
1219 | + marking->meta = new WorkflowStrongSoundnessMetaData(); |
1220 | + } |
1221 | + |
1222 | + WorkflowStrongSoundnessMetaData* meta = (WorkflowStrongSoundnessMetaData*)marking->meta; |
1223 | + |
1224 | + if(parent != NULL) meta->parents->push_back(parent); |
1225 | + |
1226 | + if(!marking->getTokenList(timer->getIndex()).empty() && |
1227 | + (marking->getTokenList(timer->getIndex()).at(0).getAge() > max_value || |
1228 | + (marking->getTokenList(timer->getIndex()).at(0).getAge() == max_value && |
1229 | + (!marking->getTokenList(term1->getIndex()).empty() || !marking->getTokenList(term2->getIndex()).empty())))){ |
1230 | + max_value = marking->getTokenList(timer->getIndex()).at(0).getAge(); |
1231 | + lastMarking = marking; |
1232 | + } |
1233 | + |
1234 | + // Add to passed |
1235 | + if(pwList->add(marking)){ |
1236 | + QueryVisitor<NonStrictMarking> checker(*marking, tapn); |
1237 | + BoolResult context; |
1238 | + |
1239 | + query->accept(checker, context); |
1240 | + if(context.value) { |
1241 | + lastMarking = marking; |
1242 | + return true; |
1243 | + } else { |
1244 | + return false; |
1245 | + } |
1246 | + } |
1247 | + |
1248 | + return false; |
1249 | + } |
1250 | + |
1251 | +} /* namespace DiscreteVerification */ |
1252 | +} /* namespace VerifyTAPN */ |
1253 | |
1254 | === added file 'src/DiscreteVerification/VerificationTypes/WorkflowStrongSoundness.hpp' |
1255 | --- src/DiscreteVerification/VerificationTypes/WorkflowStrongSoundness.hpp 1970-01-01 00:00:00 +0000 |
1256 | +++ src/DiscreteVerification/VerificationTypes/WorkflowStrongSoundness.hpp 2013-10-27 17:10:01 +0000 |
1257 | @@ -0,0 +1,83 @@ |
1258 | +/* |
1259 | + * NonStrictSearch.hpp |
1260 | + * |
1261 | + * Created on: 26/04/2012 |
1262 | + * Author: MathiasGS |
1263 | + */ |
1264 | + |
1265 | +#ifndef WORKFLOWSTRONGSOUNDNESS_HPP_ |
1266 | +#define WORKFLOWSTRONGSOUNDNESS_HPP_ |
1267 | + |
1268 | +#include "ReachabilitySearch.hpp" |
1269 | +#include "../DataStructures/WorkflowPWList.hpp" |
1270 | +#include <stack> |
1271 | + |
1272 | +namespace VerifyTAPN { |
1273 | +namespace DiscreteVerification { |
1274 | + |
1275 | +class WorkflowStrongSoundnessReachability : public ReachabilitySearch{ |
1276 | +public: |
1277 | + WorkflowStrongSoundnessReachability(TAPN::TimedArcPetriNet& tapn, NonStrictMarking& initialMarking, AST::Query* query, VerificationOptions options, WaitingList<NonStrictMarking>* waiting_list) |
1278 | + : ReachabilitySearch(tapn,initialMarking, query, options, waiting_list), pwList(new WorkflowPWList(waiting_list)), max_value(-1), timer(NULL), term1(NULL), term2(NULL) |
1279 | + { |
1280 | + // Disable dead place optimization |
1281 | + for(TimedPlace::Vector::const_iterator iter = tapn.getPlaces().begin(); iter != tapn.getPlaces().end(); iter++){ |
1282 | + if((*iter)->getType() == Dead){ |
1283 | + (*iter)->setType(Std); |
1284 | + } |
1285 | + } |
1286 | + |
1287 | + // Find timer place and store as out |
1288 | + for(TimedPlace::Vector::const_iterator iter = tapn.getPlaces().begin(); iter != tapn.getPlaces().end(); ++iter){ |
1289 | + if((*iter)->getInvariant() != (*iter)->getInvariant().LS_INF){ |
1290 | + if(timer == NULL || timer->getInvariant().getBound() < (*iter)->getInvariant().getBound()){ |
1291 | + timer = *iter; |
1292 | + } |
1293 | + } |
1294 | + |
1295 | + if(!(*iter)->getTransportArcs().empty() || !(*iter)->getInputArcs().empty()){ |
1296 | + continue; |
1297 | + } |
1298 | + |
1299 | + if(term1 == NULL){ |
1300 | + term1 = *iter; |
1301 | + }else if(term2 == NULL){ |
1302 | + term2 = *iter; |
1303 | + }else{ |
1304 | + assert(false); |
1305 | + } |
1306 | + } |
1307 | + }; |
1308 | + |
1309 | + bool verify(); |
1310 | + void getTrace(); |
1311 | + |
1312 | + void printExecutionTime(ostream& stream){ |
1313 | + stream << "Maximum execution time: " << max_value << endl; |
1314 | + } |
1315 | + |
1316 | + void printStats(){ |
1317 | + std::cout << " discovered markings:\t" << pwList->discoveredMarkings << std::endl; |
1318 | + std::cout << " explored markings:\t" << pwList->size()-pwList->explored() << std::endl; |
1319 | + std::cout << " stored markings:\t" << pwList->size() << std::endl; |
1320 | + } |
1321 | + |
1322 | + inline unsigned int maxUsedTokens(){ return pwList->maxNumTokensInAnyMarking; }; |
1323 | + |
1324 | +protected: |
1325 | + virtual bool addToPW(NonStrictMarking* m){ |
1326 | + return addToPW(m, tmpParent); |
1327 | + }; |
1328 | + |
1329 | + bool addToPW(NonStrictMarking* marking, NonStrictMarking* parent); |
1330 | +protected: |
1331 | + PWListBase* pwList; |
1332 | + int max_value; |
1333 | + TimedPlace* timer; |
1334 | + TimedPlace* term1; |
1335 | + TimedPlace* term2; |
1336 | +}; |
1337 | + |
1338 | +} /* namespace DiscreteVerification */ |
1339 | +} /* namespace VerifyTAPN */ |
1340 | +#endif /* NONSTRICTSEARCH_HPP_ */ |
1341 | |
1342 | === modified file 'src/compile-mac-32-64.sh' |
1343 | --- src/compile-mac-32-64.sh 2013-08-28 09:59:17 +0000 |
1344 | +++ src/compile-mac-32-64.sh 2013-10-27 17:10:01 +0000 |
1345 | @@ -7,9 +7,9 @@ |
1346 | |
1347 | export CPLUS_INCLUDE_PATH=$HOME/dev/boost_1_46_1 |
1348 | |
1349 | -inc64="-I$HOME/dev/ia64/include" |
1350 | +inc64="-I$HOME/dev/ia64/include -I/usr/local/include -I/opt/local/include" |
1351 | |
1352 | -inc32="-I$HOME/dev/ia32/include" |
1353 | +inc32="-I$HOME/dev/ia32/include -I/usr/local/include -I/opt/local/include" |
1354 | |
1355 | compatibility="-mmacosx-version-min=10.6" |
1356 |
Tested and works as it should. Just make sure that the normal verification (EG, AG, EG, AF) is
not influenced in any way.