pev_verify.cpp
Go to the documentation of this file.
1#include "pev_abstraction.h"
2#include "pev_verify.h"
3#include <chrono>
4
5namespace faudes {
6
7FAUDES_TYPE_IMPLEMENTATION(CompVerify::StateRef,CompVerify::StateRef,AttributeVoid)
8
9void ExtendedActiveEventSet(Idx x1, const Generator& rGen,const EventSet& silent, EventSet& result){
10 std::set<Idx> visited;
11 std::stack<Idx> todo;
12 todo.push(x1);
13 while(!todo.empty()){
14 Idx cstate = todo.top();
15 todo.pop();
16 TransSet::Iterator tit = rGen.TransRelBegin(cstate);
17 for(;tit!=rGen.TransRelEnd(cstate);tit++){
18 if(silent.Exists(tit->Ev)){
19 if (visited.find(tit->X2)==visited.end()) {
20 todo.push(tit->X2);
21 }
22 }
23 else {
24 result.Insert(tit->Ev);
25 }
26 }
27 visited.insert(cstate);
28 }
29}
30
32 Idx omega = rGen.InsEvent("_OMEGA_");
33 StateSet::Iterator sit = rGen.MarkedStatesBegin();
34 for(;sit!=rGen.MarkedStatesEnd();sit++){
35 rGen.SetTransition(*sit,omega,*sit);
36 }
37// rGen.SetDefaultStateNames(); // activate for debug
38}
39
40
41
43 SynchCandidates* candidates = new SynchCandidates(goi);
44 mAllCandidates.push(candidates);
45}
46
48
49 Idx git = 0;
50 for(;git<gvoi.Size();git++){
51 AppendOmega(gvoi.At(git));
52 }
53 SynchCandidates* candidates = new SynchCandidates(gvoi);
54 mAllCandidates.push(candidates);
55}
56
58
59 // make explicit omega to terminal with a dummy selfloop on it
60 // the dummy self loop is there to distinguish it from deadend states
61 Idx git = 0;
62 for(;git<gvoi.Size();git++){
63 AppendOmega(gvoi.At(git));
64 }
65 SynchCandidates* candidates = new SynchCandidates(gvoi, pevs);
66 mAllCandidates.push(candidates);
67 mIsPreemptive = 1;
68 mAllPevs = pevs;
69}
70
75
77 Candidate* candidate = new Candidate(goi);
78 mCandidates.push_back(candidate);
79
80}
81
83 Idx git = 0;
84 for (;git<gvoi.Size();git++){
85 Candidate* candidate = new Candidate(gvoi.At(git));
86 mCandidates.push_back(candidate);
87 }
88}
89
91 Idx git = 0;
92 for (;git<gvoi.Size();git++){
93 PCandidate* pcandidate = new PCandidate(gvoi.At(git), pevs * gvoi.At(git).Alphabet());
94 mCandidates.push_back(pcandidate);
95 }
96}
97
98
102
108
110 mCandidates.clear();
111 SynchCandidates::Iterator scit = synchcands.CandidatesBegin();
112 for (;scit!=synchcands.CandidatesEnd();scit++)
113 mCandidates.push_back(*scit);
114}
115
117 mGenRaw = cand.mGenRaw;
118 mGenHidden = cand.mGenHidden;
119 mGenMerged = cand.mGenMerged;
120 mMergeMap = cand.mMergeMap;
121 mSilentevs = cand.mSilentevs;
122 mtau = cand.mtau;
124 mDecomposedPair.first = cand.mDecomposedPair.first;
125 mDecomposedPair.second = cand.mDecomposedPair.second;
126}
127
129 mGenRaw = cand.mGenRaw;
130 mGenHidden = cand.mGenHidden;
131 mGenMerged = cand.mGenMerged;
132 mMergeMap = cand.mMergeMap;
133 mSilentevs = cand.mSilentevs;
134 mtau = cand.mtau;
136 mDecomposedPair.first = cand.mDecomposedPair.first;
137 mDecomposedPair.second = cand.mDecomposedPair.second;
138 mPevs = cand.mPevs;
140 mPtau = cand.mPtau;
141}
142
144 mGenRaw = goi;
145 // initialize trivial merge map
146 StateSet::Iterator sit = goi.StatesBegin();
147 for(;sit!=goi.StatesEnd();sit++){
148 mMergeMap.insert(std::pair<Idx,Idx>(*sit,*sit));
149 }
150}
151
152Candidate::Candidate(Generator& goi, ProductCompositionMap map, std::pair<Candidate*, Candidate*> pair){
153 mGenRaw = goi;
154 mComposeMap = map;
155 mDecomposedPair.first = pair.first;
156 mDecomposedPair.second = pair.second;
157 // initialize trivial merge map
158 StateSet::Iterator sit = goi.StatesBegin();
159 for(;sit!=goi.StatesEnd();sit++){
160 mMergeMap.insert(std::pair<Idx,Idx>(*sit,*sit));
161 }
162}
163
164std::set<Idx> Candidate::FindConcreteStates(Idx abstractState){
165 std::map<Idx,Idx>::iterator mit = mMergeMap.begin();
166 std::set<Idx> concreteStates;
167 for(;mit!=mMergeMap.end();mit++){
168 if (mit->second == abstractState) concreteStates.insert(mit->first);
169 }
170 if (concreteStates.empty())
171 throw Exception("FindConcreteStates()", "invalid abstract state index", 599);
172 return concreteStates;
173}
174
175bool Candidate::IsInMergedClass(Idx concrete, Idx abstract){
176 std::map<Idx,Idx>::iterator mit = mMergeMap.begin();
177 for(;mit!=mMergeMap.end();mit++){
178 if (mit->first == concrete){
179 if (mit->second == abstract) return true;
180 else return false;
181 }
182 }
183 throw Exception("IsInMergedClass()","the given concrete state index is not in the merge map",500);
184}
185
187 std::cout<<"================================================"<<std::endl;
188 std::cout<<"VerifyAll(): Verifying non-conflictness via conflict-preserving abstraction"<<std::endl;
189 auto start = std::chrono::steady_clock::now();
190
191 bool isnc = CompVerify::IsNonconflicting();
192
193 auto end = std::chrono::steady_clock::now();
194 std::cout<<"VerifyAll(): done with verification. Elapsed time: "
195 << std::setprecision(2) << std::fixed
196 << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()/(double)1000
197 << "sec. IsNonblocking: "<<std::boolalpha<<isnc<<std::endl;
198 std::cout<<"================================================"<<std::endl;
199 if (!isnc){
200 std::string YN;
201 std::cout<<"VerifyAll(): proceed to trace generation?";
202 while (true){
203 std::cin>> YN;
204 if (YN=="Y"||YN=="N"||YN=="y"||YN=="n") break;
205 }
206 if(YN=="Y"||YN=="y"){
207 std::cout<<"================================================"<<std::endl;
208 std::cout<<"VerifyAll(): Generating trace to some blocking state from abstraction"<<std::endl;
209 start = std::chrono::steady_clock::now();
210
213
214 auto end = std::chrono::steady_clock::now();
215 std::cout<<"VerifyAll(): done with trace generation. Elapsed time: "
216 << std::setprecision(2) << std::fixed
217 << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()/(double)1000
218 << "sec"<<std::endl;
219 std::cout<<"================================================"<<std::endl;
220
221 trace=mCounterExp;
222 // install self loops on last state, convenient for debug
223 EventSet::Iterator eit = trace.Alphabet().Begin();
224 for(;eit!=trace.Alphabet().End();eit++){
226 }
227 }
228 }
229}
230
232 SynchCandidates* mSynchCandidates = mAllCandidates.top();
233 std::stack<SynchCandidates*> allCandidates = mAllCandidates;
234 bool isInitial = true; //this will be set to false from the second iteration
235 // flagging the task. False when ordinary composition, true when preemption considered
236 if (!mIsPreemptive){
237 PCOMPVER_VERB0("IsNonconflicting::Start Iteration. Perform ordinary non-conflictingness check");
238 }
239 else {
240 PCOMPVER_VERB0("IsNonconflicting::Start Iteration. Perform non-conflictingness check w.r.t. preemption");
241 }
242 while (true){
243 PCOMPVER_VERB0("IsNonconflicting::Iterating. Remaining automata: " + ToStringInteger(mSynchCandidates->Size()));
244
245 // trivial cases
246 if(mSynchCandidates->Size()==0) return true;
247 if(mSynchCandidates->Size()==1) break;
248
249 // figure silent events
250 EventSet silent, all, shared;
251 SynchCandidates::Iterator scit = mSynchCandidates->CandidatesBegin();
252 while(true){
253 all = all+(*scit)->GenRaw().Alphabet();
254 SynchCandidates::Iterator scit_next = std::next(scit,1);
255 if (scit_next == mSynchCandidates->CandidatesEnd()) break;
256 for(;scit_next!=mSynchCandidates->CandidatesEnd();scit_next++){
257 shared = shared
258 + ((*scit)->GenRaw().Alphabet())
259 * ((*scit_next)->GenRaw().Alphabet());
260 }
261 scit++;
262 }
263 silent=all-shared; // all silent events in all current candidates
264 silent.Write();
265
266 // normalize for one silent event per generator, and then abstract
267 // note from the second iteration, this is only necessary for the
268 // automaton composed from former candidates. This is realized by
269 // the break at the end
270 scit = mSynchCandidates->CandidatesBegin();
271 for(;scit!=mSynchCandidates->CandidatesEnd();scit++){
272 // ***************************************************
273 // abstraction
274 PCOMPVER_VERB0("====================================")
275 PCOMPVER_VERB0("IsNonconflicting::Abstract generator " + (*scit)->GenRaw().Name() + ". State count: "
276 + ToStringInteger((*scit)->GenRaw().Size()));
277 if (!mIsPreemptive){
278 (*scit)->ConflictEquivalentAbstraction(silent);
279 }
280 else {
281 PCandidate* pcand = dynamic_cast<PCandidate*>(*scit);
282 pcand->ConflictEquivalentAbstraction(silent);
283 PCOMPVER_VERB0("State Count of Generator "<<pcand->GenRaw().Name()<<": "<<pcand->GenRaw().Size())
284 PCOMPVER_VERB0("State Count of Generator "<<pcand->GenMerged().Name()<<": "<<pcand->GenMerged().Size())
285
286 }
287 PCOMPVER_VERB1("IsNonconflicting::Abstraction done. State count: "
288 + ToStringInteger((*scit)->GenMerged().Size()));
289
290
291#ifdef DEBUG_VF
292 (*scit)->GenRaw().Write();
293 (*scit)->GenHidden().Write();
294 (*scit)->GenMerged().Write();
295 std::cout<<"Merge map of " + (*scit)->GenRaw().Name() + ":"<<std::endl;
296 std::map<Idx,Idx> map = (*scit)->MergeMap();
297 std::map<Idx,Idx>::iterator mit = map.begin();
298 std::map<Idx,Idx>::iterator mit_end = map.end();
299 for(;mit!=mit_end;mit++){
300 std::cout<<ToStringInteger(mit->first) + " -> " + ToStringInteger(mit->second)<<std::endl;
301 }
302
303 std::cout<<"silent events are:"<<std::endl;
304 EventSet::Iterator eit = (*scit)->Silentevs().Begin();
305 EventSet::Iterator eit_end = (*scit)->Silentevs().End();
306 for(;eit!=eit_end;eit++){
307 std::cout<< (*scit)->GenRaw().EventName(*eit)<<std::endl;
308 }
309 if (dynamic_cast<PCandidate*>(*scit)!=NULL){
310 PCandidate* pscit = dynamic_cast<PCandidate*>(*scit);
311 eit = pscit->PSilentevs().Begin();
312 eit_end = pscit->PSilentevs().End();
313 for (;eit!=eit_end;eit++){
314 std::cout<< "(P) " + pscit->GenRaw().EventName(*eit)<<std::endl;
315 }
316 }
317#endif
318 if (mAllCandidates.size()!=1) break;
319 }
320
321 // candidate choice heuritics. Branch by different tasks
322 SynchCandidates::Iterator imin = mSynchCandidates->CandidatesBegin();
323 SynchCandidates::Iterator jmin = mSynchCandidates->CandidatesBegin();
324 if (mIsPreemptive){
325 jmin++;
326 /* heuristics which attempts to eliminate shared preempting evs.
327 for(;imin!=mSynchCandidates->CandidatesEnd();imin++){
328 bool breakflag = 0;
329 jmin = std::next(imin,1);
330 if (std::next(jmin,1)==mSynchCandidates->CandidatesEnd()) break; // no shared pevs at all
331 for(;jmin!=mSynchCandidates->CandidatesEnd();jmin++){
332 PCandidate* pimin = dynamic_cast<PCandidate*>(*imin);
333 PCandidate* pjmin = dynamic_cast<PCandidate*>(*jmin);
334 if (!(pimin->Pevs()*pjmin->Pevs()).Empty()){
335 breakflag = 1;
336 break;
337 }
338 }
339 if (breakflag) break;
340 }
341 */
342 }
343
344 else {
345 // candidat pairs with fewest transitions 'minT'
346
347 scit = std::next(imin,1);
348 for(;scit!=mSynchCandidates->CandidatesEnd();scit++){
349 if((*scit)->GenMerged().TransRelSize()<(*imin)->GenMerged().TransRelSize())
350 imin = scit;
351 }
352
353 // candidat pairs with most local events 'maxL'
354
355 scit = jmin;
356 Int score=-1;
357 for(; scit!=mSynchCandidates->CandidatesEnd(); scit++){
358 if(scit==imin) continue;
359 const Generator& gi=(*imin)->GenMerged();
360 const Generator& gj=(*scit)->GenMerged();
361 EventSet aij=gi.Alphabet()+gj.Alphabet();
362 EventSet shared;
363 SynchCandidates::Iterator scit2 = mSynchCandidates->CandidatesBegin();
364 for(;scit2!=mSynchCandidates->CandidatesEnd();scit2++){
365 if(scit2==imin || scit2==scit) continue;
366 shared=shared + (*scit2)->GenMerged().Alphabet()*aij;
367 }
368 Int jscore= aij.Size()-shared.Size();
369 if(jscore>score) {score=jscore; jmin=scit;}
370 }
371 }
372
373
374 // compose candidate pair
375 Generator gimin= (*imin)->GenMerged();
376 Generator gjmin= (*jmin)->GenMerged();
377 Generator gij;
379 Parallel(gimin,gjmin,newmap,gij);
381 gij.Name("(" + gimin.Name() + "--" + gjmin.Name() + ")");
382 std::pair<Candidate*, Candidate*> newpair;
383 newpair.first = *imin;
384 newpair.second = *jmin;
385 PCOMPVER_VERB0("IsNonconflicting::" + (*imin)->GenRaw().Name() + " and " + (*jmin)->GenRaw().Name() + " will be composed.");
386 // instantiate a new synchcandidate set for next iteration
387 SynchCandidates* newSynchCandidates = new SynchCandidates();
388
389 if (!mIsPreemptive){
390 Candidate* newcand = new Candidate(gij,newmap,newpair);
391 newSynchCandidates->Insert(newcand);
392 }
393 else {
394 PCandidate* pimin = dynamic_cast<PCandidate*>(*imin);
395 PCandidate* pjmin = dynamic_cast<PCandidate*>(*jmin);
396 PCandidate* newcand = new PCandidate(gij,newmap,newpair,pimin->Pevs()+pjmin->Pevs());
397 newSynchCandidates->Insert(newcand);
398 }
399
400 scit = mSynchCandidates->CandidatesBegin();
401 for(;scit!=mSynchCandidates->CandidatesEnd();scit++){
402 if (scit == imin || scit == jmin) continue;
403 newSynchCandidates->Insert(*scit); // all other candidates are just copied to the next iteraion
404 }
405
406 mAllCandidates.push(newSynchCandidates);
407 mSynchCandidates = newSynchCandidates;
408 isInitial = false;
409 }
410
411 FD_DF("Abstraction done. Tesing nonblockingness of final automaton")
412 mGenFinal = (*(mSynchCandidates->CandidatesBegin()))->GenRaw();
413 if(mIsPreemptive){
414 PCandidate* pcand = dynamic_cast<PCandidate*>(*mSynchCandidates->CandidatesBegin());
416 }
417 mGenFinal.Write("final.gen");
419}
420
421
423 StateSet marked = rGen.CoaccessibleSet();
425 std::list<StateSet> scclist;
426 StateSet root;
427 PCOMPVER_VERB0("GenerateTrace():: Computing strongly connected components (scc)")
428 ComputeScc(rGen,filter,scclist,root);
429
430 PCOMPVER_VERB0("GenerateTrace():: Figuring out scc without outgoing transitions")
431 // consider only scc without outgoing transitions
432 std::list<StateSet>::iterator sccit = scclist.begin();
433 StateSet::Iterator rit; // root iterator
434
435 while(sccit!=scclist.end()){
436
437 bool breakflag = false; // if true, all iteration below breaks
438 StateSet::Iterator sit = sccit->Begin();
439 for(;sit!=sccit->End();sit++){
440 TransSet::Iterator tit = rGen.TransRelBegin(*sit);
441 for(;tit!=rGen.TransRelEnd(*sit);tit++){
442 if(sccit->Exists(tit->X2)) continue;
443 // else, i.e. if there is a successor state not in this scc
444 breakflag = true;
445 rit = root.Begin();// delete the corresponding root at first...
446 for (;rit!=root.End();rit++){
447 if (sccit->Exists(*rit)){
448 root.Erase(rit);
449 break;
450 }
451 }
452 sccit = scclist.erase(sccit);// ... then delete the scc
453 break;
454 }
455 if (breakflag) break;
456 }
457 if (!breakflag) {sccit++;}
458 }
459
460 // just report the first counter-example, not necessarily the shortest
461 rit = root.Begin();
462 PCOMPVER_VERB0("GenerateTrace():: Generating trace to the first scc")
463 ShortestPath(rGen,mCounterExp,rGen.InitState(),*rit);
464 PCOMPVER_VERB0("GenerateTrace():: Generation done. Trace length: " + ToStringInteger(mCounterExp.Size()))
465}
466
467bool CompVerify::ShortestPath(const Generator& rGen, Generator& rRes, Idx begin, Idx end){
468 /* This is a simplified version of Dijkstra's algorithm
469 * in which each transition only has weight=1. Path length is implied
470 * by state count.
471 */
472 /* set up map of each (reachable) state from the begin state to its shortest path.
473 * path are stored in form of generator. Maybe not efficient, but convenient for
474 * output.
475 */
476 rRes.StateNamesEnabled(true);
477 std::map<Idx, Generator> paths;
478 Generator dummy;
479 dummy.InsInitState(begin);
480 paths[begin] = dummy;
481 std::map<Idx, Idx> todo; // state index set pairs to temporily shortest distance
482 todo[begin]=dummy.Size();
483 Idx progressCounter = 1;
484 Idx progressMax = rGen.Size();
485 while(!todo.empty()){
486 // search for state with shortest distance in todo
487 std::map<Idx,Idx>::iterator sit = todo.begin();
488 Idx where = sit->first;
489 sit++;
490 for(;sit!=todo.end();sit++){
491 if (sit->second<todo[where])
492 where = sit->first;
493 }
494 // if reach the target, return
495 if (where == end) {
496 rRes = paths[where];
497 return true;
498 }
499 todo.erase(todo.find(where));
500 TransSet::Iterator tit = rGen.TransRelBegin(where);
501 for(;tit!=rGen.TransRelEnd(where);tit++){
502 if(paths.find(tit->X2)==paths.end()||paths[tit->X2].Size()>paths[where].Size()){
503 Generator newPath = paths[where];
504 newPath.InsEvents(rGen.Alphabet());
505 newPath.InsState(tit->X2);
506 newPath.SetTransition(*tit);
507 paths[tit->X2]=newPath;
508 todo[tit->X2]=newPath.Size();
509 }
510 }
511 progressCounter++;
512 }
513 // if target not reachable
514 return false;
515}
516
517StateSet::Iterator CompVerify::LastState (CounterExample& ce){
518 StateSet::Iterator sit = ce.StatesBegin();
519 for (;sit!=ce.StatesEnd();sit++){
520 if (ce.TransRelBegin(*sit)==ce.TransRelEnd(*sit)) return sit;
521 }
522 throw Exception("LastState():","no last state found (perhaps not ordinary counter-example)", 500);
523}
524
526 StateSet::Iterator sit = rCE.StatesBegin();
527 for(;sit!=rCE.StatesEnd();sit++){
528 rCE.StateAttributep(*sit)->ClearStateRef();
529 }
530}
531
533 StateSet::Iterator sit = rCE.StatesBegin();
534 for(;sit!=rCE.StatesEnd();sit++){
535 Idx x12 = rCE.StateAttributep(*sit)->FindState(cand);
536 Idx x1 = cand->ComposeMap().Arg1State(x12);
537 Idx x2 = cand->ComposeMap().Arg2State(x12);
538 rCE.StateAttributep(*sit)->InsertStateRef(cand->DecomposedPair().first,x1);
539 rCE.StateAttributep(*sit)->InsertStateRef(cand->DecomposedPair().second,x2);
540 rCE.StateAttributep(*sit)->DeleteStateRef(cand);// delete the original state attribute with composed automaton
541 }
542}
543
545 SynchCandidates* synchCands,
546 Candidate* cand,
547 CounterExample& rCE)
548{
549
550 std::set<std::pair<CounterExample,CounterExample>> queue; // pair of <concrete ce C, abstract ce to be processed C~>
551 std::set<std::pair<Idx, Idx>> visited; // pair of <state, index>
552 // delete all tau transitions corresponds to "this" cand
553 Idx cstate = *rCE.InitStatesBegin(); // we shall only have one intial state
554
555 PCOMPVER_VERB2("StateMergingExpansion(): deleting tau-transitions from current candidate")
556 TransSetX2EvX1 rtrel; // set up backwards transrel, as we want to delete tau-trans with its SOURCE state
557 rCE.TransRel().ReSort(rtrel);
558 while (true){
559 if (rCE.InitStates().Exists(cstate)){
560 cstate = rCE.TransRelBegin(cstate)->X2;
561 continue; // initial state has no preceding trans
562 }
563
564 TransSetX2EvX1::Iterator rtit = rtrel.BeginByX2(cstate);
565 // if this state has a incoming tau trans
566 if (cand->Silentevs().Exists(rtit->Ev)){
567 Idx prestate = rtit->X1;
568 // if the predecessor state is not the initial state
569 if (!rCE.InitStates().Exists(prestate)){
570 TransSetX2EvX1::Iterator pretrans = rtrel.BeginByX2(prestate);
571 rCE.SetTransition(pretrans->X1,pretrans->Ev,cstate);
572 rCE.DelState(prestate);
573 }
574 // else, i.e. predecessor is the initial state
575 else{
576 rCE.SetInitState(cstate);
577 rCE.DelState(prestate);
578 }
579 }
580 rCE.TransRel().ReSort(rtrel); // update rtrel
581 if (rCE.ActiveEventSet(cstate).Empty()) break;
582 else cstate = rCE.TransRelBegin(cstate)->X2;
583 }
584
585 PCOMPVER_VERB2("StateMergingExpansion(): deletion done")
586 // initialize CE with single state for each initial state in concrete candidate
587 StateSet::Iterator sit = cand->GenRaw().InitStatesBegin();
588 for (;sit != cand->GenRaw().InitStatesEnd();sit++){
590 Idx init = ce.InsInitState();
591 SynchCandidates::Iterator scit = synchCands->CandidatesBegin();
592 for (;scit!=synchCands->CandidatesEnd();scit++){
593 ce.InsEvents((*scit)->GenRaw().Alphabet()); //install alphabet from all raw gens
594 if (*scit == cand)
595 ce.StateAttributep(init)->InsertStateRef(*scit, *sit); // in case pointing to the abstracted candidate
596 else
597 ce.StateAttributep(init)->InsertStateRef(*scit, rCE.StateAttributep(rCE.InitState())->FindState(*scit));
598 }
599 queue.insert({ce,rCE});
600 visited.insert({*sit,0});
601 }
602 Idx counter = (*cand).Silentevs().Size();
603 while (!queue.empty()){
604 PCOMPVER_VERB2("StateMergingExpansion(): ======================================== ")
605 PCOMPVER_VERB2("StateMergingExpansion(): queue size: " + ToStringInteger(queue.size()))
606
607 // find the shortest queue element with lenght = |ceGenerated| + |ceToProceed|
608 std::set<std::pair<CounterExample,CounterExample>>::iterator queit = queue.begin();
609 std::set<std::pair<CounterExample,CounterExample>>::iterator shortest = queit;
610 for (;queit!=queue.end();queit++){
611 if (queit->first.Size()+queit->second.Size() < shortest->first.Size()+shortest->second.Size())
612 shortest = queit;
613 }
614 CounterExample ceGenerated = shortest->first;
615 CounterExample ceToProcess = shortest->second;
616 PCOMPVER_VERB2("StateMergingExpansion(): picked ceGenerated size: " + ToStringInteger(ceGenerated.Size()))
617 PCOMPVER_VERB2("StateMergingExpansion(): picked ceToProcess size: " + ToStringInteger(ceToProcess.Size()))
618 queue.erase(shortest); // ... and erase it
619
620 // some preparation for the if-else-cascade later on======>
621 // the i in paper, i.e. the first state index of ceToProceed
622 Idx i = rCE.Size()-ceToProcess.Size();
623 // state index of cand's MergedGen of the first state of ceToProceed (x~_1^i in paper)
624 Idx abstractState = ceToProcess.StateAttributep(*ceToProcess.StatesBegin())->FindState(cand);
625 // state index of cand's RawGen of the last state of ceGenerated (x_1^i in paper)
626 Idx concreteState = ceGenerated.StateAttributep(*LastState(ceGenerated))->FindState(cand);
627 // =========> preparation end
628
629 // return when ceToProceed only one state and the final state of ceGenerated is in this single state
630 if (ceToProcess.Size()==1){
631 if ((*cand).IsInMergedClass(concreteState,abstractState)){
632 rCE = ceGenerated;
633// rCE.Write();
634 return;
635 }
636 }
637
638
639
640 // else... (follow the original part of paper)
641 else{
642 // get the next transition of ceToProcess (easy to access next event and next state)
643 TransSet::Iterator nextTrans = ceToProcess.TransRelBegin(*ceToProcess.InitStatesBegin());
644
645 // if the next event in ceToProcess is not an preemptive event and cand can execute
646 // preemptive tau at the current state, then these preemptive taus must be executed and
647 // shall kill all other events. Note the check will also take preemptive tau of other candidates
648 // into consideration
649 if (IsPreemptive() && !AllPevs().Exists(nextTrans->Ev)){
650 std::cout<< "A" <<std::endl;
651 PCandidate* pcand = dynamic_cast<PCandidate*>(cand);
652 EventSet activePtau = pcand->PSilentevs() * pcand->GenRaw().ActiveEventSet(concreteState);
653
654 activePtau.Write();
655
656 if (!activePtau.Empty()){
657 TransSet::Iterator tit = pcand->GenRaw().TransRelBegin(concreteState);
658
659 std::cout<< pcand->GenRaw().EventName(tit->Ev) <<std::endl;
660
661 for (;tit!=pcand->GenRaw().TransRelEnd(concreteState);tit++) {
662 if(pcand->PSilentevs().Exists(tit->Ev) && visited.find({tit->X2,i})==visited.end()){
663 // do the same thing as the last case, i.e. perform the silent event
664 CounterExample newCeGenerated = ceGenerated;
665 Idx oldlaststate = *LastState(newCeGenerated);
666 Idx newstate = newCeGenerated.InsState();
667 newCeGenerated.SetTransition(oldlaststate,tit->Ev,newstate);
668 // install state attribute
669 SynchCandidates::Iterator scit = synchCands->CandidatesBegin();
670 for (;scit!=synchCands->CandidatesEnd();scit++){
671 if (*scit == cand)
672 newCeGenerated.StateAttributep(newstate)->InsertStateRef(*scit, tit->X2);
673 else{
674 Idx currentStateRef = ceToProcess.StateAttributep(ceToProcess.InitState())->FindState(*scit);
675 newCeGenerated.StateAttributep(newstate)->InsertStateRef(*scit, currentStateRef);
676 }
677 }
678 queue.insert({newCeGenerated,ceToProcess});
679 visited.insert({tit->X2,i});
680 }
681 }
682 continue; // break the current CE pick, as all following cases are no longer possible for this pick
683 }
684 }
685
686
687 // if the next ev is a (non-silent... this shall be guaranteed) ev in cand
688 if(((*cand).GenRaw().Alphabet()-(*cand).Silentevs()).Exists(nextTrans->Ev)){
689 std::cout<<"!Case 1: the event is " + ceToProcess.EventName(nextTrans->Ev)<<std::endl;
690 TransSet::Iterator tit = (*cand).GenRaw().TransRelBegin(concreteState);
691 for (;tit!=(*cand).GenRaw().TransRelEnd(concreteState);tit++){
692
693 if(tit->Ev == nextTrans->Ev && visited.find({tit->X2,i+1})==visited.end()){
694 std::cout<<"!Adding transition in Case 1"<<std::endl;
695 CounterExample newCeGenerated = ceGenerated;
696 Idx oldlaststate = *LastState(newCeGenerated);
697 Idx newstate = newCeGenerated.InsState();
698 newCeGenerated.SetTransition(oldlaststate,tit->Ev,newstate);
699 // install state attribute
700 SynchCandidates::Iterator scit = synchCands->CandidatesBegin();
701 for (;scit!=synchCands->CandidatesEnd();scit++){
702 if (*scit == cand)
703 newCeGenerated.StateAttributep(newstate)->InsertStateRef(*scit, tit->X2);
704 else{
705 Idx nextStateRef = ceToProcess.StateAttributep(nextTrans->X2)->FindState(*scit);
706 newCeGenerated.StateAttributep(newstate)->InsertStateRef(*scit, nextStateRef);
707 }
708 }
709 CounterExample newCeToProceed = ceToProcess;
710 TransSet::Iterator tit2 = newCeToProceed.TransRelBegin(newCeToProceed.InitState());
711 newCeToProceed.SetInitState(tit2->X2);
712 newCeToProceed.DelState(tit2->X1);
713 queue.insert({newCeGenerated,newCeToProceed});
714 visited.insert({tit->X2,i+1});
715 }
716 }
717 }
718 // else, then it shall be an event of other candidate (raw) gens, could either be silent or not
719 else if(visited.find({concreteState,i+1})==visited.end()){
720 std::cout<<"!Case 2"<<std::endl;
721 CounterExample newCeGenerated = ceGenerated;
722 Idx oldlaststate = *LastState(newCeGenerated);
723 Idx newstate = newCeGenerated.InsState();
724 newCeGenerated.SetTransition(oldlaststate,nextTrans->Ev,newstate);
725 // install state attribute
726 SynchCandidates::Iterator scit = synchCands->CandidatesBegin();
727 for (;scit!=synchCands->CandidatesEnd();scit++){
728 if (*scit == cand)
729 newCeGenerated.StateAttributep(newstate)->InsertStateRef(*scit, concreteState);
730 else{
731 Idx nextStateRef = ceToProcess.StateAttributep(nextTrans->X2)->FindState(*scit);
732 newCeGenerated.StateAttributep(newstate)->InsertStateRef(*scit, nextStateRef);
733 }
734 }
735 CounterExample newCeToProceed = ceToProcess;
736 TransSet::Iterator tit2 = newCeToProceed.TransRelBegin(newCeToProceed.InitState());
737 newCeToProceed.SetInitState(tit2->X2);
738 newCeToProceed.DelState(tit2->X1);
739 queue.insert({newCeGenerated,newCeToProceed});
740 visited.insert({concreteState,i+1});
741 }
742 else std::cout<<"!no match"<<std::endl;
743 }
744
745 // finally, if ceGenerated can perform some tau in cand (raw)
746 TransSet::Iterator tit = (*cand).GenRaw().TransRelBegin(concreteState);
747 for (;tit!=(*cand).GenRaw().TransRelEnd(concreteState);++tit){
748 if(cand->Silentevs().Exists(tit->Ev) && visited.find({tit->X2,i})==visited.end()){
749 std::cout<<"Tau step active"<<std::endl;
750 CounterExample newCeGenerated = ceGenerated;
751 Idx oldlaststate = *LastState(newCeGenerated);
752 Idx newstate = newCeGenerated.InsState();
753 newCeGenerated.SetTransition(oldlaststate,tit->Ev,newstate);
754 // install state attribute
755 SynchCandidates::Iterator scit = synchCands->CandidatesBegin();
756 for (;scit!=synchCands->CandidatesEnd();scit++){
757 if (*scit == cand)
758 newCeGenerated.StateAttributep(newstate)->InsertStateRef(*scit, tit->X2);
759 else{
760 Idx currentStateRef = ceToProcess.StateAttributep(ceToProcess.InitState())->FindState(*scit);
761 newCeGenerated.StateAttributep(newstate)->InsertStateRef(*scit, currentStateRef);
762 }
763 }
764 queue.insert({newCeGenerated,ceToProcess});
765 visited.insert({tit->X2,i});
766 }
767 }
768 }
769 throw Exception("CompVerify::StateMergingExpansion()", "can not reach a concrete final state", 500);
770}
771
773 // install state attribute for the initial CE
774 PCOMPVER_VERB0("CounterExampleRefinement(): Preparing")
776 StateSet::Iterator sit = mCounterExp.StatesBegin();
777 SynchCandidates::Iterator scit = mAllCandidates.top()->CandidatesBegin();
778 for (;sit!=mCounterExp.StatesEnd();sit++){
779 // the candidate is direct the top from allcandidate
780 // its state reference is direct the CE?
781 mCounterExp.StateAttributep(*sit)->InsertStateRef(*scit,*sit);
782 }
784 Idx itsize = mAllCandidates.size();
785 mAllCandidates.pop();
786 Idx currentit = 1;
787
788 while (!mAllCandidates.empty()){
789 PCOMPVER_VERB0("CounterExampleRefinement(): remaining iteration: " + ToStringInteger(mAllCandidates.size()));
790 scit = mAllCandidates.top()->CandidatesBegin();
791
792 // merge silent events. convenient preparation for state merging expansion
793 if (mIsPreemptive){
794 for (;scit!=mAllCandidates.top()->CandidatesEnd();scit++){
795 PCandidate* pcand = dynamic_cast<PCandidate*>(*scit);
796 EventSet mergeSilent = pcand->Silentevs() + pcand->PSilentevs();
797 pcand->SetSilentevs(mergeSilent);
798 }
799 }
800
801 scit = mAllCandidates.top()->CandidatesBegin();
802 for (;scit!=mAllCandidates.top()->CandidatesEnd();scit++){
803 PCOMPVER_VERB0("CounterExampleRefinement(): Extracting state merging for " + (*scit)->GenMerged().Name());
805 if (mAllCandidates.size()!=1){
806 PCOMPVER_VERB0("CounterExampleRefinement(): Extracting composition map for " + (*scit)->GenRaw().Name());
808 break; // if in a higher iteration, no need to concretize for other candidates
809 }
810 }
811 mAllCandidates.pop();
812 currentit++;
813 }
814}
815
816}//namespace
#define FD_DF(message)
#define FAUDES_TYPE_IMPLEMENTATION(ftype, ctype, cbase)
Definition cfl_types.h:958
ProductCompositionMap ComposeMap()
void SetSilentevs(EventSet silentevs)
std::pair< Candidate *, Candidate * > DecomposedPair()
std::map< Idx, Idx > mMergeMap
std::pair< Candidate *, Candidate * > mDecomposedPair
ProductCompositionMap mComposeMap
void DoAssign(Candidate cand)
bool IsInMergedClass(Idx concrete, Idx abstract)
std::set< Idx > FindConcreteStates(Idx abstract)
void DeleteStateRef(Candidate *cand)
Definition pev_verify.h:27
Idx FindState(Candidate *cand)
Definition pev_verify.h:25
void InsertStateRef(Candidate *cand, Idx state)
Definition pev_verify.h:26
virtual bool IsNonconflicting()
static StateSet::Iterator LastState(CounterExample &ce)
std::stack< SynchCandidates * > mAllCandidates
Definition pev_verify.h:130
virtual ~CompVerify(void)
Generator mGenFinal
Definition pev_verify.h:128
virtual void CounterExampleRefinement()
EventSet AllPevs()
Definition pev_verify.h:48
CounterExample mCounterExp
Definition pev_verify.h:129
virtual void ExtractParallel(Candidate *cand, CounterExample &rCE)
virtual void StateMergingExpansion(SynchCandidates *synchCands, Candidate *cand, CounterExample &rCE)
virtual void ClearAttribute(CounterExample &rCE)
virtual bool ShortestPath(const Generator &rGen, Generator &rRes, Idx begin, Idx end)
virtual void GenerateTrace(const Generator &rGen)
virtual void VerifyAll(Generator &trace)
const std::string & Name(void) const
bool Exists(const Idx &rIndex) const
void DoAssign(PCandidate cand)
virtual void ConflictEquivalentAbstraction(EventSet &silent)
void Insert(Candidate *cand)
std::list< Candidate * >::iterator Iterator
std::list< Candidate * > mCandidates
void DoAssign(SynchCandidates synchcands)
virtual const T & At(const Position &pos) const
Iterator BeginByX2(Idx x2) const
void ReSort(TTransSet< OtherCmp > &res) const
virtual void Clear(void)
bool SetTransition(Idx x1, Idx ev, Idx x2)
const ATransSet & TransRel(void) const
StateAttr * StateAttributep(Idx index)
void Write(const Type *pContext=0) const
StateSet::Iterator StatesBegin(void) const
StateSet::Iterator InitStatesBegin(void) const
bool SetTransition(Idx x1, Idx ev, Idx x2)
const EventSet & Alphabet(void) const
EventSet ActiveEventSet(Idx x1) const
const StateSet & InitStates(void) const
TransSet::Iterator TransRelBegin(void) const
void InsEvents(const EventSet &events)
void SetInitState(Idx index)
StateSet::Iterator MarkedStatesBegin(void) const
bool DelState(Idx index)
StateSet::Iterator StatesEnd(void) const
TransSet::Iterator TransRelEnd(void) const
StateSet::Iterator MarkedStatesEnd(void) const
Idx InitState(void) const
bool StateNamesEnabled(void) const
bool InsEvent(Idx index)
void SetDefaultStateNames(void)
std::string EventName(Idx index) const
StateSet CoaccessibleSet(void) const
Idx Size(void) const
virtual void Clear(void)
bool Empty(void) const
bool Exists(const T &rElem) const
virtual void Clear(void)
Iterator End(void) const
Iterator Begin(void) const
virtual bool Erase(const T &rElem)
Idx Size(void) const
bool ComputeScc(const Generator &rGen, const SccFilter &rFilter, std::list< StateSet > &rSccList, StateSet &rRoots)
void Parallel(const Generator &rGen1, const Generator &rGen2, Generator &rResGen)
void ShapePreemption(Generator &rGen, const EventSet &pevs)
uint32_t Idx
void ExtendedActiveEventSet(Idx x1, const Generator &rGen, const EventSet &silent, EventSet &result)
Definition pev_verify.cpp:9
bool IsNonblocking(const GeneratorVector &rGvec)
std::string ToStringInteger(Int number)
Definition cfl_utils.cpp:43
void AppendOmega(Generator &rGen)
AttrType AttributeVoid
long int Int
#define PCOMPVER_VERB0(msg)
#define PCOMPVER_VERB1(msg)
#define PCOMPVER_VERB2(msg)

libFAUDES 2.33k --- 2025.09.16 --- c++ api documentaion by doxygen