DiaDes  0.1
DIAgnosis of Discrete-Event System
SymbolicDiagnose.cc
Go to the documentation of this file.
1 
6 #include<iostream>
7 #include<string>
8 #include<vector>
9 #include<regex>
10 #include <fstream>
11 #include<boost/program_options.hpp>
22 
23 using std::cout;
24 using std::string;
25 using std::vector;
35 
36 
37 
38 namespace Poptions = boost::program_options;
40 
41 const string program("dd-symb-diagnose");
42 
43 void initialiseOptions(int argc, char * argv[],
44  Poptions::options_description & desc,
45  Poptions::options_description & visible,
46  Poptions::variables_map & vm) {
47  visible.add_options()
48  ("help", "produce help message")
49  ("scenario", Poptions::value< string >(), "scenario file (evts format), mandatory");
50 
51  Poptions::options_description hidden("Hidden options");
52  hidden.add_options()
53  ("model-file", Poptions::value< vector<string> >(), "model file (des_comp format)");
54  Poptions::positional_options_description p;
55  p.add("model-file", -1);
56  desc.add(visible).add(hidden);
57  Poptions::store(Poptions::command_line_parser(argc, argv).
58  options(desc).positional(p).run(), vm);
59  Poptions::notify(vm);
60 }
61 
62 void printErrorCmdLine(const string & msg, Poptions::options_description & visible) {
63  cout << msg << '\n';
64  cout << "Command line error: here is the usage\n"
65  << program << " [model.des_comp]\n" << visible << '\n';
66  exit(0);
67 }
68 
69 void printError(const string & msg) {
70  cout << msg << '\n';
71  exit(0);
72 }
73 
74 void analyseOptions(Poptions::variables_map & vm,
75  Poptions::options_description & visible,
76  vector<string> & models,
77  vector<string> & scenarios) {
78  if (vm.count("help")) {
79  cout << "Usage: " << program << " [model.des_comp]\n"
80  << visible << "\n";
81  exit(0);
82  }
83  if (!vm.count("model-file")) {
84  printErrorCmdLine("A model file is missing.", visible);
85  }
86  auto & modelNames = vm["model-file"].as<vector < string >> ();
87  if (modelNames.size() > 1) {
88  printError("Only one model file is allowed.");
89  }
90  if (!vm.count("scenario")) {
91  printErrorCmdLine("A scenario file is missing", visible);
92  }
93 
94  std::regex desCompSuffix("[a-zA-Z_][a-zA-Z_0-9]*\\.des_comp");
95  if (!std::regex_match(modelNames[0], desCompSuffix)) {
96  printError("Expecting a model file with a name ending with .des_comp");
97  }
98 
99  auto & scenarioName = vm["scenario"].as<string>();
100  std::regex evtsSuffix("[a-zA-Z_][a-zA-Z_0-9]*\\.evts");
101  if (!std::regex_match(scenarioName, evtsSuffix)) {
102  printError("Expecting a scenario file with a name ending with .evts");
103  }
104  models.push_back(modelNames[0]);
105  scenarios.push_back(scenarioName);
106 }
107 
108 bool loadModels(const vector<string> & modelNames,
109  vector<ObservableComponent> & models) {
110  bool result = true;
111  size_t index = 0;
112  while (result && (index < modelNames.size())) {
113  models.push_back(ObservableComponent());
114  result = models.back().import(modelNames[index]);
115  ++index;
116  }
117  return result;
118 }
119 
120 bool loadScenario(const string & scenarioFile, vector<Event> & observations,
121  const vector<ObservableComponent> & models) {
122  ifstream file(scenarioFile);
123  bool result = file.is_open();
124  if (result) {
125  while (result && file) {
126  string label;
127  file >> label;
128  if (!label.empty()) {
129  observations.push_back(Event::getEvent(label));
130  result = models[0].containsEvent(observations.back());
131  }
132  }
133  file.close();
134  }
135  return result;
136 
137 }
138 
139 void printSolution(const BddStateMachine::SlEvents & solution,
140  StateInfoEncoder & stateEncoder,
141  Lcm::CandidateManager & candManager,
142  Lcm::EvSetManager & setManager,
143  Lcm::LocalStateInfoManager & locStateInfoManager,
144  Lcm::EvManager & manager) {
145  std::list< std::list<Assignment> > listSolutions;
146  exportToDisjunctiveNormalForm(solution, listSolutions);
147 
148  std::cout << "Here is the solution:" << std::endl;
149  size_t counter = 0;
150  // listSolutions is a list (disjunction) of conjunction of Assignments: such a conjunction is candidate
151  for (auto & candidate : listSolutions) {
152  // a candidate is a list (conjunction) of Assignments
153  std::cout << "Candidate " << counter++ << ": {";
154  for (auto & fault : candidate) {
155  // first I get the CandidateId associated with the Value of the Variable in the Assignement 'fault'
156  // This CandidateId is the StateInfoId of the CandidateManager (i.e. a StateInfoManager<Candidate>)
157  // I retrieve the StateInfoId from the stateEncoder.
158  Lcm::CandidateId candId = stateEncoder.getStateInfoId(fault).first;
159 
160  // Then I can get the corresponding Candidate associated with candId.first
161  // This Candidate is stored in the CandidateManager=StateInfoManager<Candidate>
162  const Lcm::Candidate & faultCandidate = candManager.getStateProperty(candId);
163 
164 
165  // A Candidate is actually in Lcm a LocalCandidate<LocalStateInfoId,EvSet>
166  // So I can get the LocalStateInfoId of the Candidate and its EvSet
167  auto & state = faultCandidate.state();
168  auto & faults = faultCandidate.faults();
169 
170  // From the EvSet I can get back a vector of Lcm::Event thanks to the EventSetManager
171  vector<Lcm::EventInfoId> faultEvents = setManager.decodeEventSet(faults);
172 
173  // From the LocalStateInfoId I can get the LocalStateInfo = StateInfoStringLabel
174  // that is the actual information about a state of the component
175  std::cout << "state = " << locStateInfoManager.getStateProperty(state) << " ";
176 
177 
178  // From a vector of Lcm::Event I can get the label of the event thanks to the EventManager
179  std::cout << "faults = ";
180  for (auto evt : faultEvents) {
181  std::cout << evt << "<->" << manager.getEvent(evt) << " ";
182  }
183  // DONE !
184  }
185  std::cout << "}\n";
186  }
187 }
188 
190  const vector<Event> & observations) {
191  Lcm::EvManager manager;
192  Lcm::EvSetManager setManager;
193  Lcm::LocalStateInfoManager locStateInfoManager;
194  Lcm::CandidateManager candManager;
195  Lcm::Fsm result;
197  manager,
198  setManager,
199  locStateInfoManager,
200  candManager,
201  result);
202 
203  vector<Lcm::EventInfoId> observables;
204  vector<Lcm::EventInfoId> nonObservables;
205 
206 
207  // dealing with observables/non observables
208  for (auto & e : component.events()) {
209  if (component.mask().isIdentifiable(e)) {
210  observables.push_back(manager.eventId(e.label()));
211  } else {
212  nonObservables.push_back(manager.eventId(e.label()));
213  }
214  }
215 
216 
217  // result contains a Lcm::Fsm, let us convert to a BddStateMachine
218  // First I need a VariableFactory to get Variables
219  VariableFactory varFactory;
220 
221  // Then an EventEncoder to create the Variable that encodes events
222  EventEncoder evtEncoder(varFactory);
223  EventEncoder::VariableEncoderId varEventId = evtEncoder.encodeEventRange(result.eventBegin(), result.eventEnd());
224  Variable & eventVar = evtEncoder.getVariable(varEventId);
225 
226 
227  // Then a StateInfoEncoder is required to encode stateVar
228  StateInfoEncoder stateEncoder(varFactory);
229  StateInfoEncoder::VariableEncoderId varStateId = stateEncoder.encodeStateInfoRange(result.statePropertyIdBegin(), result.statePropertyIdEnd());
230  Variable & stateVar = stateEncoder.getVariable(varStateId);
231 
232  // and a nextStateVar is also required
233  StateInfoEncoder::VariableEncoderId nextVarStateId = stateEncoder.encodeStateInfoRange(result.statePropertyIdBegin(), result.statePropertyIdEnd());
234  Variable & nextStateVar = stateEncoder.getVariable(nextVarStateId);
235 
236  BddStateMachine bddMachine;
237  encode(result, stateVar, nextStateVar, eventVar, bddMachine);
238 
239  FormulaVector nonObservable;
240  nonObservable.push_back(bddMachine.factory().isFalse());
241  for (auto & evt : nonObservables) {
242  stringstream evtText;
243  evtText << evt;
244  auto & value = eventVar.getValue(evtText.str());
245  auto & nonObs = nonObservable[0].get();
246  nonObservable.clear();
247  nonObservable.push_back(nonObs || bddMachine.event(value));
248  }
249  auto & nonObs = nonObservable[0].get();
250  stringstream stream;
251  stream << result.getStatePropertyId(*result.initialStateBegin());
252  string initialStateIdText = stream.str();
253  FormulaVector currentStates;
254  currentStates.push_back(bddMachine.sources(stateVar.getValue(initialStateIdText)));
255 
256  for (auto & e : observations) {
257  Lcm::EventInfoId evt = manager.eventId(e.label());
258  stringstream evtText;
259  evtText << evt;
260  auto & value = eventVar.getValue(evtText.str());
261  auto & obs = bddMachine.event(value);
262  auto & currentBeliefState = currentStates[0].get();
263  currentStates.clear();
264  currentStates.push_back(bddMachine.reach(currentBeliefState, nonObs, obs));
265  }
266 
267  printSolution(currentStates[0].get(),stateEncoder,candManager,setManager,locStateInfoManager,manager);
268 }
269 
270 
271 
272 int main(int argc, char * argv[]) {
273 
274  Poptions::options_description desc("Complete options");
275  Poptions::options_description visible("Allowed options");
276  Poptions::variables_map vm;
277  initialiseOptions(argc, argv, desc, visible, vm);
278  // 1 model and 1 scenario for now but anyway...
279  vector<string> modelNames;
280  vector<string> scenarios;
281  analyseOptions(vm, visible, modelNames, scenarios);
282 
283  vector<ObservableComponent> models;
284  if (!loadModels(modelNames, models)) {
285  printError("Cannot read the models from the given files");
286  }
287 
288  for (auto & scenario : scenarios) {
289  vector<Event> observations;
290  if (!loadScenario(scenario, observations, models)) {
291  printError("Cannot read a scenario from the given files");
292  }
293  runGlobalDiagnosisProblem(models[0], observations);
294  }
295  return 0;
296 }
EventPropertyIdIterator eventEnd() const
StatePropertyIdIterator statePropertyIdBegin() const
void initialiseOptions(int argc, char *argv[], Poptions::options_description &desc, Poptions::options_description &visible, Poptions::variables_map &vm)
void printError(const string &msg)
VariableEncoderId encodeEventRange(EventIterator first, EventIterator last)
const Value & getValue(const string &label) const
VariableEncoderId encodeStateInfoRange(StateInfoIdIterator first, StateInfoIdIterator last)
BddStateMachine & encode(const Diades::Automata::Experimental::StateMachine< StateProperty, FaultProperty > &component, Variable &stateVar, Variable &nextStateVar, Variable &event, BddStateMachine &result)
Variable & getVariable(VariableEncoderId id)
void runGlobalDiagnosisProblem(const ObservableComponent &component, const vector< Event > &observations)
void analyseOptions(Poptions::variables_map &vm, Poptions::options_description &visible, vector< string > &models, vector< string > &scenarios)
EventId eventId(const Event &event)
Definition: Event.hh:170
vector< string > options(numberOfOptions)
Formula::FormulaVector FormulaVector
Definition: Formula.hh:434
std::vector< EventId > decodeEventSet(const EventSet &eventSet) const
Definition: EventSet.hh:319
bool loadModels(const vector< string > &modelNames, vector< ObservableComponent > &models)
std::pair< StateInfoId, bool > getStateInfoId(const Assignment &assignment) const
An observable Component defined as a automaton.
void printErrorCmdLine(const string &msg, Poptions::options_description &visible)
DdAutFsm::EventPropertyId Event
Definition: TrimState.cc:139
void exportToDisjunctiveNormalForm(const Formula &formula, std::list< std::list< Assignment > > &dnf)
const SlEvents & event(const Value &eventValue) const
const Event & getEvent(EventId id) const
Definition: Event.hh:183
bool isIdentifiable(const Event &e) const
const ObservableMask & mask() const
const Formula & isFalse() const
Definition: Formula.hh:884
bool loadScenario(const string &scenarioFile, vector< Event > &observations, const vector< ObservableComponent > &models)
EventPropertyIdIterator eventBegin() const
const string program("dd-symb-diagnose")
InitialStateIterator initialStateBegin() const
Variable & getVariable(VariableEncoderId id) const
void transformToCandidateStateMachine(const Component &component, Lcm::EvManager &manager, Lcm::EvSetManager &setManager, Lcm::LocalStateInfoManager &locStateInfoManager, Lcm::CandidateManager &candidateManager, Lcm::Fsm &result)
const SlStates & reach(const SlStates &sources, const SlEvents &nonObservables, const SlEvents &observations)
const SlEvents & sources(const Value &sourceStateValue) const
StatePropertyIdIterator statePropertyIdEnd() const
const set< Event > & events() const
Definition: Component.hh:318
const StatePropertyId & getStatePropertyId(State state) const
void printSolution(const BddStateMachine::SlEvents &solution, StateInfoEncoder &stateEncoder, Lcm::CandidateManager &candManager, Lcm::EvSetManager &setManager, Lcm::LocalStateInfoManager &locStateInfoManager, Lcm::EvManager &manager)
const StateProperty & getStateProperty(StatePropertyId id) const
int main(int argc, char *argv[])