DiaDes  0.1
DIAgnosis of Discrete-Event System
Explain.cc
Go to the documentation of this file.
1 
10 #include <cstdlib>
11 #include<iostream>
12 #include<iterator>
13 #include<fstream>
14 #include<regex>
15 #include<boost/program_options.hpp>
22 #include"../AutomataInterface.hh"
23 
24 using namespace std;
25 using namespace Diades::Automata::Experimental;
26 using namespace Diades::Utils;
27 using namespace Diades::CmdInterface;
28 
29 namespace Poptions = boost::program_options;
30 
31 
32 
37 const string program("dd-explain");
38 
39 /*
40  * File suffixes
41  */
42 FileSuffixes suffixes({"log", "ddaut", "obs", "html"});
43 
51 void
52 initialiseOptions(int argc, char * argv[],
53  Poptions::options_description & desc,
54  Poptions::variables_map & vm)
55 {
56  desc.add_options()
57  ("help,h", "produce help message")
58  ("file,f", Poptions::value< string >(), "A||P automaton file (.ddaut format)")
59  ("log,l", Poptions::value< string >(), "L log file (.log format)")
60  ("obs,s", Poptions::value< string >(), "observable event file (.obs format)")
61  ("output,o", Poptions::value< string >(), "outfile name (.ddaut format)")
62  ("web,w", Poptions::value< string >(), "html file name (.html format)")
63  ;
64  Poptions::positional_options_description p;
65  p.add("file", 1);
66  Poptions::store(Poptions::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
67  Poptions::notify(vm);
68 }
69 
70 
75 
76 
77 bool explainLog(const DdAutFA & fa,DdAutFA & explanations,DdAutFA & fullExplanations,
78  const DdAutStateManager & sManager,DdAutStateManager & sManagerExplanation,
79  const DdAutEventManager & eManager,
80  std::istream & logfile,
81  std::istream & obsfile,
82  std::unordered_map<DdAutFA::State, unordered_set<DdAutFA::Transition> > & safeAlternatives)
83 {
84  std::vector<std::string> observations;
85  std::istream_iterator<std::string> it(logfile);
86  std::istream_iterator<std::string> end;
87  while(it!=end)
88  {
89  observations.emplace_back(*it);
90  ++it;
91  }
92  Observables observables;
93  std::istream_iterator<std::string> itobs(obsfile);
94  while(itobs!=end)
95  {
96  std::for_each(eManager.begin(),eManager.end(),
97  [&](DdAutEventManager::EventId eventId)
98  {
99  if(eManager.getEvent(eventId).find(*itobs)!=DdAutEventManager::Event::npos)
100  {
101  observables.insert(eventId);
102  }
103  });
104  ++itobs;
105  }
106  return explain(fa, sManager, eManager, observations, observables, explanations,
107  fullExplanations,sManagerExplanation,safeAlternatives);
108 }
109 
110 
112  const DdAutStateManager & sManager,
113  DdAutFA & explanations,
114  DdAutStateManager & sManagerExplanation,
115  const SafeAlt<DdAutFA> & safeAlternatives)
116 {
117  for(auto stateSafeAlternatives: safeAlternatives)
118  {
119  auto explSafeSourceId = explanations.getStatePropertyId( stateSafeAlternatives.first);
120  for(auto safeTrans : stateSafeAlternatives.second)
121  {
122  auto fsaSafeSourceId = fsa.getStatePropertyId(safeTrans.source());
123  auto fsaSafeTargetId = fsa.getStatePropertyId(safeTrans.target());
124  auto explSafeTargetId = sManagerExplanation.statePropertyId("safe_" + sManager.getStateProperty(fsaSafeSourceId) + "->" + sManager.getStateProperty(fsaSafeTargetId));
125  explanations.newTransition(explSafeSourceId,explSafeTargetId,fsa.getEvent(safeTrans));
126  }
127  }
128 }
129 
130 
131 void writeTreeViewSafeAlternative(std::ostream & html,
132  const DdAutFA & fa,
133  const DdAutStateManager & sManager,
134  const DdAutEventManager & eManager,
136 {
137 
138  html << listSingleItem("Safe alternative: from state "
139  + sManager.getStateProperty(fa.getStatePropertyId(t.source()))
140  + " to state "
141  + sManager.getStateProperty(fa.getStatePropertyId(t.target()))
142  + " by event "
143  + eManager.getEvent(fa.getEvent(t))
144  + ".") << "\n";
145 }
146 
147 
148 void writeTreeViewTransition(std::ostream & html,
149  const DdAutFA & fa,
150  const DdAutStateManager & sManager,
151  const DdAutEventManager & eManager,
152  const DdAutFA & explanation,
153  const DdAutStateManager & sManagerExplanation,
154  const SafeAlt<DdAutFA> & safeAlternatives,
155  DdAutFA::Transition transition)
156 {
157  using Fsm = DdAutFA;
158  using Transition = typename Fsm::Transition;
159 
160  if(explanation.isAcceptingState(transition.target()))
161  {
162  html << listSingleItem("Event "
163  +
164  eManager.getEvent(explanation.getEvent(transition))
165  +
166  " leading to state "
167  +
168  sManagerExplanation.getStateProperty(explanation.getStatePropertyId(transition.target()))
169  +
170  " violates the property.") << "\n";
171 
172 
173  }
174  else
175  {
176  html << startListCaretItem("Event "
177  +
178  eManager.getEvent(explanation.getEvent(transition))
179  +
180  " leading to state "
181  +
182  sManagerExplanation.getStateProperty(explanation.getStatePropertyId(transition.target())))
183  << "\n"
184  << startNestedTree()
185  << "\n";
186  std::for_each(explanation.outputTransitionBegin(transition.target()),
187  explanation.outputTransitionEnd(transition.target()),
188  [&](Transition t)
189  {
190  writeTreeViewTransition(html,fa,sManager,eManager,explanation,sManagerExplanation,safeAlternatives,t);
191  });
192  auto altIt = safeAlternatives.find(transition.target());
193  if(altIt != safeAlternatives.end())
194  {
195  const auto & safeAlt = altIt->second;
196  std::for_each(safeAlt.begin(),safeAlt.end(),
197  [&](Transition t)
198  {
199  writeTreeViewSafeAlternative(html,fa,sManager,eManager,t);
200  });
201 
202  }
203  html << endNestedTree()
204  << "\n"
205  << endListCaretItem()
206  << "\n";
207 
208  }
209 
210 }
211 
212 
213 
214 void writeTreeView(std::ostream & html,
215  const DdAutFA & fa,
216  const DdAutStateManager & sManager,
217  const DdAutEventManager & eManager,
218  const DdAutFA & explanation,
219  const DdAutStateManager & sManagerExplanation,
220  const SafeAlt<DdAutFA> & safeAlternatives)
221 {
222  using Fsm = DdAutFA;
223  using Transition = typename Fsm::Transition;
224  toTreeViewHtmlStart(html);
225  html << startTree("myexplanation") << "\n";
226  for(auto it = explanation.initialStateBegin();
227  it != explanation.initialStateEnd();
228  ++it)
229  {
230  if(it->outDeg()==0)
231  {
232  html << listSingleItem(sManagerExplanation.getStateProperty(explanation.getStatePropertyId(*it))) << "\n";
233  }
234  else
235  {
236  html << startListCaretItem(sManagerExplanation.getStateProperty(explanation.getStatePropertyId(*it)))
237  << "\n"
238  << startNestedTree()
239  << "\n";
240  std::for_each(explanation.outputTransitionBegin(*it),
241  explanation.outputTransitionEnd(*it),
242  [&](Transition t)
243  {
244  writeTreeViewTransition(html,fa,sManager,eManager,explanation,sManagerExplanation,safeAlternatives,t);
245  });
246  auto altIt = safeAlternatives.find(*it);
247  if(altIt != safeAlternatives.end())
248  {
249  const auto & safeAlt = altIt->second;
250  std::for_each(safeAlt.begin(),safeAlt.end(),
251  [&](Transition t)
252  {
253  writeTreeViewSafeAlternative(html,fa,sManager,eManager,t);
254  });
255 
256  }
257  html << endNestedTree()
258  << "\n"
259  << endListCaretItem()
260  << "\n";
261  }
262  html << endTree();
263  toTreeViewHtmlEnd(html);
264  }
265 }
266 
267 
268 
275 size_t
276  explainFsm(const std::string & fileName,
277  const std::string & logName,
278  const std::string & observableName,
279  const std::string & output,
280  const std::string & htmlName)
281 {
282 
283  if(!suffixes.match(fileName, "ddaut"))
284  {
285  return printCommandLineError(Msg("Expecting a file with a name ending with .ddaut, but I read %1%") % fileName);
286  }
287  if(!suffixes.match(logName,"log"))
288  {
289  return printCommandLineError(Msg("Expecting a file with a name ending with .log, but I read %1%") % fileName);
290  }
291  if(!suffixes.match(observableName,"obs"))
292  {
293  return printCommandLineError(Msg("Expecting a file with a name ending with .obs, but I read %1%") % fileName);
294  }
295 
296  DdAutFileDescriptor descriptor;
297  DdAutEventManager eManager;
298  DdAutStateManager sManager;
299  DdAutStateManager sManagerExplanation;
300  ifstream file(fileName.c_str());
301  if(file.is_open())
302  {
303  auto loaded = descriptor.readStream(file);
304  file.close();
305  if(!loaded)
306  {
307  return printCommandLineError(Msg("Error when loading the 'ddaut' automaton file %1%") % fileName);
308  }
309  }
310  else
311  {
312  return printCommandLineError(Msg("Error when opening the 'ddaut' automaton file %1%") % fileName);
313  }
314  if(descriptor.acceptorBegin() == descriptor.acceptorEnd())
315  {
316  return printCommandLineError(Msg("Error the 'ddaut' automaton file %1% has no acceptor states that assert how the behaviour of the system can violate a given property") % fileName);
317  }
318  DdAutFA fa;
319  if(!faFromDescriptor(descriptor, fa, sManager, eManager))
320  {
321  return printCommandLineError(Msg("Error cannot read the descriptor of the 'ddaut' automaton file %1%, BUG") % fileName);
322  }
323  ifstream logfile(logName.c_str());
324  if(!logfile.is_open())
325  {
326  return printCommandLineError(Msg("Error when opening the 'log' file %1%") % logName);
327  }
328  ifstream obsfile(observableName.c_str());
329  if(!obsfile.is_open())
330  {
331  return printCommandLineError(Msg("Error when opening the 'obs' file %1%") % observableName);
332  }
333 
334  DdAutFA explanation;
335  DdAutFA fullExplanation;
336  SafeAlt<DdAutFA> safeAlternatives;
337  if(!explainLog(fa,explanation,fullExplanation,
338  sManager,sManagerExplanation,eManager,
339  logfile,obsfile,safeAlternatives))
340  {
341  return printCommandLineError(Msg("Error in the explanation phase of why system %1% violates the safety property based on the observations %2% and the observability of the system defined in %3%") % fileName % logName % observableName);
342  }
343 
344  if(!htmlName.empty())
345  {
346  if(!suffixes.match(htmlName, "html"))
347  {
348  printCommandLineWarning(Msg("Expecting a file with a name ending with .html, but I read %1% so I do not export the explanation tree.") % htmlName);
349  }
350  else
351  {
352  ofstream htmlfile(htmlName.c_str());
353  if(!htmlfile.is_open())
354  {
355  printCommandLineWarning(Msg("Error when opening the 'html' file %1% so I do not export the explanation tree.") % logName);
356  }
357  writeTreeView(htmlfile,fa,sManager,eManager,explanation,sManagerExplanation,safeAlternatives);
358  htmlfile.close();
359  }
360  }
361  consolidateWithSafeAlternatives(fa,sManager,explanation,sManagerExplanation,safeAlternatives);
362  writeFiniteAutomaton({explanation, sManagerExplanation, eManager}, output, suffixes);
363  return writeFiniteAutomaton({fullExplanation, sManagerExplanation, eManager}, "full_" + output, suffixes);
364 }
365 
372 int
373 main(int argc, char** argv)
374 {
375  std::string fileName, output, logName, observableName, htmlName;
376  try
377  {
378  Poptions::options_description desc("Options");
379  Poptions::variables_map vm;
380  initialiseOptions(argc, argv, desc, vm);
381  if(vm.count("help"))
382  {
383  return printUsage(program, desc);
384  }
385  if(vm.count("file"))
386  {
387  fileName = vm["file"].as<std::string>();
388  }
389  if(vm.count("log"))
390  {
391  logName = vm["log"].as<std::string>();
392  }
393  if(vm.count("output"))
394  {
395  output = vm["output"].as<std::string>();
396  }
397  if(vm.count("obs"))
398  {
399  observableName = vm["obs"].as<std::string>();
400  }
401  if(vm.count("web"))
402  {
403  htmlName = vm["web"].as<std::string>();
404  }
405  }
406  catch(Poptions::required_option & e)
407  {
408  return printCommandLineError(e.what());
409  }
410  catch(Poptions::error & e)
411  {
412  return printCommandLineError(e.what());
413  }
414  return explainFsm(fileName,logName,observableName,output,htmlName);
415 }
416 
InfoIdIterator end() const
Definition: InfoManager.hh:428
void initialiseOptions(int argc, char *argv[], Poptions::options_description &desc, Poptions::variables_map &vm)
Definition: Explain.cc:52
std::string startListCaretItem(const std::string &item)
StatePropertyManager< DdAutStateLabel, DdAutStateId > DdAutStateManager
Definition: DdAutFile.hh:63
Transition newTransition(State source, State target, const EventPropertyId &event)
bool explainLog(const DdAutFA &fa, DdAutFA &explanations, DdAutFA &fullExplanations, const DdAutStateManager &sManager, DdAutStateManager &sManagerExplanation, const DdAutEventManager &eManager, std::istream &logfile, std::istream &obsfile, std::unordered_map< DdAutFA::State, unordered_set< DdAutFA::Transition > > &safeAlternatives)
Definition: Explain.cc:77
StatePropertyId statePropertyId(const StateProperty &stateProperty)
void writeTreeViewTransition(std::ostream &html, const DdAutFA &fa, const DdAutStateManager &sManager, const DdAutEventManager &eManager, const DdAutFA &explanation, const DdAutStateManager &sManagerExplanation, const SafeAlt< DdAutFA > &safeAlternatives, DdAutFA::Transition transition)
Definition: Explain.cc:148
size_t writeFiniteAutomaton(const Diades::Automata::Experimental::ConstManagedDdAutFA &mfa, const std::string &output, const FileSuffixes &suffixes)
size_t printCommandLineError(const string &msg)
Definition: CmdInterface.cc:98
bool faFromDescriptor(const DdAutFileDescriptor &descriptor, DdAutFA &fa, DdAutStateManager &sManager, DdAutEventManager &eManager)
size_t explainFsm(const std::string &fileName, const std::string &logName, const std::string &observableName, const std::string &output, const std::string &htmlName)
Definition: Explain.cc:276
FaultyEventStateMachine< CandidateId, EventInfoId > Fsm
std::ostream & toTreeViewHtmlStart(std::ostream &os)
STL namespace.
vector< string > options(numberOfOptions)
OutputTransitionIterator outputTransitionBegin(State s) const
InitialStateIterator initialStateEnd() const
std::string listSingleItem(const std::string &item)
void writeTreeViewSafeAlternative(std::ostream &html, const DdAutFA &fa, const DdAutStateManager &sManager, const DdAutEventManager &eManager, DdAutFA::Transition t)
Definition: Explain.cc:131
bool explain(const DdAutFA &fsa, const DdAutStateManager &sManager, const DdAutEventManager &eManager, const std::vector< std::string > &observations, Observables &observables, DdAutFA &explanations, DdAutFA &fullExplanations, DdAutStateManager &sManagerExplanation, std::unordered_map< DdAutFA::State, unordered_set< DdAutFA::Transition > > &safeAlternatives)
Definition: Explanation.hh:555
InfoIdIterator begin() const
Definition: InfoManager.hh:418
bool match(const std::string &fileName, const std::string &suffix) const
Definition: CmdInterface.cc:54
AutFsm::Transition Transition
Definition: Run.cc:73
std::string startTree(const std::string &treeId)
const EventPropertyId & getEvent(Transition t) const
FiniteAutomaton< DdAutStateId, DdAutEventId > DdAutFA
Definition: DdAutFile.hh:47
const Event & getEvent(EventId id) const
Definition: Event.hh:183
OutputTransitionIterator outputTransitionEnd(State s) const
FileSuffixes suffixes({"log", "ddaut", "obs", "html"})
std::ostream & toTreeViewHtmlEnd(std::ostream &os)
size_t printCommandLineWarning(const string &msg)
InitialStateIterator initialStateBegin() const
EventManager< DdAutEventLabel, DdAutEventId > DdAutEventManager
Definition: DdAutFile.hh:68
std::set< DdAutFA::EventPropertyId > Observables
Definition: Explanation.hh:238
void writeTreeView(std::ostream &html, const DdAutFA &fa, const DdAutStateManager &sManager, const DdAutEventManager &eManager, const DdAutFA &explanation, const DdAutStateManager &sManagerExplanation, const SafeAlt< DdAutFA > &safeAlternatives)
Definition: Explain.cc:214
void consolidateWithSafeAlternatives(const DdAutFA &fsa, const DdAutStateManager &sManager, DdAutFA &explanations, DdAutStateManager &sManagerExplanation, const SafeAlt< DdAutFA > &safeAlternatives)
Definition: Explain.cc:111
int main(int argc, char **argv)
Definition: Explain.cc:373
boost::format Msg
Definition: Verbose.hh:42
const StatePropertyId & getStatePropertyId(State state) const
const string program("dd-explain")
const StateProperty & getStateProperty(StatePropertyId id) const
std::unordered_map< typename Fsm::State, std::unordered_set< typename Fsm::Transition > > SafeAlt
Definition: Explanation.hh:377
virtual bool readStream(std::istream &stream)
void printUsage(const po::options_description &desc)