pev_verify.cpp
Go to the documentation of this file.
1 #include "pev_abstraction.h"
2 #include "pev_verify.h"
3 #include <chrono>
4 
5 namespace faudes {
6 
7 FAUDES_TYPE_IMPLEMENTATION(CompVerify::StateRef,CompVerify::StateRef,AttributeVoid)
8 
9 void 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 
31 void AppendOmega(Generator& rGen){
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 
72  mGenFinal.Clear();
74 }
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 
100  mCandidates.clear();
101 }
102 
104  mGenRaw.Clear();
105  mSilentevs.Clear();
106  mtau = 0;
107 }
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;
123  mComposeMap = cand.mComposeMap;
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;
135  mComposeMap = cand.mComposeMap;
136  mDecomposedPair.first = cand.mDecomposedPair.first;
137  mDecomposedPair.second = cand.mDecomposedPair.second;
138  mPevs = cand.mPevs;
139  mPSilentevs = cand.mPSilentevs;
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 
152 Candidate::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 
164 std::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 
175 bool 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;
378  ProductCompositionMap newmap;
379  Parallel(gimin,gjmin,newmap,gij);
380  gij.SetDefaultStateNames();
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());
415  ShapePreemption(mGenFinal,pcand->Pevs());
416  }
417  mGenFinal.Write("final.gen");
419 }
420 
421 
423  StateSet marked = rGen.CoaccessibleSet();
424  SccFilter filter(SccFilter::FMode::FmStatesAvoid,marked);
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 
467 bool 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 
517 StateSet::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++){
589  CounterExample ce;
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:951
ProductCompositionMap ComposeMap()
void SetSilentevs(EventSet silentevs)
std::map< Idx, Idx > mMergeMap
std::pair< Candidate *, Candidate * > DecomposedPair()
Generator GenMerged()
std::pair< Candidate *, Candidate * > mDecomposedPair
virtual ~Candidate()
Definition: pev_verify.cpp:103
ProductCompositionMap mComposeMap
void DoAssign(Candidate cand)
Definition: pev_verify.cpp:116
bool IsInMergedClass(Idx concrete, Idx abstract)
Definition: pev_verify.cpp:175
std::set< Idx > FindConcreteStates(Idx abstract)
Definition: pev_verify.cpp:164
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()
Definition: pev_verify.cpp:231
static StateSet::Iterator LastState(CounterExample &ce)
Definition: pev_verify.cpp:517
std::stack< SynchCandidates * > mAllCandidates
Definition: pev_verify.h:132
virtual ~CompVerify(void)
Definition: pev_verify.cpp:71
Generator mGenFinal
Definition: pev_verify.h:130
virtual void CounterExampleRefinement()
Definition: pev_verify.cpp:772
EventSet AllPevs()
Definition: pev_verify.h:48
CounterExample mCounterExp
Definition: pev_verify.h:131
virtual void ExtractParallel(Candidate *cand, CounterExample &rCE)
Definition: pev_verify.cpp:532
virtual void StateMergingExpansion(SynchCandidates *synchCands, Candidate *cand, CounterExample &rCE)
Definition: pev_verify.cpp:544
virtual void ClearAttribute(CounterExample &rCE)
Definition: pev_verify.cpp:525
virtual bool ShortestPath(const Generator &rGen, Generator &rRes, Idx begin, Idx end)
Definition: pev_verify.cpp:467
virtual void GenerateTrace(const Generator &rGen)
Definition: pev_verify.cpp:422
virtual void VerifyAll(Generator &trace)
Definition: pev_verify.cpp:186
bool Exists(const Idx &rIndex) const
void DoAssign(PCandidate cand)
Definition: pev_verify.cpp:128
virtual void ConflictEquivalentAbstraction(EventSet &silent)
Idx Arg1State(Idx s12) const
Idx Arg2State(Idx s12) const
void Insert(Candidate *cand)
std::list< Candidate * >::iterator Iterator
std::list< Candidate * > mCandidates
void DoAssign(SynchCandidates synchcands)
Definition: pev_verify.cpp:109
virtual const T & At(const Position &pos) const
Iterator BeginByX2(Idx x2) const
TBaseSet< Transition, TransSort::X1EvX2 >::Iterator Iterator
Definition: cfl_transset.h:273
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
Definition: cfl_types.cpp:140
Idx Size(void) 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
void Name(const std::string &rName)
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
Definition: cfl_baseset.h:1841
bool Exists(const T &rElem) const
Definition: cfl_baseset.h:2132
virtual void Clear(void)
Definition: cfl_baseset.h:1919
Iterator End(void) const
Definition: cfl_baseset.h:1913
Iterator Begin(void) const
Definition: cfl_baseset.h:1908
virtual bool Erase(const T &rElem)
Definition: cfl_baseset.h:2036
Idx Size(void) const
Definition: cfl_baseset.h:1836
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)
Definition: pev_verify.cpp:31
long int Int
#define PCOMPVER_VERB0(msg)
#define PCOMPVER_VERB1(msg)
#define PCOMPVER_VERB2(msg)

libFAUDES 2.33b --- 2025.05.07 --- c++ api documentaion by doxygen