omg_rabinctrl.cpp
Go to the documentation of this file.
1 /** @file omg_rabinctrl.cpp
2 
3 Operations regarding omega languages accepted by Rabin automata
4 
5 */
6 
7 /* FAU Discrete Event Systems Library (libFAUDES)
8 
9 Copyright (C) 2025 Thomas Moor
10 
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Lesser General Public
13 License as published by the Free Software Foundation; either
14 version 2.1 of the License, or (at your option) any later version.
15 
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
20 
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
24 
25 
26 
27 #include "omg_rabinctrl.h"
28 #include "syn_include.h"
29 
30 // local degug
31 //#undef FD_DF
32 //#define FD_DF(m) FD_WARN(m)
33 
34 namespace faudes {
35 
36 /*
37 Base class for my operators to hold context
38 */
40 protected:
41  /** record context references */
42  const vGenerator& rGen;
43  const StateSet& rDomain;
48 public:
49  /** construct to record context */
51  const vGenerator& gen, const TransSetX2EvX1& revtrans, const EventSet& sigctrl)
52  :
54  rGen(gen),
55  rDomain(gen.States()),
56  rMarkedStates(gen.MarkedStates()),
57  rTransRel(gen.TransRel()),
58  rRevTransRel(revtrans),
59  mSigmaCtrl(sigctrl)
60  {
61  Name("void base class operator");
62  mArgCount=0;
63  };
64  /** overaall stateset */
65  virtual const StateSet& Domain(void) const {
66  return rDomain;
67  }
68 };
69 
70 
71 /*
72 Inverse dynamics operator theta
73 
74 Cite Thistle/Wonham "Control of w-Automata, Church's Problem, and the Emptiness
75 Problem for Tree w-Automata", 1992, Def 8.2:
76 
77 theta(X1,X2) = "the set of states, from which the automaton can be controlled to
78 enter X1 union X2 in a single transition without being prevented from entering X1."
79 
80 Rephrase: X1 is the target T, X1 union X2 is the domain D; control such that immediate
81 successors stay within within D and there is the chance to enter the T.
82 
83 We use "Z1/Z2" argument names to avoid confusion with libFAUDES naming conventions.
84 */
86 public:
87  /** construct to record context */
89  const vGenerator& gen, const TransSetX2EvX1& revtrans, const EventSet& sigctrl)
90  :
91  RabinInvDynOperator(gen,revtrans,sigctrl)
92  {
93  FD_DF("RabinInvDynTheta(): instantiated for " << rGen.Name());
94  Name("theta([Z1,Z2])");
95  mArgNames= std::vector<std::string>{"Z1","Z2"};
96  mArgCount=2;
97  };
98 protected:
99  /** actual operator implementation */
100  virtual void DoEvaluate(StateSetVector& rArgs, StateSet& rRes) const {
101  // convenience acsesors
102  const StateSet& Z1=rArgs.At(0);
103  const StateSet& Z2=rArgs.At(1);
104  // do operate
106  StateSet::Iterator sit=rRes.Begin();
107  StateSet::Iterator sit_end=rRes.End();
108  while(sit!=sit_end){
110  TransSet::Iterator tit_end=rTransRel.End(*sit);
111  bool enterZ1 = false;
112  bool exitZ12 = false;
113  for(;tit!=tit_end;++tit){
114  // successor is in Z1: will not disable, found evidence to enter Z1
115  if(Z1.Exists(tit->X2)) {enterZ1=true; continue;}
116  // successor is in Z2: will not disable
117  if(Z2.Exists(tit->X2)) {continue;}
118  // sucessor is neither in Z1 nor Z2: need to disable
119  if(!mSigmaCtrl.Exists(tit->Ev)){ exitZ12 = true; break;}
120  }
121  if(!enterZ1 || exitZ12) rRes.Erase(sit++);
122  else++sit;
123  }
124  };
125 };
126 
127 
128 /*
129 Inverse dynamics operator theta-tilde
130 
131 Cite Thistle/Wonham "Control of w-Automata, Church's Problem, and the Emptiness
132 Problem for Tree w-Automata", 1992, Def 8.3:
133 
134 "theta_tilde(X1,X2)=nu X3 mu X4 theta( X1 + (X4 - R), (X3 - R) * X2 ) ")
135 
136 We first implement the core formula without the nu/mu iteration and then apply nu/mu.
137 We use "Y1/Y2/Y3/Y4" and "Z1/Z2" argument names to
138 */
140 public:
141  /** construct to record context */
143  const vGenerator& gen, const TransSetX2EvX1& revtrans, const EventSet& sigctrl)
144  :
145  RabinInvDynTheta(gen,revtrans,sigctrl)
146  {
147  FD_DF("RabinInvDynThetaTildeCore(): instantiated for " << rGen.Name());
148  Name("theta_tilde_core([Y1,Y2,Y3,Y4])");
149  mArgNames= std::vector<std::string>{"Y1","Y2","Y3","Y4"};
150  mArgCount=4;
151  };
152 protected:
153  /** actual operator implementation */
154  virtual void DoEvaluate(StateSetVector& rArgs, StateSet& rRes) const {
155  // convenience acsesors
156  const StateSet& Y1=rArgs.At(0);
157  const StateSet& Y2=rArgs.At(1);
158  const StateSet& Y3=rArgs.At(2);
159  const StateSet& Y4=rArgs.At(3);
160  StateSetVector args;
161  args.Size(2);
162  StateSet& Z1=args.At(0);
163  StateSet& Z2=args.At(1);
164  // do operate
165  Z1= Y1 + (Y4 - rMarkedStates);
166  Z2= Y2 * (Y3 - rMarkedStates);
167  RabinInvDynTheta::DoEvaluate(args,rRes);
168  };
169 };
170 
171 
172 /*
173 Inverse dynamics operator theta tilde, outer nu/mu iteration
174 */
176 protected:
177  /** additional context */
181 public:
182  /** construct to record context */
184  const vGenerator& gen, const TransSetX2EvX1& revtrans, const EventSet& sigctrl)
185  :
186  RabinInvDynOperator(gen,revtrans,sigctrl),
187  mThetaCore(gen,revtrans,sigctrl),
190  {
191  FD_DF("RabinInvDynThetaTilde(): instantiated for " << rGen.Name());
192  Name("theta_tilde([W1,W2])");
193  mArgNames= std::vector<std::string>{"W1","W2"};
194  mArgCount=2;
195  };
196 protected:
197  /** actual operator implementation */
198  virtual void DoEvaluate(StateSetVector& rArgs, StateSet& rRes) const {
199  mNuMuThetaCore.Evaluate(rArgs, rRes);
200  };
201 };
202 
203 
204 /*
205 P-reach operator
206 
207 Cite Thistle/Wonham "Control of w-Automata, Church's Problem, and the Emptiness
208 Problem for Tree w-Automata", 1992, Def 8.4
209 
210 p-reach(X1,X2)= mu X3 . theta-tilde(X1,X) union theta-tilde((X1 u X2 u X3, I_p))
211 
212 We first implement the core formular without the nu/mu iteration, and then do the
213 mu iteration
214 
215 We use "U1/U2/U3" and "W1/W2" argument names
216 */
218  /** additional context */
219  RabinAcceptance::CIterator mRPit;
220 public:
221  /** construct to record context */
223  const RabinAutomaton& raut, const TransSetX2EvX1& revtrans, const EventSet& sigctrl)
224  :
225  RabinInvDynThetaTilde(raut,revtrans,sigctrl),
226  mRPit(raut.RabinAcceptance().Begin())
227  {
228  FD_DF("RabinInvDynPReachCore(): instantiated for " << rGen.Name());
229  Name("invdyn_op([U1,U2,U3)");
230  mArgNames= std::vector<std::string>{"U1","U2","U3"};
231  mArgCount=3;
232  };
233 protected:
234  /** actual operator implementation */
235  virtual void DoEvaluate(StateSetVector& rArgs, StateSet& rRes) const {
236  // convenience accessors
237  const StateSet& U1=rArgs.At(0);
238  const StateSet& U2=rArgs.At(1);
239  const StateSet& U3=rArgs.At(2);
240  StateSetVector args;
241  args.Size(2);
242  StateSet& W1=args.At(0);
243  StateSet& W2=args.At(1);
244  // do operate
245  W1=U1;
246  W2=Domain();
248  W1=U1+U2+U3;
249  W2=mRPit->ISet();
250  StateSet rhs;
252  rRes.InsertSet(rhs);
253  };
254 };
255 
256 /** p-reach operator, mu iteration */
258 protected:
259  /** have additional context */
262 public:
263  /** construct to record context */
265  const RabinAutomaton& raut, const TransSetX2EvX1& revtrans, const EventSet& sigctrl)
266  :
267  RabinInvDynOperator(raut,revtrans,sigctrl),
268  mPReachCore(raut,revtrans,sigctrl),
270  {
271  FD_DF("RabinInvDynPReach(): instantiated for " << rGen.Name());
272  Name("p_reach_op([O1,O2])");
273  mArgNames= std::vector<std::string>{"O1","O2"};
274  mArgCount=2;
275  };
276 protected:
277  /** actual operator implementation */
278  virtual void DoEvaluate(StateSetVector& rArgs, StateSet& rRes) const {
279  mMuPReachCore.Evaluate(rArgs, rRes);
280  };
281 };
282 
283 /*
284 Controllable subset
285 
286 Cite Thistle/Wonham "Control of w-Automata, Church's Problem, and the Emptiness
287 Problem for Tree w-Automata", 1992, Def 8.5
288 
289 CA = mu X1 nu X2 . p-reach(X1, X2 * R)
290 
291 We first implement the core formular without the mu/nu iteration, and then do the mu/nu.
292 
293 */
295  /** additional context */
296  RabinAcceptance::CIterator mRPit;
297 public:
298  /** construct to record context */
300  const RabinAutomaton& raut, const TransSetX2EvX1& revtrans, const EventSet& sigctrl)
301  :
302  RabinInvDynPReach(raut,revtrans,sigctrl),
303  mRPit(raut.RabinAcceptance().Begin())
304  {
305  FD_DF("RabinInvDynCtrlCore(): instantiated for " << rGen.Name());
306  Name("ctrl([X1,X2])");
307  mArgNames= std::vector<std::string>{"X1","X2"};
308  mArgCount=2;
309  };
310 protected:
311  /** actual operator implementation */
312  virtual void DoEvaluate(StateSetVector& rArgs, StateSet& rRes) const {
313  // convenience accessors
314  const StateSet& X1=rArgs.At(0);
315  const StateSet& X2=rArgs.At(1);
316  StateSetVector args;
317  args.Size(2);
318  StateSet& O1=args.At(0);
319  StateSet& O2=args.At(1);
320  // do operate
321  O1=X1;
322  O2=X2 * mRPit->RSet();
324  };
325 };
326 
327 /** ctrollable set, mu-nu iteration */
329 protected:
330  /** have additional context */
334 public:
335  /** construct to record context */
337  const RabinAutomaton& raut, const TransSetX2EvX1& revtrans, const EventSet& sigctrl)
338  :
339  RabinInvDynOperator(raut,revtrans,sigctrl),
340  mCtrlCore(raut,revtrans,sigctrl),
343  {
344  FD_DF("RabinInvDynCtrl(): instantiated for " << rGen.Name());
345  Name("ctrl()");
346  mArgCount=0;
347  };
348 protected:
349  /** actual operator implementation */
350  virtual void DoEvaluate(StateSetVector& rArgs, StateSet& rRes) const {
351  mMuNuCtrlCore.Evaluate(rArgs, rRes);
352  };
353 };
354 
355 
356 
357 
359  const RabinAutomaton& rRAut, const EventSet& rSigmaCtrl,
360  StateSet& rCtrlPfx){
361  // we can only handle one Rabin pair
362  if(rRAut.RabinAcceptance().Size()!=1){
363  std::stringstream errstr;
364  errstr << "the current implementation requires exactly one Rabin pair";
365  throw Exception("RabinCtrlPfx", errstr.str(), 80);
366  }
367  // set up various helper
368  TransSetX2EvX1 revtrans(rRAut.TransRel());
369  EventSet sigctrl(rSigmaCtrl);
370  // have operator
371  RabinInvDynCtrl ctrl(rRAut,revtrans,sigctrl);
372  // run
373  ctrl.Evaluate(rCtrlPfx);
374 };
375 
376 
377 
378 } // namespace faudes
379 
#define FD_DF(message)
const std::string & Name(void) const
Definition: cfl_types.cpp:422
bool Exists(const Idx &rIndex) const
virtual void DoEvaluate(StateSetVector &rArgs, StateSet &rRes) const
RabinAcceptance::CIterator mRPit
RabinInvDynCtrlCore(const RabinAutomaton &raut, const TransSetX2EvX1 &revtrans, const EventSet &sigctrl)
RabinInvDynCtrlCore mCtrlCore
virtual void DoEvaluate(StateSetVector &rArgs, StateSet &rRes) const
RabinInvDynCtrl(const RabinAutomaton &raut, const TransSetX2EvX1 &revtrans, const EventSet &sigctrl)
virtual const StateSet & Domain(void) const
RabinInvDynOperator(const vGenerator &gen, const TransSetX2EvX1 &revtrans, const EventSet &sigctrl)
const StateSet & rMarkedStates
const TransSetX2EvX1 & rRevTransRel
RabinAcceptance::CIterator mRPit
RabinInvDynPReachCore(const RabinAutomaton &raut, const TransSetX2EvX1 &revtrans, const EventSet &sigctrl)
virtual void DoEvaluate(StateSetVector &rArgs, StateSet &rRes) const
RabinInvDynPReach(const RabinAutomaton &raut, const TransSetX2EvX1 &revtrans, const EventSet &sigctrl)
virtual void DoEvaluate(StateSetVector &rArgs, StateSet &rRes) const
RabinInvDynPReachCore mPReachCore
virtual void DoEvaluate(StateSetVector &rArgs, StateSet &rRes) const
RabinInvDynThetaTildeCore(const vGenerator &gen, const TransSetX2EvX1 &revtrans, const EventSet &sigctrl)
virtual void DoEvaluate(StateSetVector &rArgs, StateSet &rRes) const
RabinInvDynThetaTildeCore mThetaCore
RabinInvDynThetaTilde(const vGenerator &gen, const TransSetX2EvX1 &revtrans, const EventSet &sigctrl)
virtual void DoEvaluate(StateSetVector &rArgs, StateSet &rRes) const
RabinInvDynTheta(const vGenerator &gen, const TransSetX2EvX1 &revtrans, const EventSet &sigctrl)
std::vector< std::string > mArgNames
Definition: syn_ctrlpfx.h:126
StateSetVector::Position mArgCount
Definition: syn_ctrlpfx.h:123
void Evaluate(StateSetVector &rArgs, StateSet &rRes) const
Definition: syn_ctrlpfx.cpp:46
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 ATransSet & TransRel(void) const
void RabinAcceptance(const faudes::RabinAcceptance &rRabAcc)
Definition: omg_rabinaut.h:324
Idx Size(void) const
bool Exists(const T &rElem) const
Definition: cfl_baseset.h:2180
Iterator End(void) const
Definition: cfl_baseset.h:1956
virtual void InsertSet(const TBaseSet &rOtherSet)
Definition: cfl_baseset.h:2052
Iterator Begin(void) const
Definition: cfl_baseset.h:1951
virtual bool Erase(const T &rElem)
Definition: cfl_baseset.h:2084
void RabinCtrlPfx(const RabinAutomaton &rRAut, const EventSet &rSigmaCtrl, StateSet &rCtrlPfx)

libFAUDES 2.33h --- 2025.06.18 --- c++ api documentaion by doxygen