omg_rabinctrlrk.cpp
Go to the documentation of this file.
1 /** @file omg_rabinctrlrk.cpp Synthesis omega languages accepted by Rabin automata */
2 
3 /* FAU Discrete Event Systems Library (libFAUDES)
4 
5 Copyright (C) 2025 Changming Yang, 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 
23 /*
24 This is an alternative implementation to compute the controllable set
25 aka the controllability prefix. Doublets w.r.t. the the base implementation
26 have been suffixed "_RK". From my petrspective, they can be safely removed
27 (for classs definitions they dont generate symbols in the bbject file and
28 the only doublet function RabinCtrlPfx is not invoked anywhere).
29 
30 See also the heeder omg_rabinctrlrk.h.
31 
32 CY/TM, 2025/07.
33 */
34 
35 
36 #include "omg_rabinctrlrk.h"
37 #include "syn_include.h"
38 
39 // local degug
40 //#undef FD_DF
41 //#define FD_DF(m) FD_WARN(m)
42 
43 namespace faudes {
44 
45 /*
46 Base class for my operators to hold context
47 */
49 protected:
50  /** record context references */
51  const vGenerator& rGen;
52  const StateSet& rDomain;
57 public:
58  /** construct to record context */
60  const vGenerator& gen, const TransSetX2EvX1& revtrans, const EventSet& sigctrl)
61  :
63  rGen(gen),
64  rDomain(gen.States()),
65  rMarkedStates(gen.MarkedStates()),
66  rTransRel(gen.TransRel()),
67  rRevTransRel(revtrans),
68  mSigmaCtrl(sigctrl)
69  {
70  Name("void base class operator");
71  mArgCount=0;
72  };
73  /** overaall stateset */
74  virtual const StateSet& Domain(void) const {
75  return rDomain;
76  }
77 };
78 
79 /*
80 Extended base class for operators that track state rankings for feedback construction
81 */
83 protected:
84  /** state ranking map for feedback construction */
86  /** current iteration levels */
87  mutable int mCurrentMuLevel;
88  mutable int mCurrentNuLevel;
89  mutable int mCurrentBranchType;
90 
91 public:
92  /** construct to record context */
94  const vGenerator& gen, const TransSetX2EvX1& revtrans, const EventSet& sigctrl)
95  :
96  RabinInvDynOperator_RK(gen, revtrans, sigctrl),
97  mpStateRanking(nullptr),
98  mCurrentMuLevel(0),
99  mCurrentNuLevel(0),
101  {
102  Name("base class operator with ranking");
103  };
104 
105  /** set state ranking map pointer */
107  mpStateRanking = pRanking;
108  }
109 
110  /** set current iteration levels */
111  void SetCurrentLevels(int muLevel, int nuLevel, int branchType) const {
112  mCurrentMuLevel = muLevel;
113  mCurrentNuLevel = nuLevel;
114  mCurrentBranchType = branchType;
115  }
116 
117 protected:
118  /** record state ranking when adding states to result */
119  void RecordStateRanking(const StateSet& rNewStates) const {
120  if (mpStateRanking == nullptr) return;
121 
123  for (StateSet::Iterator it = rNewStates.Begin(); it != rNewStates.End(); ++it) {
124  // Only record if this state hasn't been ranked yet (first time added)
125  if (!mpStateRanking->Exists(*it)) {
126  mpStateRanking->Insert(*it, ranking);
127  }
128  }
129  }
130 };
131 
132 
133 /*
134 Inverse dynamics operator theta
135 
136 Cite Thistle/Wonham "Control of w-Automata, Church's Problem, and the Emptiness
137 Problem for Tree w-Automata", 1992, Def 8.2:
138 
139 theta(X1,X2) = "the set of states, from which the automaton can be controlled to
140 enter X1 union X2 in a single transition without being prevented from entering X1."
141 
142 Rephrase: X1 is the target T, X1 union X2 is the domain D; control such that immediate
143 successors stay within within D and there is the chance to enter the T.
144 
145 We use "Z1/Z2" argument names to avoid confusion with libFAUDES naming conventions.
146 */
148 public:
149  /** construct to record context */
151  const vGenerator& gen, const TransSetX2EvX1& revtrans, const EventSet& sigctrl)
152  :
153  RabinInvDynOperator_RK(gen,revtrans,sigctrl)
154  {
155  FD_DF("RabinInvDynTheta(): instantiated for " << rGen.Name());
156  Name("theta([Z1,Z2])");
157  mArgNames= std::vector<std::string>{"Z1","Z2"};
158  mArgCount=2;
159  };
160 protected:
161  /** actual operator implementation */
162  virtual void DoEvaluate(StateSetVector& rArgs, StateSet& rRes) {
163  // convenience acsesors
164  const StateSet& Z1=rArgs.At(0);
165  const StateSet& Z2=rArgs.At(1);
166  // do operate
168  StateSet::Iterator sit=rRes.Begin();
169  StateSet::Iterator sit_end=rRes.End();
170  while(sit!=sit_end){
172  TransSet::Iterator tit_end=rTransRel.End(*sit);
173  bool enterZ1 = false;
174  bool exitZ12 = false;
175  for(;tit!=tit_end;++tit){
176  // successor is in Z1: will not disable, found evidence to enter Z1
177  if(Z1.Exists(tit->X2)) {enterZ1=true; continue;}
178  // successor is in Z2: will not disable
179  if(Z2.Exists(tit->X2)) {continue;}
180  // sucessor is neither in Z1 nor Z2: need to disable
181  if(!mSigmaCtrl.Exists(tit->Ev)){ exitZ12 = true; break;}
182  }
183  if(!enterZ1 || exitZ12) rRes.Erase(sit++);
184  else ++sit;
185  }
186  };
187 };
188 
189 
190 /*
191 Inverse dynamics operator theta-tilde
192 
193 Cite Thistle/Wonham "Control of w-Automata, Church's Problem, and the Emptiness
194 Problem for Tree w-Automata", 1992, Def 8.3:
195 
196 "theta_tilde(X1,X2)=nu X3 mu X4 theta( X1 + (X4 - R), (X3 - R) * X2 ) ")
197 
198 We first implement the core formula without the nu/mu iteration and then apply nu/mu.
199 We use "Y1/Y2/Y3/Y4" and "Z1/Z2" argument names to
200 */
202 public:
203  /** construct to record context */
205  const vGenerator& gen, const TransSetX2EvX1& revtrans, const EventSet& sigctrl)
206  :
207  RabinInvDynTheta_RK(gen,revtrans,sigctrl)
208  {
209  FD_DF("RabinInvDynThetaTildeCore(): instantiated for " << rGen.Name());
210  Name("theta_tilde_core([Y1,Y2,Y3,Y4])");
211  mArgNames= std::vector<std::string>{"Y1","Y2","Y3","Y4"};
212  mArgCount=4;
213  };
214 protected:
215  /** actual operator implementation */
216  virtual void DoEvaluate(StateSetVector& rArgs, StateSet& rRes) {
217  // convenience acsesors
218  const StateSet& Y1=rArgs.At(0);
219  const StateSet& Y2=rArgs.At(1);
220  const StateSet& Y3=rArgs.At(2);
221  const StateSet& Y4=rArgs.At(3);
222  StateSetVector args;
223  args.Size(2);
224  StateSet& Z1=args.At(0);
225  StateSet& Z2=args.At(1);
226  // do operate
227  Z1= Y1 + (Y4 - rMarkedStates);
228  Z2= Y2 * (Y3 - rMarkedStates);
230  };
231 };
232 
233 
234 /*
235 Inverse dynamics operator theta tilde, outer nu/mu iteration
236 */
238 protected:
239  /** additional context */
243 public:
244  /** construct to record context */
246  const vGenerator& gen, const TransSetX2EvX1& revtrans, const EventSet& sigctrl)
247  :
248  RabinInvDynOperator_RK(gen,revtrans,sigctrl),
249  mThetaCore(gen,revtrans,sigctrl),
252  {
253  FD_DF("RabinInvDynThetaTilde(): instantiated for " << rGen.Name());
254  Name("theta_tilde([W1,W2])");
255  mArgNames= std::vector<std::string>{"W1","W2"};
256  mArgCount=2;
257  };
258 protected:
259  /** actual operator implementation */
260  virtual void DoEvaluate(StateSetVector& rArgs, StateSet& rRes) {
261  mNuMuThetaCore.Evaluate(rArgs, rRes);
262  };
263 };
264 
265 
266 /*
267 P-reach operator
268 
269 Cite Thistle/Wonham "Control of w-Automata, Church's Problem, and the Emptiness
270 Problem for Tree w-Automata", 1992, Def 8.4
271 
272 p-reach(X1,X2)= mu X3 . theta-tilde(X1,X) union theta-tilde((X1 u X2 u X3, I_p))
273 
274 We first implement the core formular without the nu/mu iteration, and then do the
275 mu iteration
276 
277 We use "U1/U2/U3" and "W1/W2" argument names
278 */
280  /** additional context */
281  RabinAcceptance::CIterator mRPit;
282 public:
283  /** construct to record context */
285  const RabinAutomaton& raut, const TransSetX2EvX1& revtrans, const EventSet& sigctrl)
286  :
287  RabinInvDynThetaTilde_RK(raut,revtrans,sigctrl),
288  mRPit(raut.RabinAcceptance().Begin())
289  {
290  FD_DF("RabinInvDynPReachCore(): instantiated for " << rGen.Name());
291  Name("invdyn_op([U1,U2,U3)");
292  mArgNames= std::vector<std::string>{"U1","U2","U3"};
293  mArgCount=3;
294  };
295 protected:
296  /** actual operator implementation */
297  virtual void DoEvaluate(StateSetVector& rArgs, StateSet& rRes) {
298  // convenience accessors
299  const StateSet& U1=rArgs.At(0);
300  const StateSet& U2=rArgs.At(1);
301  const StateSet& U3=rArgs.At(2);
302  StateSetVector args;
303  args.Size(2);
304  StateSet& W1=args.At(0);
305  StateSet& W2=args.At(1);
306  // do operate
307  W1=U1;
308  W2=Domain();
310  W1=U1+U2+U3;
311  W2=mRPit->ISet();
312  StateSet rhs;
314  rRes.InsertSet(rhs);
315  };
316 };
317 
318 /** p-reach operator, mu iteration */
320 protected:
321  /** have additional context */
324 public:
325  /** construct to record context */
327  const RabinAutomaton& raut, const TransSetX2EvX1& revtrans, const EventSet& sigctrl)
328  :
329  RabinInvDynOperator_RK(raut,revtrans,sigctrl),
330  mPReachCore(raut,revtrans,sigctrl),
332  {
333  FD_DF("RabinInvDynPReach(): instantiated for " << rGen.Name());
334  Name("p_reach_op([O1,O2])");
335  mArgNames= std::vector<std::string>{"O1","O2"};
336  mArgCount=2;
337  };
338 protected:
339  /** actual operator implementation */
340  virtual void DoEvaluate(StateSetVector& rArgs, StateSet& rRes) {
341  mMuPReachCore.Evaluate(rArgs, rRes);
342  };
343 };
344 
345 /*
346 Controllable subset
347 
348 Cite Thistle/Wonham "Control of w-Automata, Church's Problem, and the Emptiness
349 Problem for Tree w-Automata", 1992, Def 8.5
350 
351 CA = mu X1 nu X2 . p-reach(X1, X2 * R)
352 
353 We first implement the core formular without the mu/nu iteration, and then do the mu/nu.
354 
355 */
357  /** additional context */
358  RabinAcceptance::CIterator mRPit;
359 public:
360  /** construct to record context */
362  const RabinAutomaton& raut, const TransSetX2EvX1& revtrans, const EventSet& sigctrl)
363  :
364  RabinInvDynPReach_RK(raut,revtrans,sigctrl),
365  mRPit(raut.RabinAcceptance().Begin())
366  {
367  FD_DF("RabinInvDynCtrlCore(): instantiated for " << rGen.Name());
368  Name("ctrl([X1,X2])");
369  mArgNames= std::vector<std::string>{"X1","X2"};
370  mArgCount=2;
371  };
372 protected:
373  /** actual operator implementation */
374  virtual void DoEvaluate(StateSetVector& rArgs, StateSet& rRes) {
375  // convenience accessors
376  const StateSet& X1=rArgs.At(0);
377  const StateSet& X2=rArgs.At(1);
378  StateSetVector args;
379  args.Size(2);
380  StateSet& O1=args.At(0);
381  StateSet& O2=args.At(1);
382  // do operate
383  O1=X1;
384  O2=X2 * mRPit->RSet();
386  };
387 };
388 
389 /** ctrollable set, mu-nu iteration */
391 protected:
392  /** have additional context */
396 public:
397  /** construct to record context */
399  const RabinAutomaton& raut, const TransSetX2EvX1& revtrans, const EventSet& sigctrl)
400  :
401  RabinInvDynOperator_RK(raut,revtrans,sigctrl),
402  mCtrlCore(raut,revtrans,sigctrl),
405  {
406  FD_DF("RabinInvDynCtrl(): instantiated for " << rGen.Name());
407  Name("ctrl()");
408  mArgCount=0;
409  };
410 protected:
411  /** actual operator implementation */
412  virtual void DoEvaluate(StateSetVector& rArgs, StateSet& rRes) {
413  mMuNuCtrlCore.Evaluate(rArgs, rRes);
414  };
415 };
416 
417 
418 
419 // doublet: see ong_rabinctrl.cpp --- can be safely removed
421  const RabinAutomaton& rRAut, const EventSet& rSigmaCtrl,
422  StateSet& rCtrlPfx){
423  // we can only handle one Rabin pair
424  if(rRAut.RabinAcceptance().Size()!=1){
425  std::stringstream errstr;
426  errstr << "the current implementation requires exactly one Rabin pair";
427  throw Exception("RabinCtrlPfx", errstr.str(), 80);
428  }
429  // set up various helper
430  TransSetX2EvX1 revtrans(rRAut.TransRel());
431  EventSet sigctrl(rSigmaCtrl);
432  // have operator
433  RabinInvDynCtrl_RK ctrl(rRAut,revtrans,sigctrl);
434  // run
435  ctrl.Evaluate(rCtrlPfx);
436 };
437 
438 
439 
440 /*
441 Extended controllable subset operator with state ranking tracking
442 */
444 protected:
445  /** additional context */
447  RabinAcceptance::CIterator mRPit;
448 
449 public:
450  /** construct to record context */
452  const RabinAutomaton& raut, const TransSetX2EvX1& revtrans, const EventSet& sigctrl)
453  :
454  RabinInvDynOperatorWithRanking(raut, revtrans, sigctrl),
455  mRAut(raut),
456  mRPit(raut.RabinAcceptance().Begin())
457  {
458  FD_DF("RabinInvDynCtrlWithRanking(): instantiated for " << rGen.Name());
459  Name("ctrl_with_ranking()");
460  mArgCount=0;
461  };
462 
463 protected:
464  /** actual operator implementation */
465  virtual void DoEvaluate(StateSetVector& rArgs, StateSet& rRes) {
466  // Implementation of the nested mu-nu fixpoint with ranking tracking
467  rRes.Clear();
468 
469  // Outer mu-iteration: C^A = μX1. νX2. ρ^A_p(X1, X2∩R_p)
470  StateSet X1_current; // Start with empty set for mu-iteration
471  StateSet X1_prev;
472  int muLevel = 0;
473 
474  do {
475  X1_prev = X1_current;
476  ++muLevel;
477 
478  // Inner nu-iteration: νX2. ρ^A_p(X1_current, X2∩R_p)
479  StateSet X2_current = Domain(); // Start with full domain for nu-iteration
480  StateSet X2_prev;
481  int nuLevel = 0;
482 
483  do {
484  X2_prev = X2_current;
485  ++nuLevel;
486 
487  // Compute ρ^A_p(X1_current, X2_current ∩ R_p)
488  StateSet pReachResult;
489  ComputePReachWithRanking(X1_current, X2_current * mRPit->RSet(), pReachResult, muLevel, nuLevel);
490 
491  X2_current = X2_current * pReachResult; // Intersection for nu-iteration
492 
493  } while (X2_current != X2_prev);
494 
495  X1_current = X1_current + X2_current; // Union for mu-iteration
496 
497  } while (X1_current != X1_prev);
498 
499  rRes = X1_current;
500  };
501 
502 private:
503  /** compute p-reach operator with ranking tracking */
504  void ComputePReachWithRanking(const StateSet& X1, const StateSet& X2, StateSet& rRes,
505  int muLevel, int nuLevel) const {
506  // This implements: μX3. θ̃(X1, Domain) ∪ θ̃(X1∪X2∪X3, I_p)
507  rRes.Clear();
508  StateSet X3_current; // Start with empty set for mu-iteration
509  StateSet X3_prev;
510  int pReachLevel = 0;
511 
512  do {
513  X3_prev = X3_current;
514  ++pReachLevel;
515 
516  // First branch: θ̃(X1, Domain)
517  StateSet branch1;
518  ComputeThetaTildeWithRanking(X1, Domain(), branch1, muLevel, nuLevel, 0);
519 
520  // Second branch: θ̃(X1∪X2∪X3_current, I_p)
521  StateSet branch2;
522  ComputeThetaTildeWithRanking(X1 + X2 + X3_current, mRPit->ISet(), branch2, muLevel, nuLevel, 1);
523 
524  StateSet newStates = (branch1 + branch2) - X3_current;
525  if (!newStates.Empty()) {
526  SetCurrentLevels(muLevel, nuLevel, 0); // Branch type will be set in theta-tilde
527  RecordStateRanking(newStates);
528  }
529 
530  X3_current = X3_current + branch1 + branch2; // Union for mu-iteration
531 
532  } while (X3_current != X3_prev);
533 
534  rRes = X3_current;
535  }
536 
537  /** compute theta-tilde operator with ranking tracking */
538  void ComputeThetaTildeWithRanking(const StateSet& W1, const StateSet& W2, StateSet& rRes,
539  int muLevel, int nuLevel, int branchType) const {
540  // This implements: νX3. μX4. θ(W1 ∪ (X4 - R), (X3 - R) ∩ W2)
541  rRes.Clear();
542  StateSet X3_current = Domain(); // Start with full domain for nu-iteration
543  StateSet X3_prev;
544 
545  do {
546  X3_prev = X3_current;
547 
548  // Inner mu-iteration: μX4. θ(W1 ∪ (X4 - R), (X3_current - R) ∩ W2)
549  StateSet X4_current; // Start with empty set for mu-iteration
550  StateSet X4_prev;
551 
552  do {
553  X4_prev = X4_current;
554 
555  // Compute θ(W1 ∪ (X4_current - R), (X3_current - R) ∩ W2)
556  StateSet thetaResult;
557  ComputeThetaWithRanking(W1 + (X4_current - mRPit->RSet()),
558  (X3_current - mRPit->RSet()) * W2,
559  thetaResult, muLevel, nuLevel, branchType);
560 
561  X4_current = X4_current + thetaResult; // Union for mu-iteration
562 
563  } while (X4_current != X4_prev);
564 
565  X3_current = X3_current * X4_current; // Intersection for nu-iteration
566 
567  } while (X3_current != X3_prev);
568 
569  rRes = X3_current;
570  }
571 
572  /** compute basic theta operator with ranking tracking */
573  void ComputeThetaWithRanking(const StateSet& Z1, const StateSet& Z2, StateSet& rRes,
574  int muLevel, int nuLevel, int branchType) const {
575  // This implements the basic inverse dynamics operator θ(Z1, Z2)
576  rRes = rRevTransRel.PredecessorStates(Z1);
577  StateSet::Iterator sit = rRes.Begin();
578  StateSet::Iterator sit_end = rRes.End();
579 
580  while (sit != sit_end) {
581  TransSet::Iterator tit = rTransRel.Begin(*sit);
582  TransSet::Iterator tit_end = rTransRel.End(*sit);
583  bool enterZ1 = false;
584  bool exitZ12 = false;
585 
586  for (; tit != tit_end; ++tit) {
587  // successor is in Z1: will not disable, found evidence to enter Z1
588  if (Z1.Exists(tit->X2)) {
589  enterZ1 = true;
590  continue;
591  }
592  // successor is in Z2: will not disable
593  if (Z2.Exists(tit->X2)) {
594  continue;
595  }
596  // successor is neither in Z1 nor Z2: need to disable
597  if (!mSigmaCtrl.Exists(tit->Ev)) {
598  exitZ12 = true;
599  break;
600  }
601  }
602 
603  if (!enterZ1 || exitZ12) {
604  rRes.Erase(sit++);
605  } else {
606  ++sit;
607  }
608  }
609 
610  // Record ranking for newly computed states
611  SetCurrentLevels(muLevel, nuLevel, branchType);
612  }
613 };
614 
615 
616 /*
617 State feedback constructor based on state rankings
618 */
620 private:
624 
625 public:
626  StateFeedbackConstructor(const RabinAutomaton& raut, const EventSet& sigctrl,
627  const StateRankingMap& ranking)
628  : mRAut(raut), mSigmaCtrl(sigctrl), mStateRanking(ranking) {}
629 
630  /** construct state feedback mapping based on Theorem 6.4 */
631  void ConstructStateFeedback(const StateSet& rCtrlPfx, StateFeedbackMap& rFeedback) const {
632  rFeedback.Clear();
633 
634  // Get Rabin pair (we assume exactly one pair)
635  RabinAcceptance::CIterator rpIt = mRAut.RabinAcceptance().Begin();
636  const StateSet& RSet = rpIt->RSet();
637  const StateSet& ISet = rpIt->ISet();
638 
639  // For each controllable state, construct its control pattern
640  for (StateSet::Iterator sit = rCtrlPfx.Begin(); sit != rCtrlPfx.End(); ++sit) {
641  Idx state = *sit;
642  EventSet controlPattern;
643 
644  // Get state ranking
645  if (!mStateRanking.Exists(state)) {
646  // If no ranking found, use default safe control (allow all controllable events)
647  controlPattern = mSigmaCtrl;
648  } else {
649  const StateRanking& ranking = mStateRanking.Attribute(state);
650 
651  // Construct control pattern based on ranking and Theorem 6.4
652  constructControlPatternForState(state, ranking, RSet, ISet, controlPattern);
653  }
654 
655  // Always include uncontrollable events
656  EventSet uncontrollableEvents = mRAut.Alphabet() - mSigmaCtrl;
657  controlPattern.InsertSet(uncontrollableEvents);
658 
659  rFeedback.Insert(state, controlPattern);
660  }
661  }
662 
663 private:
664  /** construct control pattern for a specific state based on its ranking */
666  const StateSet& RSet, const StateSet& ISet,
667  EventSet& rPattern) const {
668  rPattern.Clear();
669 
670  // Get all outgoing transitions from this state
672  TransSet::Iterator tit_end = mRAut.TransRelEnd(state);
673 
674  for (; tit != tit_end; ++tit) {
675  Idx event = tit->Ev;
676  Idx successor = tit->X2;
677 
678  // Check if this event should be enabled based on control strategy
679  bool enableEvent = false;
680 
681  // Get successor's ranking if it exists
682  if (mStateRanking.Exists(successor)) {
683  const StateRanking& succRanking = mStateRanking.Attribute(successor);
684 
685  // Apply control rules based on Theorem 6.4:
686  // 1. If successor has lower or equal ranking, enable the event
687  // 2. If we're in I_p and successor is in I_p, enable to maintain invariance
688  // 3. If successor is in R_p and we need to visit R_p, enable the event
689 
690  if (succRanking < ranking || succRanking.muLevel == ranking.muLevel) {
691  enableEvent = true;
692  } else if (ISet.Exists(state) && ISet.Exists(successor)) {
693  enableEvent = true; // Stay within invariant set
694  } else if (RSet.Exists(successor) && ranking.branchType == 0) {
695  enableEvent = true; // Allow reaching recurrent set when needed
696  }
697  } else {
698  // If successor is not controllable, be conservative
699  if (ISet.Exists(successor)) {
700  enableEvent = true; // Safe to go to invariant states
701  }
702  }
703 
704  // Always enable uncontrollable events
705  if (!mSigmaCtrl.Exists(event)) {
706  enableEvent = true;
707  }
708 
709  if (enableEvent) {
710  rPattern.Insert(event);
711  }
712  }
713 
714  // Ensure we have at least one enabled controllable event to avoid deadlock
715  bool hasControllableEvent = false;
716  for (EventSet::Iterator eit = rPattern.Begin(); eit != rPattern.End(); ++eit) {
717  if (mSigmaCtrl.Exists(*eit)) {
718  hasControllableEvent = true;
719  break;
720  }
721  }
722 
723  // If no controllable events are enabled, enable all to avoid deadlock
724  if (!hasControllableEvent) {
725  rPattern.InsertSet(mSigmaCtrl);
726  }
727  }
728 };
729 
730 
731 
733  const RabinAutomaton& rRAut, const EventSet& rSigmaCtrl, TaIndexSet<EventSet>& rController) {
734 
735  // we can only handle one Rabin pair
736  if(rRAut.RabinAcceptance().Size()!=1){
737  std::stringstream errstr;
738  errstr << "the current implementation requires exactly one Rabin pair";
739  throw Exception("RabinCtrlPfxWithFeedback", errstr.str(), 80);
740  }
741 
742  // set up various helper
743  TransSetX2EvX1 revtrans(rRAut.TransRel());
744  EventSet sigctrl(rSigmaCtrl);
745 
746  // State ranking map to track fixpoint computation
747  StateRankingMap stateRanking;
748 
749  // have operator with ranking capability
750  RabinInvDynCtrlWithRanking ctrl(rRAut, revtrans, sigctrl);
751  ctrl.SetStateRankingMap(&stateRanking);
752 
753  StateSet rCtrlPfx;
754  // run computation
755  ctrl.Evaluate(rCtrlPfx);
756 
757  // construct state feedback mapping
758  StateFeedbackMap rStateFeedback;
759  StateFeedbackConstructor feedbackConstructor(rRAut, sigctrl, stateRanking);
760  feedbackConstructor.ConstructStateFeedback(rCtrlPfx, rStateFeedback);
761 
762  // clear and populate controller with state -> EventSet mapping
763  rController.Clear();
764  for (StateFeedbackMap::Iterator it = rStateFeedback.Begin(); it != rStateFeedback.End(); ++it) {
765  rController.Insert(*it, rStateFeedback.Attribute(*it));
766  }
767 };
768 
769 
770 
771 } // namespace faudes
772 
#define FD_DF(message)
const std::string & Name(void) const
Definition: cfl_types.cpp:422
bool Exists(const Idx &rIndex) const
virtual void InsertSet(const NameSet &rOtherSet)
bool Insert(const Idx &rIndex)
virtual void DoEvaluate(StateSetVector &rArgs, StateSet &rRes)
RabinAcceptance::CIterator mRPit
RabinInvDynCtrlCore_RK(const RabinAutomaton &raut, const TransSetX2EvX1 &revtrans, const EventSet &sigctrl)
virtual void DoEvaluate(StateSetVector &rArgs, StateSet &rRes)
void ComputeThetaWithRanking(const StateSet &Z1, const StateSet &Z2, StateSet &rRes, int muLevel, int nuLevel, int branchType) const
RabinAcceptance::CIterator mRPit
void ComputeThetaTildeWithRanking(const StateSet &W1, const StateSet &W2, StateSet &rRes, int muLevel, int nuLevel, int branchType) const
RabinInvDynCtrlWithRanking(const RabinAutomaton &raut, const TransSetX2EvX1 &revtrans, const EventSet &sigctrl)
void ComputePReachWithRanking(const StateSet &X1, const StateSet &X2, StateSet &rRes, int muLevel, int nuLevel) const
RabinInvDynCtrl_RK(const RabinAutomaton &raut, const TransSetX2EvX1 &revtrans, const EventSet &sigctrl)
virtual void DoEvaluate(StateSetVector &rArgs, StateSet &rRes)
RabinInvDynCtrlCore_RK mCtrlCore
void SetStateRankingMap(StateRankingMap *pRanking)
RabinInvDynOperatorWithRanking(const vGenerator &gen, const TransSetX2EvX1 &revtrans, const EventSet &sigctrl)
void RecordStateRanking(const StateSet &rNewStates) const
void SetCurrentLevels(int muLevel, int nuLevel, int branchType) const
virtual const StateSet & Domain(void) const
const TransSetX2EvX1 & rRevTransRel
RabinInvDynOperator_RK(const vGenerator &gen, const TransSetX2EvX1 &revtrans, const EventSet &sigctrl)
RabinAcceptance::CIterator mRPit
virtual void DoEvaluate(StateSetVector &rArgs, StateSet &rRes)
RabinInvDynPReachCore_RK(const RabinAutomaton &raut, const TransSetX2EvX1 &revtrans, const EventSet &sigctrl)
virtual void DoEvaluate(StateSetVector &rArgs, StateSet &rRes)
RabinInvDynPReach_RK(const RabinAutomaton &raut, const TransSetX2EvX1 &revtrans, const EventSet &sigctrl)
RabinInvDynPReachCore_RK mPReachCore
virtual void DoEvaluate(StateSetVector &rArgs, StateSet &rRes)
RabinInvDynThetaTildeCore_RK(const vGenerator &gen, const TransSetX2EvX1 &revtrans, const EventSet &sigctrl)
RabinInvDynThetaTilde_RK(const vGenerator &gen, const TransSetX2EvX1 &revtrans, const EventSet &sigctrl)
RabinInvDynThetaTildeCore_RK mThetaCore
virtual void DoEvaluate(StateSetVector &rArgs, StateSet &rRes)
virtual void DoEvaluate(StateSetVector &rArgs, StateSet &rRes)
RabinInvDynTheta_RK(const vGenerator &gen, const TransSetX2EvX1 &revtrans, const EventSet &sigctrl)
const StateRankingMap & mStateRanking
StateFeedbackConstructor(const RabinAutomaton &raut, const EventSet &sigctrl, const StateRankingMap &ranking)
void ConstructStateFeedback(const StateSet &rCtrlPfx, StateFeedbackMap &rFeedback) const
void constructControlPatternForState(Idx state, const StateRanking &ranking, const StateSet &RSet, const StateSet &ISet, EventSet &rPattern) const
std::vector< std::string > mArgNames
Definition: syn_ctrlpfx.h:122
StateSetVector::Position mArgCount
Definition: syn_ctrlpfx.h:119
void Evaluate(StateSetVector &rArgs, StateSet &rRes) const
Definition: syn_ctrlpfx.cpp:43
virtual const T & At(const Position &pos) const
StateSet PredecessorStates(Idx x2) const
Iterator Begin(void) const
Iterator End(void) const
TBaseSet< Transition, TransSort::X1EvX2 >::Iterator Iterator
Definition: cfl_transset.h:273
const TaEventSet< EventAttr > & Alphabet(void) const
const ATransSet & TransRel(void) const
const Attr & Attribute(const Idx &rElem) const
Definition: cfl_indexset.h:559
void RabinAcceptance(const faudes::RabinAcceptance &rRabAcc)
Definition: omg_rabinaut.h:326
Idx Size(void) const
TransSet::Iterator TransRelBegin(void) const
TransSet::Iterator TransRelEnd(void) const
bool Empty(void) const
Definition: cfl_baseset.h:1904
bool Exists(const T &rElem) const
Definition: cfl_baseset.h:2322
virtual void Clear(void)
Definition: cfl_baseset.h:2104
Iterator End(void) const
Definition: cfl_baseset.h:2098
virtual void InsertSet(const TBaseSet &rOtherSet)
Definition: cfl_baseset.h:2194
Iterator Begin(void) const
Definition: cfl_baseset.h:2093
virtual bool Erase(const T &rElem)
Definition: cfl_baseset.h:2226
void RabinCtrlPfxWithFeedback(const RabinAutomaton &rRAut, const EventSet &rSigmaCtrl, TaIndexSet< EventSet > &rController)
uint32_t Idx
void RabinCtrlPfx_RK(const RabinAutomaton &rRAut, const EventSet &rSigmaCtrl, StateSet &rCtrlPfx)

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