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(not 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
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
219  if(tit==tit_end) continue;
220  // loop over successors
221  bool block=true;
222  for(; tit!=tit_end; ++tit) {
223  if(goodstates.Exists(tit->X2)) { block=false; continue; }
224  if(yalph.Exists(tit->Ev)) continue;
225  break;
226  }
227  // good states survive the loop and dont block
228  if(tit==tit_end && !block) {
229  FD_DIO("IsInputOmegaFree(): ins good state " << rIoSystem.SStr(*cit));
230  goodstates.Insert(*cit);
231  rQErr.Erase(cit);
232  found=true;
233  }
234  }
235  // exit
236  if(!found) break;
237  };
238 
239  // errorstates
240  if(rQErr.Empty()) {
241  FD_DIO("IsInputOmegaFree(): accessible <= good: passed");
242  return true;
243  }
244 
245  // fail
246  FD_DIO("IsInputOmegaFree(): accessible <= good: failed");
247  return false;
248 }
249 
250 
251 // IoFreeInput() wrapper
252 void IoFreeInput(IoSystem& rIoSystem) {
253  IoFreeInput(rIoSystem,rIoSystem.InputEvents());
254 }
255 
256 // IoFreeInput()
257 void IoFreeInput(Generator& rGen, const EventSet& rUAlph) {
258  FD_DIO("IoFreeInput("<< rGen.Name() << ",...)");
259  // test alphabet
260  if(!(rUAlph <= rGen.Alphabet())){
261  std::stringstream errstr;
262  errstr << "Input alphabet must be contained in generator alphabet";
263  throw Exception("IoFreeInput(..)", errstr.str(), 100);
264  }
265  // prepare error states
266  Idx qyerr=0;
267  Idx querr=0;
268  // declare some local vars
269  EventSet::Iterator eit;
270  EventSet::Iterator eit_end;
271  // test all states
272  StateSet::Iterator sit = rGen.StatesBegin();
273  StateSet::Iterator sit_end= rGen.StatesEnd();
274  for(; sit != sit_end; ++sit) {
275  // get all enabled inputs
276  EventSet lsigu;
277  TransSet::Iterator tit=rGen.TransRelBegin(*sit);
278  TransSet::Iterator tit_end=rGen.TransRelEnd(*sit);
279  for(; tit!=tit_end; tit++)
280  if(rUAlph.Exists(tit->Ev)) lsigu.Insert(tit->Ev);
281  // no inputs? fine
282  if(lsigu.Empty()) continue;
283  // all inputs? fine
284  if(lsigu == rUAlph) continue;
285  // no error states yet? insert them
286  if(qyerr==0) {
287  // todo: be smart in state names when enabled
288  qyerr = rGen.InsMarkedState();
289  querr = rGen.InsMarkedState();
290  // enable all transition
291  eit=rGen.Alphabet().Begin();
292  eit_end=rGen.Alphabet().End();
293  for(; eit!=eit_end; eit++) {
294  if(rUAlph.Exists(*eit))
295  rGen.SetTransition(querr,*eit,qyerr);
296  else
297  rGen.SetTransition(qyerr,*eit,querr);
298  }
299  }
300  // fix the state at hand
301  eit=rUAlph.Begin();
302  eit_end=rUAlph.End();
303  for(; eit!=eit_end; eit++)
304  if(!lsigu.Exists(*eit))
305  rGen.SetTransition(*sit,*eit,qyerr);
306  // continue with next state
307  }
308 }
309 
310 // IoRemoveDummyStates
311 void RemoveIoDummyStates(IoSystem& rIoSystem) {
312  FD_DIO("RemoveIoDummyStates("<< rIoSystem.Name() << ",...)");
313  // have set of all input/output events
314  EventSet sigu=rIoSystem.InputEvents();
315  EventSet sigy=rIoSystem.OutputEvents();
316  // have results
317  StateSet qerr1; // a) find all outputs to unique successor
318  StateSet qerr2; // b) collect successors from a)
319  StateSet qerr2a; // c) from qerr2 only keep all with unique successor
320  StateSet qerr; // d) restrict candidates to cyclic behaviour
321  // find states with all outputs leading to the same successor
322  // record as type 1 candidate
323  StateSet::Iterator sit = rIoSystem.StatesBegin();
324  StateSet::Iterator sit_end= rIoSystem.StatesEnd();
325  for(; sit != sit_end; ++sit) {
326  // get all enabled events, track for unique successor
327  EventSet lsig;
328  Idx qsuc=0;
329  bool qunique=true;
330  TransSet::Iterator tit=rIoSystem.TransRelBegin(*sit);
331  TransSet::Iterator tit_end=rIoSystem.TransRelEnd(*sit);
332  for(; tit!=tit_end; tit++) {
333  if(qsuc==0) qsuc=tit->X2;
334  if(qsuc!=tit->X2) { qunique=false; break;}
335  lsig.Insert(tit->Ev);
336  }
337  // non unique successor? discard
338  if(!qunique || qsuc==0) continue;
339  // outputs not enabled? discard
340  if(!(lsig == sigy)) continue;
341  // record candidate
342  qerr1.Insert(*sit);
343  qerr2.Insert(qsuc);
344  }
345  FD_DIO("RemoveIoDummyStates(): Candidates type 1 " << qerr1.ToString());
346  FD_DIO("RemoveIoDummyStates(): Candidates type 2 " << qerr2.ToString());
347  // only keep type 2 candidates with all inputs enabled and
348  // leading to a type 1 candidate
349  sit = qerr2.Begin();
350  sit_end= qerr2.End();
351  for(; sit != sit_end; ++sit) {
352  // get all enabled events, track for unique successor
353  EventSet lsig;
354  Idx qsuc=0;
355  bool qunique=true;
356  TransSet::Iterator tit=rIoSystem.TransRelBegin(*sit);
357  TransSet::Iterator tit_end=rIoSystem.TransRelEnd(*sit);
358  for(; tit!=tit_end; tit++) {
359  if(qsuc==0) qsuc=tit->X2;
360  if(qsuc!=tit->X2) { qunique=false; break;}
361  lsig.Insert(tit->Ev);
362  }
363  // non unique successor? discard
364  if(!qunique) continue;
365  // successor not in candidates? discard
366  if(!qerr1.Exists(qsuc)) continue;
367  // inputs not enabled? discard
368  if(!(lsig == sigu)) continue;
369  // record candidate
370  qerr2a.Insert(*sit);
371  }
372  FD_DIO("RemoveIoDummyStates(): Candidates type 2 (approved) " << qerr2a.ToString());
373  // only keep loops
374  while(1) {
375  StateSet qrm1;
376  sit = qerr1.Begin();
377  sit_end= qerr1.End();
378  for(; sit != sit_end; ++sit) {
379  TransSet::Iterator tit=rIoSystem.TransRelBegin(*sit);
380  TransSet::Iterator tit_end=rIoSystem.TransRelEnd(*sit);
381  if(tit==tit_end) { qrm1.Insert(*sit); break;}
382  if(!qerr2a.Exists(tit->X2)) { qrm1.Insert(*sit); break;}
383  }
384  qerr1.EraseSet(qrm1);
385  StateSet qrm2;
386  sit = qerr2a.Begin();
387  sit_end= qerr2a.End();
388  for(; sit != sit_end; ++sit) {
389  TransSet::Iterator tit=rIoSystem.TransRelBegin(*sit);
390  TransSet::Iterator tit_end=rIoSystem.TransRelEnd(*sit);
391  if(tit==tit_end) { qrm2.Insert(*sit); break;}
392  if(!qerr1.Exists(tit->X2)) { qrm2.Insert(*sit); break;}
393  }
394  qerr2a.EraseSet(qrm2);
395  if(qrm1.Empty() && qrm2.Empty()) break;
396  }
397  qerr=qerr1 + qerr2;
398  FD_DIO("RemoveIoDummyStates(): Dummy states" << qerr.ToString());
399  sit = qerr.Begin();
400  sit_end= qerr.End();
401  for(; sit != sit_end; ++sit)
402  rIoSystem.DelState(*sit);
403  FD_DIO("RemoveIoDummyStates(): done");
404 }
405 
406 // IoSynthesis(rPlant,rSpec,rSup,rErrorStates)
407 void IoSynthesisNB(const IoSystem& rPlant, const Generator& rSpec, IoSystem& rSup) {
408  FD_DIO("IosSynthesisNB");
409 
410  // synthesis
411  EventSet ualph = rPlant.InputEvents();
412  EventSet yalph = rPlant.OutputEvents();
413  OmegaSupConNB(rPlant,ualph,rSpec,rSup) ;
414 
415  // fix event attributes
416  rSup.InputEvents(yalph);
417  rSup.OutputEvents(ualph);
418 }
419 
420 // IoSynthesis(rPlant,rSpec,rSup,rErrorStates)
421 void IoSynthesis(const IoSystem& rPlant, const Generator& rSpec, IoSystem& rSup) {
422  FD_DIO("IosSynthesis");
423 
424  // synthesis
425  EventSet ualph = rPlant.InputEvents();
426  EventSet yalph = rPlant.OutputEvents();
427  SupConCmplClosed(rPlant,ualph,rSpec,rSup) ;
428 
429  // fix event attributes
430  rSup.InputEvents(yalph);
431  rSup.OutputEvents(ualph);
432 }
433 
434 
435 }// end: namespace faudes

libFAUDES 2.24g --- 2014.09.15 --- c++ api documentaion by doxygen