syn_wsupcon.cpp
Go to the documentation of this file.
1 /** @file syn_wsupcon.cpp Supremal controllable sublanguage for infinite time behaviours */
2 
3 /* FAU Discrete Event Systems Library (libfaudes)
4 
5  Copyright (C) 2010 Thomas Moor
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Lesser General Public
9  License as published by the Free Software Foundation; either
10  version 2.1 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public
18  License along with this library; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
20 
21 
22 //#define FAUDES_DEBUG_FUNCTION
23 
24 #include "syn_wsupcon.h"
25 #include "syn_supcon.h"
26 #include "syn_supnorm.h"
27 #include "syn_functions.h"
28 
29 
30 namespace faudes {
31 
32 
33 /*
34 ***************************************************************************************
35 ***************************************************************************************
36  Implementation IsOmegaControllabe
37 ***************************************************************************************
38 ***************************************************************************************
39 */
40 
41 // IsOmegaControllable()
43  const Generator& rGenPlant,
44  const EventSet& rCAlph,
45  const Generator& rGenCand)
46 {
47  FD_DF("IsOmegaControllable(\"" << rGenPlant.Name() << "\", \"" << rGenCand.Name() << "\")");
48 
49  // alphabets must match
50  if ( rGenPlant.Alphabet() != rGenCand.Alphabet()) {
51  std::stringstream errstr;
52  errstr << "Alphabets of generators do not match.";
53  throw Exception("IsOmegaControllable(..)", errstr.str(), 100);
54  }
55 
56 #ifdef FAUDES_CHECKED
57  // generators are meant to be nonblocking
58  if( !IsOmegaTrim(rGenCand) ) {
59  std::stringstream errstr;
60  errstr << "Argument \"" << rGenCand.Name() << "\" is not omega-trim.";
61  throw Exception("IsOmegaControllable(..)", errstr.str(), 201);
62  }
63  if( !IsOmegaTrim(rGenPlant) ) {
64  std::stringstream errstr;
65  errstr << "Argument \"" << rGenPlant.Name() << "\" is not omega-trim.";
66  throw Exception("IsOmegaControllable(..)", errstr.str(), 201);
67  }
68 #endif
69 
70  // the trivial case: empty cand is fine
71  // (we must treat this case because empty generators are not regarded deterministic)
72  if(rGenCand.Empty()) {
73  FD_DF("IsOmegaControllable(..): empty candidate, pass");
74  return true;
75  }
76 
77  // the trivial case: empty plant is fails
78  // (we must treat this case because empty generators are not regarded deterministic)
79  if(rGenPlant.Empty()) {
80  FD_DF("IsOmegaControllable(..): empty plant, fail");
81  return false;
82  }
83 
84 #ifdef FAUDES_CHECKED
85  // generators are meant to be deterministic
86  if ( !IsDeterministic(rGenCand) || !IsDeterministic(rGenPlant)) {
87  std::stringstream errstr;
88  errstr << "Arguments are expected to be deterministic.";
89  throw Exception("IsOmegaControllable", errstr.str(), 202);
90  }
91 #endif
92 
93  // test controllability
94  StateSet dummy;
95  if(!IsControllableUnchecked(rGenPlant,rCAlph,rGenCand,dummy)) return false;
96 
97  // test relative closedness
98  if(!IsRelativelyOmegaClosedUnchecked(rGenPlant,rGenCand)) return false;
99 
100  // pass
101  FD_DF("IsOmegaControllable(...): passed");
102  return true;
103 }
104 
105 
106 // IsOmegaControllable() wrapper
108  const System& rPlantGen,
109  const Generator& rCandGen)
110 {
111  return IsOmegaControllable(rPlantGen,rPlantGen.ControllableEvents(),rCandGen);
112 }
113 
114 /*
115 ***************************************************************************************
116 ***************************************************************************************
117  Implementation SupConCmplClosed
118 ***************************************************************************************
119 ***************************************************************************************
120 */
121 
122 
123 // supcon complete
125  const Generator& rPlantGen,
126  const EventSet& rCAlph,
127  const Generator& rSpecGen,
128  Generator& rResGen)
129 {
130  FD_DF("SupConCmplClosed(" << rPlantGen.Name() << "," << rSpecGen.Name()<< ")");
131 
132  // exceptions on invalid parameters, same as std synthesis
133  ControlProblemConsistencyCheck(rPlantGen,rCAlph,rSpecGen);
134 
135  // prepare result
136  Generator* pResGen = &rResGen;
137  if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
138  pResGen= rResGen.New();
139  }
140  pResGen->Clear();
141  pResGen->Name("SupConCmplClosed("+rPlantGen.Name()+", "+rSpecGen.Name()+")");
142  pResGen->InjectAlphabet(rPlantGen.Alphabet());
143 
144  //check for trivial result
145  if(rSpecGen.InitStatesEmpty()){
146  FD_DF("SupConCmplClosed: empty language specification - empty result.");
147  }
148 
149 
150  // have a reverse composition map
151  std::map< std::pair<Idx,Idx>, Idx> revmap;
152 
153  // parallel composition (result is reachable)
154  SupConProduct(rPlantGen, rCAlph, rSpecGen, revmap, *pResGen);
155 
156  // make resulting generator complete and controllabel
157  while(true) {
158  Idx state_num = pResGen->Size();
159  if(pResGen->InitStates().Empty()) break;
160  pResGen->Complete();
161  if(pResGen->InitStates().Empty()) break;
162  SupConClosedUnchecked(rPlantGen, rCAlph, *pResGen);
163  if(pResGen->Size() == state_num) break;
164  }
165 
166  // convenience state names
167  if(rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && rResGen.StateNamesEnabled())
168  SetComposedStateNames(rPlantGen, rSpecGen, revmap, *pResGen);
169  else
170  pResGen->StateNamesEnabled(false);
171 
172  // copy result
173  if(pResGen != &rResGen) {
174  pResGen->Move(rResGen);
175  delete pResGen;
176  }
177 
178 }
179 
180 
181 // user wrapper
183  const System& rPlantGen,
184  const Generator& rSpecGen,
185  Generator& rResGen)
186 {
187 
188  // execute
189  SupConCmplClosed(rPlantGen, rPlantGen.ControllableEvents(),rSpecGen,rResGen);
190 
191  // copy all attributes of input alphabet
192  rResGen.EventAttributes(rPlantGen.Alphabet());
193 
194 }
195 
196 
197 
198 
199 /*
200 ***************************************************************************************
201 ***************************************************************************************
202  Implementation SupConCmplNB
203 ***************************************************************************************
204 ***************************************************************************************
205 */
206 
207 
208 // supcon complete
210  const Generator& rPlantGen,
211  const EventSet& rCAlph,
212  const Generator& rSpecGen,
213  Generator& rResGen)
214 {
215  FD_DF("SupConCmplNB(" << rPlantGen.Name() << "," << rSpecGen.Name()<< ")");
216 
217  // exceptions on invalid parameters, same as std synthesis
218  ControlProblemConsistencyCheck(rPlantGen,rCAlph,rSpecGen);
219 
220  // prepare result
221  Generator* pResGen = &rResGen;
222  if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
223  pResGen= rResGen.New();
224  }
225  pResGen->Clear();
226  pResGen->Name("SupConCmplNB("+rPlantGen.Name()+", "+rSpecGen.Name()+")");
227  pResGen->InjectAlphabet(rPlantGen.Alphabet());
228 
229  //check for trivial result
230  if(rSpecGen.InitStatesEmpty()){
231  FD_DF("SupConCmplNB: empty language specification - empty result.");
232  }
233 
234 
235  // have a reverse composition map
236  std::map< std::pair<Idx,Idx>, Idx> revmap;
237 
238  // parallel composition (result is reachable)
239  SupConProduct(rPlantGen, rCAlph, rSpecGen, revmap, *pResGen);
240 
241  // make resulting generator complete and controllabel and coaccessible
242  while(true) {
243  Idx state_num = pResGen->Size();
244  if(pResGen->InitStates().Empty()) break;
245  pResGen->Coaccessible();
246  if(pResGen->InitStates().Empty()) break;
247  pResGen->Complete();
248  if(pResGen->InitStates().Empty()) break;
249  SupConClosedUnchecked(rPlantGen, rCAlph, *pResGen);
250  if(pResGen->Size() == state_num) break;
251  }
252 
253  // convenience state names
254  if(rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && rResGen.StateNamesEnabled())
255  SetComposedStateNames(rPlantGen, rSpecGen, revmap, *pResGen);
256  else
257  pResGen->StateNamesEnabled(false);
258 
259  // copy result
260  if(pResGen != &rResGen) {
261  pResGen->Move(rResGen);
262  delete pResGen;
263  }
264 
265 }
266 
267 
268 // user wrapper
270  const System& rPlantGen,
271  const Generator& rSpecGen,
272  Generator& rResGen)
273 {
274 
275  // execute
276  SupConCmplNB(rPlantGen, rPlantGen.ControllableEvents(),rSpecGen,rResGen);
277 
278  // copy all attributes of input alphabet
279  rResGen.EventAttributes(rPlantGen.Alphabet());
280 
281 }
282 
283 
284 
285 /*
286 ***************************************************************************************
287 ***************************************************************************************
288  Implementation SupConNormCmplNB
289 ***************************************************************************************
290 ***************************************************************************************
291 */
292 
293 
294 // SupConNormCmplNB(rL,rCAlph,rOAlph,rK,rResult)
296  const Generator& rL,
297  const EventSet& rCAlph,
298  const EventSet& rOAlph,
299  const Generator& rK,
300  Generator& rResult)
301 {
302  FD_DF("SupConNormCmplNB(" << rL.Name() << "," << rK.Name() << ")");
303  // initialize: K0
304  Generator K0;
305  K0.StateNamesEnabled(false);
306  Product(rL,rK,K0);
307  K0.Coaccessible();
308  // initialize: closure(rL)
309  Generator L=rL;
310  L.StateNamesEnabled(false);
311  L.Trim();
312  MarkAllStates(L);
313  // loop
314  Generator Ki=K0;
315  Ki.StateNamesEnabled(false);
316  while(1) {
317  FD_DF("SupConNormCmplNB(" << rL.Name() << "," << rK.Name() << "): #" << Ki.Size() << " m#" << Ki.MarkedStatesSize());
318  // keep copy of recent
319  rResult=Ki;
320  // cheep closure (for coreachable generator)
321  Ki.InjectMarkedStates(Ki.States());
322  // synthesise closed
323  SupConNormClosed(L,rCAlph,rOAlph,Ki,Ki);
324  Complete(Ki);
325  // restrict
326  Product(K0,Ki,Ki);
327  Ki.Coaccessible();
328  // test (sequence is decreasing anyway)
329  if(LanguageInclusion(rResult,Ki)) break;
330  }
331  FD_DF("SupConNormCmplNB(" << rL.Name() << "," << rK.Name() << "): done");
332 }
333 
334 
335 /** rti wrapper */
337  const System& rPlantGen,
338  const Generator& rSpecGen,
339  Generator& rResGen)
340 {
341  FD_DF("SupConNormCmplNB(" << rPlantGen.Name() << "," << rSpecGen.Name() << "): rti wrapper");
342  // prepare result
343  Generator* pResGen = &rResGen;
344  if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
345  pResGen= rResGen.New();
346  }
347  // execute
348  SupConNormCmplNB(rPlantGen,rPlantGen.ControllableEvents(),rPlantGen.ObservableEvents(),rSpecGen,*pResGen);
349  // copy all attributes of input alphabet
350  pResGen->EventAttributes(rPlantGen.Alphabet());
351  // copy result
352  if(pResGen != &rResGen) {
353  pResGen->Move(rResGen);
354  delete pResGen;
355  }
356 }
357 
358 
359 /*
360 ***************************************************************************************
361 ***************************************************************************************
362  Computation of the controllable prefix / enforcing omega-controlled liveness
363 ***************************************************************************************
364 ***************************************************************************************
365 */
366 
367 
368 
369 /*
370 Initial libFAUDES implementation of omega-controlled liveness, tmoor 2011, last used
371 for libFAUDES 2.22p. The function retsricts the candidate to states for which a
372 prefix-closed controller exists such that in closed-loop configuration the acceptance condition
373 is implied by the plant acceptance condition. This corresponds to the controllable prefix,
374 originally proposed by J. Thistle et al. The actual implementation, however, is based on a sufficient
375 but not necessary test. It therefore identifies a subset of the controllable prefix, which may
376 turn out empty even when a prefix-closed controller exists. The below code is obsolete and will
377 be removed eventually.
378 */
379 
380 /*
381 
382 // OmegaControlledLiveness(...)
383 bool OmegaControlledLiveness(
384  Generator& rSupCandGen,
385  const EventSet& rCAlph,
386  StateSet& rMarkedPlantStates,
387  StateSet& rMarkedSpecStates)
388 {
389  FD_DF("OmegaControlledLiveness(...)");
390 
391  // set of critical states
392  StateSet critical;
393 
394  // return true if parallelcomp contains no initial states
395  if(rSupCandGen.InitStatesEmpty()) {
396  return true;
397  }
398 
399 #ifdef FAUDES_DEBUG_FUNCTION
400  FD_DF("OmegaControlledLiveness(): marked states: ");
401  StateSet ssd= rMarkedPlantStates + rMarkedSpecStates;
402  ssd.Write();
403 #endif
404 
405  // find un-marked sccs
406  StateSet astates = rMarkedPlantStates + rMarkedSpecStates;
407  SccFilter umfilter(SccFilter::FmIgnoreTrivial | SccFilter::FmStatesAvoid, astates);
408  std::list<StateSet> umsccs;
409  StateSet umroots;
410  ComputeScc(rSupCandGen,umfilter,umsccs,umroots);
411 
412  // report
413  std::list<StateSet>::iterator ssit=umsccs.begin();
414  for(;ssit!=umsccs.end(); ++ssit) {
415  FD_DF("OmegaControlledLiveness(): unmarked scc: " << ssit->ToString());
416  }
417 
418  // good-states iteration
419  StateSet goodstates = rMarkedSpecStates;
420 
421  // drive states to good states
422  while(true) {
423  // LoopCallback();
424  // allow for user interrupt, incl progress report
425  FD_WPC(1,2,"OmegaControlledLiveness(): iterating states");
426  // test individual states
427  FD_DF("OmegaControlledLiveness(): iterate over states (#" << rSupCandGen.Size() << ")");
428  bool found=false;
429 
430  StateSet::Iterator sit = rSupCandGen.StatesBegin();
431  StateSet::Iterator sit_end = rSupCandGen.StatesEnd();
432  for(; sit!=sit_end; ++sit) {
433  bool fail = false; // cbaier 20121011
434  bool positive=false; // cbaier 20121011
435  // goodstate anyway
436  if(goodstates.Exists(*sit)) continue;
437  // test transitions
438  TransSet::Iterator tit = rSupCandGen.TransRelBegin(*sit);
439  TransSet::Iterator tit_end = rSupCandGen.TransRelEnd(*sit);
440  // no transitions at all
441  if(tit==tit_end) continue;
442  // loop over successors
443  for(; tit!=tit_end; ++tit) {
444  if(goodstates.Exists(tit->X2))
445  {positive=true; // cbaier 20121011: added
446  continue;}
447  if(rCAlph.Exists(tit->Ev)) continue;
448 
449  // good states survive the loop // cbaier 20121011: added
450  if(tit!=tit_end) {
451  fail=true;
452  break;
453  }
454  }
455 
456  // good states survive
457  if(!fail && positive) { // cbaier 20121011: changed
458  FD_DF("OmegaControlledLiveness(): good state " << rSupCandGen.SStr(*sit));
459  goodstates.Insert(*sit);
460  found=true;
461  }
462  }
463 
464  // test individual unmarked sccs
465  FD_DF("OmegaControlledLiveness(): iterate over unmarked sccs (#" << umsccs.size() <<")");
466  std::list<StateSet>::iterator ssit=umsccs.begin();
467  while(ssit!=umsccs.end()) {
468  bool fail=false;
469  bool positive=false;
470  sit=ssit->Begin();
471  sit_end=ssit->End();
472  for(; sit!=sit_end; ++sit) {
473  // goodstate anyway
474  if(goodstates.Exists(*sit)) continue;
475  // test transitions
476  TransSet::Iterator tit = rSupCandGen.TransRelBegin(*sit);
477  TransSet::Iterator tit_end = rSupCandGen.TransRelEnd(*sit);
478  // no transitions at all
479  if(tit==tit_end) continue;
480  // loop over successors
481  for(; tit!=tit_end; ++tit) {
482  if(goodstates.Exists(tit->X2)) { positive=true; continue;}
483  if(rCAlph.Exists(tit->Ev)) continue; // tmoor 20110202: fixed typo
484  if(ssit->Exists(tit->X2)) continue;
485  break;
486  }
487  // good states survive the loop
488  if(tit!=tit_end) {
489  fail=true;
490  break;
491  }
492  }
493 
494  // prepare next scc iterator
495  std::list<StateSet>::iterator ssitnext=ssit;
496  ++ssitnext;
497  bool lend= (ssitnext==umsccs.end());
498  // all states passed, then they are all good
499  if(!fail && positive) {
500  FD_DF("OmegaControlledLiveness(): good scc " << ssit->ToString());
501  goodstates.InsertSet(*ssit);
502  umsccs.erase(ssit);
503  found=true;
504  }
505  // break on end of list
506  if(lend) break;
507  // progress
508  ssit=ssitnext;
509  }
510 
511  // exit
512  if(!found) break;
513  };
514 
515  // delete critical states
516  FD_DF("OmegaControlledLiveness(): good states: " << goodstates.ToString())
517  StateSet::Iterator sit = rSupCandGen.StatesBegin();
518  StateSet::Iterator sit_end = rSupCandGen.StatesEnd();
519  for(; sit!=sit_end; ++sit) {
520  if(!goodstates.Exists(*sit))
521  rSupCandGen.DelState(*sit);
522  }
523 
524  // return true
525  FD_DF("OmegaControlledLiveness(): done");
526  return true;
527 }
528 
529 */
530 
531 
532 /*
533 This implementation is a direct transscript of the mu-calculus formulas stated in "Control of
534 w-Automata, Church's Problem, and the Emptiness Problem for Tree w-Automata", by J. Thistle and
535 W.M. Wonham, 1992, adapted for the special case of deterministic Buchi-automata. Referring to the
536 referenced literature, the corresponding iteration is "essentially optimal" in terms of performance.
537 In the below implementation, we unwind each individual mu/nu quantifiation literally and resist
538 to apply strategic substitutions in order to obtain a reference implementation. This is suspected
539 to introduce (linear) penalty for avoidable boolean operations on sets of states. In a recent study,
540 Christian Wamser proposes a fine-tuned alternative implementation which will be integrated in
541 libFAUDES in due course.
542 */
543 
545  Generator& rSupCandGen,
546  const EventSet& rCAlph,
547  const StateSet& rPlantMarking)
548 {
549 
550  FD_DF("OmegaControlledLiveness()");
551 
552  // declare iterate sets
553  StateSet resolved, initialK, targetLstar;
554  StateSet initialL, targetL;
555  StateSet domainL, target1;
556  StateSet target, domain, theta;
557 
558  // convenience
559  const StateSet& full = rSupCandGen.States();
560  Idx fsz=full.Size();
561 
562  // evaluate mu(resolved).nu(initialK)[ p(initialK * markedK + resolved )) ];
563  // here, p(T) denotes the set of states that can be driven to enter T under liveness assumption inf-markL;
564  // use std. mu-nu-iteration
565  resolved.Clear();
566  while(true) {
567  Idx rsz = resolved.Size();
568  initialK = full;
569  while(true) {
570  Idx iKsz = initialK.Size();
571 
572  // prepare target for P(): targetLstar = initialK * markedK + resolved
573  targetLstar = (initialK * rSupCandGen.MarkedStates()) + resolved;
574  FD_DF("OmegaControlledLiveness(): [STD] iterate resolved/targetLstar #" << xsz << "/" << targetLstar.Size());
575 
576  // evaluate p(targetLstar) = mu(initialL).[ thetaTilde(targetLstar+initialL) ]
577  // here, thetaTilde(T) denotes the set of states that can be controlled such that T is persistently
578  // reachable and markL is not passed before T is entered;
579  // start with initialL:=0 and iterate initialL += thetaTilde(targetLstar+initialL);
580  initialL.Clear();
581  while(true) {
582  Idx iLsz = initialL.Size();
583 
584  // prepare targetL=targetLstar+initialL
585  targetL=targetLstar+initialL;
586  FD_DF("OmegaControlledLiveness(): [STD] ---- iterate targetL #" << targetL.Size());
587 
588  // evaluate thetaTilde(targetL)=nu(domainL).mu(target1)[ theta(targetL+(target1-markL), domainL-markL) ];
589  // here, theta(T,D) is the set of states that, by one transition, can enter T and can be controlled not to exit D+T;
590  // start with domainL:=full and iterate domainL -= mu(target1)[theta(targetL+(target1-markL), domainL-markL)];
591  domainL=full;
592  targetL = targetLstar + initialL;
593  while(true) {
594  Idx dLsz = domainL.Size();
595  FD_DF("OmegaControlledLiveness(): [STD] --- iterate domainL #" << domainL.Size());
596 
597  // user interrupt/ progress
598  FD_WPC(1,2,"OmegaControlledLiveness(): [STD] iterating reverse dynamics");
599 
600  // prepare domain = domainL - marL
601  domain=domainL-rPlantMarking;
602 
603  // evaluate mu(target1)[ theta(targetL+(target1-markL), domain) ];
604  // start with target1:=0 and iterate target+=theta(targetL+(target1-markL), domainL-markL) ];
605  target1.Clear();
606  while(true) {
607  Idx t1sz = target1.Size();
608 
609  // prepare target= targetL+(target1-markL)
610  target = targetL + (target1-rPlantMarking);
611 
612  // evaluate theta(target,domain)
613  FD_DF("OmegaControlledLiveness(): [STD] -- evaluate theta for target/domain # "
614  << target.Size() << "/" << domain.Size());
615  theta.Clear();
616  StateSet::Iterator sit = full.Begin();
617  StateSet::Iterator sit_end = full.End();
618  for(;sit!=sit_end;++sit) {
619  bool pass = false;
620  bool fail = false;
621  TransSet::Iterator tit = rSupCandGen.TransRelBegin(*sit);
622  TransSet::Iterator tit_end = rSupCandGen.TransRelEnd(*sit);
623  for(;tit!=tit_end; ++tit) {
624  if(target.Exists(tit->X2)) {pass = true; continue;}
625  if(domain.Exists(tit->X2)) {continue;}
626  if(!rCAlph.Exists(tit->Ev)){ fail = true; break;}
627  }
628  if(pass && !fail) {
629  theta.Insert(*sit);
630  FD_DF("OmegaControlledLiveness(): [STD] theta found state " << rSupCandGen.SStr(*sit));
631  }
632  } // end: theta
633 
634  // mu-loop on target1
635  target1.InsertSet(theta);
636  if(target1.Size()==t1sz) break;
637  if(target1.Size()==fsz) break;
638  } // end: mu
639 
640  FD_DF("OmegaControlledLiveness(): [STD] -- mu-target1 # " << target1.Size());
641 
642  // nu-loop on domainL
643  domainL.RestrictSet(target1);
644  if(domainL.Size()==dLsz) break;
645  if(domainL.Size()==0) break;
646  } // end: nu
647 
648  FD_DF("OmegaControlledLiveness(): [STD] --- nu-domainL-mu-target1 # " << domainL.Size());
649 
650  // mu-loop on initialL
651  initialL.InsertSet(domainL);
652  if(initialL.Size()==iLsz) break;
653  if(initialL.Size()==fsz) break;
654  } // end: mu
655 
656  // nu-loop on initialK
657  initialK.RestrictSet(initialL);
658  if(initialK.Size()==iKsz) break;
659  if(initialK.Size()==0) break;
660  } // end: nu
661 
662  // mu-loop on resolved
663  resolved.InsertSet(initialK);
664  if(resolved.Size()==rsz) break;
665  if(resolved.Size()==fsz) break;
666  } // end: mu
667 
668  // restrict candidate to resolved states
669  rSupCandGen.DelStates(full - resolved);
670 
671  // done
672  return true;
673 }
674 
675 
676 /*
677 Variant of the controllable prefix to extract a particular feedback map. Again, this is
678 very close to the relevant literature and meant as a reference. A more efficient
679 implementation proposed by Christian Wamser will be integrated in due course.
680 */
681 
683  Generator& rSupCandGen,
684  const EventSet& rCAlph,
685  const StateSet& rPlantMarking,
686  std::map< Idx , EventSet>& rFeedbackMap)
687 {
688 
689  FD_WARN("OmegaControlledLiveness()");
690 
691  // declare iterate sets
692  StateSet resolved, initialK, targetLstar;
693  StateSet initialL, targetL;
694  StateSet domainL, target1;
695  StateSet target, domain, theta;
696 
697  // record controls per state
698  EventSet disable;
699  std::map< Idx , EventSet> controls1;
700  std::map< Idx , EventSet> controls1L;
701  std::map< Idx , EventSet> controls1X;
702 
703  // convenience
704  const StateSet& full = rSupCandGen.States();
705  Idx fsz=full.Size();
706 
707  // evaluate mu(resolved).nu(initialK)[ p(initialK * markedK + resolved )) ];
708  resolved.Clear();
709  while(true) {
710  Idx xsz = resolved.Size();
711  initialK = full;
712  while(true) {
713  Idx rsz = initialK.Size();
714  targetLstar = (initialK * rSupCandGen.MarkedStates()) + resolved;
715  FD_WARN("OmegaControlledLiveness(): [FBM] iterate resolved/targetLstar #" << xsz << "/" << targetLstar.Size());
716 
717  // reset controls
718  controls1L.clear();
719 
720  // evaluate p(targetLstar) = mu(initialL).[ thetaTilde(targetLstar+initialL) ]
721  initialL.Clear();
722  while(true) {
723  Idx t1Lsz = initialL.Size();
724  targetL = targetLstar + initialL;
725  FD_WARN("OmegaControlledLiveness(): [FBM] ---- iterate targetL #" << targetL.Size());
726 
727  // evaluate thetaTilde(targetL)=nu(domainL).mu(target1)[ theta(targetL+(target1-markL), domainL-markL) ];
728  domainL=full;
729  while(true) {
730  Idx dsz = domainL.Size();
731  domain=domainL-rPlantMarking;
732  FD_WARN("OmegaControlledLiveness(): [FBM] --- iterate domain #" << domain.Size());
733 
734  // reset controls
735  controls1.clear();
736 
737  // user interrupt/ progress
738  FD_WPC(1,2,"OmegaControlledLiveness(): [FBM] iterating reverse dynamics");
739 
740  // evaluate mu(target1)[ theta(targetL+(target1-markL), domain) ];
741  target1.Clear();
742  while(true) {
743  Idx t1sz = target1.Size();
744  target = targetL + (target1-rPlantMarking);
745 
746  // evaluate theta(target,domain)
747  FD_WARN("OmegaControlledLiveness(): [FBM] -- evaluate theta for target/domain # "
748  << target.Size() << "/" << domain.Size());
749  theta.Clear();
750  StateSet::Iterator sit = full.Begin();
751  StateSet::Iterator sit_end = full.End();
752  for(;sit!=sit_end;++sit) {
753  bool pass = false;
754  bool fail = false;
755  disable.Clear();
756  TransSet::Iterator tit = rSupCandGen.TransRelBegin(*sit);
757  TransSet::Iterator tit_end = rSupCandGen.TransRelEnd(*sit);
758  for(;tit!=tit_end; ++tit) {
759  if(target.Exists(tit->X2)) { pass = true; continue; }
760  if(domain.Exists(tit->X2)) { continue; }
761  if(!rCAlph.Exists(tit->Ev)){ fail = true; break; }
762  disable.Insert(tit->Ev);
763  }
764  if(pass && !fail) {
765  theta.Insert(*sit);
766  if(controls1.find(*sit)==controls1.end()) controls1[*sit]=disable;
767  FD_WARN("OmegaControlledLiveness(): [FBM] theta found state " << rSupCandGen.SStr(*sit));
768  if(!disable.Empty())disable.Write();
769  }
770  } // end: theta
771 
772  // mu-loop on target1
773  target1.InsertSet(theta);
774  if(target1.Size()==t1sz) break;
775  if(target1.Size()==fsz) break;
776  } // end: mu
777 
778  FD_WARN("OmegaControlledLiveness(): [FBM] -- mu-target1 # " << target1.Size());
779 
780  // nu-loop on domainL
781  domainL.RestrictSet(target1);
782  if(domainL.Size()==dsz) break;
783  if(domainL.Size()==0) break;
784  } // end: nu
785 
786  FD_WARN("OmegaControlledLiveness(): [FBM] --- nu-domainL-mu-target1 # " << domainL.Size());
787 
788  // merge controls
789  std::map< Idx , EventSet>::iterator cit=controls1.begin();
790  std::map< Idx , EventSet>::iterator cit_end=controls1.end();
791  for(;cit!=cit_end;++cit) {
792  if(controls1L.find(cit->first)!=controls1L.end()) continue;
793  controls1L[cit->first]=cit->second;
794  }
795 
796  // mu-loop on initialL
797  initialL.InsertSet(domainL);
798  if(initialL.Size()==t1Lsz) break;
799  if(initialL.Size()==fsz) break;
800  } // end: mu
801 
802  // nu-loop on initialK
803  initialK.RestrictSet(initialL);
804  if(initialK.Size()==rsz) break;
805  if(initialK.Size()==0) break;
806  } // end: nu
807 
808  // merge controls
809  std::map< Idx , EventSet>::iterator cit=controls1L.begin();
810  std::map< Idx , EventSet>::iterator cit_end=controls1L.end();
811  for(;cit!=cit_end;++cit) {
812  if(controls1X.find(cit->first)!=controls1X.end()) continue;
813  controls1X[cit->first]=cit->second;
814  }
815 
816  // mu-loop on resolved
817  resolved.InsertSet(initialK);
818  if(resolved.Size()==xsz) break;
819  if(resolved.Size()==fsz) break;
820  } // end: mu
821 
822  // restrict candidate to valid restrict
823  rSupCandGen.DelStates(full - resolved);
824 
825  // re-write controls as feedback map
826  EventSet ucalph = rSupCandGen.Alphabet() - rCAlph;
827  StateSet::Iterator sit = resolved.Begin();
828  StateSet::Iterator sit_end = resolved.End();
829  for(;sit!=sit_end;++sit) {
830  FD_WARN("OmegaControlledLiveness(): [FBM] controls " << rSupCandGen.SStr(*sit) << " " << controls1X[*sit].ToString());
831  rFeedbackMap[*sit]= (rSupCandGen.ActiveEventSet(*sit) + ucalph) - controls1X[*sit];
832  }
833 
834  // done
835  return true;
836 }
837 
838 
839 
840 
841 // helper class: mergable control pattern
843 public:
844  // merge with other
845  void merge(const MCtrlPattern& other) {
847  enable_one.insert(other.enable_one.begin(),other.enable_one.end());
848  }
849  // test conflict
850  bool conflict() {
851  std::set< EventSet >::iterator eit =enable_one.begin();
852  std::set< EventSet >::iterator eit_end =enable_one.end();
853  for(; eit!=eit_end ; ++eit)
854  if( (*eit - disable_all).Empty() ) return true;
855  return false;
856  }
857  // member variables
859  std::set< EventSet > enable_one;
860 };
861 
862 
863 
864 /*
865 Variant of a controllable prefix under partial observation. This is **experimantal**.
866 Based on the situation of full observation, this variant records control patterns
867 used to establish controlled liveness and only accepts a new state if the corresponding
868 pattern complies all recorded patterns that correspond to the same observation.
869 The result is a (possibly strict) subset of the controllable prefix for the purpose.
870 Theoretical background will be provided in due course.
871 */
872 
874  Generator& rSupCandGen,
875  const EventSet& rCAlph,
876  const StateSet& rPlantMarking,
877  std::map< Idx , Idx>& rControllerStatesMap,
878  std::map< Idx , EventSet>& rFeedbackMap)
879 {
880 
881  FD_WARN("OmegaControlledLiveness(): [POBS]: cand #" << rSupCandGen.Size());
882 
883  // debugging: interpret empty controllermap as identity
884  StateSet::Iterator xit = rSupCandGen.StatesBegin();
885  StateSet::Iterator xit_end = rSupCandGen.StatesEnd();
886  for(;xit!=xit_end;++xit) {
887  std::map< Idx , Idx >::const_iterator cxit=rControllerStatesMap.find(*xit);
888  if(cxit==rControllerStatesMap.end()) rControllerStatesMap[*xit]=*xit;
889  }
890 
891  // informative
892  std::map< Idx , Idx>::const_iterator oit = rControllerStatesMap.begin();
893  std::set< Idx > ostates;
894  for(; oit != rControllerStatesMap.end(); ++oit)
895  ostates.insert(oit->second);
896  FD_WARN("OmegaControlledLiveness(): [POBS]: " << "obs #" << ostates.size());
897 
898  // declare iterate sets
899  StateSet resolved, initialK, targetLstar;
900  StateSet initialL, targetL;
901  StateSet domainL, target1;
902  StateSet target, domain, theta;
903 
904  // record controls per state
905  EventSet disable;
906  EventSet enable;
907  std::map< Idx , MCtrlPattern> controlsT;
908  std::map< Idx , MCtrlPattern> controls1;
909  std::map< Idx , MCtrlPattern> controls1L;
910  std::map< Idx , MCtrlPattern> controls1X;
911 
912  // convenience
913  const StateSet& full = rSupCandGen.States();
914  Idx fsz=full.Size();
915 
916  // evaluate mu(resolved).nu(initialK)[ p(initialK * markedK + resolved )) ];
917  resolved.Clear();
918  while(true) {
919  Idx xsz = resolved.Size();
920  initialK = full;
921  while(true) {
922  Idx rsz = initialK.Size();
923  targetLstar = (initialK * rSupCandGen.MarkedStates()) + resolved;
924  FD_WARN("OmegaControlledLiveness(): [POBS] iterate resolved/targetLstar #" << xsz << "/" << targetLstar.Size());
925 
926  // reset controls
927  controls1L.clear();
928 
929  // evaluate p(targetLstar) = mu(initialL).[ thetaTilde(targetLstar+initialL) ]
930  initialL.Clear();
931  while(true) {
932  Idx t1Lsz = initialL.Size();
933  targetL = targetLstar + initialL;
934  FD_WARN("OmegaControlledLiveness(): [POBS] ---- iterate targetL #" << targetL.Size());
935 
936  // evaluate thetaTilde(targetL)=nu(domainL).mu(target1)[ theta(targetL+(target1-markL), domainL-markL) ];
937  domainL=full;
938  while(true) {
939  Idx dsz = domainL.Size();
940  domain=domainL-rPlantMarking;
941  FD_WARN("OmegaControlledLiveness(): [POBS] --- iterate domain #" << domain.Size());
942 
943  // reset controls
944  controls1.clear();
945 
946  // user interrupt/ progress
947  FD_WPC(1,2,"OmegaControlledLiveness(): [POBS] iterating reverse dynamics");
948 
949  // evaluate mu(target1)[ theta(targetL+(target1-markL), domain) ];
950  target1.Clear();
951  while(true) {
952  Idx t1sz = target1.Size();
953  target = targetL + (target1-rPlantMarking);
954 
955  // evaluate theta(target,domain) in three passes
956  FD_WARN("OmegaControlledLiveness(): [POBS] -- evaluate theta for target/domain # "
957  << target.Size() << "/" << domain.Size());
958  theta.Clear();
959  controlsT.clear();
960 
961  // pass 1: find new candidate states and acumulate required controls
962  StateSet::Iterator sit = full.Begin();
963  StateSet::Iterator sit_end = full.End();
964  for(;sit!=sit_end;++sit) {
965  Idx cx=rControllerStatesMap[*sit];
966  bool pass = false;
967  bool fail = false;
968  disable.Clear();
969  enable.Clear();
970  TransSet::Iterator tit = rSupCandGen.TransRelBegin(*sit);
971  TransSet::Iterator tit_end = rSupCandGen.TransRelEnd(*sit);
972  for(;tit!=tit_end; ++tit) {
973  if(disable.Exists(tit->Ev)) continue;
974  if(target.Exists(tit->X2)) {enable.Insert(tit->Ev); pass = true; continue;}
975  if(domain.Exists(tit->X2)) {continue;}
976  if(!rCAlph.Exists(tit->Ev)){ fail = true; break;}
977  disable.Insert(tit->Ev);
978  }
979  if(pass && !fail) {
980  // initialize control with existing patterns
981  if(controlsT.find(cx)==controlsT.end()) {
982  if(controls1.find(cx)!=controls1.end())
983  controlsT[cx].merge(controls1[cx]);
984  if(controls1L.find(cx)!=controls1L.end())
985  controlsT[cx].merge(controls1L[cx]);
986  if(controls1X.find(cx)!=controls1X.end())
987  controlsT[cx].merge(controls1X[cx]);
988  }
989  // apply additional pattern
990  controlsT[cx].disable_all.InsertSet(disable);
991  controlsT[cx].enable_one.insert(enable);
992  }
993  } // end: theta pass 1
994 
995  // pass 2: merge new controls to controls1, reject conflicting
996  std::map< Idx , MCtrlPattern >::iterator cpit=controlsT.begin();
997  std::map< Idx , MCtrlPattern >::iterator cpit_end=controlsT.end();
998  while(cpit!=cpit_end) {
999  if(cpit->second.conflict()) {controlsT.erase(cpit++); continue;}
1000  controls1[cpit->first].merge(cpit->second);
1001  ++cpit;
1002  }
1003 
1004  // pass 3: evaluate theta by accumulated controls control
1005  sit = rSupCandGen.StatesBegin();
1006  sit_end = rSupCandGen.StatesEnd();
1007  for(;sit!=sit_end;++sit) {
1008  bool pass = false;
1009  bool fail = false;
1010  Idx cx=rControllerStatesMap[*sit];
1011  if(controls1.find(cx)==controls1.end()) continue;
1012  disable=controls1[cx].disable_all;
1013  TransSet::Iterator tit = rSupCandGen.TransRelBegin(*sit);
1014  TransSet::Iterator tit_end = rSupCandGen.TransRelEnd(*sit);
1015  for(;tit!=tit_end; ++tit) {
1016  if(disable.Exists(tit->Ev)) continue;
1017  if(target.Exists(tit->X2)) {pass = true; continue;}
1018  if(domain.Exists(tit->X2)) {continue;}
1019  fail = true;
1020  }
1021  if(pass && !fail) {
1022  theta.Insert(*sit);
1023  //FD_WARN("OmegaControlledLiveness(): [POBS] theta candidate verified " << rSupCandGen.SStr(*sit));
1024  }
1025  } // end: theta pass 3
1026 
1027  // mu-loop on target1
1028  target1.InsertSet(theta);
1029  if(target1.Size()==t1sz) break;
1030  if(target1.Size()==fsz) break;
1031  } // end: mu
1032 
1033  FD_WARN("OmegaControlledLiveness(): [POBS] -- mu-target1 # " << target1.Size());
1034 
1035  // nu-loop on domainL
1036  domainL.RestrictSet(target1);
1037  if(domainL.Size()==dsz) break;
1038  if(domainL.Size()==0) break;
1039  } // end: nu
1040 
1041  FD_WARN("OmegaControlledLiveness(): [POBS] --- nu-domainL-mu-target1 # " << domainL.Size());
1042 
1043  // merge controls
1044  std::map< Idx , MCtrlPattern>::iterator cit = controls1.begin();
1045  std::map< Idx , MCtrlPattern>::iterator cit_end = controls1.end();
1046  for(;cit!=cit_end;++cit)
1047  controls1L[cit->first].merge(cit->second);
1048 
1049  // mu-loop on initialL
1050  initialL.InsertSet(domainL);
1051  if(initialL.Size()==t1Lsz) break;
1052  if(initialL.Size()==fsz) break;
1053  } // end: mu
1054 
1055  // nu-loop on initialK
1056  initialK.RestrictSet(initialL);
1057  if(initialK.Size()==rsz) break;
1058  if(initialK.Size()==0) break;
1059  } // end: nu
1060 
1061  // merge controls
1062  std::map< Idx , MCtrlPattern>::iterator cit = controls1L.begin();
1063  std::map< Idx , MCtrlPattern>::iterator cit_end = controls1L.end();
1064  for(;cit!=cit_end;++cit)
1065  controls1X[cit->first].merge(cit->second);
1066 
1067  // mu-loop on resolved
1068  resolved.InsertSet(initialK);
1069  if(resolved.Size()==xsz) break;
1070  if(resolved.Size()==fsz) break;
1071  } // end: mu
1072 
1073  // restrict candidate to valid restrict
1074  rSupCandGen.DelStates(full - resolved);
1075 
1076  // debugging
1077  if(rSupCandGen.IsCoaccessible())
1078  FD_WARN("OmegaControlledLiveness(): [POBS] ---- coaccessible ok");
1079  if(rSupCandGen.IsComplete())
1080  FD_WARN("OmegaControlledLiveness(): [POBS] ---- complete ok");
1081  if(!rSupCandGen.InitStates().Empty())
1082  FD_WARN("OmegaControlledLiveness(): [POBS] ---- init state ok");
1083 
1084  // re-write controls as feedback map (w.r.t. candidate states)
1085  StateSet::Iterator sit = resolved.Begin();
1086  StateSet::Iterator sit_end = resolved.End();
1087  for(;sit!=sit_end;++sit) {
1088  Idx cx=rControllerStatesMap[*sit];
1089  //FD_WARN("OmegaControlledLiveness(): [POBS] controls at cx=" << cx << " for plant state " << rSupCandGen.SStr(*sit) << " " << controls1X[cx].disable_all.ToString());
1090  rFeedbackMap[*sit]= rSupCandGen.Alphabet() - controls1X[cx].disable_all;
1091  }
1092 
1093  // done
1094  return true;
1095 }
1096 
1097 
1098 /*
1099 ***************************************************************************************
1100 ***************************************************************************************
1101  Implementation of OmegaSupConNB and friends
1102 ***************************************************************************************
1103 ***************************************************************************************
1104 */
1105 
1106 // helper class: omega-product state
1107 class OPSState {
1108 public:
1109  // minimal interface
1110  OPSState() {};
1111  OPSState(const Idx& rq1, const Idx& rq2, const bool& rf) :
1112  q1(rq1), q2(rq2), m1required(rf) {};
1113  std::string Str(void) { return ToStringInteger(q1)+"|"+
1115  // order
1116  bool operator < (const OPSState& other) const {
1117  if (q1 < other.q1) return(true);
1118  if (q1 > other.q1) return(false);
1119  if (q2 < other.q2) return(true);
1120  if (q2 > other.q2) return(false);
1121  if (m1required && !other.m1required) return(true);
1122  return(false);
1123  }
1124  // member variables
1128 };
1129 
1130 
1131 // OmegaSupConProduct(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, rResGen)
1133  const Generator& rPlantGen,
1134  const EventSet& rCAlph,
1135  const Generator& rSpecGen,
1136  std::map< OPSState , Idx>& rProductCompositionMap,
1137  Generator& rResGen)
1138 {
1139  FD_DF("OmegaSupConProduct(" << &rPlantGen << "," << &rSpecGen << ")");
1140 
1141  // prepare result
1142  rResGen.Clear();
1143  rResGen.InjectAlphabet(rPlantGen.Alphabet());
1144 
1145  // trivial case
1146  if (rPlantGen.InitStatesEmpty()) {
1147  FD_DF("OmegaSupConProduct: plant got no initial states. "
1148  << "parallel composition contains empty language.");
1149  return;
1150  }
1151  if (rSpecGen.InitStatesEmpty()) {
1152  FD_DF("OmegaSupConProduct: spec got no initial states. "
1153  << "parallel composition contains empty language.");
1154  return;
1155  }
1156 
1157  // todo stack
1158  std::stack< OPSState > todo;
1159  // current/next state as pair with flag
1160  OPSState currentp, nextp;
1161  // current/next state as target index
1162  Idx currentt, nextt;
1163  TransSet::Iterator ptit, ptit_end, stit, stit_end;
1164  std::map< OPSState, Idx>::iterator rcit;
1165  // critical states
1166  StateSet critical;
1167  // disabled events
1168  EventSet disable;
1169 
1170 
1171  // push initial state on todo stack
1172  currentp = OPSState(*rPlantGen.InitStatesBegin(), *rSpecGen.InitStatesBegin(), true);
1173  todo.push(currentp);
1174  currentt=rResGen.InsInitState();
1175  rProductCompositionMap[currentp] = currentt;
1176 
1177  // process/feed todo stack
1178  FD_DF("OmegaSupConProduct: processing reachable states:");
1179  while(!todo.empty()) {
1180  // allow for user interrupt
1181  // LoopCallback();
1182  // allow for user interrupt, incl progress report
1183  FD_WPC(rProductCompositionMap.size(),rProductCompositionMap.size()+todo.size(),"OmegaSupConProduct(): processing");
1184  FD_DF("OmegaSupConProduct(): processing" << rProductCompositionMap.size() << " " << todo.size());
1185  // get next reachable state from todo stack
1186  currentp = todo.top();
1187  currentt = rProductCompositionMap[currentp];
1188  todo.pop();
1189  // skip critical (tmoor 201308)
1190  if(critical.Exists(currentt)) continue;
1191  // report
1192  FD_DF("OmegaSupConProduct: processing (" << currentp.Str() << " -> " << currentt <<")");
1193 
1194  // iterate over transitions, pass1: figure whether current state becomes critical (tmoor 201308)
1195  ptit = rPlantGen.TransRelBegin(currentp.q1);
1196  ptit_end = rPlantGen.TransRelEnd(currentp.q1);
1197  stit = rSpecGen.TransRelBegin(currentp.q2);
1198  stit_end = rSpecGen.TransRelEnd(currentp.q2);
1199  disable.Clear();
1200  // process all transitions and increment iterators strategically
1201  while((ptit != ptit_end) && (stit != stit_end)) {
1202  FD_DF("OmegaSupConProduct: current plant-transition: " << rPlantGen.TStr(*ptit) );
1203  FD_DF("OmegaSupConProduct: current spec-transition: " << rSpecGen.TStr(*stit));
1204  // case A: execute common event
1205  if(ptit->Ev == stit->Ev) {
1206  nextp = OPSState(ptit->X2, stit->X2,currentp.m1required);
1207  if(currentp.m1required) {
1208  if(rPlantGen.ExistsMarkedState(currentp.q1)) nextp.m1required=false;
1209  } else {
1210  if(rSpecGen.ExistsMarkedState(currentp.q2)) nextp.m1required=true;
1211  }
1212  // figure whether successor state is known to be critical
1213  rcit = rProductCompositionMap.find(nextp);
1214  if(rcit != rProductCompositionMap.end()) {
1215  if(critical.Exists(rcit->second)) {
1216  FD_DF("OmegaSupconOmegaParallel: common event " << rSpecGen.EStr(stit->Ev) << " to a critical states");
1217  // if event is uncontrollable, current state becomes critical
1218  if(!rCAlph.Exists(ptit->Ev)) {
1219  FD_DF("OmegaSupConProduct: critical insert" << currentt);
1220  critical.Insert(currentt); // tmoor 201308
1221  // exit all loops
1222  ptit = ptit_end;
1223  stit = stit_end;
1224  break;
1225  }
1226  // else, event is disabled
1227  disable.Insert(stit->Ev);
1228  }
1229  }
1230  // increment transition
1231  ++ptit;
1232  ++stit;
1233  }
1234  // case B: process plant event that is disabled by the specification
1235  else if (ptit->Ev < stit->Ev) {
1236  FD_DF("SupConProduct: " << rPlantGen.EStr(ptit->Ev) << " is enabled in the plant but disabled in the specification");
1237  // if the event is uncontrollable, this makes the current state critical
1238  if (!rCAlph.Exists(ptit->Ev)) {
1239  FD_DF("OmegaSupConProduct: disabled event " << rPlantGen.EStr(ptit->Ev) << " is uncontrollable");
1240  FD_DF("OmegaSupConProduct: critical insert" << currentt);
1241  critical.Insert(currentt);
1242  // exit all loops
1243  ptit = ptit_end;
1244  stit = stit_end;
1245  break;
1246  }
1247  FD_DF("OmegaSupConProduct: incrementing plant transrel");
1248  ++ptit;
1249  }
1250  // increment titg and titg, case C: process h event that is not enabled for g
1251  else {
1252  FD_DF("OmegaSupConProduct: incrementing spec transrel");
1253  ++stit;
1254  }
1255  } // end while incrementing
1256  // increment iterators case D: process leftover events of plant
1257  while (ptit != ptit_end) {
1258  FD_DF("OmegaSupConProduct: current g-transition: " << rPlantGen.TStr(*ptit));
1259  FD_DF("OmegaSupConProduct: current h-transition: end");
1260  // if uncontrollable event leaves candidate
1261  if (!rCAlph.Exists(ptit->Ev)) {
1262  FD_DF("OmegaSupConProduct: asynchron executed uncontrollable "
1263  << "event " << rPlantGen.EStr(ptit->Ev) << " leaves specification:");
1264  FD_DF("SupConProduct: critical insert" << rPlantGen.SStr(currentt));
1265  critical.Insert(currentt);
1266  // exit this loop
1267  break;
1268  }
1269  FD_DF("OmegaSupConProduct: incrementing g transrel");
1270  ++ptit;
1271  } // end iterating pass1
1272 
1273  // skip critical (tmoor 201308)
1274  if(critical.Exists(currentt)) continue;
1275 
1276  // iterate over transitions, pass2: execute shared events (tmoor 201308)
1277  FD_DF("OmegaSupConProduct(): processing pass2");
1278  ptit = rPlantGen.TransRelBegin(currentp.q1);
1279  ptit_end = rPlantGen.TransRelEnd(currentp.q1);
1280  stit = rSpecGen.TransRelBegin(currentp.q2);
1281  stit_end = rSpecGen.TransRelEnd(currentp.q2);
1282  // process all transitions and increment iterators strategically
1283  while((ptit != ptit_end) && (stit != stit_end)) {
1284  FD_DF("OmegaSupConProduct: current plant-transition: " << rPlantGen.TStr(*ptit) );
1285  FD_DF("OmegaSupConProduct: current spec-transition: " << rSpecGen.TStr(*stit));
1286  // case A: execute common event
1287  if(ptit->Ev == stit->Ev) {
1288  if(!disable.Exists(stit->Ev)) {
1289  FD_DF("OmegaSupConProduct: executing common event " << rPlantGen.EStr(ptit->Ev));
1290  nextp = OPSState(ptit->X2, stit->X2,currentp.m1required);
1291  if(currentp.m1required) {
1292  if(rPlantGen.ExistsMarkedState(currentp.q1)) nextp.m1required=false;
1293  } else {
1294  if(rSpecGen.ExistsMarkedState(currentp.q2)) nextp.m1required=true;
1295  }
1296  // figure target index
1297  rcit = rProductCompositionMap.find(nextp);
1298  // if state is new: add to todo list and result
1299  if(rcit == rProductCompositionMap.end()) {
1300  todo.push(nextp);
1301  nextt = rResGen.InsState();
1302  rProductCompositionMap[nextp] = nextt;
1303  if(!nextp.m1required)
1304  if(rSpecGen.ExistsMarkedState(nextp.q2))
1305  rResGen.SetMarkedState(nextt);
1306  FD_DF("OmegaSupConProduct: todo push: (" << nextp.Str() << ") -> " << nextt);
1307  } else {
1308  nextt = rcit->second;
1309  }
1310  // set the transition and increment iterators
1311  FD_DF("OmegaSuperParallel: add transition to new generator: " << rResGen.TStr(Transition(currentt, ptit->Ev, nextt)));
1312  rResGen.SetTransition(currentt, ptit->Ev, nextt);
1313  }
1314  // increment transition
1315  ++ptit;
1316  ++stit;
1317  } // end: if processing common event
1318  // case B: process plant event that is disabled by the specification
1319  else if (ptit->Ev < stit->Ev) {
1320  ++ptit;
1321  }
1322  // increment titg and titg, case C: process h event that is not enabled for g
1323  else {
1324  ++stit;
1325  }
1326  } // end while incrementing for pass2
1327 
1328  } // while todo
1329 
1330  FD_DF("OmegaSupConProduct: deleting critical states: " << critical.ToString());
1331  rResGen.DelStates(critical);
1332 
1333  // restrict composition map
1334  std::map< OPSState , Idx>::iterator cit = rProductCompositionMap.begin();
1335  while(cit != rProductCompositionMap.end())
1336  if(!rResGen.ExistsState(cit->second)) rProductCompositionMap.erase(cit++);
1337  else cit++;
1338 
1339 }
1340 
1341 
1342 
1343 
1344 // OmegaSupConNBUnchecked(rPlantGen, rCAlph, rSpecGen,rResGen)
1346  const Generator& rPlantGen,
1347  const EventSet& rCAlph,
1348  const Generator& rSpecGen,
1349  StateSet& rPlantMarking,
1350  Generator& rResGen)
1351 {
1352  FD_DF("OmegaSupConNBUnchecked(\"" << rPlantGen.Name() << "\", \"" << rSpecGen.Name() << "\")");
1353 
1354  // PREPARE RESULT:
1355  Generator* pResGen = &rResGen;
1356  if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
1357  pResGen= rResGen.New();
1358  }
1359  pResGen->Clear();
1360  pResGen->InjectAlphabet(rPlantGen.Alphabet());
1361 
1362  // controllable events
1363  FD_DF("OmegaSupConNB: controllable events: " << rCAlph.ToString());
1364 
1365  // perform product
1366  std::map< OPSState , Idx> cmap;
1367  OmegaSupConProduct(rPlantGen, rCAlph, rSpecGen, cmap, *pResGen);
1368 
1369  // figure plant marking
1370  rPlantMarking.Clear();
1371  std::map< OPSState, Idx>::iterator pcit;
1372  for(pcit=cmap.begin(); pcit!=cmap.end(); ++pcit)
1373  if(rPlantGen.ExistsMarkedState(pcit->first.q1))
1374  rPlantMarking.Insert(pcit->second);
1375 
1376  // fix statenames (debugging)
1377 #ifdef FAUDES_DEBUG_FUNCTION
1378  std::map< OPSState, Idx>::iterator dcit;
1379  for(dcit=cmap.begin(); dcit!=cmap.end(); ++dcit) {
1380  Idx x1=dcit->first.q1;
1381  Idx x2=dcit->first.q2;
1382  bool m1requ=dcit->first.m1required;
1383  Idx x12=dcit->second;
1384  if(!pResGen->ExistsState(x12)) continue;
1385  std::string name1= rPlantGen.StateName(x1);
1386  if(name1=="") name1=ToStringInteger(x1);
1387  std::string name2= rSpecGen.StateName(x2);
1388  if(name2=="") name1=ToStringInteger(x2);
1389  std::string name12;
1390  if(m1requ) name12= name1 + "|" + name2 + "|r1m";
1391  else name12= name1 + "|" + name2 + "|r2m";
1392  name12=pResGen->UniqueStateName(name12);
1393  pResGen->StateName(x12,name12);
1394  }
1395 #endif
1396 
1397 #ifdef FAUDES_DEBUG_FUNCTION
1398  pResGen->DWrite();
1399  pResGen->Write("tmp_syn_xxx_"+pResGen->Name()+".gen");
1400  pResGen->WriteStateSet(rPlantMarking);
1401 #endif
1402 
1403  // iterate for required properties
1404  while(true) {
1405  // catch trivial
1406  if(pResGen->Empty()) break;
1407  // fast inner loop: prefix controllability and omega-trim
1408  while(true) {
1409  Idx count1 = pResGen->Size();
1410  FD_WARN("OmegaSupConNB: iterate: do prefix con on #" << pResGen->Size());
1411  SupConClosedUnchecked(rPlantGen, rCAlph, *pResGen);
1412  FD_WARN("OmegaSupConNB: iterate: do coaccessible on #" << pResGen->Size());
1413  pResGen->Coaccessible();
1414  FD_WARN("OmegaSupConNB: iterate: do accessible on #" << pResGen->Size());
1415  pResGen->Accessible();
1416  FD_WARN("OmegaSupConNB: iterate: do complete on #" << pResGen->Size());
1417  pResGen->Complete();
1418  if(pResGen->Size() == count1) break;
1419  if(pResGen->Size() == 0) break;
1420  }
1421  // slow outer loop: controlled liveness aka restrict to controllable prefix
1422  Idx count2 = pResGen->Size();
1423  FD_WARN("OmegaSupConNB: iterate: do controlled liveness on #" << pResGen->Size());
1424  OmegaControlledLiveness(*pResGen,rCAlph,rPlantMarking);
1425  if(pResGen->Size() == count2) break;
1426  }
1427 
1428  // fix statenames ...
1429  std::map< OPSState, Idx>::iterator rcit;
1430  if(rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && pResGen->StateNamesEnabled())
1431  for(rcit=cmap.begin(); rcit!=cmap.end(); rcit++) {
1432  Idx x1=rcit->first.q1;
1433  Idx x2=rcit->first.q2;
1434  bool m1requ=rcit->first.m1required;
1435  Idx x12=rcit->second;
1436  if(!pResGen->ExistsState(x12)) continue;
1437  std::string name1= rPlantGen.StateName(x1);
1438  if(name1=="") name1=ToStringInteger(x1);
1439  std::string name2= rSpecGen.StateName(x2);
1440  if(name2=="") name1=ToStringInteger(x2);
1441  std::string name12;
1442  if(m1requ) name12= name1 + "|" + name2 + "|r1m";
1443  else name12= name1 + "|" + name2 + "|r2m";
1444  name12=pResGen->UniqueStateName(name12);
1445  pResGen->StateName(x12,name12);
1446  }
1447 
1448  // .. or clear them (?)
1449  if(!(rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && pResGen->StateNamesEnabled()))
1450  pResGen->StateNamesEnabled(false);
1451 
1452  // copy result
1453  if(pResGen != &rResGen) {
1454  pResGen->Move(rResGen);
1455  delete pResGen;
1456  }
1457 
1458  FD_WARN("OmegaSupConNB: return #" << rResGen.Size());
1459 }
1460 
1461 
1462 // OmegaSupConNormNBUnchecked(rPlantGen, rCAlph, rOAlph, rSpecGen, rFeedbackMap, rResGen)
1464  const Generator& rPlantGen,
1465  const EventSet& rCAlph,
1466  const EventSet& rOAlph,
1467  const Generator& rSpecGen,
1468  StateSet& rPlantMarking,
1469  std::map< Idx , Idx >& rObserverStateMap,
1470  std::map< Idx , EventSet>& rFeedbackMap,
1471  Generator& rResGen)
1472 {
1473  FD_WARN("OmegaSupConNormNB(\"" << rPlantGen.Name() << "\", \"" << rSpecGen.Name() << "\")");
1474 
1475  // prepare result
1476  Generator* pResGen = &rResGen;
1477  if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
1478  pResGen= rResGen.New();
1479  }
1480  pResGen->Clear();
1481  pResGen->InjectAlphabet(rPlantGen.Alphabet());
1482 
1483  // report events
1484  FD_WARN("OmegaSupConNormNB: controllable events: " << rCAlph.ToString());
1485  FD_WARN("OmegaSupConNormNB: un-observabel events: " << (rPlantGen.Alphabet()-rOAlph).ToString());
1486 
1487  // perform product
1488  std::map< OPSState , Idx> cmap;
1489  OmegaSupConProduct(rPlantGen, rCAlph, rSpecGen, cmap, *pResGen);
1490  pResGen->OmegaTrim();
1491 
1492  // no statenames impülemented
1493  pResGen->StateNamesEnabled(false);
1494 
1495  // figure plant marking
1496  rPlantMarking.Clear();
1497  std::map< OPSState, Idx>::iterator pcit;
1498  for(pcit=cmap.begin(); pcit!=cmap.end(); ++pcit)
1499  if(rPlantGen.ExistsMarkedState(pcit->first.q1))
1500  rPlantMarking.Insert(pcit->second);
1501 
1502  // extend by observer states
1503  Generator obsG= *pResGen;
1504  MarkAllStates(obsG);
1505  Project(obsG,rOAlph,obsG);
1506  InvProject(obsG,pResGen->Alphabet());
1507  std::map< std::pair<Idx,Idx>, Idx> rObserverCompositionMap;
1508  Product(*pResGen, obsG, rObserverCompositionMap, *pResGen);
1509  // track plantmarking
1510  StateSet fixmarking;
1511  std::map< std::pair<Idx,Idx>, Idx>::iterator cit;
1512  for(cit=rObserverCompositionMap.begin(); cit!=rObserverCompositionMap.end();++cit)
1513  if(rPlantMarking.Exists(cit->first.first)) fixmarking.Insert(cit->second);
1514  rPlantMarking=fixmarking;
1515  // construct reverse map "pResGen.State --> obsG.State"
1516  std::map< std::pair<Idx,Idx>, Idx>::iterator sit;
1517  for(sit=rObserverCompositionMap.begin(); sit!=rObserverCompositionMap.end();++sit)
1518  rObserverStateMap[sit->second]=sit->first.second;
1519 
1520 #ifdef FAUDES_DEBUG_FUNCTION
1521  pResGen->DWrite();
1522  pResGen->Write("tmp_syn_xxx_"+pResGen->Name()+".gen");
1523  pResGen->WriteStateSet(rPlantMarking);
1524 #endif
1525 
1526  FD_WARN("OmegaSupConNormNB(): cand #" << pResGen->Size() << " obs #" << obsG.Size());
1527  // make resulting generator trim until it's fully controllable
1528  while(true) {
1529  // catch trivial
1530  if(pResGen->Empty()) break;
1531  // fast inner loop: prefix controllability and omega-trim
1532  while(true) {
1533  Idx count1 = pResGen->Size();
1534  FD_WARN("OmegaSupConNormNB: iterate: do prefix-contr on #" << pResGen->Size());
1535  SupConClosedUnchecked(rPlantGen, rCAlph, *pResGen);
1536  FD_WARN("OmegaSupConNormNB: iterate: do accessible on #" << pResGen->Size());
1537  pResGen->Accessible();
1538  FD_WARN("OmegaSupConNormNB: iterate: do coaccessible on #" << pResGen->Size());
1539  pResGen->Coaccessible();
1540  FD_WARN("OmegaSupConNormNB: iterate: do prefix-norm on #" << pResGen->Size());
1541  SupConNormClosedUnchecked(rPlantGen, rOAlph, rOAlph, obsG, *pResGen);
1542  FD_WARN("OmegaSupConNormNB: iterate: do coaccessible on #" << pResGen->Size());
1543  pResGen->Coaccessible();
1544  FD_WARN("OmegaSupConNormNB: iterate: do accessible on #" << pResGen->Size());
1545  pResGen->Accessible();
1546  FD_WARN("OmegaSupConNormNB: iterate: do complete on #" << pResGen->Size());
1547  pResGen->Complete();
1548  if(pResGen->Size() == count1) break;
1549  if(pResGen->Size() == 0) break;
1550  }
1551  // slow outer loop: controlled liveness
1552  Idx count2 = pResGen->Size();
1553  FD_WARN("OmegaSupConNormNB: iterate: do controlled liveness on #" << pResGen->Size());
1554 
1555  // cosmetic: restrict observer map and count effective states
1556  std::map< Idx , Idx>::iterator oit = rObserverStateMap.begin();
1557  while(oit != rObserverStateMap.end())
1558  if(!pResGen->ExistsState(oit->first)) rObserverStateMap.erase(oit++);
1559  else oit++;
1560  std::set< Idx > ostates;
1561  for(oit = rObserverStateMap.begin(); oit != rObserverStateMap.end(); ++oit)
1562  ostates.insert(oit->second);
1563 
1564  //omega controlled liveness aka controllabe prefix
1565  FD_WARN("OmegaSupConNormNB(): cand #" << pResGen->Size() << " obs #" << ostates.size());
1566  std::map< Idx , EventSet> feedback;
1567  OmegaControlledLiveness(*pResGen,rCAlph,rPlantMarking,rObserverStateMap,feedback);
1568  //OmegaControlledLiveness(*pResGen,rCAlph,rPlantMarking);
1569  if(pResGen->Size() == count2) break;
1570  }
1571 
1572  // copy result
1573  if(pResGen != &rResGen) {
1574  pResGen->Move(rResGen);
1575  delete pResGen;
1576  }
1577 }
1578 
1579 
1580 /*
1581 ****************************************
1582 * SUPCON: WRAPPER / USER FUNCTIONS *
1583 ****************************************
1584 */
1585 
1586 
1587 // OmegaSupConNB(rPlantGen, rCAlph, rSpecGen, rResGen)
1589  const Generator& rPlantGen,
1590  const EventSet& rCAlph,
1591  const Generator& rSpecGen,
1592  Generator& rResGen)
1593 {
1594  // consitenct check
1595  ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen);
1596  // execute
1597  StateSet plantmarking;
1598  OmegaSupConNBUnchecked(rPlantGen, rCAlph, rSpecGen, plantmarking, rResGen);
1599  // record name
1600  rResGen.Name(CollapsString("OmegaSupConNB(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))"));
1601 }
1602 
1603 
1604 // OmegaSupConNB for Systems:
1605 // uses and maintains controllablity from plant
1607  const System& rPlantGen,
1608  const Generator& rSpecGen,
1609  Generator& rResGen) {
1610  // prepare result
1611  Generator* pResGen = &rResGen;
1612  if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
1613  pResGen= rResGen.New();
1614  }
1615  // execute
1616  OmegaSupConNB(rPlantGen, rPlantGen.ControllableEvents(),rSpecGen,*pResGen);
1617  // copy all attributes of input alphabet
1618  pResGen->EventAttributes(rPlantGen.Alphabet());
1619  // copy result
1620  if(pResGen != &rResGen) {
1621  pResGen->Move(rResGen);
1622  delete pResGen;
1623  }
1624 }
1625 
1626 // OmegaConNB(rPlantGen, rCAlph, rSpecGen, rResGen)
1628  const Generator& rPlantGen,
1629  const EventSet& rCAlph,
1630  const Generator& rSpecGen,
1631  Generator& rResGen)
1632 {
1633 
1634  // consitency check
1635  ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen);
1636  // compute supremal closed-loop behaviour
1637  StateSet plantmarking;
1638  OmegaSupConNBUnchecked(rPlantGen, rCAlph, rSpecGen, plantmarking, rResGen);
1639  // compute restrictive feedback
1640  std::map< Idx , EventSet> feedback;
1641  OmegaControlledLiveness(rResGen, rCAlph, plantmarking, feedback);
1642  // apply restrictive feedback
1643  StateSet::Iterator sit = rResGen.StatesBegin();
1644  StateSet::Iterator sit_end = rResGen.StatesEnd();
1645  for(;sit!=sit_end;++sit) {
1646  const EventSet& pattern = feedback[*sit];
1647  TransSet::Iterator tit = rResGen.TransRelBegin(*sit);
1648  TransSet::Iterator tit_end = rResGen.TransRelEnd(*sit);
1649  while(tit!=tit_end) {
1650  if(pattern.Exists(tit->Ev)) { tit++; continue;};
1651  rResGen.ClrTransition(tit++);
1652  }
1653  }
1654  // cosmetic trim
1655  rResGen.Trim();
1656 
1657 #ifdef FAUDES_CODE
1658  // during development: test controllability and livenes
1659  if(!IsControllable(rPlantGen,rCAlph,rResGen)) {
1660  throw Exception("OmegaConNB(..)", "ERROR: controllability test failed", 500);
1661  }
1662  if(!IsRelativelyOmegaClosed(rPlantGen,rResGen)) {
1663  throw Exception("OmegaConNB(..)", "ERROR: rel. top. closedness test failed", 500);
1664  }
1665 #endif
1666 
1667  // record name
1668  rResGen.Name(CollapsString("OmegaConNB(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))"));
1669 }
1670 
1671 // OmegaConNB for Systems:
1672 // uses and maintains controllablity from plant
1674  const System& rPlantGen,
1675  const Generator& rSpecGen,
1676  Generator& rResGen) {
1677  // prepare result
1678  Generator* pResGen = &rResGen;
1679  if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
1680  pResGen= rResGen.New();
1681  }
1682  // execute
1683  OmegaConNB(rPlantGen, rPlantGen.ControllableEvents(),rSpecGen,*pResGen);
1684  // copy all attributes of input alphabet
1685  pResGen->EventAttributes(rPlantGen.Alphabet());
1686  // copy result
1687  if(pResGen != &rResGen) {
1688  pResGen->Move(rResGen);
1689  delete pResGen;
1690  }
1691 }
1692 
1693 
1694 // OmegaSupConNormNB(rPlantGen, rCAlph, rOAlph, rSpecGen, rResGen)
1696  const Generator& rPlantGen,
1697  const EventSet& rCAlph,
1698  const EventSet& rOAlph,
1699  const Generator& rSpecGen,
1700  Generator& rResGen)
1701 {
1702  // consitenct check
1703  ControlProblemConsistencyCheck(rPlantGen, rCAlph, rOAlph, rSpecGen);
1704  // execute
1705  std::map< Idx , Idx> constates;
1706  std::map< Idx , EventSet> feedback;
1707  StateSet plantmarking;
1708  OmegaSupConNormNBUnchecked(rPlantGen, rCAlph, rOAlph, rSpecGen, plantmarking, constates, feedback, rResGen);
1709  // record name
1710  rResGen.Name(CollapsString("OmegaSupConNormNB(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))"));
1711 }
1712 
1713 
1714 // OmegaSupConNormNB for Systems:
1715 // uses and maintains controllablity from plant
1717  const System& rPlantGen,
1718  const Generator& rSpecGen,
1719  Generator& rResGen) {
1720  // prepare result
1721  Generator* pResGen = &rResGen;
1722  if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
1723  pResGen= rResGen.New();
1724  }
1725  // execute
1726  OmegaSupConNormNB(rPlantGen, rPlantGen.ControllableEvents(),rPlantGen.ObservableEvents(),rSpecGen,*pResGen);
1727  // copy all attributes of input alphabet
1728  pResGen->EventAttributes(rPlantGen.Alphabet());
1729  // copy result
1730  if(pResGen != &rResGen) {
1731  pResGen->Move(rResGen);
1732  delete pResGen;
1733  }
1734 }
1735 
1736 // OmegaConNrmNB(rPlantGen, rCAlph, rOAlph, rSpecGen, rResGen)
1738  const Generator& rPlantGen,
1739  const EventSet& rCAlph,
1740  const EventSet& rOAlph,
1741  const Generator& rSpecGen,
1742  Generator& rResGen)
1743 {
1744 
1745  // consitency check
1746  ControlProblemConsistencyCheck(rPlantGen, rCAlph, rOAlph, rSpecGen);
1747  // compute supremal closed-loop behaviour
1748  StateSet plantmarking;
1749  std::map< Idx , Idx> cxmap;
1750  std::map< Idx , EventSet> feedback;
1751  OmegaSupConNormNBUnchecked(rPlantGen, rCAlph, rOAlph, rSpecGen, plantmarking, cxmap, feedback, rResGen);
1752  // compute restrictive feedback
1753  OmegaControlledLiveness(rResGen, rCAlph, plantmarking, cxmap, feedback);
1754  // apply restrictive feedback
1755  StateSet::Iterator sit = rResGen.StatesBegin();
1756  StateSet::Iterator sit_end = rResGen.StatesEnd();
1757  for(;sit!=sit_end;++sit) {
1758  // Idx cx = cxmap[*sit]; etc ...
1759  const EventSet& pattern = feedback[*sit];
1760  TransSet::Iterator tit = rResGen.TransRelBegin(*sit);
1761  TransSet::Iterator tit_end = rResGen.TransRelEnd(*sit);
1762  while(tit!=tit_end) {
1763  if(pattern.Exists(tit->Ev)) { tit++; continue;};
1764  rResGen.ClrTransition(tit++);
1765  }
1766  }
1767  // trim (?)
1768  rResGen.OmegaTrim();
1769 //#ifdef FAUDES_CODE
1770  // during development: test controllability, normality and livenes
1771  if(!IsControllable(rPlantGen,rCAlph,rResGen)) {
1772  throw Exception("OmegaConNormNB(..)", "ERROR: controllability test failed", 500);
1773  }
1774  if(!IsRelativelyOmegaClosed(rPlantGen,rResGen)) {
1775  throw Exception("OmegaConNormNB(..)", "ERROR: rel. top. closedness test failed", 500);
1776  }
1777  Generator prK=rResGen;
1778  MarkAllStates(prK);
1779  Generator prL=rPlantGen;
1780  prL.Trim();
1781  MarkAllStates(prL);
1782  if(!IsNormal(prL,rOAlph,prK)){
1783  throw Exception("OmegaConNormNB(..)", "ERROR: prefix normality test failed", 500);
1784  }
1785 //#endif
1786 
1787  // record name
1788  rResGen.Name(CollapsString("OmegaConNormNB(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))"));
1789 }
1790 
1791 // OmegaConNormNB for Systems
1792 // uses and maintains controllablity from plant
1794  const System& rPlantGen,
1795  const Generator& rSpecGen,
1796  Generator& rResGen) {
1797  // prepare result
1798  Generator* pResGen = &rResGen;
1799  if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
1800  pResGen= rResGen.New();
1801  }
1802  // execute
1803  OmegaConNormNB(rPlantGen, rPlantGen.ControllableEvents(),rPlantGen.ObservableEvents(), rSpecGen,*pResGen);
1804  // copy all attributes of input alphabet
1805  pResGen->EventAttributes(rPlantGen.Alphabet());
1806  // copy result
1807  if(pResGen != &rResGen) {
1808  pResGen->Move(rResGen);
1809  delete pResGen;
1810  }
1811 }
1812 
1813 
1814 
1815 } // name space
#define FD_WPC(cntnow, contdone, message)
Application callback: optional write progress report to console or application, incl count
#define FD_WARN(message)
Debug: always report warnings.
#define FD_DF(message)
Debug: optional report on user functions.
Faudes exception class.
Set of indices.
Definition: cfl_indexset.h:78
Idx Insert(void)
Insert new index to set.
std::set< EventSet > enable_one
void merge(const MCtrlPattern &other)
Set of indices with symbolic names.
Definition: cfl_nameset.h:69
bool Exists(const Idx &rIndex) const
Test existence of index.
virtual void InsertSet(const NameSet &rOtherSet)
Inserts all elements of rOtherSet.
bool Insert(const Idx &rIndex)
Add an element by index.
std::string Str(void)
bool operator<(const OPSState &other) const
OPSState(const Idx &rq1, const Idx &rq2, const bool &rf)
TBaseSet< Transition, TransSort::X1EvX2 >::Iterator Iterator
Iterator on transition.
Definition: cfl_transset.h:269
const TaEventSet< EventAttr > & Alphabet(void) const
Return const reference to alphabet.
Generator with controllability attributes.
EventSet ControllableEvents(void) const
Get EventSet with controllable events.
EventSet ObservableEvents(void) const
Get EventSet with observable events.
Triple (X1,Ev,X2) to represent current state, event and next state.
Definition: cfl_transset.h:57
void DWrite(const Type *pContext=0) const
Write configuration data to console, debugging format.
Definition: cfl_types.cpp:225
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
Write configuration data to a string.
Definition: cfl_types.cpp:169
void Write(const Type *pContext=0) const
Write configuration data to console.
Definition: cfl_types.cpp:139
Base class of all FAUDES generators.
StateSet::Iterator StatesBegin(void) const
Iterator to Begin() of state set.
StateSet::Iterator InitStatesBegin(void) const
Iterator to Begin() of mInitStates.
bool SetTransition(Idx x1, Idx ev, Idx x2)
Add a transition to generator by indices.
const StateSet & MarkedStates(void) const
Return const ref of marked states.
const EventSet & Alphabet(void) const
Return const reference to alphabet.
virtual void Move(vGenerator &rGen)
Destructive copy to other vGenerator.
bool InitStatesEmpty(void) const
Check if set of initial states are empty.
EventSet ActiveEventSet(Idx x1) const
Return active event set at state x1.
const StateSet & InitStates(void) const
Const ref to initial states.
TransSet::Iterator TransRelBegin(void) const
Iterator to Begin() of transition relation.
void ClrTransition(Idx x1, Idx ev, Idx x2)
Remove a transition by indices.
bool Accessible(void)
Make generator accessible.
bool Trim(void)
Make generator trim.
void WriteStateSet(const StateSet &rStateSet) const
Write a stateset to console (no re-indexing).
bool IsComplete(void) const
Check if generator is complete.
virtual vGenerator * New(void) const
Construct on heap.
void InjectMarkedStates(const StateSet &rNewMarkedStates)
Replace mMarkedStates with StateSet given as parameter without consistency checks.
Idx MarkedStatesSize(void) const
Get number of marked states.
bool ExistsState(Idx index) const
Test existence of state in state set.
bool IsCoaccessible(void) const
Check if generator is Coaccessible.
bool Coaccessible(void)
Make generator Coaccessible.
std::string TStr(const Transition &rTrans) const
Return pretty printable transition (eg for debugging)
std::string StateName(Idx index) const
State name lookup.
void Name(const std::string &rName)
Set the generator's name.
StateSet::Iterator StatesEnd(void) const
Iterator to End() of state set.
void DelStates(const StateSet &rDelStates)
Delete a set of states Cleans mpStates, mInitStates, mMarkedStates, mpTransrel, and mpStateSymboltabl...
TransSet::Iterator TransRelEnd(void) const
Iterator to End() of transition relation.
std::string EStr(Idx index) const
Pretty printable event name for index (eg for debugging).
Idx InsState(void)
Add new anonymous state to generator.
void SetMarkedState(Idx index)
Set an existing state as marked state by index.
bool Empty(void) const
Check if generator is empty (no states)
Idx InsInitState(void)
Create new anonymous state and set as initial state.
virtual void EventAttributes(const EventSet &rEventSet)
Set attributes for existing events.
bool StateNamesEnabled(void) const
Whether libFAUEDS functions are requested to generate state names.
Idx Size(void) const
Get generator size (number of states)
bool OmegaTrim(void)
Make generator omega-trim.
std::string SStr(Idx index) const
Return pretty printable state name for index (eg for debugging)
virtual void Clear(void)
Clear generator data.
bool ExistsMarkedState(Idx index) const
Test existence of state in mMarkedStates.
std::string UniqueStateName(const std::string &rName) const
Create a new unique symbolic state name.
bool Complete(void)
Make generator Complete.
const StateSet & States(void) const
Return reference to state set.
void InjectAlphabet(const EventSet &rNewalphabet)
Set mpAlphabet without consistency check.
bool Empty(void) const
Test whether if the TBaseSet is Empty.
Definition: cfl_baseset.h:1824
bool Exists(const T &rElem) const
Test existence of element.
Definition: cfl_baseset.h:2115
virtual void Clear(void)
Clear all set.
Definition: cfl_baseset.h:1902
Iterator End(void) const
Iterator to the end of set.
Definition: cfl_baseset.h:1896
virtual void RestrictSet(const TBaseSet &rOtherSet)
Restrict elements given by other set.
Definition: cfl_baseset.h:2064
virtual void InsertSet(const TBaseSet &rOtherSet)
Insert elements given by rOtherSet.
Definition: cfl_baseset.h:1987
Iterator Begin(void) const
Iterator to the begin of set.
Definition: cfl_baseset.h:1891
Idx Size(void) const
Get Size of TBaseSet.
Definition: cfl_baseset.h:1819
void Complete(vGenerator &rGen)
RTI wrapper function.
bool LanguageInclusion(const Generator &rGen1, const Generator &rGen2)
Test language inclusion, Lm1<=Lm2.
bool IsOmegaTrim(const vGenerator &rGen)
RTI wrapper function.
void Product(const Generator &rGen1, const Generator &rGen2, Generator &rResGen)
Product composition.
void MarkAllStates(vGenerator &rGen)
RTI wrapper function.
void Project(const Generator &rGen, const EventSet &rProjectAlphabet, Generator &rResGen)
Deterministic projection.
void InvProject(Generator &rGen, const EventSet &rProjectAlphabet)
Inverse projection.
bool IsDeterministic(const vGenerator &rGen)
RTI wrapper function.
void OmegaConNormNB(const Generator &rPlantGen, const EventSet &rCAlph, const EventSet &rOAlph, const Generator &rSpecGen, Generator &rResGen)
Omega-synthesis for partial observation (experimental!)
bool IsControllable(const Generator &rPlantGen, const EventSet &rCAlph, const Generator &rSupCandGen)
Test controllability.
Definition: syn_supcon.cpp:718
bool IsNormal(const Generator &rL, const EventSet &rOAlph, const Generator &rK)
IsNormal: checks normality of a language K generated by rK wrt a language L generated by rL and the s...
void SupConNormClosed(const Generator &rL, const EventSet &rCAlph, const EventSet &rOAlph, const Generator &rK, Generator &rResult)
SupConNormClosed: compute supremal controllable, normal and closed sublanguage.
void OmegaSupConNormNB(const Generator &rPlantGen, const EventSet &rCAlph, const EventSet &rOAlph, const Generator &rSpecGen, Generator &rResGen)
Omega-synthesis for partial observation (experimental!)
bool IsOmegaControllable(const Generator &rGenPlant, const EventSet &rCAlph, const Generator &rGenCand)
Test omega controllability.
Definition: syn_wsupcon.cpp:42
bool IsRelativelyOmegaClosed(const Generator &rGenPlant, const Generator &rGenCand)
Test for relative closedness, omega languages.
void SupConCmplClosed(const Generator &rPlantGen, const EventSet &rCAlph, const Generator &rSpecGen, Generator &rResGen)
Supremal controllable and complete sublanguage.
void OmegaSupConNB(const Generator &rPlantGen, const EventSet &rCAlph, const Generator &rSpecGen, Generator &rResGen)
Omega-synthesis.
void SupConCmplNB(const Generator &rPlantGen, const EventSet &rCAlph, const Generator &rSpecGen, Generator &rResGen)
Supremal controllable and complete sublanguage.
void SupConNormCmplNB(const Generator &rL, const EventSet &rCAlph, const EventSet &rOAlph, const Generator &rK, Generator &rResult)
Supremal controllable, normal and complete sublanguage.
void OmegaConNB(const Generator &rPlantGen, const EventSet &rCAlph, const Generator &rSpecGen, Generator &rResGen)
Omega-synthesis.
libFAUDES resides within the namespace faudes.
uint32_t Idx
Type definition for index type (allways 32bit)
void SetComposedStateNames(const Generator &rGen1, const Generator &rGen2, const std::map< std::pair< Idx, Idx >, Idx > &rCompositionMap, Generator &rGen12)
Helper: uses composition map to track state names in a paralell composition.
void SupConProduct(const Generator &rPlantGen, const EventSet &rCAlph, const Generator &rSpecGen, std::map< std::pair< Idx, Idx >, Idx > &rCompositionMap, Generator &rResGen)
Parallel composition optimized for the purpose of SupCon (internal function)
Definition: syn_supcon.cpp:386
void SupConNormClosedUnchecked(const Generator &rPlantGen, const EventSet &rCAlph, const EventSet &rOAlph, Generator &rObserverGen, Generator &rSupCandGen)
Supremal Normal Controllable Sublangauge (internal function)
void OmegaSupConNBUnchecked(const Generator &rPlantGen, const EventSet &rCAlph, const Generator &rSpecGen, StateSet &rPlantMarking, Generator &rResGen)
void OmegaSupConNormNBUnchecked(const Generator &rPlantGen, const EventSet &rCAlph, const EventSet &rOAlph, const Generator &rSpecGen, StateSet &rPlantMarking, std::map< Idx, Idx > &rObserverStateMap, std::map< Idx, EventSet > &rFeedbackMap, Generator &rResGen)
std::string CollapsString(const std::string &rString, unsigned int len)
Limit length of string, return head and tail of string.
Definition: cfl_helper.cpp:91
void ControlProblemConsistencyCheck(const GeneratorVector &rPlantGenVec, const EventSet &rConAlph, const GeneratorVector &rSpecGenVec)
Compositional synthesis.
bool IsRelativelyOmegaClosedUnchecked(const Generator &rGenPlant, const Generator &rGenCand)
Test for relative closedness, omega languages.
void SupConClosedUnchecked(const Generator &rPlantGen, const EventSet &rCAlph, Generator &rSupCandGen)
Supremal Controllable Sublangauge (internal function)
Definition: syn_supcon.cpp:57
bool OmegaControlledLiveness(Generator &rSupCandGen, const EventSet &rCAlph, const StateSet &rPlantMarking)
std::string ToStringInteger(Int number)
integer to string
Definition: cfl_helper.cpp:43
bool IsControllableUnchecked(const Generator &rPlantGen, const EventSet &rCAlph, const Generator &rSupCandGen, StateSet &rCriticalStates)
Controllability (internal function)
Definition: syn_supcon.cpp:243
void OmegaSupConProduct(const Generator &rPlantGen, const EventSet &rCAlph, const Generator &rSpecGen, std::map< OPSState, Idx > &rProductCompositionMap, Generator &rResGen)
Misc functions related to synthesis.
Supremal controllable sublanguage.
Supremal normal sublanguage.
Supremal controllable sublanguage for infinite time behaviours.

libFAUDES 2.32b --- 2024.03.01 --- c++ api documentaion by doxygen