ios_algorithms.cpp
Go to the documentation of this file.
1 #include "ios_algorithms.h"
2 #include "syn_wsupcon.h"
3 
4 namespace faudes {
5 
6 // IsIoSystem() implementation
7 bool IsIoSystem(const IoSystem& rIoSystem,
8  StateSet& rQU,
9  StateSet& rQY,
10  StateSet& rQErr)
11 {
12  FD_DIO("IsIoSystem("<< rIoSystem.Name() << ",...)");
13  // prepare result
14  rQU.Clear();
15  rQY.Clear();
16  rQErr.Clear();
17  rQErr.Name("ErrorStates");
18  // completeness (iterate over accessible states only)
19  FD_DIO("IsIoSystem("<< rIoSystem.Name() << ",...): testing completeness");
20  StateSet acc = rIoSystem.AccessibleSet();
21  StateSet coacc = rIoSystem.CoaccessibleSet();
22  StateSet::Iterator sit=acc.Begin();
23  StateSet::Iterator sit_end=acc.End();
24  for(;sit!=sit_end;sit++){
25  // cannot extend
26  TransSet::Iterator tit=rIoSystem.TransRelBegin(*sit);
27  TransSet::Iterator tit_end=rIoSystem.TransRelEnd(*sit);
28  if(tit==tit_end) rQErr.Insert(*sit);
29  // not coreachable
30  if(!coacc.Exists(*sit)) rQErr.Insert(*sit);
31  }
32  if(!rQErr.Empty()) {
33  FD_DIO("IsIoSystem("<< rIoSystem.Name() << ",...): not complete");
34  return false;
35  }
36  // insist in a u-y partition
37  EventSet errev;
38  bool hasu=false;
39  bool hasy=false;
40  EventSet::Iterator eit = rIoSystem.AlphabetBegin();
41  EventSet::Iterator eit_end= rIoSystem.AlphabetEnd();
42  for(; eit != eit_end; ++eit) {
43  if(rIoSystem.InputEvent(*eit))
44  hasu=true;
45  if(rIoSystem.InputEvent(*eit))
46  hasy=true;
47  if(rIoSystem.InputEvent(*eit))
48  if(rIoSystem.OutputEvent(*eit))
49  errev.Insert(*eit);
50  if(!rIoSystem.InputEvent(*eit))
51  if(!rIoSystem.OutputEvent(*eit))
52  errev.Insert(*eit);
53  }
54  if(!errev.Empty()) {
55  FD_DIO("IsIoSystem("<< rIoSystem.Name() << ",...): not a u-y partition of events");
56  TransSet::Iterator tit=rIoSystem.TransRelBegin();
57  TransSet::Iterator tit_end=rIoSystem.TransRelEnd();
58  for(; tit!=tit_end; tit++)
59  if(errev.Exists(tit->Ev)) rQErr.Insert(tit->X1);
60  return false;
61  }
62  if(!hasu || !hasy) {
63  FD_DIO("IsIoSystem("<< rIoSystem.Name() << ",...): trivial partition");
64  return false;
65  }
66  // io-alternation: fill todo stack with initial states
67  FD_DIO("IsIoSystem("<< rIoSystem.Name() << ",...): i/o alternation");
68  std::stack<Idx> todo;
69  sit = rIoSystem.InitStatesBegin();
70  sit_end= rIoSystem.InitStatesEnd();
71  for(; sit != sit_end; ++sit) {
72  // figure type of initial state
73  TransSet::Iterator tit=rIoSystem.TransRelBegin(*sit);
74  TransSet::Iterator tit_end=rIoSystem.TransRelEnd(*sit);
75  for(; tit!=tit_end; tit++) {
76  if(rIoSystem.InputEvent(tit->Ev)) rQU.Insert(*sit);
77  if(rIoSystem.OutputEvent(tit->Ev)) rQY.Insert(*sit);
78  }
79  // push
80  todo.push(*sit);
81  }
82  // io-alternation: multiple initialstates are fine, but must be of same type.
83  if(!rQU.Empty() && !rQY.Empty()) {
84  sit = rIoSystem.InitStatesBegin();
85  sit_end= rIoSystem.InitStatesEnd();
86  for(; sit != sit_end; ++sit) {
87  rQErr.Insert(*sit);
88  return false;
89  }
90  }
91  // io-alternation: process stack
92  while(!todo.empty()) {
93  const Idx current = todo.top();
94  todo.pop();
95  bool uok = rQU.Exists(current);
96  bool yok = rQY.Exists(current);
97  // iterate all transitions
98  TransSet::Iterator tit=rIoSystem.TransRelBegin(current);
99  TransSet::Iterator tit_end=rIoSystem.TransRelEnd(current);
100  for(; tit!=tit_end; tit++) {
101  if(!rQY.Exists(tit->X2) && !rQU.Exists(tit->X2))
102  todo.push(tit->X2);
103  if(rIoSystem.InputEvent(tit->Ev)) {
104  rQY.Insert(tit->X2);
105  if(!uok) rQErr.Insert(current);
106  }
107  if(rIoSystem.OutputEvent(tit->Ev)) {
108  rQU.Insert(tit->X2);
109  if(!yok) rQErr.Insert(current);
110  }
111  }
112  }
113  if(!rQErr.Empty()) {
114  return false;
115  }
116  // done
117  return true;
118 }
119 
120 
121 // IsIoSystem wrapper function
122 bool IsIoSystem(IoSystem& rIoSystem) {
123  StateSet QU,QY, QErr;
124  bool res= IsIoSystem(rIoSystem, QU, QY, QErr);
125  rIoSystem.InputStates(QU);
126  rIoSystem.OutputStates(QY);
127  rIoSystem.ErrorStates(QErr);
128  return res;
129 }
130 
131 
132 // rti function interface
133 void IoStatePartition(IoSystem& rIoSystem) {
134  IsIoSystem(rIoSystem);
135 }
136 
137 
138 // IsInputLocallyFree wrapper function
139 bool IsInputLocallyFree(IoSystem& rIoSystem) {
140  FD_DIO("IsInputLocallyFree("<< rIoSystem.Name() << ",...)");
141  StateSet QErr;
142  bool res=IsInputLocallyFree(rIoSystem, QErr);
143  rIoSystem.ErrorStates(QErr);
144  return res;
145 }
146 
147 // IsInputLocallyFree implementation
148 bool IsInputLocallyFree(const IoSystem& rIoSystem, StateSet& rQErr) {
149  FD_DIO("IsInputLocallyFree("<< rIoSystem.Name() << ",...)");
150  // prepare result
151  rQErr.Clear();
152  rQErr.Name("ErrorStates");
153  // have set of all input events
154  EventSet sigu=rIoSystem.InputEvents();
155  // test all states
156  StateSet::Iterator sit = rIoSystem.StatesBegin();
157  StateSet::Iterator sit_end= rIoSystem.StatesEnd();
158  for(; sit != sit_end; ++sit) {
159  // get all enabled inputs
160  EventSet lsigu;
161  TransSet::Iterator tit=rIoSystem.TransRelBegin(*sit);
162  TransSet::Iterator tit_end=rIoSystem.TransRelEnd(*sit);
163  for(; tit!=tit_end; tit++)
164  if(rIoSystem.InputEvent(tit->Ev)) lsigu.Insert(tit->Ev);
165  //FD_DIO("DUMP " << rIoSystem.StateName(*sit) << " "<< lsigu.ToString());
166  // no inputs? fine
167  if(lsigu.Empty()) continue;
168  // all inputs? fine
169  if(lsigu == sigu) continue;
170  // error
171  rQErr.Insert(*sit);
172  //FD_DIO("DUMP " << *sit << " " << rQErr.ToString());
173  }
174  return rQErr.Empty();
175 }
176 
177 
178 // IsInputOmegaFree wrapper function
179 bool IsInputOmegaFree(IoSystem& rIoSystem) {
180  FD_DIO("IsInputOmegaFree("<< rIoSystem.Name() << ",...)");
181  StateSet QErr;
182  bool res=IsInputOmegaFree(rIoSystem, QErr);
183  rIoSystem.ErrorStates(QErr);
184  return res;
185 }
186 
187 // Is InputOmegaFree implementation
188 bool IsInputOmegaFree(const IoSystem& rIoSystem, StateSet& rQErr) {
189  FD_DIO("IsInputOmegaFree("<< rIoSystem.Name() << ",...)");
190 
191  // test for locally free input first
192  rQErr.Clear();
193  if(!IsInputLocallyFree(rIoSystem,rQErr)) {
194  FD_DIO("IsInputOmegaFree("<< rIoSystem.Name() << ",...): failed for locally free");
195  return false;
196  }
197 
198  // prepare good state iteration
199  StateSet goodstates=rIoSystem.MarkedStates();
200  EventSet yalph=rIoSystem.OutputEvents();
201  rQErr=rIoSystem.AccessibleSet()-goodstates;
202  rQErr.Name("ErrorStates");
203 
204  // control to good states by choosing strategic y-events
205  while(true) {
206  // test individual states
207  FD_DIO("IsInputOmegaFree(...): iterate over good states");
208  bool found=false;
209  StateSet::Iterator sit = rQErr.Begin();
210  while(sit!=rQErr.End()) {
211  // pre-increment
212  StateSet::Iterator cit=sit++;
213  // goodstate anyway
214  if(goodstates.Exists(*cit)) continue;
215  // test transitions
216  TransSet::Iterator tit = rIoSystem.TransRelBegin(*cit);
217  TransSet::Iterator tit_end = rIoSystem.TransRelEnd(*cit);
218  // no transitions at all: no chance
219  if(tit==tit_end) continue;
220  // iterate successors
221  bool exgood=false;
222  for(; tit!=tit_end; ++tit) {
223  if(goodstates.Exists(tit->X2)) { exgood=true; continue; };
224  if(!yalph.Exists(tit->Ev)) break; // break on not-good successor with non-y-event (aka u-event)
225  }
226  // succes: good successor exists and all not-good successors are y-events [rev tmoor 201507]
227  if(exgood && (tit==tit_end)) {
228  FD_DIO("IsInputOmegaFree(): ins good state " << rIoSystem.SStr(*cit));
229  goodstates.Insert(*cit);
230  rQErr.Erase(cit);
231  found=true;
232  }
233  }
234  // exit
235  if(!found) break;
236  };
237 
238  // errorstates
239  if(rQErr.Empty()) {
240  FD_DIO("IsInputOmegaFree(): accessible <= good: passed");
241  return true;
242  }
243 
244  // fail
245  FD_DIO("IsInputOmegaFree(): accessible <= good: failed");
246  return false;
247 }
248 
249 
250 // IoFreeInput() wrapper
251 void IoFreeInput(IoSystem& rIoSystem) {
252  IoFreeInput(rIoSystem,rIoSystem.InputEvents());
253 }
254 
255 // IoFreeInput()
256 void IoFreeInput(Generator& rGen, const EventSet& rUAlph) {
257  FD_DIO("IoFreeInput("<< rGen.Name() << ",...)");
258  // test alphabet
259  if(!(rUAlph <= rGen.Alphabet())){
260  std::stringstream errstr;
261  errstr << "Input alphabet must be contained in generator alphabet";
262  throw Exception("IoFreeInput(..)", errstr.str(), 100);
263  }
264  // prepare error states
265  Idx qyerr=0;
266  Idx querr=0;
267  // declare some local vars
268  EventSet::Iterator eit;
269  EventSet::Iterator eit_end;
270  // test all states
271  StateSet::Iterator sit = rGen.StatesBegin();
272  StateSet::Iterator sit_end= rGen.StatesEnd();
273  for(; sit != sit_end; ++sit) {
274  // get all enabled inputs
275  EventSet lsigu;
276  TransSet::Iterator tit=rGen.TransRelBegin(*sit);
277  TransSet::Iterator tit_end=rGen.TransRelEnd(*sit);
278  for(; tit!=tit_end; tit++)
279  if(rUAlph.Exists(tit->Ev)) lsigu.Insert(tit->Ev);
280  // no inputs? fine
281  if(lsigu.Empty()) continue;
282  // all inputs? fine
283  if(lsigu == rUAlph) continue;
284  // no error states yet? insert them
285  if(qyerr==0) {
286  // todo: be smart in state names when enabled
287  qyerr = rGen.InsMarkedState();
288  querr = rGen.InsMarkedState();
289  // enable all transition
290  eit=rGen.Alphabet().Begin();
291  eit_end=rGen.Alphabet().End();
292  for(; eit!=eit_end; eit++) {
293  if(rUAlph.Exists(*eit))
294  rGen.SetTransition(querr,*eit,qyerr);
295  else
296  rGen.SetTransition(qyerr,*eit,querr);
297  }
298  }
299  // fix the state at hand
300  eit=rUAlph.Begin();
301  eit_end=rUAlph.End();
302  for(; eit!=eit_end; eit++)
303  if(!lsigu.Exists(*eit))
304  rGen.SetTransition(*sit,*eit,qyerr);
305  // continue with next state
306  }
307 }
308 
309 // IoRemoveDummyStates
310 void RemoveIoDummyStates(IoSystem& rIoSystem) {
311  FD_DIO("RemoveIoDummyStates("<< rIoSystem.Name() << ",...)");
312  // have set of all input/output events
313  EventSet sigu=rIoSystem.InputEvents();
314  EventSet sigy=rIoSystem.OutputEvents();
315  // have results
316  StateSet qerr1; // a) find all outputs to unique successor
317  StateSet qerr2; // b) collect successors from a)
318  StateSet qerr2a; // c) from qerr2 only keep all with unique successor
319  StateSet qerr; // d) restrict candidates to cyclic behaviour
320  // find states with all outputs leading to the same successor
321  // record as type 1 candidate
322  StateSet::Iterator sit = rIoSystem.StatesBegin();
323  StateSet::Iterator sit_end= rIoSystem.StatesEnd();
324  for(; sit != sit_end; ++sit) {
325  // get all enabled events, track for unique successor
326  EventSet lsig;
327  Idx qsuc=0;
328  bool qunique=true;
329  TransSet::Iterator tit=rIoSystem.TransRelBegin(*sit);
330  TransSet::Iterator tit_end=rIoSystem.TransRelEnd(*sit);
331  for(; tit!=tit_end; tit++) {
332  if(qsuc==0) qsuc=tit->X2;
333  if(qsuc!=tit->X2) { qunique=false; break;}
334  lsig.Insert(tit->Ev);
335  }
336  // non unique successor? discard
337  if(!qunique || qsuc==0) continue;
338  // outputs not enabled? discard
339  if(!(lsig == sigy)) continue;
340  // record candidate
341  qerr1.Insert(*sit);
342  qerr2.Insert(qsuc);
343  }
344  FD_DIO("RemoveIoDummyStates(): Candidates type 1 " << qerr1.ToString());
345  FD_DIO("RemoveIoDummyStates(): Candidates type 2 " << qerr2.ToString());
346  // only keep type 2 candidates with all inputs enabled and
347  // leading to a type 1 candidate
348  sit = qerr2.Begin();
349  sit_end= qerr2.End();
350  for(; sit != sit_end; ++sit) {
351  // get all enabled events, track for unique successor
352  EventSet lsig;
353  Idx qsuc=0;
354  bool qunique=true;
355  TransSet::Iterator tit=rIoSystem.TransRelBegin(*sit);
356  TransSet::Iterator tit_end=rIoSystem.TransRelEnd(*sit);
357  for(; tit!=tit_end; tit++) {
358  if(qsuc==0) qsuc=tit->X2;
359  if(qsuc!=tit->X2) { qunique=false; break;}
360  lsig.Insert(tit->Ev);
361  }
362  // non unique successor? discard
363  if(!qunique) continue;
364  // successor not in candidates? discard
365  if(!qerr1.Exists(qsuc)) continue;
366  // inputs not enabled? discard
367  if(!(lsig == sigu)) continue;
368  // record candidate
369  qerr2a.Insert(*sit);
370  }
371  FD_DIO("RemoveIoDummyStates(): Candidates type 2 (approved) " << qerr2a.ToString());
372  // only keep loops
373  while(1) {
374  StateSet qrm1;
375  sit = qerr1.Begin();
376  sit_end= qerr1.End();
377  for(; sit != sit_end; ++sit) {
378  TransSet::Iterator tit=rIoSystem.TransRelBegin(*sit);
379  TransSet::Iterator tit_end=rIoSystem.TransRelEnd(*sit);
380  if(tit==tit_end) { qrm1.Insert(*sit); break;}
381  if(!qerr2a.Exists(tit->X2)) { qrm1.Insert(*sit); break;}
382  }
383  qerr1.EraseSet(qrm1);
384  StateSet qrm2;
385  sit = qerr2a.Begin();
386  sit_end= qerr2a.End();
387  for(; sit != sit_end; ++sit) {
388  TransSet::Iterator tit=rIoSystem.TransRelBegin(*sit);
389  TransSet::Iterator tit_end=rIoSystem.TransRelEnd(*sit);
390  if(tit==tit_end) { qrm2.Insert(*sit); break;}
391  if(!qerr1.Exists(tit->X2)) { qrm2.Insert(*sit); break;}
392  }
393  qerr2a.EraseSet(qrm2);
394  if(qrm1.Empty() && qrm2.Empty()) break;
395  }
396  qerr=qerr1 + qerr2;
397  FD_DIO("RemoveIoDummyStates(): Dummy states" << qerr.ToString());
398  sit = qerr.Begin();
399  sit_end= qerr.End();
400  for(; sit != sit_end; ++sit)
401  rIoSystem.DelState(*sit);
402  FD_DIO("RemoveIoDummyStates(): done");
403 }
404 
405 // IoSynthesis(rPlant,rSpec,rSup,rErrorStates)
406 void IoSynthesisNB(const IoSystem& rPlant, const Generator& rSpec, IoSystem& rSup) {
407  FD_DIO("IosSynthesisNB");
408 
409  // synthesis
410  EventSet ualph = rPlant.InputEvents();
411  EventSet yalph = rPlant.OutputEvents();
412  OmegaSupConNB(rPlant,ualph,rSpec,rSup) ;
413 
414  // fix event attributes
415  rSup.InputEvents(yalph);
416  rSup.OutputEvents(ualph);
417 }
418 
419 // IoSynthesis(rPlant,rSpec,rSup,rErrorStates)
420 void IoSynthesis(const IoSystem& rPlant, const Generator& rSpec, IoSystem& rSup) {
421  FD_DIO("IosSynthesis");
422 
423  // synthesis
424  EventSet ualph = rPlant.InputEvents();
425  EventSet yalph = rPlant.OutputEvents();
426  SupConCmplClosed(rPlant,ualph,rSpec,rSup) ;
427 
428  // fix event attributes
429  rSup.InputEvents(yalph);
430  rSup.OutputEvents(ualph);
431 }
432 
433 
434 }// end: namespace faudes
Faudes exception class.
Set of indices.
Definition: cfl_indexset.h:78
Idx Insert(void)
Insert new index to set.
Set of indices with symbolic names.
Definition: cfl_nameset.h:69
bool Exists(const Idx &rIndex) const
Test existence of index.
bool Insert(const Idx &rIndex)
Add an element by index.
TBaseSet< Transition, TransSort::X1EvX2 >::Iterator Iterator
Iterator on transition.
Definition: cfl_transset.h:269
Generator with I/O-system attributes.
Definition: ios_system.h:34
bool InputEvent(Idx index) const
Test for input event.
Definition: ios_system.h:967
StateSet InputStates(void) const
Retrieve all input states.
Definition: ios_system.h:1100
StateSet OutputStates(void) const
Retrieve all output states.
Definition: ios_system.h:1023
StateSet ErrorStates(void) const
Retrieve all error states.
Definition: ios_system.h:1179
bool OutputEvent(Idx index) const
Test for output event.
Definition: ios_system.h:890
EventSet OutputEvents(void) const
Retrieve all output events.
Definition: ios_system.h:870
EventSet InputEvents(void) const
Retrieve all input events.
Definition: ios_system.h:946
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
Write configuration data to a string.
Definition: cfl_types.cpp:169
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.
Idx InsMarkedState(void)
Create new anonymous state and set as marked state.
TransSet::Iterator TransRelBegin(void) const
Iterator to Begin() of transition relation.
EventSet::Iterator AlphabetBegin(void) const
Iterator to Begin() of alphabet.
StateSet AccessibleSet(void) const
Compute set of accessible states.
void Name(const std::string &rName)
Set the generator's name.
bool DelState(Idx index)
Delete a state from generator by index.
StateSet::Iterator StatesEnd(void) const
Iterator to End() of state set.
TransSet::Iterator TransRelEnd(void) const
Iterator to End() of transition relation.
StateSet::Iterator InitStatesEnd(void) const
Iterator to End() of mInitStates.
EventSet::Iterator AlphabetEnd(void) const
Iterator to End() of alphabet.
StateSet CoaccessibleSet(void) const
Compute set of Coaccessible states.
std::string SStr(Idx index) const
Return pretty printable state name for index (eg for debugging)
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
Iterator Begin(void) const
Iterator to the begin of set.
Definition: cfl_baseset.h:1891
virtual bool Erase(const T &rElem)
Erase element by reference.
Definition: cfl_baseset.h:2019
const std::string & Name(void) const
Return name of TBaseSet.
Definition: cfl_baseset.h:1755
virtual void EraseSet(const TBaseSet &rOtherSet)
Erase elements given by other set.
Definition: cfl_baseset.h:2042
void RemoveIoDummyStates(IoSystem &rIoSystem)
Remove dummy states.
bool IsInputOmegaFree(IoSystem &rIoSystem)
Test whether the system behaviour has exhibits a free input.
bool IsInputLocallyFree(IoSystem &rIoSystem)
Test whether the system has a locally free input.
bool IsIoSystem(const IoSystem &rIoSystem, StateSet &rQU, StateSet &rQY, StateSet &rQErr)
Test whether the system satisfies basic I/O conditions.
void IoFreeInput(IoSystem &rIoSystem)
Enable all input events for each input state.
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.
Algorithms addressing I/O-systems.
#define FD_DIO(message)
libFAUDES resides within the namespace faudes.
uint32_t Idx
Type definition for index type (allways 32bit)
void IoSynthesisNB(const IoSystem &rPlant, const Generator &rSpec, IoSystem &rSup)
IO system synthesis.
void IoStatePartition(IoSystem &rIoSystem)
Construct io state partition.
void IoSynthesis(const IoSystem &rPlant, const Generator &rSpec, IoSystem &rSup)
IO system synthesis.
Supremal controllable sublanguage for infinite time behaviours.

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