DiaDes  0.1
DIAgnosis of Discrete-Event System
DesGenerate.cc
Go to the documentation of this file.
1 
55 #include<iostream>
56 #include<sstream>
57 #include<string>
58 #include<map>
59 #include<list>
60 #include <cmath>
61 #include<diades/utils/Random.hh>
63 #include<diades/utils/Log.hh>
73 //#include<diades/petri/AutomataConversion.hh>
74 #include"CmdInterface.hh"
75 
76 using namespace std;
77 using namespace Diades::Utils;
78 using namespace Diades::Automata;
79 using namespace Diades::CmdInterface;
80 
81 typedef enum {
82  STATEMIN = 0, STATEMAX = 1, OBSMIN = 2, OBSMAX = 3, EVTMIN = 4, EVTMAX = 5, SEED = 6, DIRNAME = 7, LATEXFILENAME = 8,
85 } Option;
86 
87 
88 unsigned numberOfOptions = 16;
89 unsigned numberOfFileExtensions = 0; // no file extension as no file is used as an option in this interface,
90 // files are always the parameter of an option
91 
93 vector<string> options(numberOfOptions);
94 vector<bool> isSet(numberOfOptions, false);
95 
96 
97 string description = "Usage: dd-generate\n\t --help |\n\t [--topo topologyFileName.topo]\n\t [--seed randomSeed]\n\t [--evtMin nbEvtMin]\n\t [--evtMax nbEvtMax]\n\t [--obsMin nbObsMin]\n\t [--obsMax nbObsMax]\n\t [--stateMin nbStateMin]\n\t [--stateMax nbStateMax]\n\t [--latex latexFileName]\n\t [--outputdir dirName]\n\t [--obsInteractionMin nbObsIntMin]\n\t [--obsInteractionMax nbObsIntMax]\n\t [--nodeBehaviour node=file.descomp ci=ej ck=el ...]]\n\t [--outputDegreeMax outDeg]\n\t [--petrinet]\n\n\n Generate a distributed discrete-event system that has the topology\n defined in the file topologyFileName.topo. The generator uses\n a random generator of number that can be initialised with the\n seed 'randomSeed'. If not provided, the seed is the starting time\n of each run of the program. As far as the behaviour of a component\n is concerned, the number of generated states is between nbStateMin\n and nbStateMax. The number of event is between nbEvtMin and nbEvtMax\n as long as it is compatible with the topology. The number of\n observable events is between nbObsMin and nbObsMax. The generated model\n consists of a set of files written in the directory 'dirName'. The\n model generator also generates a document in latex format for documentation\n purposes (if the option is set). The parameters --obsInteractionMin\n and --obsInteractionMax states the possible numbers of observable interactions.\n The --nodeBehaviour parameters states that one (and only one) of the node\n called 'node' has the predefined behaviour described in 'file.descomp'. \nConstraints like 'ci=sj' assert that the component 'node' implements the\n connection 'ci' of the topology with the iteractive event 'sj'.\n The option '--outputDegreeMax' rules the maximal number of transitions\n (i.e. events) that are the output of one state. If the --petrinet option is set, the distributed system is generated as a 1-bounded petri net. ";
98 
100  options[STATEMIN] = "--stateMin";
101  options[STATEMAX] = "--stateMax";
102  options[OBSMIN] = "--obsMin";
103  options[OBSMAX] = "--obsMax";
104  options[EVTMIN] = "--evtMin";
105  options[EVTMAX] = "--evtMax";
106  options[SEED] = "--seed";
107  options[DIRNAME] = "--outputdir";
108  options[LATEXFILENAME] = "--latex";
109  options[TOPOLOGYFILENAME] = "--topo";
110  options[OBSINTERACTIONMIN] = "--obsInteractionMin";
111  options[OBSINTERACTIONMAX] = "--obsInteractionMax";
112  options[NODEBEHAVIOUR] = "--nodeBehaviour";
113  options[HELP] = "--help";
114  options[OUTPUTDEGREEMAX] = "--outputDegreeMax";
115  //options[PETRINET] = "--petrinet";
116 }
117 
118 /************************************************************************************************/
119 
120 unsigned eventNumber = 0;
121 
122 /************************************************************************************************/
123 
127 
128 /************************************************************************************************/
129 
138 void makeComponentComplete(unsigned outputDegreeMax, Selection<Event> & eventSelection, ObservableComponent & result);
139 
140 
141 /************************************************************************************************/
142 
156  State currentInteractingState,
157  const Event & eventCurrentNode,
158  map<Event, Topology::Connection> & mappingCurrentSideToInteraction,
159  map<Topology::Connection, Event> & mappingConnectionToInteraction,
160  const set<Event> & constrainedEvents);
161 
162 /************************************************************************************************/
163 
190 void generateTransitionSystem(const Topology & topology,
191  const Node & node,
192  SharedEventNodeMap & sharedEventOfNode,
193  const ObservableComponent & interaction,
194  set<Node>::const_iterator first,
195  set<Node>::const_iterator last,
196  unsigned numberOfStates,
197  unsigned outputDegreeMax,
198  ObservableComponent & result);
199 
200 
201 /************************************************************************************************/
202 
214 void defineObservableMask(unsigned obsMin, unsigned obsMax, unsigned obsInteractionMin,
215  unsigned obsInteractionMax, const set<Event> & interactiveEvents,
216  const set<Event> & nonInteractiveEvents,
217  ObservableComponent & result);
218 
219 /************************************************************************************************/
220 
233 void generateNonInteractiveEvents(const Topology & topology,
234  Topology::Node node,
235  unsigned evtMin,
236  unsigned evtMax,
237  unsigned obsMin,
238  unsigned obsInteractionMax,
239  ObservableComponent & result,
240  set<Event> & nonInteractiveEvents);
241 
242 /************************************************************************************************/
243 
268 void generateRandomComponent(const Topology & topology, const Node & node,
269  SharedEventNodeMap & sharedEventOfNode,
270  const ObservableComponent & interaction,
271  set<Node>::const_iterator first,
272  set<Node>::const_iterator last,
273  unsigned stateMin,
274  unsigned stateMax,
275  unsigned obsMin,
276  unsigned obsMax,
277  unsigned evtMin,
278  unsigned evtMax,
279  unsigned obsInteractionMin,
280  unsigned obsInteractionMax,
281  unsigned outputDegreeMax,
282  ObservableComponent * result);
283 
284 /************************************************************************************************/
285 
296 void initialiseSynchronisationRules(const Topology & topology,
297  set<Node>::const_iterator first,
298  set<Node>::const_iterator last,
299  SharedEventNodeMap & sharedEventOfNode,
300  const Diades::Graph::ConstNodeMap< pair<string, ObservableComponent *> > & projection,
301  ParametrizedSynchronisation & synchronisation);
302 
303 /************************************************************************************************/
304 
328 ObservableComponent * getSynchronisedInteraction(const Topology & topology, const Node & node,
329  SharedEventNodeMap & sharedEventOfNode,
330  const Diades::Graph::ConstNodeMap< pair<string, ObservableComponent *> > & projection,
331  set<Node>::const_iterator first,
332  set<Node>::const_iterator last);
333 
334 /************************************************************************************************/
335 
349 void getOutputProjection(const Topology & topology,
350  const Node & node,
351  SharedEventNodeMap & sharedEventOfNode,
352  const ObservableComponent & component,
353  const set<Node> & nonGeneratedNeighbours,
354  pair<string, ObservableComponent *> & result);
355 
356 /************************************************************************************************/
357 
369 void propagateConstrainedInteractions(const Topology & topology,
370  Topology::Node node,
371  Diades::Graph::ConstNodeMap<int> & visitedNodes,
372  set<Topology::Node> & generatedNeighbours,
373  set<Topology::Node> & nonGeneratedNeighbours,
374  list<Topology::Node> & nodesToVisit);
375 
376 /************************************************************************************************/
377 
378 
385 void writeComponent(const ObservableComponent & component,
386  const string & dirName);
387 
388 
389 /************************************************************************************************/
390 
391 
392 bool checkEventConsistency(const Topology & topology, unsigned evtMax, unsigned obsInteractionMin);
393 
394 /************************************************************************************************/
395 
396 
397 
398 //template<typename T>
399 //void getParameter(int argc, char ** argv, int index, T & param, bool & alreadyRegistered);
400 void generateSharedEvents(const Topology & topology,
401  ComponentNodeMap & componentOfNode,
402  SharedEventNodeMap & sharedEventOfNode,
403  Topology::Node fixedTopoNode);
404 void generateBehaviour(const Topology & topology,
405  unsigned stateMin,
406  unsigned stateMax,
407  unsigned evtMin,
408  unsigned evtMax,
409  unsigned obsMin,
410  unsigned obsMax,
411  unsigned obsInteractionMin,
412  unsigned obsInteractionMax,
413  ComponentNodeMap & componentOfNode,
414  SharedEventNodeMap & sharedEventOfNode,
415  string dirName, Node fixedTopoNode,
416  unsigned outputDegreeMax);
417 void generateLatexComponents(const Topology & topology, SharedEventNodeMap & sharedEventOfNode, const ComponentNodeMap & componentOfNode, ofstream & latexfile);
418 void generateLatexEventIndex(const Topology & topology, SharedEventNodeMap & sharedEventOfNode, const ComponentNodeMap & componentOfNode, ofstream & latexfile);
419 void generateLatexEpilog(ofstream & latexfile);
420 void generateLatexTopology(const Topology & topology, SharedEventNodeMap & sharedEventOfNode, ofstream & latexfile);
421 void generateLatexPreamble(const Topology & topology,
422  unsigned stateMin,
423  unsigned stateMax,
424  unsigned evtMin,
425  unsigned evtMax,
426  unsigned obsMin,
427  unsigned obsMax,
428  unsigned obsInteractionMin,
429  unsigned obsInteractionMax,
430  unsigned seed,
431  unsigned outputDegreeMax,
432  const string & fixedNode,
433  const string & behaviourFileName,
434  map<string, string> & assignedConnections,
435  const ComponentNodeMap & componentOfNode,
436  SharedEventNodeMap & sharedEventOfNode,
437  const string & filename,
438  ofstream & latexfile);
439 void generateLatexFile(const Topology & topology,
440  unsigned stateMin,
441  unsigned stateMax,
442  unsigned evtMin,
443  unsigned evtMax,
444  unsigned obsMin,
445  unsigned obsMax,
446  unsigned obsInteractionMin,
447  unsigned obsInteractionMax,
448  unsigned seed,
449  unsigned outputDegreeMax,
450  const string & fixedNode,
451  const string & behaviourFileName,
452  map<string, string> & assignedConnections,
453  const ComponentNodeMap & componentOfNode,
454  SharedEventNodeMap & sharedEventOfNode,
455  const string & filename);
456 
457 void exportTopologyMap(const Topology & topology,
458  SharedEventNodeMap & sharedEventOfNode,
459  const ComponentNodeMap & componentOfNode,
460  const string & mapTopoFileNameDest);
461 
462 void generateStates(ObservableComponent & result, unsigned numberOfStates,
463  vector<Node> & indexState);
464 
465 void generateTriggerableEvents(unsigned numberOfUnusedEventPerState,
466  unsigned numberOfTrans,
469  unsigned nbEvents,
470  //const set<Event> & constrainedEvents,
471  set<Event> & newSelection,
472  set<Event> & unusedEvents);
473 
474 // result is almost generated. The problem is that some transitions
475 // of interaction may not have their correpsondance in result yet
476 // (triggeredTransition[t] = 0)
477 // so we complete the model to have full correspondance by adding some
478 // transitions in the result
480  const Node & node,
481  SharedEventNodeMap & sharedEventOfNode,
482  const ObservableComponent & interaction,
483  map<Event, Topology::Connection> & mappingInteractionToCurrentSide,
484  map<Event, Topology::Connection> & mappingCurrentSideToInteraction,
485  EdgeMap<int> & triggeredTransition,
486  NodeMap< set<State> > & stateMapping,
487  unsigned outputDegreeMax,
488  Selection<Event> & eventSelection);
489 
490 // Here we just inserted the fact that the state 'state' has a new corresponding
491 // state 'correspondingState' in the interaction model.
492 // This new information must be propagated to the successors of 'state'
493 void propagateInteractingStates(ObservableComponent & result, const Node & node,
494  SharedEventNodeMap & sharedEventOfNode,
495  map<Event, Topology::Connection> & mappingInteractionToCurrentSide,
496  const ObservableComponent & interaction,
497  State state,
498  State correspondingState,
499  NodeMap< set<State> > & stateMapping);
500 
501 /************************************************************************************************/
503 /************************************************************************************************/
504 
505 void printDebugStartVisit(const Topology & topology, Topology::Node node);
506 void printDebugProjectionOnGeneratedNeighbours(const set<Topology::Node> & generatedNeighbours,
507  const Diades::Graph::NodeMap< pair<string, ObservableComponent *> > & projection);
508 void printDebugLaw(const ParametrizedSynchronisation & synchronisation);
509 
510 /************************************************************************************************/
511 
524 int main(int argc, char ** argv) {
528  cout << "Discrete-event system generator" << endl;
529  cout << "LAAS-CNRS, 2006-2017, 7 avenue du Colonel Roche, Toulouse, France" << endl;
530  cout << "Contact: yannick.pencole@laas.fr" << endl;
531  unsigned stateMin = 3;
532  unsigned stateMax = 10;
533  unsigned obsMin = 0;
534  unsigned obsMax = 3;
535  unsigned evtMin = 1;
536  unsigned evtMax = 3;
537  unsigned seed = initialiseSeed();
538  string dirName = "model_generator_directory";
539  string latexFileName = "generated_model_report.tex";
540  string topologyFileName = "";
541  unsigned obsInteractionMin = 0;
542  unsigned obsInteractionMax = 3;
543  unsigned outputDegreeMax = evtMax;
544  string behaviourFileName = "";
545  bool petrinet = false;
546  map<string, string> assignedConnections;
547  string fixedNode = "";
548  if (argc < 2) {
550  }
551 
552  int index = 1;
553  while (index < argc) {
554  Option currentOption;
555  if (getOption<Option>(argv[index], options, currentOption)) {
556  if (isSet[currentOption]) {
557  printCommandLineError("The option '" + options[currentOption] + "' occurs at least twice.");
558  } else {
559  isSet[currentOption] = true;
560  }
561  switch (currentOption) {
562  case HELP:
563  {
564  if ((index != 1) || (argc != 2)) {
565  printCommandLineError("Incorrect use of option --help.");
566  } else {
568  return 0;
569  }
570  break;
571  }
572  case STATEMIN:
573  {
574  ++index;
575  getParameter<unsigned>(argc, argv, index, stateMin);
576  log<LgDebug>("stateMin = %1%") % stateMin;
577  if (stateMin == 0) {
578  printCommandLineError("'stateMin' must be greater than 0");
579  }
580  break;
581  }
582  case STATEMAX:
583  {
584  ++index;
585  getParameter<unsigned>(argc, argv, index, stateMax);
586  log<LgDebug>("stateMax = %1%") % stateMax;
587  if (stateMax == 0) {
588  printCommandLineError("'stateMax' must be greater than 0");
589  }
590  }
591  break;
592  case EVTMIN:
593  {
594  ++index;
595  getParameter<unsigned>(argc, argv, index, evtMin);
596  log<LgDebug>("evtMin = %1%") % evtMin;
597  if (evtMin == 0) {
598  printCommandLineError("'evtMin' must be greater than 0.");
599  }
600  break;
601  }
602  case EVTMAX:
603  {
604  ++index;
605  getParameter<unsigned>(argc, argv, index, evtMax);
606  log<LgDebug>("evtMax = %1%") % evtMax;
607  if (evtMax == 0) {
608  printCommandLineError("'evtMax' must be greater than 0.");
609  }
610  break;
611  }
612  case OBSMIN:
613  {
614  ++index;
615  getParameter<unsigned>(argc, argv, index, obsMin);
616  log<LgDebug>("obsMin = %1%") % obsMin;
617  break;
618  }
619  case OBSMAX:
620  {
621  ++index;
622  getParameter<unsigned>(argc, argv, index, obsMax);
623  log<LgDebug>("obsMax = %1%") % obsMax;
624  break;
625  }
626 
627  case SEED:
628  {
629  ++index;
630  getParameter<unsigned>(argc, argv, index, seed);
631  log<LgDebug>("seed = %1%") % seed;
632  break;
633  }
634  case DIRNAME:
635  {
636  ++index;
637  getParameter<string>(argc, argv, index, dirName);
638  log<LgDebug>("dirName = %1%") % dirName;
639  break;
640  }
641  case LATEXFILENAME:
642  {
643  ++index;
644  getParameter<string>(argc, argv, index, latexFileName);
645  log<LgDebug>("latexFileName = %1%") % latexFileName;
646  break;
647  }
648  case TOPOLOGYFILENAME:
649  {
650  ++index;
651  getParameter<string>(argc, argv, index, topologyFileName);
652  log<LgDebug>("TololgyFileName = %1%") % topologyFileName;
653  break;
654  }
655  case OBSINTERACTIONMIN:
656  {
657  ++index;
658  getParameter<unsigned>(argc, argv, index, obsInteractionMin);
659  log<LgDebug>(" obsInteractionMin = %1%") % obsInteractionMin;
660  break;
661  }
662  case OBSINTERACTIONMAX:
663  {
664  ++index;
665  getParameter<unsigned>(argc, argv, index, obsInteractionMax);
666  log<LgDebug>(" obsInteractionMax = %1%") % obsInteractionMax;
667  break;
668  }
669  case NODEBEHAVIOUR:
670  {
671  ++index;
672  set<string> parameters;
673  getParameterList<string>(argc, argv, options, fileExtensions, index, parameters);
674  if (parameters.empty()) {
675  printCommandLineError("--nodeBehaviour expects at least one parameter. Check the command line, merci.");
676  }
677  for (set<string>::const_iterator it = parameters.begin();
678  it != parameters.end();
679  ++it) {
680  string::size_type idx = it->find('=');
681  if (idx == string::npos) {
682  printCommandLineError("Expecting --nodeBehaviour node=file.des_comp ci=sj, ck=sl..., check your command line. Merci.");
683  } else {
684  assignedConnections[it->substr(0, idx)] = it->substr(idx + 1);
685  log<LgDebug>(" node behaviour = <%1%,%2%>\n")
686  % it->substr(0, idx)
687  % it->substr(idx + 1);
688  }
689  }
690  break;
691  }
692  case OUTPUTDEGREEMAX:
693  {
694  ++index;
695  getParameter<unsigned>(argc, argv, index, outputDegreeMax);
696  log<LgDebug>(" outputDegreeMax = %1%") % outputDegreeMax;
697  break;
698  }
699  case PETRINET:
700  {
701  petrinet = true;
702  ++index;
703  log<LgDebug>(" petrinet = %1%") % petrinet;
704  break;
705  }
706  default:
707  {
709  break;
710  }
711  }
712  } else {
713  string msg = "Unrecognized option: ";
714  msg += argv[index];
716  }
717  }
718 
719 
720 
721 
722  // Some consistency tests
723  Topology topology;
724  if (isSet[TOPOLOGYFILENAME]) {
725  cout << "Loading the topology in file " << topologyFileName << flush;
726  try {
727  topology.import(topologyFileName);
728  } catch (exception & e) {
729  cerr << endl << "The following exception has been caught:" << endl << ">>> " << e.what() << "<<< " << endl;
730  cerr << "The generation is aborted." << endl;
731  exit(EXIT_FAILURE);
732  }
733  cout << "Done" << endl;
734  } else {
735  topology.addNode();
736  obsInteractionMax = 0;
737  obsInteractionMin = 0;
738  }
739  Topology::Node fixedTopoNode;
740  if (isSet[NODEBEHAVIOUR] && !isSet[TOPOLOGYFILENAME]) {
741  printCommandLineError("You attempt to generate a model containing one node but you already fixed this node, so no generation is required.");
742  }
743  map<Topology::Connection, string> assignedTopoConnections;
744  if (isSet[NODEBEHAVIOUR]) {
745  set<string> topoElements;
746  set<Topology::Node> topoNodes;
747  set<Topology::Connection> topoConnections;
748 
749  for (const std::pair<string, string> & p : assignedConnections) {
750  if (topoElements.find(p.first) != topoElements.end()) {
751  string msg = "The same connection/node '";
752  msg += p.first;
753  msg += "' appears more than once in the command line. Check the command line, merci.";
755  }
756  topoElements.insert(p.first);
757  }
758  Topology::NodeIterator it = topology.nodeBegin();
759  while (it != topology.nodeEnd()) {
760  if (topoElements.find(topology.getNodeName(*it).str()) != topoElements.end()) {
761  topoNodes.insert(*it);
762  topoElements.erase(topology.getNodeName(*it).str());
763  }
764  ++it;
765  }
766  if (topoNodes.size() == 0) {
767  string msg = "Impossible to find in the given topology a node that corresponds to any of the following names: { ";
768  for (const string & e : topoElements) {
769  msg += e;
770  msg += " ";
771  }
772  msg += "}";
774  }
775  if (topoNodes.size() > 1) {
776  string msg = "Found more than one corresponding node in the given topology: { ";
777  for (set<Topology::Node>::const_iterator nodeIt = topoNodes.begin();
778  nodeIt != topoNodes.end();
779  ++nodeIt) {
780  msg += topology.getNodeName(*it).str();
781  msg += " ";
782  }
783  msg += "}. Check the command line, merci.";
785  }
786  fixedTopoNode = *topoNodes.begin();
787  fixedNode = topology.getNodeName(fixedTopoNode).str();
788  behaviourFileName = assignedConnections[ topology.getNodeName(fixedTopoNode).str()];
789  log<LgDebug>(" found topology node = %1% assigned to model in file %2%.\n")
790  % topology.getNodeName(fixedTopoNode)
791  % behaviourFileName;
792  assignedConnections.erase(topology.getNodeName(fixedTopoNode).str());
794  while (it2 != topology.connectionEnd()) {
795  if (topoElements.find(topology.getConnectionLabel(*it2).str()) != topoElements.end()) {
796  assignedTopoConnections[*it2] = assignedConnections[topology.getConnectionLabel(*it2).str()];
797  topoElements.erase(topology.getConnectionLabel(*it2).str());
798  }
799  ++it2;
800  }
801  if (!topoElements.empty()) {
802  string msg = "Unrecognized connection/nodes: {";
803  for (const string & s : topoElements) {
804  msg += s;
805  msg += " ";
806  }
807  msg += "}. Check the command line. Merci.";
809  }
810  set<Topology::Connection> wrongConnections;
811  for (const Topology::Connection & connection : topoConnections) {
812  Topology::CliqueIterator nodeIt = topology.cliqueBegin(connection);
813  bool foundNode = false;
814  while (!foundNode && (nodeIt != topology.cliqueEnd(connection))) {
815  foundNode = (*nodeIt) == fixedTopoNode;
816  ++it;
817  }
818  if (!foundNode) {
819  wrongConnections.insert(connection);
820  }
821  }
822  if (!wrongConnections.empty()) {
823  string msg = "The following connections are not connected to the node '";
824  msg += topology.getNodeName(fixedTopoNode).str();
825  msg += "': {";
826  for (const Topology::Connection & connection : wrongConnections) {
827  msg += topology.getConnectionLabel(connection).str();
828  }
830  }
831  }
832 
833  if (stateMin > stateMax) {
834  printCommandLineError("stateMax should be at least equal to stateMin");
835  }
836  if (evtMin > evtMax) {
837  printCommandLineError("evtMax should be at least equal to evtMin");
838  }
839  if (obsMin > obsMax) {
840  printCommandLineError("obsMax should be at least equal to obsMin");
841  }
842  if (obsMin > evtMax) {
843  printCommandLineError("obsMin should be at at most equal to evtMax");
844  }
845  if (obsMax > evtMax) {
846  printCommandLineError("obsMax should be less than evtMax");
847  }
848  if (obsInteractionMax > obsMax) {
849  printCommandLineError("obsInteractionMax should be at most less or equal to obsMax");
850  }
851  if (obsInteractionMin > obsMin) {
852  printCommandLineError("obsInteractionMin should be at most less or equal to obsMin");
853  }
854  if (obsInteractionMin > obsInteractionMax) {
855  printCommandLineError("obsInteractionMin should be at most less or equal to obsInteractionMax");
856  }
857  if ((isSet[OUTPUTDEGREEMAX]) && (stateMax * outputDegreeMax < evtMin)) {
858  stringstream stream;
859  stream << "evtMin (" << evtMin
860  << ") is too important as the maximal number of events that are possible is stateMax * outputDegreeMax ("
861  << stateMax * outputDegreeMax << ").";
862  printCommandLineError(stream.str());
863 
864  }
865 
866  if (!checkEventConsistency(topology, evtMax, obsInteractionMin)) {
867  printCommandLineError("evtMax or obsInteractionMin are incompatible with the given topology");
868  }
869  verbose<VbOutput>("Initialisation of the random generator with the seed %1%.\n") % seed;
871  ComponentNodeMap componentOfNode(topology.graph());
872  SharedEventNodeMap sharedEventOfNode(topology.graph());
873 
874  if (isSet[NODEBEHAVIOUR]) {
875  map<Event, Event> translation;
876  try {
877  componentOfNode[fixedTopoNode] = new ObservableComponent();
878  componentOfNode[fixedTopoNode]->import(behaviourFileName);
879  componentOfNode[fixedTopoNode]->setId(fixedTopoNode.id());
880  componentOfNode[fixedTopoNode]->setName(topology.getNodeName(fixedTopoNode).str());
881  // need also to change the absolute name of the events
882  list<Event> oldEvents;
883  oldEvents.insert(oldEvents.end(), componentOfNode[fixedTopoNode]->eventBegin(),
884  componentOfNode[fixedTopoNode]->eventEnd());
885  // need to change the mask as well !!
886  ObservableMask obsCopy(componentOfNode[fixedTopoNode]->mask());
887  ObservableMask newMask;
888  while (!oldEvents.empty()) {
889  Event current = oldEvents.front();
890  oldEvents.pop_front();
891  Event newEvent = EventFactory::factory()->getEvent(componentOfNode[fixedTopoNode]->name() + "." + current.nickname());
892  newEvent.setNickname(current.nickname());
893  componentOfNode[fixedTopoNode]->replaceEvent(current, newEvent);
894  translation[newEvent] = current;
895  if (obsCopy.isIdentifiable(current)) {
896  newMask.addMask(newEvent, newEvent);
897  } else {
898  newMask.addMask(newEvent, newEvent);
899  }
900  }
901  componentOfNode[fixedTopoNode]->setMask(newMask);
902  } catch (exception & e) {
903  string msg = "des_generate caught the following exception when attempting to load the model file"
904  + behaviourFileName + ":\n" + e.what();
906  }
907 
908  set<Event> usedEvents;
909  for (const pair<Topology::Connection, string> & p : assignedTopoConnections) {
910 
911  bool foundEvent = false;
912  ObservableComponent::EventIterator eventIt = componentOfNode[fixedTopoNode]->eventBegin();
913  while ((!foundEvent) && (eventIt != componentOfNode[fixedTopoNode]->eventEnd())) {
914  foundEvent = (translation[*eventIt].label() == p.second) || (eventIt->nickname() == p.second);
915  if (!foundEvent) {
916  ++eventIt;
917  }
918  }
919  if (!foundEvent) {
920  string msg = "The event ";
921  msg += p.second;
922  msg += " is not contained in the model ";
923  msg += behaviourFileName;
925  }
926  if (foundEvent && (usedEvents.find(*eventIt) != usedEvents.end())) {
927  string msg = "The event ";
928  msg += p.second;
929  msg += " cannot implement two different connections.";
931  }
932  bool foundNode = false;
933  Topology::CliqueIterator cliqueIt = topology.cliqueBegin(p.first);
934  while (!foundNode && (cliqueIt != topology.cliqueEnd(p.first))) {
935  foundNode = fixedTopoNode == *cliqueIt;
936  ++cliqueIt;
937  }
938  if (!foundNode) {
939 
940  string msg = "The connection ";
941  msg += topology.getConnectionLabel(p.first).str();
942  msg += " does not involve the component ";
943  msg += topology.getNodeName(fixedTopoNode).str();
944  msg += ".";
946  }
947 
948 
949 
950  usedEvents.insert(*eventIt);
951  always_assertion(FunctionException, eventIt->isValid(),
952  "Main: invalid event in sharedEventOfNode");
953  sharedEventOfNode[fixedTopoNode][p.first] = *eventIt;
954  }
955  // let assigned the pending connections with other events
956 
957  unsigned numberOfPendingConnections = topology.connectivity(fixedTopoNode) - assignedTopoConnections.size();
958 
959  if (numberOfPendingConnections > 0) {
960  vector<Event> unusedEvents;
961  for (ObservableComponent::EventIterator eventIt = componentOfNode[fixedTopoNode]->eventBegin();
962  eventIt != componentOfNode[fixedTopoNode]->eventEnd();
963  ++eventIt) {
964  if (usedEvents.find(*eventIt) == usedEvents.end()) {
965  unusedEvents.push_back(*eventIt);
966  }
967  }
968 
969  set<unsigned> selectedIndexes;
970  selectNValues(0, unusedEvents.size() - 1, numberOfPendingConnections, selectedIndexes);
971 
972 
973  for (Topology::NodeConnectionIterator connIt = topology.nodeConnectionBegin(fixedTopoNode);
974  connIt != topology.nodeConnectionEnd(fixedTopoNode);
975  ++connIt) {
976 
977  if (!sharedEventOfNode[fixedTopoNode][*connIt].isValid()) {
978  if (selectedIndexes.empty()) {
979  throw (FunctionException("main", "BUG in the selection of shared events for the fixed node."));
980  }
981 
982  always_assertion(FunctionException, unusedEvents[*selectedIndexes.begin()].isValid(),
983  "Main: invalid event in sharedEventOfNode");
984  sharedEventOfNode[fixedTopoNode][*connIt] = unusedEvents[*selectedIndexes.begin()];
985  selectedIndexes.erase(selectedIndexes.begin());
986  }
987  }
988  }
989  }
990 
991 
992 
993 
994 
995 
996  // prepare the outputs
997  stringstream stream;
998  string param = "mkdir -p " + dirName;
999  system(param.c_str());
1000  string topoFileNameDest = dirName + "/" + "topology.topo";
1001  topology.save(topoFileNameDest);
1002 
1003 
1004  for (Topology::NodeIterator nodeIt = topology.nodeBegin();
1005  nodeIt != topology.nodeEnd();
1006  ++nodeIt) {
1007  if (!isSet[NODEBEHAVIOUR] || (*nodeIt != fixedTopoNode)) {
1008  componentOfNode[*nodeIt] = new ObservableComponent();
1009  componentOfNode[*nodeIt]->setId(nodeIt->id());
1010  componentOfNode[*nodeIt]->setName(topology.getNodeName(*nodeIt).str());
1011  }
1012  }
1013  // generation of the shared events consistent with the topology
1014  generateSharedEvents(topology, componentOfNode, sharedEventOfNode, fixedTopoNode);
1015 
1016 
1017  // write the synchronisation rules
1018  string rulesFileNameDest = dirName + "/" + "sync.rules";
1019  ofstream file(rulesFileNameDest.c_str());
1020  file << "components: ";
1021  for (Topology::NodeIterator nodeIt = topology.nodeBegin();
1022  nodeIt != topology.nodeEnd();
1023  ++nodeIt) {
1024  file << topology.getNodeName(*nodeIt);
1025  Topology::NodeIterator nextNodeIt = nodeIt;
1026  ++nextNodeIt;
1027  if (nextNodeIt == topology.nodeEnd()) {
1028  file << ";" << endl;
1029  } else {
1030  file << ", ";
1031  }
1032  }
1033  file << "rules:" << endl;
1034  for (Topology::ConnectionIterator connIt = topology.connectionBegin();
1035  connIt != topology.connectionEnd();
1036  ++connIt) {
1037  file << "<";
1038  for (Topology::CliqueIterator cliqueIt = topology.cliqueBegin(*connIt);
1039  cliqueIt != topology.cliqueEnd(*connIt);
1040  ++cliqueIt) {
1041  file << sharedEventOfNode[*cliqueIt][*connIt];
1042  Topology::CliqueIterator nextCliqueIt = cliqueIt;
1043  ++nextCliqueIt;
1044  if (nextCliqueIt == topology.cliqueEnd(*connIt)) {
1045  file << ">;" << endl;
1046  } else {
1047  file << ", ";
1048  }
1049  }
1050  }
1051  file.close();
1052 
1053  if (topology.nodeBegin() == topology.nodeEnd()) {
1054  verbose<VbWarning>("It seems that the current topology is empty. No generation then...Au revoir.\n");
1055  } else {
1056  // generation of the behaviours
1057  try {
1058  generateBehaviour(topology, stateMin, stateMax, evtMin, evtMax, obsMin, obsMax, obsInteractionMin, obsInteractionMax,
1059  componentOfNode, sharedEventOfNode, dirName, fixedTopoNode, outputDegreeMax);
1060  } catch (exception & e) {
1061  stringstream stream;
1062  stream << "des_generate caught an exception when calling generateBehaviour():\n";
1063  stream << "\t here are the parameters of des_generate:" << endl;
1064  stream << "\t\tstateMin = " << stateMin << endl;
1065  stream << "\t\tstateMax = " << stateMax << endl;
1066  stream << "\t\tobsMin = " << obsMin << endl;
1067  stream << "\t\tobsMax = " << obsMax << endl;
1068 
1069  stream << "\t\tevtMin = " << evtMin << endl;
1070  stream << "\t\tevtMax = " << evtMax << endl;
1071  stream << "\t\tseed = " << seed << endl;
1072  stream << "\t\tdirName = " << dirName << endl;
1073  stream << "\t\tlatexFileName = " << latexFileName << endl;
1074  stream << "\t\ttopologyFileName = " << topologyFileName << endl;
1075 
1076  stream << "\t\tobsInteractionMin = " << obsInteractionMin << endl;
1077  stream << "\t\tobsInteractionMax = " << obsInteractionMax << endl;
1078  stream << "\t\toutputDegreeMax = " << outputDegreeMax << endl;
1079  stream << "\t\tbehaviourFileName= " << behaviourFileName << endl;
1080  stream << "\t\tfixedNode= " << fixedNode << endl;
1081  stream << "Here is the exception: " << endl;
1082  stream << e.what();
1083  cerr << stream.str() << endl;
1084  cerr << "LOGS: " << endl;
1085  debug(saveAllLogs(cerr));
1086  exit(EXIT_FAILURE);
1087  }
1088 
1089 
1090 
1091  // generation of the latex file
1092  string latexFileNameDest = dirName + "/" + latexFileName;
1093  generateLatexFile(topology, stateMin, stateMax, evtMin,
1094  evtMax, obsMin, obsMax, obsInteractionMin, obsInteractionMax, seed, outputDegreeMax, fixedNode, behaviourFileName, assignedConnections, componentOfNode, sharedEventOfNode, latexFileNameDest);
1095 
1096  // ... and finally the topology mapping
1097  string mapTopoFileNameDest = dirName + "/" + "topology.maptopo";
1098  exportTopologyMap(topology, sharedEventOfNode, componentOfNode, mapTopoFileNameDest);
1099 
1100  if (petrinet) {
1101  cout << "Not implemented yet" << endl;
1102 // string rulesFileNameDest = dirName + "/" + "sync.rules";
1103 //
1104 // std::vector< std::reference_wrapper<const ObservableComponent> > components;
1105 // Diades::Automata::SynchronisationRules::ComponentVector compVect;
1106 //
1107 // for (Topology::NodeIterator nIt = topology.nodeBegin();
1108 // nIt != topology.nodeEnd(); ++nIt) {
1109 // components.push_back(std::cref(*componentOfNode[*nIt]));
1110 // compVect.push_back(componentOfNode[*nIt]);
1111 // }
1112 // Diades::Automata::ParametrizedSynchronisation sync;
1113 // loadSynchronisationRules(compVect, rulesFileNameDest, sync);
1114 //
1115 // Diades::Petri::Net net;
1116 // Diades::Petri::automataConversion(components.begin(), components.end(), sync, net);
1117 // net.setName("generated_net");
1118 // string netFileName = dirName + "/petrinet.net";
1119 // ofstream file(netFileName.c_str());
1120 // net.net2Tina(file);
1121 // cout << "Generated net: places = " << net.numberOfPlaces() << " transitions = "
1122 // << net.numberOfTransitions() << endl;
1123 // file.close();
1124  }
1125  }
1126 
1127  ofstream logfile("lastlog.output");
1128  saveAllLogs(logfile);
1129  logfile.close();
1130  verbose<VbOutput>("Model successfully generated...\n");
1131  return EXIT_SUCCESS;
1132 }
1133 
1134 
1135 /************************************************************************************************/
1136 
1150 bool checkEventConsistency(const Topology & topology, unsigned evtMax, unsigned nbObsIntMin) {
1151  unsigned connectivityMax = 0;
1152  unsigned connectivityMin = 0;
1153  for (Topology::NodeIterator it = topology.nodeBegin();
1154  it != topology.nodeEnd();
1155  ++it) {
1156  if (connectivityMin == 0) {
1157  connectivityMin = topology.connectivity(*it);
1158  } else {
1159  if (connectivityMin > topology.connectivity(*it)) {
1160  connectivityMin = topology.connectivity(*it);
1161  }
1162  }
1163  if (connectivityMax < topology.connectivity(*it)) {
1164  connectivityMax = topology.connectivity(*it);
1165  }
1166  }
1167  log<LgOutput>("evtMax=%1% and max(connectivity)=%2%")
1168  % evtMax % connectivityMax;
1169  if (evtMax < connectivityMax) {
1170  log<LgOutput>("evtMax is smaller than the maximal connectivity of this topology");
1171  }
1172  log<LgOutput>("nbObsIntMin=%1% and min(connectivity)=%2%")
1173  % nbObsIntMin % connectivityMin;
1174 
1175  if (nbObsIntMin > connectivityMin) {
1176  log<LgOutput>("nbObsIntMin is strictly greater than the minimal connectivity of this topology");
1177  }
1178  return (evtMax >= connectivityMax) && (nbObsIntMin <= connectivityMin);
1179 }
1180 
1181 
1182 /************************************************************************************************/
1183 
1193 void generateSharedEvents(const Topology & topology, ComponentNodeMap & componentOfNode,
1194  SharedEventNodeMap & sharedEventOfNode, Topology::Node fixedTopoNode) {
1195  for (Topology::NodeIterator nodeIt = topology.nodeBegin();
1196  nodeIt != topology.nodeEnd();
1197  ++nodeIt) {
1198  if (!fixedTopoNode.valid() || (fixedTopoNode != *nodeIt)) {
1199  for (Topology::NodeConnectionIterator connIt = topology.nodeConnectionBegin(*nodeIt);
1200  connIt != topology.nodeConnectionEnd(*nodeIt);
1201  ++connIt) {
1202  stringstream stream;
1203  stream << topology.getNodeName(*nodeIt) << ".s" << eventNumber;
1204  Event evt = EventFactory::factory()->getEvent(stream.str());
1205  stringstream nickname;
1206  nickname << "s" << eventNumber;
1207  evt.setNickname(nickname.str());
1209  "generateSharedEvents: invalid event in sharedEventOfNode");
1210  sharedEventOfNode[*nodeIt][*connIt] = evt;
1211  componentOfNode[*nodeIt]->insertEvent(evt);
1212  ++eventNumber;
1213  }
1214  }
1215  }
1216 
1217  // final check
1218  for (Topology::NodeIterator nodeIt = topology.nodeBegin();
1219  nodeIt != topology.nodeEnd();
1220  ++nodeIt) {
1221 
1222 
1223  for (Topology::NodeConnectionIterator connIt = topology.nodeConnectionBegin(*nodeIt);
1224  connIt != topology.nodeConnectionEnd(*nodeIt);
1225  ++connIt) {
1226 
1227  always_assertion(FunctionException, sharedEventOfNode[*nodeIt][*connIt].isValid(),
1228  "generateSharedEvents: invalid event in sharedEventOfNode");
1229 
1230 
1231  }
1232  }
1233 
1234 }
1235 
1236 /************************************************************************************************/
1237 
1282 void generateBehaviour(const Topology & topology,
1283  unsigned stateMin,
1284  unsigned stateMax,
1285  unsigned evtMin,
1286  unsigned evtMax,
1287  unsigned obsMin,
1288  unsigned obsMax,
1289  unsigned obsInteractionMin,
1290  unsigned obsInteractionMax,
1291  ComponentNodeMap & componentOfNode,
1292  SharedEventNodeMap & sharedEventOfNode,
1293  string dirName,
1294  Node fixedTopoNode,
1295  unsigned outputDegreeMax) {
1296  list<Topology::Node> nodesToVisit;
1298  ObservableComponent * interaction = 0;
1299  try {
1300  Diades::Graph::ConstNodeMap<int> visitedNodes(topology.graph(), 0); // 0:not visited 1:visited 2:generated
1301  Topology::Node initialNode;
1302 
1303  if (fixedTopoNode.valid()) {
1304  // in this case, one node has a predefined behaviour, so it is set to be already visited.
1305  initialNode = fixedTopoNode;
1306  visitedNodes[initialNode] = 2;
1307 
1308  // write the output immediately (to get a better debug output)
1309  writeComponent(*componentOfNode[initialNode], dirName);
1310 
1311 
1312  // now we generate the neighbours that will initiate the node generation
1313  // obviusly, in this case generatedNeighbours is always empty.
1314  set<Topology::Node> generatedNeighbours;
1315  set<Topology::Node> nonGeneratedNeighbours;
1317  initialNode,
1318  visitedNodes,
1319  generatedNeighbours,
1320  nonGeneratedNeighbours,
1321  nodesToVisit);
1322 
1323  // projection of the initial component on the events in
1324  // interaction with the set of nonGeneratedNeighbours (i.e. here all the neighbours)
1325  // moreover nonGeneratedNeighbours is not empty as the topology must contain
1326  // at least two nodes in this case.
1327  projection[initialNode] = make_pair("", new ObservableComponent());
1328  getOutputProjection(topology, initialNode, sharedEventOfNode,
1329  *componentOfNode[initialNode],
1330  nonGeneratedNeighbours,
1331  projection[initialNode]);
1332 
1333  } else {
1334  // in this case, no node has a predefined behaviour.
1335  // take the first one that can be found and mark as visited but not saturated
1336  initialNode = *topology.nodeBegin();
1337  nodesToVisit.push_back(initialNode);
1338  visitedNodes[initialNode] = 1;
1339  }
1340 
1341  // Breadth-first search
1342  while (!nodesToVisit.empty()) {
1343  Node node = nodesToVisit.front();
1344  debug(printDebugStartVisit(topology, node));
1345  nodesToVisit.pop_front();
1346 
1347  // now we generate the neighbours that will initiate the node generation
1348  set<Topology::Node> generatedNeighbours;
1349  set<Topology::Node> nonGeneratedNeighbours;
1351  node,
1352  visitedNodes,
1353  generatedNeighbours,
1354  nonGeneratedNeighbours,
1355  nodesToVisit);
1356  debug(printDebugProjectionOnGeneratedNeighbours(generatedNeighbours, projection));
1357 
1358 
1359  if (generatedNeighbours.empty() && (node != initialNode)) {
1360  throw (FunctionException("generateBehaviour", "the current node has no interaction with generated neighbours. BUG.\n"));
1361  }
1362 
1363  // generation of the interactive behaviour that the current node must comply with.
1364  interaction = getSynchronisedInteraction(topology, node,
1365  sharedEventOfNode,
1366  projection,
1367  generatedNeighbours.begin(),
1368  generatedNeighbours.end());
1369 
1370  if ((node != initialNode) && (interaction->numberOfTransitions() < generatedNeighbours.size())) {
1371  delete interaction;
1372  interaction = 0;
1373  throw (FunctionException("generateBehaviour", "the interactions with generated neighbours are incorrect. BUG\n"));
1374  }
1375 
1376  // generation of the current node
1377  generateRandomComponent(topology, node,
1378  sharedEventOfNode,
1379  *interaction,
1380  generatedNeighbours.begin(),
1381  generatedNeighbours.end(),
1382  stateMin,
1383  stateMax,
1384  obsMin,
1385  obsMax,
1386  evtMin,
1387  evtMax,
1388  obsInteractionMin,
1389  obsInteractionMax,
1390  outputDegreeMax,
1391  componentOfNode[node]);
1392 
1393  // write the output immediately (to get a better debug output)
1394  writeComponent(*componentOfNode[node], dirName);
1395 
1396  if (!nonGeneratedNeighbours.empty()) {
1397  // compute the interactive behaviour of the current generated node for futher node generations
1398  projection[node] = make_pair("", new ObservableComponent());
1399  getOutputProjection(topology, node, sharedEventOfNode, *componentOfNode[node],
1400  nonGeneratedNeighbours,
1401  projection[node]);
1402  }
1403  // now this node is saturated
1404  visitedNodes[node] = 2;
1405  delete interaction;
1406  interaction = 0;
1407  }
1408  } catch (exception & e) {
1409  if (interaction != 0) {
1410  delete interaction;
1411  interaction = 0;
1412  }
1413  for (Topology::NodeIterator nodeIt = topology.nodeBegin();
1414  nodeIt != topology.nodeEnd();
1415  ++nodeIt) {
1416  if (projection[*nodeIt].second != 0) {
1417  delete projection[*nodeIt].second;
1418  }
1419  }
1420  throw (FunctionException("generateBehaviour", e.what()));
1421  }
1422 }
1423 
1424 /************************************************************************************************/
1425 
1439 void getOutputProjection(const Topology & topology,
1440  const Node & node,
1441  SharedEventNodeMap & sharedEventOfNode,
1442  const ObservableComponent & component,
1443  const set<Node> & nonGeneratedNeighbours,
1444  pair<string, ObservableComponent *> & result) {
1445  always_require(FunctionException, !nonGeneratedNeighbours.empty(), "getOutputProjection: empty set of non generated neighbours");
1446  stringstream streamP;
1447  streamP << "P_{";
1448  for (set<Node>::const_iterator outIt = nonGeneratedNeighbours.begin();
1449  outIt != nonGeneratedNeighbours.end(); ++outIt) {
1450  streamP << topology.getNodeName(*outIt) << " ";
1451  }
1452  streamP << "}(" << topology.getNodeName(node) << ")";
1453  result.first = streamP.str();
1454 
1455  set<Event> projectedEvents;
1456  for (Topology::NodeConnectionIterator it = topology.nodeConnectionBegin(node);
1457  it != topology.nodeConnectionEnd(node);
1458  ++it) {
1459  Topology::CliqueIterator it2 = topology.cliqueBegin(*it);
1460  bool found = false;
1461  while (!found && (it2 != topology.cliqueEnd(*it))) {
1462  found = (*it2 != node) && (nonGeneratedNeighbours.find(*it2) != nonGeneratedNeighbours.end());
1463  ++it2;
1464  }
1465  if (found) {
1466  always_require(FunctionException, sharedEventOfNode[node][*it].isValid(),
1467  "getOutputProjection: invalid shared event found in sharedEventOfNode");
1468  projectedEvents.insert(sharedEventOfNode[node][*it]);
1469  }
1470  }
1471  try {
1472  result.second->project(&component, projectedEvents);
1473  } catch (exception & e) {
1474  stringstream msg;
1475  msg << "caught an exception." << endl;
1476  msg << "getOutputProjection called with the following parameters:" << endl;
1477  msg << "\t node= " << topology.getNodeName(node) << endl;
1478  msg << "\t non generated nodes= " << toStream(nonGeneratedNeighbours.begin(), nonGeneratedNeighbours.end()) << endl;
1479  msg << "Here is the caught exception:" << endl;
1480  msg << e.what() << endl;
1481  throw (FunctionException(msg.str()));
1482  }
1483  result.second->setName(result.first);
1484  always_ensure(FunctionException, result.second->isValid(), "getOutputProjection: invalid returned projection");
1485  set<Event> effectiveEvents;
1486  for (ObservableComponent::TransitionIterator trIt = result.second->transitionBegin();
1487  trIt != result.second->transitionEnd(); ++trIt) {
1488  effectiveEvents.insert(result.second->getEvent(*trIt));
1489  }
1490  always_ensure(FunctionException, effectiveEvents == projectedEvents, "getOutputProjection: the set of projected events is incorrect");
1491 }
1492 
1493 /************************************************************************************************/
1494 
1518 getSynchronisedInteraction(const Topology & topology, const Node & node,
1519  SharedEventNodeMap & sharedEventOfNode,
1520  const Diades::Graph::ConstNodeMap< pair<string, ObservableComponent *> > & projection,
1521  set<Node>::const_iterator first,
1522  set<Node>::const_iterator last) {
1523 
1524  ObservableComponent * projectedInteraction = 0;
1525  ObservableComponent * interaction = 0;
1526 
1527  debug(verbose<VbDebug>("getSynchronisedInteraction on node %1%.\n") % topology.getNodeName(node).str());
1528 
1529  if (first == last) {
1530  projectedInteraction = new ObservableComponent();
1531  projectedInteraction->setInitial(projectedInteraction->newState());
1532  } else {
1533  vector<const ComposableModel *> composableModels;
1534  bool interactionToBeDestroyed = false;
1535  try {
1536  vector<const Component *> models;
1537  for (set<Node>::const_iterator it = first; it != last; ++it) {
1538  models.push_back(projection[*it].second);
1539  }
1540  if (models.size() == 1) {
1541  interaction = projection[*first].second;
1542  interactionToBeDestroyed = false;
1543  } else {
1544  // synchronisation of the input projections
1545 
1546  // first let us create the synchronisation law
1547  ParametrizedSynchronisation synchronisation(models);
1548  initialiseSynchronisationRules(topology, first, last,
1549  sharedEventOfNode, projection, synchronisation);
1550  debug(printDebugLaw(synchronisation));
1551 
1552  // then apply the synchronsation law
1553 
1554  for (set<Node>::const_iterator it = first; it != last; ++it) {
1555  composableModels.push_back(new ComposableModel(*projection[*it].second, synchronisation));
1556  }
1557 
1558 
1559  interaction = new ObservableComponent();
1560  interactionToBeDestroyed = true;
1561 
1562  ComposableModel composedModel(composableModels, synchronisation, false, interaction);
1563  for (vector<const ComposableModel *>::size_type i = 0; i < composableModels.size(); ++i) {
1564  delete composableModels[i];
1565  }
1566  composableModels.clear();
1567  }
1568 
1569  // and finally project on the events in synchronisation with the node to generate
1570  projectedInteraction = new ObservableComponent();
1571  set<Event> projectedEvents;
1572 
1573  for (Topology::NodeConnectionIterator it = topology.nodeConnectionBegin(node);
1574  it != topology.nodeConnectionEnd(node);
1575  ++it) {
1576  for (Topology::CliqueIterator it2 = topology.cliqueBegin(*it);
1577  it2 != topology.cliqueEnd(*it);
1578  ++it2) {
1579  if (find(first, last, *it2) != last) {
1580  projectedEvents.insert(sharedEventOfNode[*it2][*it]);
1581  }
1582  }
1583  }
1584  projectedInteraction->project(interaction, projectedEvents);
1585  if (interactionToBeDestroyed) {
1586  delete interaction;
1587  interaction = 0;
1588  interactionToBeDestroyed = false;
1589  }
1590  // let us do some checking
1591  // 1) first != last implies that projectedInteraction is not empty
1592  if ((first != last) && (projectedInteraction->numberOfTransitions() == 0)) {
1593  throw FunctionException("getSynchronisedInteraction", "The returned interaction is empty, BUG. Be careful it is maybe due to a fundamental problem of the whole generation algorithm. This algorithm is based on a random generator and has not been proved to always work. Sorry for any inconvenience. Try again with another seed and good luck :-) Merci for trying\n");
1594  }
1595  } catch (exception & e) {
1596  if (projectedInteraction != 0) {
1597  delete projectedInteraction;
1598  }
1599  if (interaction != 0 && interactionToBeDestroyed) {
1600  delete interaction;
1601  interaction = 0;
1602  interactionToBeDestroyed = false;
1603  }
1604  for (vector<const ComposableModel *>::size_type i = 0; i < composableModels.size(); ++i) {
1605  delete composableModels[i];
1606  }
1607  composableModels.clear();
1608  throw (FunctionException("getSynchronisedInteraction", e.what()));
1609  }
1610  }
1611  return projectedInteraction;
1612 }
1613 
1614 /************************************************************************************************/
1615 
1640 void generateRandomComponent(const Topology & topology, const Node & node,
1641  SharedEventNodeMap & sharedEventOfNode,
1642  const ObservableComponent & interaction,
1643  set<Node>::const_iterator first,
1644  set<Node>::const_iterator last,
1645  unsigned stateMin,
1646  unsigned stateMax,
1647  unsigned obsMin,
1648  unsigned obsMax,
1649  unsigned evtMin,
1650  unsigned evtMax,
1651  unsigned obsInteractionMin,
1652  unsigned obsInteractionMax,
1653  unsigned outputDegreeMax,
1654  ObservableComponent * result) {
1655  set<Event> interactiveEvents;
1656  for (ObservableComponent::EventIterator eventIt = result->eventBegin();
1657  eventIt != result->eventEnd();
1658  ++eventIt) {
1659  interactiveEvents.insert(*eventIt);
1660  }
1661 
1662  set<Event> nonInteractiveEvents;
1663  generateNonInteractiveEvents(topology, node, evtMin, evtMax, obsMin, obsInteractionMax, *result, nonInteractiveEvents);
1664 
1665 
1666  // Let define the observable mask
1667  defineObservableMask(obsMin, obsMax, obsInteractionMin, obsInteractionMax, interactiveEvents,
1668  nonInteractiveEvents, *result);
1669 
1670  // let's generate the number of states in this component
1671  always_require(FunctionException, stateMin <= stateMax, "generateRandomComponent: stateMin > stateMax");
1672  unsigned numberOfStates = generateRandomValue(stateMin, stateMax);
1673  always_assertion(FunctionException, numberOfStates <= stateMax, "generateRandomComponent: numberOfStates > stateMax.");
1674  always_assertion(FunctionException, numberOfStates >= stateMin, "generateRandomComponent: numberOfStates < stateMin.");
1675 
1676 
1677  // let's generate the transition system of the component
1678  generateTransitionSystem(topology, node, sharedEventOfNode, interaction, first, last, numberOfStates,
1679  outputDegreeMax, *result);
1680 }
1681 
1682 
1683 /************************************************************************************************/
1684 
1697 void generateStates(ObservableComponent & result, unsigned numberOfStates, vector<Node> & indexState) {
1698 
1699  indexState.resize(numberOfStates);
1700  for (unsigned i = 0; i < numberOfStates; ++i) {
1701  stringstream s;
1702  s << "q" << i;
1703  indexState[i] = result.newState(s.str());
1704  }
1705 }
1706 
1707 /************************************************************************************************/
1708 
1726 void logDetailsBeforeCallingGenerateTransitionSystem(const Topology & topology,
1727  const Node & node,
1728  SharedEventNodeMap & sharedEventOfNode,
1729  const ObservableComponent & interaction,
1730  set<Node>::const_iterator first,
1731  set<Node>::const_iterator last,
1732  unsigned numberOfStates,
1733  unsigned outputDegreeMax,
1734  ObservableComponent & result) {
1735  verbose<VbDebug>("Call of generateTransitionSystem on the node %1%\n") % topology.getNodeName(node);
1736  verbose<VbDebug>("Generation of %1% states.\n") % numberOfStates;
1737  verbose<VbDebug>("Shared events involved: \n[");
1738  for (map<Topology::Connection, Event>::const_iterator it = sharedEventOfNode[node].begin();
1739  it != sharedEventOfNode[node].end();
1740  ++it) {
1741  string nodeNames;
1742  for (Topology::CliqueIterator cliqueIt = topology.cliqueBegin(it->first);
1743  cliqueIt != topology.cliqueEnd(it->first);
1744  ++cliqueIt) {
1745  if (*cliqueIt != node) {
1746  string nodeName = topology.getNodeName(*cliqueIt).str();
1747  nodeNames += nodeName + " ";
1748  }
1749  }
1750  verbose<VbDebug>("%1% ( in connection with %2%)\n") % it->second % nodeNames;
1751  }
1752  string logs;
1753  interaction.component2dot("interaction.dot");
1754 }
1755 
1756 
1757 /************************************************************************************************/
1758 
1772 void initConstrainedConnectionMappings(const Topology & topology,
1773  const Node & node,
1774  SharedEventNodeMap & sharedEventOfNode,
1775  set<Node>::const_iterator first,
1776  set<Node>::const_iterator last,
1777  map<Event, Topology::Connection> & mappingInteractionToCurrentSide,
1778  map<Topology::Connection, Event> & mappingConnectionToInteraction,
1779  map<Event, Topology::Connection> & mappingCurrentSideToInteraction,
1780  set<Event>& constrainedEvents) {
1781  for (Topology::NodeConnectionIterator it = topology.nodeConnectionBegin(node);
1782  it != topology.nodeConnectionEnd(node);
1783  ++it) {
1784  for (Topology::CliqueIterator it2 = topology.cliqueBegin(*it);
1785  it2 != topology.cliqueEnd(*it);
1786  ++it2) {
1787  if (find(first, last, *it2) != last) {
1788  mappingCurrentSideToInteraction[sharedEventOfNode[node][*it]] = *it;
1789  mappingInteractionToCurrentSide[sharedEventOfNode[*it2][*it]] = *it;
1790  constrainedEvents.insert(sharedEventOfNode[node][*it]);
1794  mappingConnectionToInteraction[*it] = sharedEventOfNode[*it2][*it];
1795  }
1796  }
1797  }
1798 }
1799 
1800 
1801 /************************************************************************************************/
1802 
1827 unsigned getNumberOfTransitions(const Selection<Event> & eventSelection,
1828  const set<Event> & constrainedEvents,
1829  const set<Event> & constrainedTriggerableEvents,
1830  unsigned numberOfAdmissibleEvents,
1831  unsigned numberOfStatesToVisit,
1832  unsigned outputDegreeMax,
1833  bool & mustUseNewEvent) {
1834  always_require(FunctionException, numberOfAdmissibleEvents > 0, "getNumberOfTransitions: there is no admissible event");
1835  always_require(FunctionException, outputDegreeMax > 0, "getNumberOfTransitions: outputDegreeMax is null.");
1836  unsigned result = 0;
1837  mustUseNewEvent = false;
1838  unsigned numberOfNonInsertedAndTriggerableEvents =
1839  count_if(eventSelection.nonSelectedBegin(),
1840  eventSelection.nonSelectedEnd(),
1841  unaryOr(isNotIn(constrainedEvents.begin(), constrainedEvents.end()),
1842  isIn(constrainedTriggerableEvents.begin(), constrainedTriggerableEvents.end())));
1843 
1844  if (numberOfNonInsertedAndTriggerableEvents != 0) {
1845  double probablilityOfCertainlyUsingSomeNewEventInThisState = 1;
1846  if (numberOfStatesToVisit > 0) {
1847  probablilityOfCertainlyUsingSomeNewEventInThisState =
1848  min((double) 1, ((double) eventSelection.numberOfNonSelectedItems()) / ((double) numberOfStatesToVisit));
1849  }
1850  double value = generateRandomDouble(0, 1);
1851  mustUseNewEvent = value <= probablilityOfCertainlyUsingSomeNewEventInThisState;
1852  }
1853 
1854  unsigned minimalNumberOfTrans = 1;
1855  unsigned maximalNumberOfTrans = min(numberOfAdmissibleEvents, outputDegreeMax);
1856  result = generateRandomValue(minimalNumberOfTrans, maximalNumberOfTrans);
1857  ensure(FunctionException, result > 0, "getNumberOfTransitions: null result.");
1858  ensure(FunctionException, result <= outputDegreeMax, "getNumberOfTransitions: result greater than outputDegreeMax.");
1859  ensure(FunctionException, result <= numberOfAdmissibleEvents, "getNumberOfTransitions: result greater than the number of admissible events");
1860  return result;
1861 }
1862 /************************************************************************************************/
1863 
1880 void generateTriggerableEvents(unsigned nbTransitions,
1881  Selection<Event> & eventSelection,
1882  const vector<unsigned> & admissibleEventIndexes,
1883  unsigned numberOfNonPreviouslySelectedButAdmissibleEvents,
1884  bool mustUseNewEvent,
1885  set<Event> & selectedEvents) {
1886  always_require(FunctionException, (!mustUseNewEvent) || (numberOfNonPreviouslySelectedButAdmissibleEvents != 0),
1887  "generateTriggerableEvents: BUG the parameters mustUseNewEvent and numberOfNonPreviouslySelectedButAdmissibleEvents are incompatible.");
1888  always_require(FunctionException, nbTransitions > 0, "generateTriggerableEvents: BUG nbTransitions is null");
1889  always_require(FunctionException, eventSelection.numberOfItems() >= admissibleEventIndexes.size(),
1890  "generateTriggerableEvents: BUG the set of admissible events is greater than the number of events.");
1891  always_require(FunctionException, numberOfNonPreviouslySelectedButAdmissibleEvents <= admissibleEventIndexes.size(),
1892  "generateTriggerableEvents: BUG there are more unselected admissible events than admissible events.");
1893  always_require(FunctionException, numberOfNonPreviouslySelectedButAdmissibleEvents <= eventSelection.numberOfNonSelectedItems(),
1894  "generateTriggerableEvents: BUG there are more unselected admissible events than unselected events.");
1895  // in order to be as random as possible, first we try to get directly nbTransitions
1896  // from the admissibleEventIndexes independently from the fact a new event
1897  // must be selected or not.
1898  set<unsigned> randomResult;
1899  try {
1900  selectNValues(0, admissibleEventIndexes.size() - 1, nbTransitions, randomResult);
1901  } catch (exception & e) {
1902  stringstream stream;
1903  stream << "Exception caught: parameters of generateTriggerableEvents:\n nbTransitions = " << nbTransitions
1904  << "\n eventSelection.numberOfItems() = " << eventSelection.numberOfItems()
1905  << "\n admissibleEventIndexes.size() = " << admissibleEventIndexes.size()
1906  << "\n numberOfNonPreviouslySelectedButAdmissibleEvents = " << numberOfNonPreviouslySelectedButAdmissibleEvents
1907  << "\n mustUseNewEvent = " << mustUseNewEvent
1908  << "selectedEvents.size() = " << selectedEvents.size()
1909  << endl;
1910  throw (FunctionException(stream.str(), e.what()));
1911  }
1912  // now we check the first index, if it is greater than numberOfNonPreviouslySelectedButAdmissibleEvents
1913  // we know that the selection does not contain any new event
1914  if ((mustUseNewEvent) && (*(randomResult.begin()) >= numberOfNonPreviouslySelectedButAdmissibleEvents)) {
1915  // bad luck, let us force a bit the destiny
1916  // selection of an event never selected.
1917  unsigned selectionIndex = generateRandomValue(0, numberOfNonPreviouslySelectedButAdmissibleEvents);
1918  randomResult.erase(randomResult.begin());
1919  randomResult.insert(selectionIndex);
1920  }
1921 
1922  // now randomResult context the index of events included in eventSelection
1923  // some have never been selected, it is time to notice this fact.
1924  for (const unsigned & index : randomResult) {
1925  selectedEvents.insert(eventSelection.getItem(admissibleEventIndexes[index]));
1926  if (!eventSelection.hasBeenAlreadySelectedOnce(admissibleEventIndexes[index])) {
1927  eventSelection.select(admissibleEventIndexes[index]);
1928  }
1929  }
1930 
1931  always_ensure(FunctionException, selectedEvents.size() == nbTransitions,
1932  "generateTriggerableEvents: BUG wrong number of selected events");
1933 
1934 }
1935 
1936 
1937 
1938 /************************************************************************************************/
1939 
1956 void getSelectedEvents(const ObservableComponent & interaction,
1957  State currentInteractingState,
1958  map<Event, Topology::Connection> & mappingInteractionToCurrentSide,
1959  map<Event, Topology::Connection> & mappingCurrentSideToInteraction,
1960  map<Topology::Connection, Event> & mappingConnectionToInteraction,
1961  Selection<Event> & eventSelection,
1962  const set<Event> & constrainedEvents,
1963  const set<Topology::Connection> & constrainedConnections,
1964  unsigned numberOfVisitedStates,
1965  ObservableComponent & result,
1966  unsigned outputDegreeMax,
1967  set<Event> & selectedEvents) {
1968  set<Event> constrainedTriggerableEvents;
1969  for (const Event & e : constrainedEvents) {
1970  if (constrainedConnections.find(mappingCurrentSideToInteraction[e])
1971  != constrainedConnections.end()) {
1972  // ok event e is involved with a constrainedConnection
1973  // let us see whether the associated event can be triggered by
1974  // currentInteractingState
1975  Event associatedEvent = mappingConnectionToInteraction[mappingCurrentSideToInteraction[e]];
1976  if (interaction.outputEventTransitionBegin(currentInteractingState,
1977  associatedEvent)
1978  != interaction.outputEventTransitionEnd(currentInteractingState,
1979  associatedEvent)
1980  ) {
1981  //yes
1982  constrainedTriggerableEvents.insert(e);
1983 
1984  }
1985  }
1986  }
1987 
1988 
1989  vector<unsigned> admissibleEventIndexes;
1990  always_require(FunctionException, result.numberOfEvents() > 0,
1991  "getSelectedEvents: there is no event in the component to be generated.");
1992 
1993  always_require(FunctionException, eventSelection.numberOfItems() > 0,
1994  "getSelectedEvents: there is no event of the component in the eventSelection object.");
1995 
1996 
1997  always_require(FunctionException, eventSelection.numberOfItems() == result.numberOfEvents(),
1998  "getSelectedEvents: eventSelection.numberOfItems() != result.numberOfEvents().");
1999 
2000  admissibleEventIndexes.reserve(result.numberOfEvents());
2001 
2002  // an event is admissible iff it is not a constrained event or, if it is,
2003  // its corresponding event in the interaction model can be triggered
2004  // in the state currentInteractingState
2005  // In order to be more efficient when generating the selection of events,
2006  // we explore first the events that are still not in the model and then the one that
2007  // are in the model already.
2008 
2009  for (Selection<Event>::IndexIterator indexIt = eventSelection.nonSelectedIndexBegin();
2010  indexIt != eventSelection.nonSelectedIndexEnd();
2011  ++indexIt) {
2012 
2013  if (constrainedEvents.find(eventSelection.getItem(*indexIt)) == constrainedEvents.end()) {
2014  admissibleEventIndexes.push_back(*indexIt);
2015  } else {
2016  if (constrainedTriggerableEvents.find(eventSelection.getItem(*indexIt)) != constrainedTriggerableEvents.end()) {
2017  admissibleEventIndexes.push_back(*indexIt);
2018  }
2019  }
2020  }
2021 
2022  unsigned numberOfNonPreviouslySelectedButAdmissibleEvents = admissibleEventIndexes.size();
2023  for (Selection<Event>::IndexIterator indexIt = eventSelection.selectedIndexBegin();
2024  indexIt != eventSelection.selectedIndexEnd();
2025  ++indexIt) {
2026 
2027  if (constrainedEvents.find(eventSelection.getItem(*indexIt)) == constrainedEvents.end()) {
2028  admissibleEventIndexes.push_back(*indexIt);
2029  } else {
2030  if (constrainedTriggerableEvents.find(eventSelection.getItem(*indexIt)) != constrainedTriggerableEvents.end()) {
2031  admissibleEventIndexes.push_back(*indexIt);
2032  }
2033  }
2034  }
2035 
2036  // Generation of the number of output transitions for the current state.
2037  // From a state, the behaviour is deterministic so the number of transitions
2038  // is at most the number of admissible events. Since the state of the component
2039  // is live, I also suppose that there exists at least one transition
2040  // but I also need to take care about the fact that every event is at least used
2041  // once in the model.
2042 
2043  bool mustUseNewEvent = false;
2044  unsigned nbTransitions = getNumberOfTransitions(eventSelection,
2045  constrainedEvents,
2046  constrainedTriggerableEvents,
2047  admissibleEventIndexes.size(),
2048  result.numberOfStates() - numberOfVisitedStates,
2049  outputDegreeMax, mustUseNewEvent);
2050 
2051  generateTriggerableEvents(nbTransitions,
2052  eventSelection,
2053  admissibleEventIndexes,
2054  numberOfNonPreviouslySelectedButAdmissibleEvents,
2055  mustUseNewEvent,
2056  selectedEvents);
2057 
2058 
2059  always_ensure(FunctionException, !selectedEvents.empty(),
2060  "getSelectedEvents: the returned set of events is empty. BUG.");
2061 }
2062 
2063 
2064 /************************************************************************************************/
2065 
2092 void generateTransitionSystem(const Topology & topology,
2093  const Node & node,
2094  SharedEventNodeMap & sharedEventOfNode,
2095  const ObservableComponent & interaction,
2096  set<Node>::const_iterator first,
2097  set<Node>::const_iterator last,
2098  unsigned numberOfStates,
2099  unsigned outputDegreeMax,
2100  ObservableComponent & result) {
2101  debug(logDetailsBeforeCallingGenerateTransitionSystem(topology, node,
2102  sharedEventOfNode,
2103  interaction,
2104  first,
2105  last,
2106  numberOfStates,
2107  outputDegreeMax,
2108  result););
2109 
2110 
2111  // state generation
2112  vector<State> indexedState; // at each index, there is a state
2113  generateStates(result, numberOfStates, indexedState);
2114  Selection<State> stateSelection(indexedState);
2115 
2116  // the component is deterministic but not minimal
2117  // I also need to take care about the fact that every event is at least used
2118  // once in the model and every transition in interaction must be triggered once.
2119  // Moreover no transition with a code shared with interaction is independent from
2120  // interaction.
2121 
2122  // here are the connections that are contrained by interaction
2123  map<Event, Topology::Connection> mappingInteractionToCurrentSide;
2124  map<Topology::Connection, Event> mappingConnectionToInteraction;
2125  map<Event, Topology::Connection> mappingCurrentSideToInteraction;
2126  set<Event> constrainedEvents;
2127  initConstrainedConnectionMappings(topology, node, sharedEventOfNode, first,
2128  last, mappingInteractionToCurrentSide,
2129  mappingConnectionToInteraction,
2130  mappingCurrentSideToInteraction,
2131  constrainedEvents);
2132 
2133 
2134  // will state whether a transition of the interaction model
2135  // is taken into account into the generated model
2136  // (must be true for every transition in the end)
2137  Graph behaviour = interaction.behaviour();
2138  EdgeMap<int> triggeredTransition(behaviour);
2139 
2140  // contains a mapping between the state of the generated model
2141  // and some corresponding states in the interaction model.
2142  // structure mainly used to complete the model in the end
2143  NodeMap< set<State> > stateMapping(result.behaviour());
2144 
2145 
2146  // for guaranteeing that any event type will be used at least once.
2147  vector<Event> events;
2148  events.reserve(result.numberOfEvents());
2149  copy(result.eventBegin(), result.eventEnd(), inserter(events, events.end()));
2150  Selection<Event> eventSelection(events);
2151 
2152 
2153  // common structures for visiting the state of the generated model
2154  // in parallel with the interaction model
2155  // here we suppose that the transition system has one initial state only
2156  list<State> stateToVisit; // BFS from the initial state
2157  list<State> interactingStateToVisit; // parallel exploration of the interactive model
2158  NodeMap<bool> inThePool(result.behaviour(), false);
2159  unsigned numberOfVisitedStates = 0;
2160 
2161  // let us start with the first state of indexState. It will
2162  // be the initial state of the component
2163  unsigned selectedIndex = stateSelection.newSelection();
2164  result.setInitial(indexedState[selectedIndex]);
2165  stateToVisit.push_back(indexedState[selectedIndex]);
2166  inThePool[indexedState[selectedIndex]] = true;
2167  stateMapping[indexedState[selectedIndex]].insert(*interaction.initialStateBegin());
2168  interactingStateToVisit.push_back(*interaction.initialStateBegin());
2169 
2170  // if outputDegreeMax is not set, let make it maximal
2171  if (!isSet[OUTPUTDEGREEMAX]) {
2172  outputDegreeMax = result.numberOfEvents();
2173  }
2174 
2175  // if outputDegreeMax is set but greater than the number of events
2176  // set it it to this number of events
2177  if (isSet[OUTPUTDEGREEMAX] && (outputDegreeMax > result.numberOfEvents())) {
2178  outputDegreeMax = result.numberOfEvents();
2179  }
2180 
2181 
2182  // start the transition generation
2183  while (!stateToVisit.empty()) {
2184  // current state in the model under construction
2185  State currentState = stateToVisit.front();
2186  stateToVisit.pop_front();
2187 
2188  // current state in the interaction model
2189  State currentInteractingState = interactingStateToVisit.front();
2190  interactingStateToVisit.pop_front();
2191 
2192  set<Topology::Connection> constrainedConnections;
2193  for (ObservableComponent::OutputTransitionIterator it = interaction.outputTransitionBegin(currentInteractingState);
2194  it != interaction.outputTransitionEnd(currentInteractingState);
2195  ++it) {
2196  constrainedConnections.insert(mappingInteractionToCurrentSide[interaction.getEvent(*it)]);
2197  }
2198 
2199 
2200 
2201  set<Event> selectedEvents;
2202 
2203  getSelectedEvents(interaction, currentInteractingState,
2204  mappingInteractionToCurrentSide,
2205  mappingCurrentSideToInteraction,
2206  mappingConnectionToInteraction,
2207  eventSelection,
2208  constrainedEvents,
2209  constrainedConnections,
2210  numberOfVisitedStates,
2211  result,
2212  outputDegreeMax,
2213  selectedEvents);
2214 
2215  // before creating transitions I check whether there are still unreached states.
2216  // If there are, I select one as a target of a transition with the current
2217  // state. It is a way to be sure that every state is at least reachable from
2218  // the initial state by at least one transition since the current state is
2219  // reachable from the initial state.
2220  State unreachedState;
2221  int numberOfIterationsBefore = 0;
2222  if (!stateSelection.allSelected()) {
2223  unreachedState = indexedState[stateSelection.newSelection()];
2224  numberOfIterationsBefore = generateRandomValue(0, selectedEvents.size() - 1);
2225  }
2226 
2227 
2228  // generation of the target states and the transitions
2229 
2230  int counter = 0;
2231  set<Event>::const_iterator eventIt = selectedEvents.begin();
2232  for (unsigned i = 0; i < selectedEvents.size(); ++i) {
2233  State nextState;
2234  if ((unreachedState.valid()) &&
2235  (counter == numberOfIterationsBefore)) {
2236  // here this is the case where the transition is created
2237  // to a reach a unreached state as we selected before
2238  nextState = unreachedState;
2239  } else {
2240  // here, this is the normal case, we choose the target state randomly
2241  // (between the reached and unreached ones)
2242  unsigned targetId = 0;
2243  targetId = generateRandomValue(0, numberOfStates - 1);
2244  // is the selected target state reached or not ?
2245  if (!stateSelection.hasBeenAlreadySelectedOnce(targetId)) {
2246  // no it was a unreached state, make it reached now
2247  stateSelection.select(targetId);
2248  }
2249  nextState = indexedState[targetId];
2250  }
2251 
2252  result.newTransition(currentState, nextState, *eventIt);
2253 
2254  // it is possible that this state has been already inserted as a reached state
2255  // in a previous iteration of this loop, in this case nothing to be done
2256  if (!inThePool[nextState]) {
2257  stateToVisit.push_back(nextState);
2258  inThePool[nextState] = true;
2259 
2260  Transition correspondingInteractionTransition =
2261  getTransitionFromInteractiveCurrentState(interaction, currentInteractingState,
2262  *eventIt,
2263  mappingCurrentSideToInteraction,
2264  mappingConnectionToInteraction,
2265  constrainedEvents);
2266  if (correspondingInteractionTransition.valid()) {
2267  // the interaction state is changing
2268  interactingStateToVisit.push_back(correspondingInteractionTransition.target());
2269  triggeredTransition[correspondingInteractionTransition] = 1;
2270  stateMapping[nextState].insert(correspondingInteractionTransition.target());
2271  } else {
2272  // the interaction state is not changing
2273  interactingStateToVisit.push_back(currentInteractingState);
2274  stateMapping[nextState].insert(currentInteractingState);
2275  }
2276  }
2277  ++eventIt;
2278  ++counter;
2279  }
2280  ++numberOfVisitedStates;
2281  }
2282  // end of the transition generation
2283 
2284 
2285 
2286  // Now we may have a problem. Some transitions from the interaction model may not be taken into account
2287  // we have to complete the generated model to make it fully consistent with the interaction model
2288  makeComponentFullyConsistent(result, node, sharedEventOfNode, interaction, mappingInteractionToCurrentSide,
2289  mappingCurrentSideToInteraction, triggeredTransition, stateMapping, outputDegreeMax, eventSelection);
2290 
2291  // And finally, in the worst case some events during the generation of the component did not occur
2292  makeComponentComplete(outputDegreeMax, eventSelection, result);
2293 }
2294 
2295 /************************************************************************************************/
2296 
2327 void makeComponentFullyConsistent(ObservableComponent & result,
2328  const Node & node,
2329  SharedEventNodeMap & sharedEventOfNode,
2330  const ObservableComponent & interaction,
2331  map<Event, Topology::Connection> & mappingInteractionToCurrentSide,
2332  map<Event, Topology::Connection> & mappingCurrentSideToInteraction,
2333  EdgeMap<int> & triggeredTransition,
2334  NodeMap< set<State> > & stateMapping,
2335  unsigned outputDegreeMax,
2336  Selection<Event> & eventSelection) {
2337 
2338  list<Transition> unmatchedTransitions;
2339  for (ObservableComponent::TransitionIterator it = interaction.transitionBegin();
2340  it != interaction.transitionEnd();
2341  ++it) {
2342 
2343  if (triggeredTransition[*it] == 0) {
2344  unmatchedTransitions.push_back(*it);
2345  }
2346  }
2347 
2348  while (!unmatchedTransitions.empty()) {
2349 
2350  Transition currentTrans = unmatchedTransitions.front();
2351  unmatchedTransitions.pop_front();
2352 
2353  // looking for a source/target states:
2354  list<State> potentialSourceStates;
2355  State possibleSource;
2356  State possibleTarget;
2357  bool stop = false;
2358  ObservableComponent::StateIterator stateIt = result.stateBegin();
2359  while (!stop && (stateIt != result.stateEnd())) {
2360  if (stateMapping[*stateIt].find(currentTrans.source()) != stateMapping[*stateIt].end()) {
2361  potentialSourceStates.push_back(*stateIt);
2362  // looking whether there is a possible target state for this source
2363  Diades::Graph::OutEdgeIterator outTransIt = stateIt->outEdgeBegin();
2364  bool found = false;
2365  while (!found && (outTransIt != stateIt->outEdgeEnd())) {
2366 
2367  found = mappingCurrentSideToInteraction[result.getEvent(*outTransIt)] ==
2368  mappingInteractionToCurrentSide[interaction.getEvent(currentTrans)];
2369  if (found) {
2370  possibleTarget = outTransIt->target();
2371  }
2372  ++outTransIt;
2373  }
2374  stop = found;
2375  if (stop) {
2376  possibleSource = potentialSourceStates.back();
2377  }
2378  }
2379  ++stateIt;
2380  }
2381  if (stop) {
2382  // we found a transition in the model that matches currentEdge
2383  triggeredTransition[currentTrans] = 1;
2384  if (stateMapping[possibleTarget].find(currentTrans.target()) == stateMapping[possibleTarget].end()) {
2385  stateMapping[possibleTarget].insert(currentTrans.target());
2386  propagateInteractingStates(result,
2387  node,
2388  sharedEventOfNode,
2389  mappingInteractionToCurrentSide,
2390  interaction, possibleTarget,
2391  currentTrans.target(),
2392  stateMapping);
2393  }
2394  } else {
2395  // we haven't found a transition we need to create a new one
2396  if (potentialSourceStates.empty()) {
2397  // we cannot do anything at this stage so we must push the current transition back to the
2398  // list and wait that a source state will appear (it will!).
2399  unmatchedTransitions.push_back(currentTrans);
2400  } else {
2401  // we are lucky, we found some sources
2402  // I just select one of them randomly and then I select a target state randomly.
2403  // Since the generation is already very randomized, I just consider a deterministic
2404  // procedure for the rest. It can be randomized. The code would be longer and a bit
2405  // more complex.
2406 
2407  // but first we need to eliminate the source that already have the maximal output degree
2408  list<State> potentialSourceStatesWithCompatibleOutDeg;
2409  for (const State & s : potentialSourceStates) {
2410  if (s.outDeg() < outputDegreeMax) {
2411  potentialSourceStatesWithCompatibleOutDeg.push_back(s);
2412  }
2413  }
2414  State source;
2415  unsigned counter = 0;
2416  if (potentialSourceStatesWithCompatibleOutDeg.empty()) {
2417  // we are in big trouble, unsolvable problem now I emit a warning
2418  cout << "WARNING: the outputDegreeMax option cannot be respected in the component " << result.name() << ", the problem looks unsolvable to me. Te constraint is violated to ensure that the model is consistent with its neighbourhood" << endl;
2419  unsigned indexSource = generateRandomValue(0, potentialSourceStates.size() - 1);
2420  list<State>::const_iterator sourceIt = potentialSourceStates.begin();
2421  while (counter != indexSource) {
2422  ++sourceIt;
2423  ++counter;
2424  }
2425  source = *sourceIt;
2426  } else {
2427  unsigned indexSource = generateRandomValue(0, potentialSourceStatesWithCompatibleOutDeg.size() - 1);
2428  list<State>::const_iterator sourceIt = potentialSourceStatesWithCompatibleOutDeg.begin();
2429  while (counter != indexSource) {
2430  ++sourceIt;
2431  ++counter;
2432  }
2433  source = *sourceIt;
2434  }
2435  unsigned indexTarget = generateRandomValue(0, result.numberOfStates() - 1);
2436  counter = 0;
2437  ObservableComponent::StateIterator targetIt = result.stateBegin();
2438  while (counter != indexTarget) {
2439  ++targetIt;
2440  ++counter;
2441  }
2442  State target = *targetIt;
2443  Event eventToUse = sharedEventOfNode[node][mappingInteractionToCurrentSide[interaction.getEvent(currentTrans)]];
2444 
2445 
2446  result.newTransition(source, target, eventToUse);
2447 
2449  unsigned i = 0;
2450  while (eventToUse != eventSelection.getItem(i)) {
2451  ++i;
2452  always_assertion(FunctionException, i < eventSelection.numberOfItems(),
2453  "completeObservableCom ponent: use of an event that is not recorded in the event selection. BUG.");
2454  }
2455 
2456  if (!eventSelection.hasBeenAlreadySelectedOnce(i)) {
2457  eventSelection.select(i);
2458  }
2459  triggeredTransition[currentTrans] = 1;
2460  stateMapping[target].insert(currentTrans.target());
2461  propagateInteractingStates(result,
2462  node,
2463  sharedEventOfNode,
2464  mappingInteractionToCurrentSide,
2465  interaction,
2466  target,
2467  currentTrans.target(),
2468  stateMapping);
2469  }
2470  }
2471  }
2472 }
2473 
2492 void propagateInteractingStates(ObservableComponent & result, const Node & node,
2493  SharedEventNodeMap & sharedEventOfNode,
2494  map<Event, Topology::Connection> & mappingInteractionToCurrentSide,
2495  const ObservableComponent & interaction,
2496  State state,
2497  State correspondingState,
2498  NodeMap< set<State> > & stateMapping) {
2499 
2500  list< pair<State, State> > stack;
2501  stack.push_back(make_pair(state, correspondingState));
2502 
2503  while (!stack.empty()) {
2504 
2505  State currentState = stack.back().first;
2506  State currentCorrespondingState = stack.back().second;
2507  Diades::Graph::OutEdgeIterator outTransIt = currentCorrespondingState.outEdgeBegin();
2508  bool stop = false;
2509  while ((!stop) && (outTransIt != currentCorrespondingState.outEdgeEnd())) {
2510 
2511  Event currentEvent = interaction.getEvent(*outTransIt);
2512  Event eventResultSide = sharedEventOfNode[node][mappingInteractionToCurrentSide[currentEvent]];
2513  Diades::Graph::OutEdgeIterator outTransIt2 = currentState.outEdgeBegin();
2514  bool found = false;
2515  State targetState;
2516  while ((!found) && (outTransIt2 != currentState.outEdgeEnd())) {
2517 
2518  found = result.getEvent(*outTransIt2) == eventResultSide;
2519  if (found) {
2520  targetState = outTransIt2->target();
2521  }
2522  ++outTransIt2;
2523  }
2524 
2525  if (found) {
2526  if (stateMapping[targetState].find(outTransIt->target()) == stateMapping[targetState].end()) {
2527  stateMapping[targetState].insert(outTransIt->target());
2528  stack.push_back(make_pair(targetState, outTransIt->target()));
2529  stop = true;
2530  }
2531  }
2532  ++outTransIt;
2533  }
2534  if (!stop) {
2535  // all the successors of the (currentState,currentCorrespondingState) are correctly tagged
2536  stack.pop_back();
2537  }
2538  }
2539 }
2540 
2541 
2542 
2543 
2544 /***********************************************************************************************/
2545 
2562 void generateLatexFile(const Topology & topology,
2563  unsigned stateMin,
2564  unsigned stateMax,
2565  unsigned evtMin,
2566  unsigned evtMax,
2567  unsigned obsMin,
2568  unsigned obsMax,
2569  unsigned obsInteractionMin,
2570  unsigned obsInteractionMax,
2571  unsigned seed,
2572  unsigned outputDegreeMax,
2573  const string & fixedNode,
2574  const string & behaviourFileName,
2575  map<string, string> & assignedConnections,
2576  const ComponentNodeMap & componentOfNode,
2577  SharedEventNodeMap & sharedEventOfNode,
2578  const string & filename) {
2579  ofstream latexfile;
2580  latexfile.open(filename.c_str());
2581  generateLatexPreamble(topology,
2582  stateMin,
2583  stateMax,
2584  evtMin,
2585  evtMax,
2586  obsMin,
2587  obsMax,
2588  obsInteractionMin,
2589  obsInteractionMax, seed, outputDegreeMax, fixedNode, behaviourFileName, assignedConnections,
2590  componentOfNode,
2591  sharedEventOfNode,
2592  filename,
2593  latexfile);
2594  generateLatexTopology(topology, sharedEventOfNode, latexfile);
2595  generateLatexComponents(topology, sharedEventOfNode, componentOfNode, latexfile);
2596  generateLatexEventIndex(topology, sharedEventOfNode, componentOfNode, latexfile);
2597  generateLatexEpilog(latexfile);
2598  latexfile.close();
2599 }
2600 
2601 /*****************************************************************************************/
2602 
2620 void generateLatexPreamble(const Topology & topology,
2621  unsigned stateMin,
2622  unsigned stateMax,
2623  unsigned evtMin,
2624  unsigned evtMax,
2625  unsigned obsMin,
2626  unsigned obsMax,
2627  unsigned obsInteractionMin,
2628  unsigned obsInteractionMax,
2629  unsigned seed,
2630  unsigned outputDegreeMax,
2631  const string & fixedNode,
2632  const string & behaviourFileName,
2633  map<string, string> & assignedConnections,
2634  const ComponentNodeMap & componentOfNode,
2635  SharedEventNodeMap & sharedEventOfNode,
2636  const string & filename,
2637  ofstream & latexfile) {
2638 
2639  latexfile << "\\documentclass[11pt]{article}" << endl;
2640  latexfile << "\\usepackage{array}" << endl;
2641  latexfile << "\\textwidth 17cm \\textheight 26cm \\voffset -3cm \\hoffset -1.6cm" << endl;
2642  latexfile << "\\title{Generated discrete-event model}" << endl;
2643  time_t rawtime;
2644  time(&rawtime);
2645  latexfile << "\\date{" << ctime(&rawtime) << "}" << endl;
2646  latexfile << "\\begin{document}" << endl;
2647  latexfile << "\\maketitle" << endl;
2648  latexfile << "\\section{Introduction}" << endl;
2649  latexfile << "This model has been generated with the following parameters of {\\tt des\\_generate}." << endl;
2650  latexfile << "\\begin{center}" << endl;
2651  latexfile << "{\\small" << endl;
2652  latexfile << "\\begin{tabular}{|c|c|c|} " << endl;
2653  latexfile << "\\hline" << endl;
2654  latexfile << "Random generator seed & {\\tt --seed} & " << seed << " \\\\ " << endl;
2655  latexfile << "\\hline" << endl;
2656  latexfile << "Number of components & {\\tt --topology} & " << topology.numberOfNodes() << " \\\\ " << endl;
2657  latexfile << "\\hline" << endl;
2658  latexfile << "Minimal number of observable per component & {\\tt --obsMin} & " << obsMin << " \\\\" << endl;
2659  latexfile << "\\hline" << endl;
2660  latexfile << "Maximal number of observable events per component & {\\tt --obsMax} & " << obsMax << " \\\\" << endl;
2661  latexfile << "\\hline" << endl;
2662  latexfile << "Minimal number of non-interactive events per component & {\\tt --evtMin} & " << evtMin << " \\\\" << endl;
2663  latexfile << "\\hline" << endl;
2664  latexfile << "Maximal number of non-interactive events per component & {\\tt --evtMax} & " << evtMax << " \\\\" << endl;
2665  latexfile << "\\hline" << endl;
2666  latexfile << "Minimal number of states per component & {\\tt --stateMin} & " << stateMin << " \\\\" << endl;
2667  latexfile << "\\hline" << endl;
2668  latexfile << "Maximal number of states per component & {\\tt --stateMax} & " << stateMax << " \\\\" << endl;
2669  latexfile << "\\hline" << endl;
2670  latexfile << "Maximal number of observable interaction per component & {\\tt --obsInteractionMax} & " << obsInteractionMax << " \\\\" << endl;
2671  latexfile << "\\hline" << endl;
2672  latexfile << "Minimal number of observable interaction per component & {\\tt --obsInteractionMin} & " << obsInteractionMin << " \\\\" << endl;
2673  latexfile << "\\hline" << endl;
2674  latexfile << "Maximal number of output transitions per state & {\\tt --outputDegreeMax} & " << outputDegreeMax << " \\\\" << endl;
2675  latexfile << "\\hline" << endl;
2676  latexfile << "\\end{tabular}" << endl;
2677  latexfile << "}" << endl;
2678  latexfile << "\\end{center}" << endl;
2679 
2680  if (!fixedNode.empty()) {
2681  latexfile << "~\\\\";
2682  latexfile << "The topology node {\\tt " << fixedNode << "} has been fixed by the user and contains the behaviour described in the file: \\begin{center} \\verb| " << behaviourFileName << "| \\end{center}\n";
2683  if (assignedConnections.empty()) {
2684  latexfile << "No connection of the node has been assigned by the user." << endl;
2685  } else {
2686  latexfile << "Here are the connections assigned by the user:" << endl;
2687  for (map<string, string>::const_iterator it = assignedConnections.begin();
2688  it != assignedConnections.end();
2689  ++it) {
2690  latexfile << it->first << "$\\leftrightarrow$" << it->second << "\\\\";
2691  }
2692  }
2693  }
2694 };
2695 
2696 
2697 
2698 /***********************************************************************************************/
2699 
2707 void generateLatexTopology(const Topology & topology, SharedEventNodeMap & sharedEventOfNode, ofstream & latexfile) {
2708  latexfile << "\\section{Topology}" << endl;
2709  latexfile << "\\label{sec:topology}" << endl;
2710  latexfile << "The topology of the system is composed of ";
2711  latexfile << topology.numberOfNodes();
2712  latexfile << " components and " << topology.numberOfConnections();
2713  latexfile << " connections." << endl;
2714 
2715 
2716  for (Topology::NodeIterator nodeIt = topology.nodeBegin();
2717  nodeIt != topology.nodeEnd();
2718  ++nodeIt) {
2719  latexfile << "\\paragraph{Neighbourhood of component {\\tt ";
2720  latexfile << topology.getNodeName(*nodeIt) << "}}~\\\\" << endl;
2721  if (topology.nodeConnectionBegin(*nodeIt) != topology.nodeConnectionEnd(*nodeIt)) {
2722  latexfile << "\\begin{enumerate}" << endl;
2723  for (Topology::NodeConnectionIterator connIt = topology.nodeConnectionBegin(*nodeIt);
2724  connIt != topology.nodeConnectionEnd(*nodeIt);
2725  ++connIt) {
2726  for (Topology::CliqueIterator cliqueIt = topology.cliqueBegin(*connIt);
2727  cliqueIt != topology.cliqueEnd(*connIt);
2728  ++cliqueIt) {
2729  if (*cliqueIt != *nodeIt) {
2730  latexfile << "\\item Component {\\tt " << topology.getNodeName(*cliqueIt) << "} with events {\\tt ";
2731  latexfile << sharedEventOfNode[*cliqueIt][*connIt] << "}." << endl;
2732  }
2733  }
2734  }
2735  latexfile << "\\end{enumerate}" << endl;
2736  }
2737  }
2738 }
2739 
2740 /***********************************************************************************************/
2741 
2750 void generateLatexComponents(const Topology & topology, SharedEventNodeMap & sharedEventOfNode, const ComponentNodeMap & componentOfNode, ofstream & latexfile) {
2751  for (Topology::NodeIterator nodeIt = topology.nodeBegin();
2752  nodeIt != topology.nodeEnd();
2753  ++nodeIt) {
2754  latexfile << "\\newpage" << endl;
2755  latexfile << "\\subsection{Component {\\tt " << topology.getNodeName(*nodeIt) << "}}" << endl;
2756  latexfile << "\\label{comp:" << topology.getNodeName(*nodeIt) << "}" << endl;
2757  latexfile << "\\begin{center}" << endl;
2758  latexfile << "{\\small" << endl;
2759  latexfile << "\\begin{tabular}{|c|m{8cm}|}" << endl;
2760  latexfile << "\\hline" << endl;
2761  latexfile << "Number of states & " << componentOfNode[*nodeIt]->numberOfStates() << " \\\\" << endl;
2762  latexfile << "\\hline" << endl;
2763  latexfile << "Number of Transitions & " << componentOfNode[*nodeIt]->numberOfTransitions() << " \\\\" << endl;
2764  latexfile << "\\hline" << endl;
2765  latexfile << "Interactive events & {\\tt ";
2766  set<Event> interactives;
2767  for (map<Topology::Connection, Event>::const_iterator it = sharedEventOfNode[*nodeIt].begin();
2768  it != sharedEventOfNode[*nodeIt].end();
2769  ++it) {
2770  latexfile << "\\verb|" << it->second << "| ";
2771  interactives.insert(it->second);
2772  }
2773  latexfile << "} \\\\" << endl;
2774  latexfile << "\\hline" << endl;
2775  latexfile << "Observable events & {\\tt ";
2776  ObservableComponent::EventIterator it = componentOfNode[*nodeIt]->observableBegin();
2777  ++it;
2778  for (;
2779  it != componentOfNode[*nodeIt]->observableEnd();
2780  ++it) {
2781  latexfile << "\\verb|" << *it << "| ";
2782  }
2783  latexfile << "} \\\\" << endl;
2784  latexfile << "\\hline" << endl;
2785  latexfile << "Non-interactive events & {\\tt ";
2786  for (ObservableComponent::EventIterator it = componentOfNode[*nodeIt]->eventBegin();
2787  it != componentOfNode[*nodeIt]->eventEnd();
2788  ++it) {
2789  if (interactives.find(*it) == interactives.end()) {
2790  latexfile << "\\verb|" << *it << "| ";
2791  }
2792  }
2793  latexfile << "} \\\\" << endl;
2794  latexfile << "\\hline" << endl;
2795  latexfile << "\\end{tabular} }" << endl << endl;
2796  latexfile << "\\end{center}" << endl << endl << endl;
2797  latexfile << "\\paragraph{Initial state:} $" << componentOfNode[*nodeIt]->getLabel(*componentOfNode[*nodeIt]->initialStateBegin()) << "$" << endl;
2798  latexfile << "\\paragraph{Transition system:}" << endl;
2799  if (componentOfNode[*nodeIt]->numberOfStates() > 10) {
2800  latexfile << "Note: as the number of states is greater than 10, only transitions involved in the first 10 states are printed." << endl;
2801  }
2802 
2803  vector<Node> printedNodes(1);
2804  printedNodes[0] = *componentOfNode[*nodeIt]->initialStateBegin();
2805  map<Node, int> mappingNodes;
2806  mappingNodes[*componentOfNode[*nodeIt]->initialStateBegin()] = 0;
2807  list<Node> visitingNodes;
2808  visitingNodes.push_back(*componentOfNode[*nodeIt]->initialStateBegin());
2809  int stateNb = 1;
2810  while ((!visitingNodes.empty()) && (stateNb < 10)) {
2811  Node currentState = visitingNodes.front();
2812  visitingNodes.pop_front();
2813  ObservableComponent::OutputTransitionIterator outTransIt = componentOfNode[*nodeIt]->outputTransitionBegin(currentState);
2814  while ((stateNb < 10) && (outTransIt != componentOfNode[*nodeIt]->outputTransitionEnd(currentState))) {
2815  if (mappingNodes.find(outTransIt->target()) == mappingNodes.end()) {
2816  ++stateNb;
2817  printedNodes.push_back(outTransIt->target());
2818  mappingNodes[printedNodes.back()] = printedNodes.size() - 1;
2819  visitingNodes.push_back(outTransIt->target());
2820  }
2821  ++outTransIt;
2822  }
2823  }
2824 
2825  latexfile << "\\begin{center}" << endl;
2826  latexfile << "{\\small" << endl;
2827 
2828  latexfile << "\\begin{tabular}{|c";
2829  for (unsigned i = 0; i < printedNodes.size(); ++i) {
2830  latexfile << "|m{1cm}";
2831  }
2832  latexfile << "|}" << endl;
2833  latexfile << "\\hline" << endl;
2834  for (unsigned i = 0; i < printedNodes.size(); ++i) {
2835  latexfile << " & {\\bf $" << componentOfNode[*nodeIt]->getLabel(printedNodes[i]) << "$}";
2836  }
2837  latexfile << "\\\\" << endl;
2838  latexfile << "\\hline" << endl;
2839  for (unsigned i = 0; i < printedNodes.size(); ++i) {
2840  latexfile << "{\\bf $" << componentOfNode[*nodeIt]->getLabel(printedNodes[i]) << "$}";
2841  map< State, set<string> > outEvents;
2842  for (ObservableComponent::OutputTransitionIterator outTransIt = componentOfNode[*nodeIt]->outputTransitionBegin(printedNodes[i]);
2843  outTransIt != componentOfNode[*nodeIt]->outputTransitionEnd(printedNodes[i]);
2844  ++outTransIt) {
2845  if (mappingNodes.find(outTransIt->target()) != mappingNodes.end()) {
2846  outEvents[outTransIt->target()].insert(componentOfNode[*nodeIt]->getEvent(*outTransIt).nickname());
2847  }
2848  }
2849  for (unsigned j = 0; j < printedNodes.size(); ++j) {
2850  latexfile << " & ";
2851  for (set<string>::const_iterator stringIt = outEvents[printedNodes[j]].begin();
2852  stringIt != outEvents[printedNodes[j]].end();
2853  ++stringIt) {
2854  latexfile << "\\verb|" << *stringIt << "| ";
2855  }
2856  }
2857  latexfile << "\\\\" << endl;
2858  latexfile << "\\hline" << endl;
2859 
2860  }
2861 
2862  latexfile << "\\end{tabular}";
2863  latexfile << "}" << endl;
2864  latexfile << "\\end{center}";
2865  }
2866 
2867 }
2868 
2869 \
2870 
2871 
2872 /***********************************************************************************************/
2873 
2879 void generateLatexEpilog(ofstream & latexfile) {
2880  latexfile << "\\end{document}" << endl;
2881 }
2882 
2883 
2884 /***********************************************************************************************/
2885 
2894 void exportTopologyMap(const Topology & topology,
2895  SharedEventNodeMap & sharedEventOfNode,
2896  const ComponentNodeMap & componentOfNode,
2897  const string & mapTopoFileNameDest) {
2898  TopologyMap mapping(topology);
2899  for (Topology::NodeIterator it = topology.nodeBegin();
2900  it != topology.nodeEnd();
2901  ++it) {
2902  mapping.mapComponentToNode(*componentOfNode[*it], *it);
2903  }
2904  for (Topology::ConnectionIterator it = topology.connectionBegin();
2905  it != topology.connectionEnd();
2906  ++it) {
2907  for (Topology::CliqueIterator it2 = topology.cliqueBegin(*it);
2908  it2 != topology.cliqueEnd(*it);
2909  ++it2) {
2910  mapping.addConnection(*it, *it2, sharedEventOfNode[*it2][*it]);
2911  }
2912  }
2913  mapping.exportMap(mapTopoFileNameDest);
2914 }
2915 
2916 
2917 /********************************************************************************/
2918 
2925 void writeComponent(const ObservableComponent & component,
2926  const string & dirName) {
2927  string compFileNameDest = dirName + "/" + component.name() + ".des_comp";
2928  verbose<VbOutput>("Writing the file %1%...") % compFileNameDest;
2929  component.exportDesCompModel(compFileNameDest);
2930  verbose<VbOutput>("done.\n");
2931  string compFileNameDestDot = dirName + "/" + component.name() + ".dot";
2932  verbose<VbOutput>("Writing the file %1%...") % compFileNameDestDot;
2933  component.component2dot(compFileNameDestDot);
2934  verbose<VbOutput>("done.\n");
2935 }
2936 
2937 /************************************************************************************************/
2938 
2950 void propagateConstrainedInteractions(const Topology & topology,
2951  Topology::Node node,
2952  Diades::Graph::ConstNodeMap<int> & visitedNodes,
2953  set<Topology::Node> & generatedNeighbours,
2954  set<Topology::Node> & nonGeneratedNeighbours,
2955  list<Topology::Node> & nodesToVisit) {
2956  for (Topology::NodeConnectionIterator it = topology.nodeConnectionBegin(node);
2957  it != topology.nodeConnectionEnd(node);
2958  ++it) {
2959  for (Topology::CliqueIterator cliqueIt = topology.cliqueBegin(*it);
2960  cliqueIt != topology.cliqueEnd(*it);
2961  ++cliqueIt) {
2962  switch (visitedNodes[*cliqueIt]) {
2963  case 0: // not visited
2964  {
2965  nodesToVisit.push_back(*cliqueIt);
2966  visitedNodes[*cliqueIt] = 1;
2967  if (node != *cliqueIt) {
2968  nonGeneratedNeighbours.insert(*cliqueIt);
2969  }
2970  break;
2971  }
2972  case 1: // visited
2973  {
2974  if (node != *cliqueIt) {
2975  nonGeneratedNeighbours.insert(*cliqueIt);
2976  }
2977  break;
2978  }
2979  case 2: // saturated
2980  {
2981  if (node != *cliqueIt) {
2982  generatedNeighbours.insert(*cliqueIt);
2983  }
2984  break;
2985  }
2986  default:
2987  {
2988  throw (FunctionException("propagateConstrainedInteractions", "The status of a node is neither 'not visited', 'visited', 'generated', BUG"));
2989  }
2990  }
2991  }
2992  }
2993 }
2994 
2995 /***************************************************************************************/
2996 
2997 void printDebugStartVisit(const Topology & topology, Topology::Node node) {
2998  verbose<VbDebug>("************************************************\n");
2999  verbose<VbDebug>("Generation of %1% based on P_{%2%}(")
3000  % topology.getNodeName(node).str()
3001  % topology.getNodeName(node).str();
3002 }
3003 
3004 /***************************************************************************************/
3005 
3006 void printDebugProjectionOnGeneratedNeighbours(const set<Topology::Node> & generatedNeighbours,
3007  const Diades::Graph::NodeMap< pair<string, ObservableComponent *> > & projection) {
3008  // projection on inputs
3009  for (set<Node>::const_iterator inIt = generatedNeighbours.begin(); inIt != generatedNeighbours.end(); ++inIt) {
3010  verbose<VbDebug>("%1% ") % projection[*inIt].second->name();
3011  set<Node>::const_iterator nextInIt = inIt;
3012  ++nextInIt;
3013  if (nextInIt != generatedNeighbours.end()) {
3014  verbose<VbDebug>(" || ");
3015  }
3016  }
3017  verbose<VbDebug>(")\n");
3018 }
3019 
3020 /***************************************************************************************/
3021 
3032 void initialiseSynchronisationRules(const Topology & topology,
3033  set<Node>::const_iterator first,
3034  set<Node>::const_iterator last,
3035  SharedEventNodeMap & sharedEventOfNode,
3036  const Diades::Graph::ConstNodeMap< pair<string, ObservableComponent *> > & projection,
3037  ParametrizedSynchronisation & synchronisation) {
3038 
3039  for (set<Node>::const_iterator it = first; it != last; ++it) {
3040  set<Node>::const_iterator nextIt = it;
3041  ++nextIt;
3042  for (Topology::NodeConnectionIterator it2 = topology.nodeConnectionBegin(*it);
3043  it2 != topology.nodeConnectionEnd(*it);
3044  ++it2) {
3045 
3046  vector<Event> synchronisedEvents;
3047  verbose<VbDebug>("synchronised events: {");
3048  if (projection[*it].second->containsEvent(sharedEventOfNode[*it][*it2])) {
3049  synchronisedEvents.push_back(sharedEventOfNode[*it][*it2]);
3050  for (Topology::CliqueIterator it3 = topology.cliqueBegin(*it2);
3051  it3 != topology.cliqueEnd(*it2);
3052  ++it3) {
3053 
3054  if (find(nextIt, last, *it3) != last) {
3055  if (projection[*it3].second->containsEvent(sharedEventOfNode[*it3][*it2])) {
3056  verbose<VbDebug>("%1%.%2%") % topology.getNodeName(*it3).str() % sharedEventOfNode[*it3][*it2].label();
3057  synchronisedEvents.push_back(sharedEventOfNode[*it3][*it2]);
3058  }
3059  }
3060  }
3061  synchronisation.synchronise(synchronisedEvents);
3062  }
3063  verbose<VbDebug>("}.\n");
3064  }
3065  }
3066  synchronisation.close();
3067 }
3068 
3069 /***************************************************************************************/
3070 
3071 void printDebugLaw(const ParametrizedSynchronisation & synchronisation) {
3072  stringstream law;
3073  law << synchronisation;
3074  verbose<VbDebug>("getSynchronisedInteraction: composition of the input interactions based on the following synchronisation law:\n %1%\n") % law.str();
3075 }
3076 
3077 /***************************************************************************************/
3078 
3091 void generateNonInteractiveEvents(const Topology & topology,
3092  Topology::Node node,
3093  unsigned evtMin,
3094  unsigned evtMax,
3095  unsigned obsMin,
3096  unsigned obsInteractionMax,
3097  ObservableComponent & result,
3098  set<Event> & nonInteractiveEvents) {
3099  always_require(FunctionException, evtMin <= evtMax, "generateNonInteractiveEvents: evtMin > evtMax.");
3100  always_require(FunctionException, obsMin <= evtMax, "generateNonInteractiveEvents: obsMin > evtMax.");
3101  always_require(FunctionException, obsInteractionMax <= evtMax, "generateNonInteractiveEvents: obsInteractionMax <=evtMax.");
3102  always_require(FunctionException, result.numberOfEvents() <= evtMax, "generateNonInteractiveEvents: there is more interactive events in this component that evtMax.");
3103 
3114  unsigned minimumNumberOfNonInteractiveEvents = 0;
3115  if (obsMin > obsInteractionMax) {
3116  minimumNumberOfNonInteractiveEvents = obsMin - obsInteractionMax;
3117  }
3118  if (result.numberOfEvents() <= evtMin) {
3119  if ((evtMin - result.numberOfEvents()) > (minimumNumberOfNonInteractiveEvents)) {
3120  minimumNumberOfNonInteractiveEvents = (evtMin - result.numberOfEvents());
3121  }
3122  }
3123  always_assertion(FunctionException, minimumNumberOfNonInteractiveEvents <= evtMax - result.numberOfEvents(),
3124  "generateNonInteractiveEvents: impossible case, minimumNumberOfNonInteractiveEvents > evtMax-result->numberOfEvents().BUG");
3125 
3126  unsigned numberOfNonInteractiveEvents =
3127  generateRandomValue(minimumNumberOfNonInteractiveEvents, evtMax - result.numberOfEvents());
3128 
3129  unsigned numberOfEvents =
3130  result.numberOfEvents() + numberOfNonInteractiveEvents;
3131 
3132  while (result.numberOfEvents() < numberOfEvents) {
3133  stringstream stream;
3134  stream << topology.getNodeName(node) << ".e" << eventNumber;
3135  Event evt = EventFactory::factory()->getEvent(stream.str());
3136  stringstream nickname;
3137  nickname << "e" << eventNumber;
3138  evt.setNickname(nickname.str());
3139  result.insertEvent(evt);
3140  nonInteractiveEvents.insert(evt);
3141  ++eventNumber;
3142  }
3143  always_ensure(FunctionException, nonInteractiveEvents.size() == numberOfNonInteractiveEvents,
3144  "generateNonInteractiveEvents: BUG wrong number of generated events");
3145 }
3146 
3147 /***************************************************************************************/
3148 
3160 void defineObservableMask(unsigned obsMin, unsigned obsMax, unsigned obsInteractionMin,
3161  unsigned obsInteractionMax, const set<Event> & interactiveEvents,
3162  const set<Event> & nonInteractiveEvents,
3163  ObservableComponent & result) {
3164  always_require(FunctionException, obsMin <= obsMax, "defineObservableMask: obsMin > obsMax.");
3165  always_require(FunctionException, obsInteractionMin <= obsInteractionMax,
3166  "defineObservableMask: obsInteractionMin > obsInteractionMax.");
3167  always_require(FunctionException, interactiveEvents.size() + nonInteractiveEvents.size() == result.numberOfEvents(),
3168  "defineObservableMask: interactiveEvents.size() + nonInteractiveEvents.size() != result.numberOfEvents().");
3169  always_require(FunctionException, obsInteractionMin <= interactiveEvents.size(), "defineObservableMask: obsInteractionMin > interactiveEvents.size()");
3170  always_require(FunctionException, obsInteractionMin <= obsMin, "defineObservableMask: obsInteractionMin > obsMin");
3171  always_require(FunctionException, obsInteractionMax <= obsMax, "defineObservableMask: obsInteractionMax > obsMax");
3172  always_require(FunctionException, obsMin <= result.numberOfEvents(), "defineObservableMask: obsMin>result.numberOfEvents()");
3173 
3174 
3175 
3176 
3177  // // Let define the observable mask
3178  // unsigned int maxOfMin = obsInteractionMin < obsMin ? obsMin : obsInteractionMin;
3179  // always_assertion(FunctionException, maxOfMin >= obsMin, "defineObservableMask: maxOfMin < obsMin.");
3180 
3181 
3182  // unsigned int minOfMax = (obsMax<(result.numberOfEvents()))?obsMax:result.numberOfEvents();
3183  // always_assertion(FunctionException, minOfMax <= obsMax, "defineObservableMask: minOfMax > obsMax.");
3184  // always_assertion(FunctionException, maxOfMin <= minOfMax, "defineObservableMask: maxOfMin > minOfMax.");
3185 
3186  // unsigned int numberOfObservableEvents = generateRandomValue( maxOfMin, minOfMax );
3187 
3188 
3189  // unsigned int interactiveMinOfMax = obsInteractionMax < numberOfObservableEvents ? obsInteractionMax : numberOfObservableEvents;
3190  // if(interactiveMinOfMax > interactiveEvents.size())
3191  // {
3192  // interactiveMinOfMax = interactiveEvents.size();
3193  // }
3194  // always_assertion(FunctionException,interactiveMinOfMax <= interactiveEvents.size(),
3195  // "defineObservableMask:interactiveMinOfMax > interactiveEvents.size().");
3196 
3197  // always_assertion(FunctionException,interactiveMinOfMax <= obsInteractionMax,
3198  // "defineObservableMask:interactiveMinOfMax > obsInteractionMax.");
3199  // always_assertion(FunctionException, obsInteractionMin<= interactiveMinOfMax,
3200  // "defineObservableMask:obsInteractionMin > interactiveMinOfMax.");
3201 
3202  // unsigned int numberOfObservableInteractions = generateRandomValue(obsInteractionMin,interactiveMinOfMax);
3203  // always_assertion(FunctionException, numberOfObservableEvents>= numberOfObservableInteractions,
3204  // "defineObservableMask:numberOfObservableEvents< numberOfObservableInteractions.");
3205 
3206  // unsigned int numberOfObservableNonInteractiveEvents = numberOfObservableEvents - numberOfObservableInteractions;
3207 
3208 
3209 
3210  unsigned int numberOfObservableInteractions = 0;
3211  if (obsMin - obsInteractionMin > nonInteractiveEvents.size()) {
3212  numberOfObservableInteractions = generateRandomValue(max((unsigned) obsInteractionMin, (unsigned) (obsMin - obsInteractionMin - nonInteractiveEvents.size())), min((unsigned) interactiveEvents.size(), (unsigned) obsInteractionMax));
3213  } else {
3214  numberOfObservableInteractions = generateRandomValue(obsInteractionMin, min((unsigned) interactiveEvents.size(), (unsigned) obsInteractionMax));
3215  }
3216 
3217  unsigned numberOfObservableNonInteractiveEvents = 0;
3218  if (obsMin > numberOfObservableInteractions) {
3219  numberOfObservableNonInteractiveEvents = generateRandomValue(obsMin - numberOfObservableInteractions,
3220  min((unsigned) obsMax - numberOfObservableInteractions, (unsigned) nonInteractiveEvents.size()));
3221  } else {
3222  numberOfObservableNonInteractiveEvents = generateRandomValue(0,
3223  min((unsigned) obsMax - numberOfObservableInteractions, (unsigned) nonInteractiveEvents.size()));
3224  }
3225 
3226 
3227  debug(log<LgDebug>("numberOfObservableEvents = %1%\n numberOfObservableInteractions = %2%\n numberOfObservableNonInteractiveEvents = %3%")
3228  % (numberOfObservableInteractions + numberOfObservableNonInteractiveEvents)
3229  % numberOfObservableInteractions
3230  % numberOfObservableNonInteractiveEvents);
3231 
3232  always_assertion(FunctionException, numberOfObservableInteractions <= obsInteractionMax,
3233  "defineObservableMask: numberOfObservableInteractions > obsInteractionMax");
3234  always_assertion(FunctionException, numberOfObservableInteractions >= obsInteractionMin,
3235  "defineObservableMask: numberOfObservableInteractions < obsInteractionMin");
3236  always_assertion(FunctionException, numberOfObservableInteractions + numberOfObservableNonInteractiveEvents >= obsMin,
3237  "defineObservableMask: numberOfObservables < obsMin");
3238  always_assertion(FunctionException, numberOfObservableInteractions + numberOfObservableNonInteractiveEvents <= obsMax,
3239  "defineObservableMask: numberOfObservables > obsMin");
3240  always_assertion(FunctionException, numberOfObservableInteractions <= interactiveEvents.size(),
3241  "defineObservableMask: numberOfObservableInteractions > interactiveEvents.size()");
3242  always_assertion(FunctionException, numberOfObservableNonInteractiveEvents <= nonInteractiveEvents.size(),
3243  "defineObservableMask: numberOfObservableNonInteractiveEvents > nonInteractiveEvents.size()");
3244 
3245  ObservableMask mask;
3246  for (ObservableComponent::EventIterator it = result.eventBegin();
3247  it != result.eventEnd();
3248  ++it) {
3249  mask.makeUnobservable(*it);
3250  }
3251 
3252 
3253  list<Event> selectedEvents;
3254  selectNRandomElements(interactiveEvents.begin(),
3255  interactiveEvents.end(),
3256  Diades::Utils::AlwaysTrue<Event>(),
3257  numberOfObservableInteractions,
3258  inserter(selectedEvents, selectedEvents.end()));
3259 
3260 
3261  // selection of non interactive observable events
3262  if (!nonInteractiveEvents.empty()) {
3263 
3264  always_assertion(FunctionException, numberOfObservableNonInteractiveEvents <= nonInteractiveEvents.size(),
3265  "defineObservableMask: numberOfObservableNonInteractiveEvents > nonInteractiveEvents.size()");
3266  selectNRandomElements(nonInteractiveEvents.begin(),
3267  nonInteractiveEvents.end(),
3268  Diades::Utils::AlwaysTrue<Event>(),
3269  numberOfObservableNonInteractiveEvents,
3270  inserter(selectedEvents, selectedEvents.end()));
3271  }
3272 
3273  for (const Event & e : selectedEvents) {
3274  mask.removeMask(e,mask.noEvent());
3275  mask.addMask(e, e);
3276  }
3277 
3278  result.setMask(mask);
3279  ensure(FunctionException, selectedEvents.size() == numberOfObservableNonInteractiveEvents + numberOfObservableInteractions,
3280  "defineObservableMask: selectedEvents.size() != numberOfObservableNonInteractiveEvents + numberOfObservableInteractions.");
3281  ensure(FunctionException,
3282  result.mask().numberOfIdentifiableEvents() == numberOfObservableNonInteractiveEvents + numberOfObservableInteractions,
3283  Msg("defineObservableMask: result.mask().numberOfIdentifiableEvents() (%1%) != numberOfObservableNonInteractiveEvents (%2%) + numberOfObservableInteractions (%3%).")
3284  % result.mask().numberOfIdentifiableEvents() % numberOfObservableNonInteractiveEvents % numberOfObservableInteractions);
3285 
3286 }
3287 
3288 /***************************************************************************************/
3289 
3302 Transition getTransitionFromInteractiveCurrentState(const ObservableComponent & interaction,
3303  State currentInteractingState,
3304  const Event & eventCurrentNode,
3305  map<Event, Topology::Connection> & mappingCurrentSideToInteraction,
3306  map<Topology::Connection, Event> & mappingConnectionToInteraction,
3307  const set<Event> & constrainedEvents) {
3308  always_require(FunctionException, currentInteractingState.valid(), "getTransitionFromInteractiveCurrentState: invalid state");
3309  Transition result;
3310  map<Event, Topology::Connection>::const_iterator connIt = mappingCurrentSideToInteraction.find(eventCurrentNode);
3311 
3312  if ((constrainedEvents.find(eventCurrentNode) != constrainedEvents.end())
3313  &&
3314  (connIt != mappingCurrentSideToInteraction.end())) {
3315 
3316  // there is a transition from currentInteractingState in interaction associated to eventFromCurrentNode
3317  ObservableComponent::OutputTransitionIterator outTransIt = interaction.outputTransitionBegin(currentInteractingState);
3318  bool found = false;
3320  Event eventInteractionSide = mappingConnectionToInteraction[connIt->second];
3321 
3322  while ((!found) && (outTransIt != interaction.outputTransitionEnd(currentInteractingState))) {
3323 
3324  found = (interaction.getEvent(*outTransIt)) == eventInteractionSide;
3325  if (!found) {
3326  ++outTransIt;
3327  }
3328  }
3329  always_assertion(FunctionException, found, "getTransitionFromInteractiveCurrentState: This case is impossible :-(, an event from the interaction should be triggered but it does not exist : bug probably in getSelectedEvents.");
3330  result = *outTransIt;
3331  }
3332  return result;
3333 }
3334 
3335 
3336 
3337 /************************************************************************************************/
3338 
3349 bool makeMinimalRequirement(unsigned outputDegreeMax, Selection<Event> & eventSelection,
3350  vector<State> & candidates, ObservableComponent & result) {
3351  bool solution = !candidates.empty();
3352  Selection<Event>::IndexIterator indexIt = eventSelection.nonSelectedIndexBegin();
3353  while (solution &&
3354  (indexIt != eventSelection.nonSelectedIndexEnd())) {
3355  unsigned int index = generateRandomValue(0, candidates.size() - 1);
3356  State source = candidates[index];
3357  ObservableComponent::StateIterator targetIt = selectRandomElement(result.numberOfStates(),
3358  result.stateBegin(),
3359  result.stateEnd());
3360 
3361 
3362  result.newTransition(source, *targetIt, eventSelection.getItem(*indexIt));
3363  if (source.outDeg() == outputDegreeMax) {
3364  candidates[index] = candidates[candidates.size() - 1];
3365  candidates.pop_back();
3366  }
3367  solution = !candidates.empty();
3368  ++indexIt;
3369  }
3370  if (!solution) {
3371  bool isViolated = indexIt != eventSelection.nonSelectedIndexEnd();
3372  while (indexIt != eventSelection.nonSelectedIndexEnd()) {
3373  // this is the case where there is no more solution,
3374  // we violate the outputDegreeMax constraint
3375  ObservableComponent::StateIterator sourceIt = selectRandomElement(result.numberOfStates(),
3376  result.stateBegin(),
3377  result.stateEnd());
3378 
3379  ObservableComponent::StateIterator targetIt = selectRandomElement(result.numberOfStates(),
3380  result.stateBegin(),
3381  result.stateEnd());
3382 
3383 
3384  result.newTransition(*sourceIt, *targetIt, eventSelection.getItem(*indexIt));
3385  ++indexIt;
3386  }
3387  if (isViolated) {
3388  // I tried my best, I give up, I violate the outputDegreeMax condition
3392  cout << "WARNING, the outputDegreeMax parameter is violated in component " << result.name() << endl;
3393  }
3394  }
3395  return solution;
3396 }
3397 
3398 
3399 /************************************************************************************************/
3400 
3409 void makeComponentComplete(unsigned outputDegreeMax, Selection<Event> & eventSelection, ObservableComponent & result) {
3410  vector<State> candidates;
3411  candidates.reserve(result.numberOfStates());
3412  for (ObservableComponent::StateIterator stateIt = result.stateBegin();
3413  stateIt != result.stateEnd();
3414  ++stateIt) {
3415  if (stateIt->outDeg() < outputDegreeMax) {
3416  candidates.push_back(*stateIt);
3417  }
3418  }
3419  if (makeMinimalRequirement(outputDegreeMax, eventSelection, candidates, result)) {
3420  // yeah we are safe all the constraints are ok, let now be a bit more random
3421  // without constraint violation
3422  while ((!candidates.empty())
3423  &&
3424  (!eventSelection.allSelected())) {
3425  // now we really select the events
3426  Event event = eventSelection.getItem(eventSelection.newSelection());
3427  unsigned nbTransForThisEvent = generateRandomValue(1, candidates.size());
3428  set<unsigned> sourceSelection;
3429  selectNValues(0, candidates.size() - 1, nbTransForThisEvent, sourceSelection);
3430  for (set<unsigned>::const_reverse_iterator selectionIt = sourceSelection.rbegin();
3431  selectionIt != sourceSelection.rend(); ++selectionIt) {
3432  ObservableComponent::StateIterator targetIt = selectRandomElement(result.numberOfStates(),
3433  result.stateBegin(),
3434  result.stateEnd());
3435  // it may happen that the source state already has an output transition
3436  // with this event. In this case, I simply do not add the new one
3437  // to keep the model deterministic
3438  if (result.outputEventTransitionBegin(candidates[*selectionIt], event)
3439  == result.outputEventTransitionEnd(candidates[*selectionIt], event)) {
3440  result.newTransition(candidates[*selectionIt], *targetIt, event);
3441  if (candidates[*selectionIt].outDeg() == outputDegreeMax) {
3442  candidates[*selectionIt] = candidates[candidates.size() - 1];
3443  candidates.pop_back();
3444  }
3445  }
3446  }
3447 
3448  }
3449  }
3450 }
3451 
3452 void generateLatexEventIndex(const Topology & topology,
3453  SharedEventNodeMap & sharedEventOfNode,
3454  const ComponentNodeMap & componentOfNode, ofstream & latexfile) {
3455  latexfile << "\n \\section{Event index}" << endl;
3456  map<Event, pair<Node, bool> > infoEvents;
3457  map<Event, pair < Topology::Connection, pair<Node, bool> > > infoSharedEvents;
3458  for (Topology::NodeIterator nodeIt = topology.nodeBegin();
3459  nodeIt != topology.nodeEnd();
3460  ++nodeIt) {
3461  for (map<Topology::Connection, Event>::const_iterator cit = sharedEventOfNode[*nodeIt].begin();
3462  cit != sharedEventOfNode[*nodeIt].end();
3463  ++cit) {
3464  infoSharedEvents[cit->second] = make_pair(cit->first, make_pair(*nodeIt, componentOfNode[*nodeIt]->mask().isIdentifiable(cit->second)));
3465  }
3466  for (ObservableComponent::EventIterator eventIt = componentOfNode[*nodeIt]->eventBegin();
3467  eventIt != componentOfNode[*nodeIt]->eventEnd();
3468  ++eventIt) {
3469  if (infoSharedEvents.find(*eventIt) == infoSharedEvents.end()) {
3470  infoEvents[*eventIt] = make_pair(*nodeIt, componentOfNode[*nodeIt]->mask().isIdentifiable(*eventIt));
3471  }
3472  }
3473  }
3474  latexfile << "\\subsection{Non shared events}" << endl;
3475  latexfile << "\n Here are the set of non-shared events of the generated model associated" << endl;
3476  latexfile << " with the component where each of them occurs. The event may be observable or not.\\\\" << endl;
3477 
3478  for (map < Event, pair < Node, bool> >::const_iterator it = infoEvents.begin();
3479  it != infoEvents.end();
3480  ++it) {
3481  latexfile << "{\\tt " << it->first.nickname() << "}: " << "{\\tt " << topology.getNodeName(it->second.first) << "} ";
3482  if (it->second.second) {
3483  latexfile << ", observable";
3484  }
3485  latexfile << "~\\\\" << endl;
3486  }
3487  latexfile << "\\subsection{Shared events}" << endl;
3488  latexfile << "\n Here are the set of shared events of the generated model associated" << endl;
3489  latexfile << " with the component where each of them occurs, the connection label involved with the event";
3490  latexfile << " followed by the clique of components involved in the connection. The event may be observable or not.\\\\" << endl;
3491 
3492 
3493 
3494  for (map < Event, pair < Topology::Connection, pair < Node, bool> > >::const_iterator it = infoSharedEvents.begin();
3495  it != infoSharedEvents.end();
3496  ++it) {
3497  latexfile << "{\\tt " << it->first.nickname() << "}: " << "{\\tt " << topology.getNodeName(it->second.second.first) << "}, ";
3498  latexfile << "{\\tt " << topology.getConnectionLabel(it->second.first) << "} $\\{$";
3499 
3500  for (Topology::CliqueIterator cliqueIt = topology.cliqueBegin(it->second.first);
3501  cliqueIt != topology.cliqueEnd(it->second.first);
3502  ++cliqueIt) {
3503  latexfile << "{\\tt " << topology.getNodeName(*cliqueIt) << "} ";
3504  }
3505  latexfile << "$\\}$";
3506  if (it->second.second.second) {
3507  latexfile << ", observable";
3508  }
3509  latexfile << "~\\\\" << endl;
3510  }
3511 }
3512 
3513 
unordered_set< Node >::const_iterator NodeIterator
Definition: Topology.hh:41
static Event getEvent(const Label &evtLabel)
void generateBehaviour(const Topology &topology, unsigned stateMin, unsigned stateMax, unsigned evtMin, unsigned evtMax, unsigned obsMin, unsigned obsMax, unsigned obsInteractionMin, unsigned obsInteractionMax, ComponentNodeMap &componentOfNode, SharedEventNodeMap &sharedEventOfNode, string dirName, Node fixedTopoNode, unsigned outputDegreeMax)
CliqueIterator cliqueBegin(Connection connection) const
Definition: Topology.hh:258
ConnectionIterator connectionBegin() const
Definition: Topology.hh:304
#define always_require(Exception, expr, message)
Definition: Assertion.hh:122
unsigned numberOfEvents() const
Definition: Component.hh:284
void generateLatexComponents(const Topology &topology, SharedEventNodeMap &sharedEventOfNode, const ComponentNodeMap &componentOfNode, ofstream &latexfile)
Some utilities to deal with the command line.
void generateLatexPreamble(const Topology &topology, unsigned stateMin, unsigned stateMax, unsigned evtMin, unsigned evtMax, unsigned obsMin, unsigned obsMax, unsigned obsInteractionMin, unsigned obsInteractionMax, unsigned seed, unsigned outputDegreeMax, const string &fixedNode, const string &behaviourFileName, map< string, string > &assignedConnections, const ComponentNodeMap &componentOfNode, SharedEventNodeMap &sharedEventOfNode, const string &filename, ofstream &latexfile)
vector< string > options(numberOfOptions)
Diades::Graph::Edge Transition
Definition: Component.hh:46
Diades::Graph::ConstNodeMap< Event > ConnectionMap
global variable to globally index the generated events
Definition: DesGenerate.cc:124
unsigned initialiseSeed()
int main(int argc, char **argv)
Definition: DesGenerate.cc:524
unsigned eventNumber
Definition: DesGenerate.cc:120
void defineObservableMask(unsigned obsMin, unsigned obsMax, unsigned obsInteractionMin, unsigned obsInteractionMax, const set< Event > &interactiveEvents, const set< Event > &nonInteractiveEvents, ObservableComponent &result)
size_t printCommandLineError(const string &msg)
Definition: CmdInterface.cc:98
void exportTopologyMap(const Topology &topology, SharedEventNodeMap &sharedEventOfNode, const ComponentNodeMap &componentOfNode, const string &mapTopoFileNameDest)
NodeIterator nodeEnd() const
Definition: Topology.hh:457
Diades::Graph::Node Connection
Definition: Topology.hh:38
void propagateConstrainedInteractions(const Topology &topology, Topology::Node node, Diades::Graph::ConstNodeMap< int > &visitedNodes, set< Topology::Node > &generatedNeighbours, set< Topology::Node > &nonGeneratedNeighbours, list< Topology::Node > &nodesToVisit)
void setVerboseLevel(Diades::Utils::VerboseLevel level)
Definition: Verbose.hh:135
bool valid() const
Definition: NodeImpl.hh:23
void generateTransitionSystem(const Topology &topology, const Node &node, SharedEventNodeMap &sharedEventOfNode, const ObservableComponent &interaction, set< Node >::const_iterator first, set< Node >::const_iterator last, unsigned numberOfStates, unsigned outputDegreeMax, ObservableComponent &result)
void makeComponentComplete(unsigned outputDegreeMax, Selection< Event > &eventSelection, ObservableComponent &result)
const Label & nickname() const
Definition: Event.hh:190
STL namespace.
const string & str() const
Definition: Identifier.hh:421
void writeComponent(const ObservableComponent &component, const string &dirName)
#define ensure(Exception, expr, message)
Definition: Assertion.hh:98
NodeConnectionIterator nodeConnectionEnd(Node n) const
Definition: Topology.hh:489
ObservableComponent * getSynchronisedInteraction(const Topology &topology, const Node &node, SharedEventNodeMap &sharedEventOfNode, const Diades::Graph::ConstNodeMap< pair< string, ObservableComponent *> > &projection, set< Node >::const_iterator first, set< Node >::const_iterator last)
StIndexes states
Definition: Run.cc:266
void selectNValues(unsigned int min, unsigned int max, unsigned int n, set< unsigned > &result)
void initialiseRandomGenerator()
void generateLatexFile(const Topology &topology, unsigned stateMin, unsigned stateMax, unsigned evtMin, unsigned evtMax, unsigned obsMin, unsigned obsMax, unsigned obsInteractionMin, unsigned obsInteractionMax, unsigned seed, unsigned outputDegreeMax, const string &fixedNode, const string &behaviourFileName, map< string, string > &assignedConnections, const ComponentNodeMap &componentOfNode, SharedEventNodeMap &sharedEventOfNode, const string &filename)
void generateSharedEvents(const Topology &topology, ComponentNodeMap &componentOfNode, SharedEventNodeMap &sharedEventOfNode, Topology::Node fixedTopoNode)
void printDebugLaw(const ParametrizedSynchronisation &synchronisation)
An observable Component defined as a automaton.
const Graph & graph() const
Definition: Topology.hh:602
Transition getTransitionFromInteractiveCurrentState(const ObservableComponent &interaction, State currentInteractingState, const Event &eventCurrentNode, map< Event, Topology::Connection > &mappingCurrentSideToInteraction, map< Topology::Connection, Event > &mappingConnectionToInteraction, const set< Event > &constrainedEvents)
void printDebugProjectionOnGeneratedNeighbours(const set< Topology::Node > &generatedNeighbours, const Diades::Graph::NodeMap< pair< string, ObservableComponent *> > &projection)
#define always_ensure(Exception, expr, message)
Definition: Assertion.hh:123
unsigned numberOfTransitions() const
Definition: Component.hh:958
NodeConnectionIterator nodeConnectionBegin(Node n) const
Definition: Topology.hh:469
unordered_set< Connection >::const_iterator ConnectionIterator
Definition: Topology.hh:40
NodeIterator nodeBegin() const
Definition: Topology.hh:447
#define debug(x)
Definition: Assertion.hh:118
unsigned numberOfIdentifiableEvents() const
Diades::Graph::ConstNodeMap< ObservableComponent * > ComponentNodeMap
Definition: DesGenerate.cc:125
void makeComponentFullyConsistent(ObservableComponent &result, const Node &node, SharedEventNodeMap &sharedEventOfNode, const ObservableComponent &interaction, map< Event, Topology::Connection > &mappingInteractionToCurrentSide, map< Event, Topology::Connection > &mappingCurrentSideToInteraction, EdgeMap< int > &triggeredTransition, NodeMap< set< State > > &stateMapping, unsigned outputDegreeMax, Selection< Event > &eventSelection)
#define always_assertion(Exception, expr, message)
Definition: Assertion.hh:124
void setInitial(State state)
Definition: Component.hh:589
Random generation utilities.
bool isValid() const
Definition: Event.hh:172
void saveAllLogs(ostream &os)
Option
Definition: abstract.cc:32
bool checkEventConsistency(const Topology &topology, unsigned evtMax, unsigned obsInteractionMin)
unsigned numberOfFileExtensions
Definition: DesGenerate.cc:89
vector< bool > isSet(numberOfOptions, false)
Diades::Graph::Node Node
Definition: Topology.hh:39
EventIterator eventBegin() const
Definition: Component.hh:328
void generateStates(ObservableComponent &result, unsigned numberOfStates, vector< Node > &indexState)
Diades::Utils::ToStream< InputIterator, Diades::Utils::AlwaysTrue< typename InputIterator::reference > > toStream(InputIterator first, InputIterator last)
Definition: Verbose.hh:143
vector< string > fileExtensions(numberOfFileExtensions)
bool isIdentifiable(const Event &e) const
Definition: Run.cc:83
const ObservableMask & mask() const
void save(const string &fileName)
string description
Definition: DesGenerate.cc:97
const Identifier & getNodeName(Node node) const
Definition: Topology.hh:98
void getSelectedEvents(const ObservableComponent &interaction, State currentInteractingState, map< Event, Topology::Connection > &mappingInteractionToCurrentSide, map< Event, Topology::Connection > &mappingCurrentSideToInteraction, map< Topology::Connection, Event > &mappingConnectionToInteraction, Selection< Event > &eventSelection, const set< Event > &constrainedEvents, const set< Topology::Connection > &constrainedConnections, unsigned numberOfVisitedStates, ObservableComponent &result, unsigned outputDegreeMax, set< Event > &selectedEvents)
void generateLatexEventIndex(const Topology &topology, SharedEventNodeMap &sharedEventOfNode, const ComponentNodeMap &componentOfNode, ofstream &latexfile)
void generateRandomComponent(const Topology &topology, const Node &node, SharedEventNodeMap &sharedEventOfNode, const ObservableComponent &interaction, set< Node >::const_iterator first, set< Node >::const_iterator last, unsigned stateMin, unsigned stateMax, unsigned obsMin, unsigned obsMax, unsigned evtMin, unsigned evtMax, unsigned obsInteractionMin, unsigned obsInteractionMax, unsigned outputDegreeMax, ObservableComponent *result)
const Identifier & getConnectionLabel(Connection connection) const
Definition: Topology.hh:114
unsigned numberOfOptions
Definition: DesGenerate.cc:88
EventIterator eventEnd() const
Definition: Component.hh:338
set< Event >::const_iterator EventIterator
Definition: Component.hh:73
unsigned getNumberOfTransitions(const Selection< Event > &eventSelection, const set< Event > &constrainedEvents, const set< Event > &constrainedTriggerableEvents, unsigned numberOfAdmissibleEvents, unsigned numberOfStatesToVisit, unsigned outputDegreeMax, bool &mustUseNewEvent)
void addMask(const Event &e, const Event &obs)
void generateTriggerableEvents(unsigned numberOfUnusedEventPerState, unsigned numberOfTrans, Component::EventIterator first, Component::EventIterator last, unsigned nbEvents, set< Event > &newSelection, set< Event > &unusedEvents)
Diades::Graph::Node State
Definition: BeliefState.hh:36
void generateLatexTopology(const Topology &topology, SharedEventNodeMap &sharedEventOfNode, ofstream &latexfile)
void setNickname(const Label &nick)
Definition: Event.hh:197
ConnectionIterator connectionEnd() const
Definition: Topology.hh:314
void initialiseSynchronisationRules(const Topology &topology, set< Node >::const_iterator first, set< Node >::const_iterator last, SharedEventNodeMap &sharedEventOfNode, const Diades::Graph::ConstNodeMap< pair< string, ObservableComponent *> > &projection, ParametrizedSynchronisation &synchronisation)
void printDebugStartVisit(const Topology &topology, Topology::Node node)
Logging facilities for the Diades projects.
void import(const string &fileName)
virtual bool project(const ObservableComponent *comp, const set< Event > &projectedEvents)
void propagateInteractingStates(ObservableComponent &result, const Node &node, SharedEventNodeMap &sharedEventOfNode, map< Event, Topology::Connection > &mappingInteractionToCurrentSide, const ObservableComponent &interaction, State state, State correspondingState, NodeMap< set< State > > &stateMapping)
void getOutputProjection(const Topology &topology, const Node &node, SharedEventNodeMap &sharedEventOfNode, const ObservableComponent &component, const set< Node > &nonGeneratedNeighbours, pair< string, ObservableComponent *> &result)
void generateLatexEpilog(ofstream &latexfile)
void initialiseOptions()
Definition: DesGenerate.cc:99
Diades::Graph::ConstNodeMap< map< Topology::Connection, Event > > SharedEventNodeMap
Definition: DesGenerate.cc:126
Option
Definition: DesGenerate.cc:81
void generateNonInteractiveEvents(const Topology &topology, Topology::Node node, unsigned evtMin, unsigned evtMax, unsigned obsMin, unsigned obsInteractionMax, ObservableComponent &result, set< Event > &nonInteractiveEvents)
unsigned connectivity(const Node &n) const
CliqueIterator cliqueEnd(Connection connection) const
Definition: Topology.hh:279
void printUsage(const po::options_description &desc)