DiaDes  0.1
DIAgnosis of Discrete-Event System
Simulator.cc
Go to the documentation of this file.
1 
11 #include <diades/utils/Random.hh>
12 #include <diades/utils/Functors.hh>
13 #include <diades/automata/Trace.hh>
14 #include "Simulator.hh"
15 
16 using namespace std;
17 using namespace Diades::Utils;
18 
19 namespace Diades {
20  namespace Automata {
21 
42  void randomSimulateState(const ObservableComponent & component,
43  State source,
44  const set<Event> & noEvents,
45  unsigned obsMin,
46  unsigned obsMax, unsigned depth,
47  list<Event> & simulation) {
48  if (obsMin == 0) {
49  // the simulation has reached the required minimum
50  if (obsMax != 0) {
51  // let now generate the effective number of observable
52  // we want to generate
53  unsigned nbObsLeft = generateRandomValue(0, obsMax);
54  if (nbObsLeft != 0) {
55  randomSimulateState(component, source, noEvents, nbObsLeft, nbObsLeft, depth, simulation);
56  }
57  //else stop
58  }
59  //else stop
60  } else {
61  if (depth > 2 * component.numberOfTransitions()) {
62  throw (FunctionException("randomSimulateState",
63  "simulated twice the number of transitions of the component and still no observable transitions: the simulation is very likely in an unobservable deadend. Give up for the beauty of randomness."));
64  } else {
66  component.outputTransitionEnd(source),
67  fgx(isNotIn(noEvents.begin(), noEvents.end()),
68  GetEvent(component)));
69  if (transIt == component.outputTransitionEnd(source)) {
70  stringstream msg;
71  msg << "Reaching the state " << component.getLabel(source);
72  if (source.outDeg() == 0) {
73  msg << " but it has no output events. Simulation stopped" << std::endl;
74  } else {
75  msg << " but it has only fordidden events as output events, cannot go futher. Simulation stopped"
76  << endl << "Output events of the last state:" << endl;
77 
79  it != component.outputTransitionEnd(source);
80  ++it) {
81  msg << component.getEvent(*it) << std::endl;
82  }
83  }
84  std::cerr << "WARNING: " << msg.str() << std::endl;
85  } else {
86  Transition transition = *transIt;
87  simulation.push_back(component.getEvent(transition));
88  if (component.mask().isObservable(component.getEvent(transition))) {
89  depth = 0;
90  --obsMin;
91  --obsMax;
92  } else {
93  ++depth;
94  }
95  randomSimulateState(component, transition.target(), noEvents, obsMin, obsMax, depth, simulation);
96  }
97  }
98  }
99  }
100 
111  void randomSimulate(const ObservableComponent & component,
112  const set<Event> & noEvents,
113  unsigned obsMin,
114  unsigned obsMax,
115  list<Event> & simulation) {
116  // select randomly an initial state
117  State state = *selectRandomElement(component.numberOfInitialStates(),
118  component.initialStateBegin(),
119  component.initialStateEnd());
120 
121  randomSimulateState(component, state, noEvents, obsMin, obsMax, 0, simulation);
122  }
123 
124  /*************************************************************************************/
125 
138  void reallySimulate(const ObservableComponent & component,
139  const set<Event> & noEvents,
140  unsigned obsMin,
141  unsigned obsMax,
142  list<Event> & simulation) {
143  randomSimulate(component, noEvents, obsMin, obsMax, simulation);
144  }
145 
146 
147  /*************************************************************************************/
148 
158  bool getEvents(const Component & component,
159  const set<string> & labels,
160  set<Event> & events) {
161  set<string> labelsLeft = labels;
162  ObservableComponent::EventIterator eventIt = component.eventBegin();
163  while ((!labelsLeft.empty()) && (eventIt != component.eventEnd())) {
164  set<string>::iterator labelIt = labelsLeft.find(eventIt->label());
165  if (labelIt == labelsLeft.end()) {
166  labelIt = labelsLeft.find(eventIt->nickname());
167  }
168  if (labelIt != labelsLeft.end()) {
169  events.insert(*eventIt);
170  labelsLeft.erase(labelIt);
171  }
172  ++eventIt;
173  }
174 
175  return labelsLeft.empty();
176  }
177 
178 
179  /*************************************************************************************/
180 
192  bool simulate(const ObservableComponent & component,
193  const set<string> & absentEvents,
194  unsigned obsMin,
195  unsigned obsMax,
196  unsigned seed,
197  list<Event> & simulation) {
198  bool result = true;
199  try {
200 
201  set<Event> noEvents;
202  getEvents(component, absentEvents, noEvents);
203 
204 
205  // initialise the random generator
207 
208  // get normal obsMin and obsMax if not initialised
209  if (obsMax < obsMin) {
210  throw (FunctionException("simulate", "Please check obsMin and obsMax, they are inconsistent."));
211  }
212  if (obsMin == 0) {
213  obsMin = 1;
214  }
215  if (obsMax == 0) {
216  obsMax = 100;
217  }
218 
219  //let start the real job
220  reallySimulate(component, noEvents, obsMin, obsMax, simulation);
221  } catch (exception & e) {
222  log<LgProcess>("The function 'simulate' caught the exception: \n\t%1%") % e.what();
223  result = false;
224  }
225  return result;
226  }
227 
228 
229  /****************************************************************************************/
230 
253  const ObservableMask & mask,
254  State source,
255  const set<Event> & noEvents,
256  unsigned obsMin,
257  unsigned obsMax, unsigned depth,
258  list<Event> & simulation) {
259  if (obsMin == 0) {
260  // the simulation has reached the required minimum
261  if (obsMax != 0) {
262  // let now generate the effective number of observable
263  // we want to generate
264  unsigned nbObsLeft = generateRandomValue(0, obsMax);
265  if (nbObsLeft != 0) {
266  randomSimulateState(composable, mask, source, noEvents, nbObsLeft, nbObsLeft, depth, simulation);
267  }
268  //else stop
269  }
270  //else stop
271  } else {
272  if (depth > 200) {
273  throw (FunctionException("randomSimulateState",
274  "simulated 200 transitions of the model and still no observable transitions: the simulation is very likely in an unobservable deadend. Give up for the beauty of randomness."));
275  } else {
277  composable.outputTransitionEnd(source),
278  fgx(isNotIn(noEvents.begin(), noEvents.end()),
279  GetEvent(composable.component())));
280  if (transIt == composable.outputTransitionEnd(source)) {
281  stringstream msg;
282  msg << "Reaching the state " << composable.component().getLabel(source);
283 
284  if (source.outDeg() == 0) {
285  msg << " but it has no output events. Simulation stopped" << std::endl;
286  } else {
287  msg << " but it has only fordidden events as output events, cannot go futher. Simulation stopped"
288  << endl << "Output events of the last state:" << endl;
289 
291  it != composable.component().outputTransitionEnd(source);
292  ++it) {
293  msg << composable.component().getEvent(*it) << std::endl;
294  }
295  }
296  std::cerr << "WARNING: " << msg.str() << std::endl;
297  } else {
298  Transition transition = *transIt;
299  simulation.push_back(composable.component().getEvent(transition));
300  if (mask.isObservable(composable.component().getEvent(transition)))
301  {
302  depth = 0;
303  --obsMin;
304  --obsMax;
305  }
306  else {
307  ++depth;
308  }
309  randomSimulateState(composable, mask, transition.target(), noEvents, obsMin, obsMax, depth, simulation);
310  }
311  }
312  }
313  }
314 
315 
316  /****************************************************************************************/
317 
329  void randomSimulate(ComposableModel & composable,
330  const ObservableMask & mask,
331  const set<Event> & noEvents,
332  unsigned obsMin,
333  unsigned obsMax,
334  list<Event> & simulation) {
335  // select randomly an initial state
336  State state = *selectRandomElement(composable.numberOfInitialStates(),
337  composable.beginOfInitialStates(),
338  composable.endOfInitialStates());
339 
340  randomSimulateState(composable, mask, state, noEvents, obsMin, obsMax, 0, simulation);
341 
342  }
343 
344  /****************************************************************************************/
345 
359  void reallySimulate(ComposableModel & composable,
360  const ObservableMask & mask,
361  const set<Event> & noEvents,
362  unsigned obsMin,
363  unsigned obsMax,
364  list<Event> & simulation) {
365  randomSimulate(composable, mask, noEvents, obsMin, obsMax, simulation);
366  }
367 
368  /****************************************************************************************/
369 
382  bool simulate(ComposableModel & composable,
383  const ObservableMask & mask,
384  const set<string> & absentEvents,
385  unsigned obsMin,
386  unsigned obsMax,
387  unsigned seed,
388  list<Event> & simulation) {
389  bool result = true;
390  try {
391 
392  set<Event> noEvents;
393  getEvents(composable.component(), absentEvents, noEvents);
394 
395 
396  // initialise the random generator
398 
399  // get normal obsMin and obsMax if not initialised
400  if (obsMax < obsMin) {
401  throw (FunctionException("simulate", "Please check obsMin and obsMax, they are inconsistent."));
402  }
403  if (obsMin == 0) {
404  obsMin = 1;
405  }
406  if (obsMax == 0) {
407  obsMax = 100;
408  }
409 
410  //let start the real job
411  reallySimulate(composable, mask, noEvents, obsMin, obsMax, simulation);
412  } catch (exception & e) {
413  log<LgProcess>("The function 'simulate' caught the exception: \n\t%1%") % e.what();
414  result = false;
415  }
416  return result;
417  }
418 
419  void printStop(unsigned index)
420  {
421  cout << endl << "\t[" << index << "]- Stop" << endl;
422  }
423 
424  template<typename StateIterator>
425  void generateStateList(const Component & component,
426  StateIterator first,
427  StateIterator last)
428  {
429  unsigned index = 1;
430  while(first != last)
431  {
432  cout << "\t[" << index << "]- " << component.getLabel(*first) << endl;
433  ++first;
434  ++index;
435  }
436  printStop(index);
437  }
438 
439 
440 
441 
442  template<typename StateIterator>
443  State getStateOfIndex(const Component & component,
444  StateIterator first,
445  StateIterator last,
446  unsigned index)
447  {
448  unsigned current = 1;
449  while(current != index)
450  {
451  ++first; ++ current;
452  }
453  return *first;
454  }
455 
456 
457 
458 
459 
460  bool readResponse(istream & in, unsigned & index,
461  unsigned maxValue,
462  bool & stop)
463  {
464  in >> index;
465  if(index < 1 || index > (maxValue+1))
466  {
467  return false;
468  }
469  stop = (index== maxValue+1);
470  return true;
471  }
472 
473 
474 
475  bool initialStateSelection(const Component & component,
476  State & result)
477  {
478  bool stop = false;
479  if(component.numberOfInitialStates()==0)
480  {
481  return true;
482  }
483  if(component.numberOfInitialStates()==1)
484  {
485  result = *component.initialStateBegin();
486  cout << "Initial state: "
487  << component.getLabel(result)
488  << endl;
489  }
490  else
491  {
492  generateStateList(component,component.initialStateBegin(),component.initialStateEnd());
493  unsigned index = 0;
494  while(!readResponse(cin,index,component.numberOfInitialStates(),stop)) {}
495  if(!stop)
496  {
497  result = getStateOfIndex(component,component.initialStateBegin(),
498  component.initialStateEnd(),
499  index);
500  }
501  }
502  return !stop;
503  }
504 
505 
507  State & result)
508  {
509  return initialStateSelection(model.component(),result);
510  }
511 
512 
513 
514 
515 
516 
517 
518  template<typename TransitionIterator>
519  void generateTransitionList(const Component & component, const ObservableMask & mask,
520  TransitionIterator first,
521  TransitionIterator last)
522  {
523  cout << "Current State: " << component.getLabel(first->source()) << endl;
524  cout << endl;
525  unsigned index = 1;
526  while(first!=last)
527  {
528  cout << "\t[" << index << "]- "
529  << component.getLabel(first->source())
530  << " -> "
531  << component.getLabel(first->target())
532  << " ["
533  << component.getEvent(*first) << ":"
534  << toStream(mask.observableBegin(component.getEvent(*first)),
535  mask.observableEnd(component.getEvent(*first))) << "]"
536  << endl;
537  ++first;
538  ++index;
539  }
540  printStop(index);
541 
542  }
543 
544 
545  template<typename TransitionIterator>
547  TransitionIterator first,
548  TransitionIterator last,unsigned index)
549  {
550  unsigned current = 1;
551  while(current != index)
552  {
553  ++first; ++ current;
554  }
555  return *first;
556  }
557 
558 
569  State & current,
570  list<Event> & simulation)
571  {
572  bool stop = false;
573  if(current.outDeg()==0)
574  {
575  log<LgProcess>("The current state is a deadlock. STOP.");
576  return true;
577  }
578  generateTransitionList(component,component.mask(),
579  component.outputTransitionBegin(current),
580  component.outputTransitionEnd(current));
581  unsigned index = 0;
582  while(!readResponse(cin,index,current.outDeg(),stop)) {}
583  if(!stop)
584  {
585  Transition selection = getTransitionOfIndex(component,component.outputTransitionBegin(current),
586  component.outputTransitionEnd(current),
587  index);
588  simulation.push_back(component.getEvent(selection));
589  cout << "run : " << component.getLabel(current) << " -> "
590  << component.getLabel(selection.target()) << " ["
591  << component.getEvent(selection) << ":"
592  << toStream(component.mask().observableBegin(component.getEvent(selection)),
593  component.mask().observableEnd(component.getEvent(selection))) << "]" << endl;
594  current = selection.target();
595  }
596  return !stop;
597 
598  }
599 
610  const ObservableMask & mask,
611  State & current,
612  list<Event> & simulation)
613  {
614  bool stop = false;
615  unsigned outDeg = 0;
616  // computation of the output transitions if
617  // they are not computed yet
618  for(auto it = model.outputTransitionBegin(current);
619  it != model.outputTransitionEnd(current);
620  ++it)
621  {
622  ++outDeg;
623  }
624 
625  if(outDeg==0)
626  {
627  log<LgProcess>("The current state is a deadlock. STOP.");
628  return true;
629  }
630  const Component & component = model.component();
631  generateTransitionList(component,mask,component.outputTransitionBegin(current),
632  component.outputTransitionEnd(current));
633  unsigned index = 0;
634  while(!readResponse(cin,index,current.outDeg(),stop)) {}
635  if(!stop)
636  {
637  Transition selection = getTransitionOfIndex(component,component.outputTransitionBegin(current),
638  component.outputTransitionEnd(current),
639  index);
640  simulation.push_back(component.getEvent(selection));
641  cout << "run : " << component.getLabel(current) << " -> "
642  << component.getLabel(selection.target()) << " ["
643  << component.getEvent(selection) << ":"
644  << toStream(mask.observableBegin(component.getEvent(selection)),
645  mask.observableEnd(component.getEvent(selection))) << "]" << endl;
646  current = selection.target();
647  }
648  return !stop;
649 
650  }
651 
652 
660  list<Event> & simulation)
661  {
662  State current;
663  if(!initialStateSelection(component,current))
664  {
665  log<LgProcess>("The interactive simulation has been aborted by the user.");
666  return false;
667  }
668  if(!current.valid())
669  {
670  log<LgProcess>("The interactive simulation has failed as there is no valid initial state.");
671  return false;
672  }
673  while(interactiveSimulation(component,current,simulation)){}
674  return true;
675  }
676 
677 
686  const ObservableMask & mask,
687  list<Event> & simulation)
688  {
689  State current;
690  if(!initialStateSelection(composable,current))
691  {
692  log<LgProcess>("The interactive simulation has been aborted by the user.");
693  return false;
694  }
695  if(!current.valid())
696  {
697  log<LgProcess>("The interactive simulation has failed as there is no valid initial state.");
698  return false;
699  }
700  while(interactiveSimulation(composable,mask,current,simulation)){}
701  return true;
702  }
703 
704  };
705 };
706 
void randomSimulateState(ComposableModel &composable, const ObservableMask &mask, State source, const set< Event > &noEvents, unsigned obsMin, unsigned obsMax, unsigned depth, list< Event > &simulation)
Definition: Simulator.cc:252
Diades::Graph::Edge Transition
Definition: Component.hh:46
void printStop(unsigned index)
Definition: Simulator.cc:419
bool initialStateSelection(ComposableModel &model, State &result)
Definition: Simulator.cc:506
bool interactiveSimulation(ComposableModel &composable, const ObservableMask &mask, list< Event > &simulation)
Definition: Simulator.cc:685
CompositionFunctorFGx< F, G > fgx(const F &f, const G &g)
Definition: Functors.hh:373
STL namespace.
bool readResponse(istream &in, unsigned &index, unsigned maxValue, bool &stop)
Definition: Simulator.cc:460
void reallySimulate(ComposableModel &composable, const ObservableMask &mask, const set< Event > &noEvents, unsigned obsMin, unsigned obsMax, list< Event > &simulation)
Definition: Simulator.cc:359
const StateLabel & getLabel(State state) const
Definition: Component.hh:521
Component::OutputTransitionIterator OutputTransitionIterator
State getStateOfIndex(const Component &component, StateIterator first, StateIterator last, unsigned index)
Definition: Simulator.cc:443
void initialiseRandomGenerator()
bool simulate(ComposableModel &composable, const ObservableMask &mask, const set< string > &absentEvents, unsigned obsMin, unsigned obsMax, unsigned seed, list< Event > &simulation)
Definition: Simulator.cc:382
IsNotIn< InputIterator > isNotIn(InputIterator first, InputIterator last)
Definition: Functors.hh:226
void randomSimulate(ComposableModel &composable, const ObservableMask &mask, const set< Event > &noEvents, unsigned obsMin, unsigned obsMax, list< Event > &simulation)
Definition: Simulator.cc:329
InitialStateIterator initialStateEnd() const
Definition: Component.hh:648
An observable Component defined as a automaton.
unsigned numberOfInitialStates() const
Definition: Component.hh:659
void generateStateList(const Component &component, StateIterator first, StateIterator last)
Definition: Simulator.cc:425
unsigned numberOfTransitions() const
Definition: Component.hh:958
OutputTransitionIterator outputTransitionEnd(State s) const
bool getEvents(const Component &component, const set< string > &labels, set< Event > &events)
Definition: Simulator.cc:158
InitialStateIterator initialStateBegin() const
Definition: Component.hh:638
Transition getTransitionOfIndex(const Component &component, TransitionIterator first, TransitionIterator last, unsigned index)
Definition: Simulator.cc:546
Random generation utilities.
Diades::Graph::OutEdgeIterator OutputTransitionIterator
Definition: Component.hh:72
Namespace of the Diades project.
ObservableEventIterator observableBegin() const
long generateRandomValue(long lower, long upper)
EventIterator eventBegin() const
Definition: Component.hh:328
Diades::Utils::ToStream< InputIterator, Diades::Utils::AlwaysTrue< typename InputIterator::reference > > toStream(InputIterator first, InputIterator last)
Definition: Verbose.hh:143
OutputTransitionIterator outputTransitionBegin(State s) const
Definition: Component.hh:913
Definition: Run.cc:83
const ObservableMask & mask() const
ObservableEventIterator observableEnd() const
Iterator selectRandomElement(unsigned number, Iterator first, Iterator last)
Definition: Random.hh:68
bool isObservable(const Event &e) const
const Event & getEvent(Transition t) const
Definition: Component.hh:304
const Component & component() const
EventIterator eventEnd() const
Definition: Component.hh:338
set< Event >::const_iterator EventIterator
Definition: Component.hh:73
Diades::Graph::Node State
Definition: BeliefState.hh:36
OutputTransitionIterator outputTransitionBegin(State s) const
InitialStateIterator endOfInitialStates() const
void generateTransitionList(const Component &component, const ObservableMask &mask, TransitionIterator first, TransitionIterator last)
Definition: Simulator.cc:519
OutputTransitionIterator outputTransitionEnd(State s) const
Definition: Component.hh:925
InitialStateIterator beginOfInitialStates() const