DiaDes  0.1
DIAgnosis of Discrete-Event System
TrimState.cc
Go to the documentation of this file.
1 
42 #include <cstdlib>
43 #include<iostream>
44 #include<fstream>
45 #include<regex>
46 #include<boost/program_options.hpp>
47 
50 #include"../AutomataInterface.hh"
54 using namespace std;
55 using namespace Diades::Automata::Experimental;
56 using namespace Diades::Utils;
57 using namespace Diades::CmdInterface;
58 
59 namespace Poptions = boost::program_options;
60 
61 
62 
67 const string program("dd-trimstates");
68 const string briefcomment(": this program removes some states from the given ddaut automaton and\n write as output the new automaton (output file or standard output).\n\n");
69 const string detailedcomment=R"(dd-trimstates removes some states from the given ddaut automaton and
70 writes as output the new automaton (output file or standard output). The states to
71 remove can be characterised by a regular expression regexp so that if the label
72 of the state matches the regular expression, it is simply removed (and all the transitions
73 involved with this state).
74 
75 Here is a first example:
76 
77  dd-trimstates file.ddaut -r '.*o\.p=ko.*'
78 
79 In this example, we ask to remove the states in file.ddaut labeled with string such
80 that it contains the substring 'o.p=ko'. dd-trimstates can also be used to remove
81 deadlocks in file.ddaut, as follows:
82 
83  dd-trimstates file.ddaut --no-deadlock
84 
85 It is also possible to remove deadlocks by automatically disabling some controllable events
86 (see Ramadge and Wonham theory). In the following example, dd-trimstates will simply disable
87 some controllable events from some states to ensure that the result has no deadlocks. A file
88 with a 'cont' suffix is a file that contains a list of events, one per line.
89 
90 dd-trimstates file.ddaut --no-deadlock -c controllable.cont
91 
92 It is also possible to combine both type of operations like:
93 
94 dd-trimstates file.ddaut --no-deadlock -c controllable.cont -r '.*o\.p=ko.*'
95 
96 In this case, the program will first remove the states '.*o\.p=ko.*' and then remove
97 deadlocks by disabling controllable events.
98 )";
99 
100 
101 /*
102  * File suffixes
103  */
104 FileSuffixes suffixes({"ddaut","cont"});
105 
113 void
114 initialiseOptions(int argc, char * argv[],
115  Poptions::options_description & desc,
116  Poptions::variables_map & vm)
117 {
118  desc.add_options()
119  ("help,h", "produce help message")
120  ("file,f", Poptions::value< string >(), "file (.ddaut format)")
121  ("regexp,r", Poptions::value< string >(), "regular expression on the name of the states inside a set of quotes: 'regexp' for details see\n http://www.cplusplus.com/reference/regex/ECMAScript/")
122  ("output,o", Poptions::value< string >(), "outfile name (.ddaut format)")
123  ("controllable,c", Poptions::value< string >(), "controllable event name (.cont format, single list of events, one per line)")
124  ("no-deadlock", "removing deadlocks")
125  ("verbose", "verbose mode")
126  ;
127  Poptions::positional_options_description p;
128  // 1 that The command line can accept 1 file name as positional option
129  p.add("file", 1);
130  Poptions::store(Poptions::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
131  Poptions::notify(vm);
132 }
133 
134 
140 
141 size_t readControllableEvents(const string & contName,
142  std::set<std::string> & controllable)
143 {
144  if(!contName.empty())
145  {
146  ifstream file(contName.c_str());
147  if(file.is_open())
148  {
149  std::istream_iterator<std::string> it(file);
150  std::istream_iterator<std::string> end;
151  while(it!=end)
152  {
153  controllable.insert(*it);
154  ++it;
155  }
156  file.close();
157  }
158  else
159  {
160  return printCommandLineError(Msg("Error when opening the 'cont' automaton file %1%") % contName);
161  }
162  }
163  return SUCCESS;
164 }
165 
166 size_t
167 trimDdAutStates2(const string & fileName, const string & output, const string & regexp,const string & contName, bool noDeadLock, bool verbose)
168  {
169  DdAutFsm fsm;
170  DdAutFileDescriptor descriptor;
171  DdAutEventManager eManager;
172  DdAutStateManager sManager;
173  ifstream file(fileName.c_str());
174  if(file.is_open())
175  {
176  auto loaded = descriptor.readStream(file);
177  file.close();
178  if(!loaded)
179  {
180  return printCommandLineError(Msg("Error when loading the 'ddaut' automaton file %1%") % fileName);
181  }
182  }
183  else
184  {
185  return printCommandLineError(Msg("Error when opening the 'ddaut' automaton file %1%") % fileName);
186  }
187  DdAutFA fa;
188  bool result = faFromDescriptor(descriptor, fa, sManager, eManager);
189  if(!result)
190  {
191  return printCommandLineError(Msg("Error when converting the DdAutFileDescriptor from %1% to a Finite Automaton") % fileName);
192  }
193  if(verbose)
194  {
195  std::cout << "Verbose mode is on.\n";
196  }
197  if(!regexp.empty())
198  {
199  if(verbose)
200  {
201  std::cout << "Trimming states whose label matches the following regular expression: " << regexp << "\n";
202  }
203  std::regex reg(regexp);
204  for(const auto & stateProperty: sManager.storage())
205  {
206  if(std::regex_match(stateProperty,reg))
207  {
208  if(verbose)
209  {
210  std::cout << "Deleting state: " << stateProperty << "\n";
211  }
212  fa.deleteState(fa.getState(sManager.statePropertyId(stateProperty)));
213  }
214  }
215  }
216  if(verbose && regexp.empty())
217  {
218  std::cout << "No regular expression found.\n";
219  }
220 
221  if(noDeadLock)
222  {
223  if(verbose)
224  {
225  std::cout << "Need to trim deadlock states.\n";
226  }
227  ControlPattern pattern(fa);
228  std::set<std::string> controllable;
229  readControllableEvents(contName,controllable);
230  if(verbose)
231  {
232  std::cout << "Controllable events:\n";
233  }
234  std::for_each(fa.eventBegin(),fa.eventEnd(),
235  [&](const Event & e)
236  {
237  bool found = false;
238  if(controllable.empty())
239  {
240  pattern.disable(e);
241  }
242  else
243  {
244  auto it = controllable.begin();
245  while(!found && it!=controllable.end())
246  {
247  found= eManager.getEvent(e).find(*it)!=std::string::npos;
248  if(!found) { ++it; }
249  }
250  if(found)
251  {
252  if(verbose)
253  {
254  std::cout << eManager.getEvent(e) << " (-> " << *it << ")\n";
255  }
256  pattern.disable(e);
257  }
258  }
259  });
260  std::list<DdAutFsm::StatePropertyId> stateIds;
261  std::list<std::pair<DdAutFsm::StatePropertyId, DdAutFsm::EventPropertyId>> disabled;
262 if(!controlledTrimmingDeadlockState(fa, pattern,fa.stateBegin(),fa.stateEnd(),std::inserter(stateIds,stateIds.begin()),
263  std::inserter(disabled,disabled.begin())))
264  {
265  return printCommandLineError("The result is empty, check that it is really what you want to do.");
266  }
267  if(verbose)
268  {
269  for(const auto & d : disabled)
270  {
271  std::cout << "Disabling "
272  << eManager.getEvent(d.second)
273  << " from state "
274  << sManager.getStateProperty(d.first)
275  << "\n";
276  }
277  for(const auto & id: stateIds)
278  {
279  std::cout << "Deleting state: " << sManager.getStateProperty(id) << "\n";
280  }
281  }
282  }
283  if(output.empty())
284  {
285  if(verbose)
286  {
287  std::cout << "Writing resulting finite-state machine herebelow:\n";
288  }
289  faToDdAutFile(std::cout, {fa, sManager, eManager});
290  }
291  else
292  {
293  if(verbose)
294  {
295  std::cout << "Writing resulting finite-state machine in " << output << "\n";
296  }
297  ofstream outfile(output.c_str());
298  if(outfile.is_open())
299  {
300  faToDdAutFile(outfile, {fa, sManager, eManager});
301  outfile.close();
302  if(verbose)
303  {
304  std::cout << "done.\n";
305  }
306  return SUCCESS;
307  }
308  else
309  {
310  return printCommandLineError(Msg("Error when creating the dot file %1%") % output);
311  }
312  }
314 }
315 
316 
317 size_t
318 trimDdAutStates(const string & fileName, const string & output, const string & regexp, const string & contName, bool noDeadLock, bool verbose)
319 {
320  if(!output.empty())
321  {
322  if(!suffixes.match(output, "ddaut"))
323  {
324  return printCommandLineError(Msg("Expecting an output file with a name ending with .ddaut, but I read %1%") % output);
325  }
326  }
327  if(!contName.empty())
328  {
329  if(!suffixes.match(contName, "cont"))
330  {
331  return printCommandLineError(Msg("Expecting a file containing a list of controllable events with a name ending with .cont, but I read %1%") % contName);
332  }
333 
334  }
335 
336  if(suffixes.match(fileName, "ddaut"))
337  {
338  return trimDdAutStates2(fileName, output,regexp,contName,noDeadLock,verbose);
339  }
340  else
341  {
342  return printCommandLineError(Msg("Expecting a file with a name ending with .ddaut, but I read %1%") % fileName);
343  }
345 }
346 
347 
354  int
355  main(int argc, char** argv)
356  {
357  std::string fileName, output, contName;
358  std::string regexp;
359  bool deadlock = false;
360  bool verbose = false;
361  try
362  {
363 
364  Poptions::options_description desc("Options");
365  Poptions::variables_map vm;
366  initialiseOptions(argc, argv, desc, vm);
367  if(vm.count("help"))
368  {
370  }
371  if(vm.count("file"))
372  {
373  fileName = vm["file"].as<std::string> ();
374  }
375  if(vm.count("output"))
376  {
377  output = vm["output"].as<std::string>();
378  }
379  if(vm.count("regexp"))
380  {
381  regexp = vm["regexp"].as<std::string>();
382  }
383  if(vm.count("no-deadlock"))
384  {
385  deadlock = true;
386  }
387  if(vm.count("verbose"))
388  {
389  verbose = true;
390  }
391  if(vm.count("controllable"))
392  {
393  contName = vm["controllable"].as<std::string> ();
394  }
395  }
396  catch(Poptions::required_option & e)
397  {
398  return printCommandLineError(e.what());
399  }
400  catch(Poptions::error & e)
401  {
402  return printCommandLineError(e.what());
403  }
404 
405 
406  return trimDdAutStates(fileName, output,regexp, contName, deadlock, verbose);
407  }
408 
409 
size_t readControllableEvents(const string &contName, std::set< std::string > &controllable)
Definition: TrimState.cc:141
EventPropertyIdIterator eventEnd() const
Set of functions that trim states/transitions from StateMachines.
const size_t SUCCESS
Definition: CmdInterface.hh:34
StatePropertyManager< DdAutStateLabel, DdAutStateId > DdAutStateManager
Definition: DdAutFile.hh:63
StatePropertyId statePropertyId(const StateProperty &stateProperty)
const size_t ERROR_UNHANDLED_EXCEPTION
Definition: CmdInterface.hh:35
size_t printCommandLineError(const string &msg)
Definition: CmdInterface.cc:98
bool faFromDescriptor(const DdAutFileDescriptor &descriptor, DdAutFA &fa, DdAutStateManager &sManager, DdAutEventManager &eManager)
STL namespace.
vector< string > options(numberOfOptions)
A control pattern is a mapping between the set of Events of a StateMachine and a Boolean.
bool faToDdAutFile(ostream &stream, const ConstManagedDdAutFA &mFa)
const string detailedcomment
Definition: TrimState.cc:69
bool match(const std::string &fileName, const std::string &suffix) const
Definition: CmdInterface.cc:54
DdAutFsm::EventPropertyId Event
Definition: TrimState.cc:139
void initialiseOptions(int argc, char *argv[], Poptions::options_description &desc, Poptions::variables_map &vm)
Definition: TrimState.cc:114
bool controlledTrimmingDeadlockState(Fsm &machine, ControlPattern< Fsm > &pattern, BeliefStateIterator bfBegin, BeliefStateIterator bfEnd, StateIdInsertIterator insertIt, DisableInsertIterator disableIt)
remove deadlock states of the machine by exploiting the events that are disabled in the current Contr...
Definition: Trimming.hh:258
bool disable(const Event &e)
Disable an event of the StateMachine.
virtual void deleteState(State state)
delete state
const Event & getEvent(EventId id) const
Definition: Event.hh:183
size_t trimDdAutStates(const string &fileName, const string &output, const string &regexp, const string &contName, bool noDeadLock, bool verbose)
Definition: TrimState.cc:318
FileSuffixes suffixes({"ddaut","cont"})
size_t trimDdAutStates2(const string &fileName, const string &output, const string &regexp, const string &contName, bool noDeadLock, bool verbose)
Definition: TrimState.cc:167
const string program("dd-trimstates")
EventPropertyIdIterator eventBegin() const
Diades::Utils::Verbose verbose(const char *msg)
Definition: Verbose.hh:126
EventManager< DdAutEventLabel, DdAutEventId > DdAutEventManager
Definition: DdAutFile.hh:68
const string briefcomment(": this program removes some states from the given ddaut automaton and\ write as output the new automaton (output file or standard output).\")
StateMachine< DdAutStateId, DdAutEventId > DdAutFsm
Definition: DdAutFile.hh:42
boost::format Msg
Definition: Verbose.hh:42
const std::vector< Info > & storage() const
Definition: InfoManager.hh:408
const StateProperty & getStateProperty(StatePropertyId id) const
int main(int argc, char **argv)
Definition: TrimState.cc:355
State getState(const StatePropertyId &sProperty) const
virtual bool readStream(std::istream &stream)
void printUsage(const po::options_description &desc)