DiaDes  0.1
DIAgnosis of Discrete-Event System
ComposableModelSearch.hh
Go to the documentation of this file.
1 #ifndef __DIADES__AUTOMATA__COMPOSABLEMODELSEARCH_HH_
2 #define __DIADES__AUTOMATA__COMPOSABLEMODELSEARCH_HH_
3 
4 #include"Diagnosis.hh"
5 #include"ComposableModel.hh"
6 #include"FaultDiagProblem.hh"
7 
8 namespace Diades
9 {
10  namespace Automata
11  {
12 
18  class DiagState
19  {
20  private:
22  unordered_set<Event> _faults;
23  unsigned _obsNb;
24  public:
25  DiagState(const State & state, const unordered_set<Event> & faults, unsigned obsNb):_state(state),_faults(faults),_obsNb(obsNb){}
26  DiagState(const DiagState & dstate):_state(dstate.state()),_faults(dstate.faults()),_obsNb(dstate.obsNb()){}
27  const State & state() const { return _state; }
28  const unordered_set<Event> & faults() const { return _faults; }
29  unsigned obsNb() const { return _obsNb; }
30  void addFault(const Event & event) { _faults.insert(event); }
31  unsigned incrObsNb() { return ++_obsNb; }
32  void setState(const State & state) { _state = state; }
33  bool operator==(const DiagState & dstate) const { return (state() == dstate.state()) && (obsNb() == dstate.obsNb()) && (faults().size() == dstate.faults().size()) && (faults() == dstate.faults()); }
34  bool operator!=(const DiagState & dstate) const { return !(*this == dstate); }
35 
36  };
37 
38 
39  inline ostream & operator << (ostream & os, const DiagState & dstate)
40  {
41  return os << "(state= " << dstate.state() << ", nbObs=" << dstate.obsNb() << ", faults= " << toStream(dstate.faults().begin(), dstate.faults().end()) << ")";
42  }
43 
51  {
52  public:
53  typedef DiagState Node;
55 
56  private:
58  public:
59  VisitedDiagState(const ComposableModel & model):_visited(model.component().behaviour()){}
60  void mark(const Node & s)
61  {
62  if(_visited[s.state()].size() <= s.obsNb())
63  {
64  _visited[s.state()].resize(s.obsNb()+1);
65  }
66  _visited[s.state()][s.obsNb()].push_back(s.faults());
67  }
68 
69  bool isMarked(const Node & s)
70  {
71  if(_visited[s.state()].size() <= s.obsNb())
72  {
73  return false;
74  }
75  return find(_visited[s.state()][s.obsNb()].begin(),
76  _visited[s.state()][s.obsNb()].end(),s.faults()) != _visited[s.state()][s.obsNb()].end();
77  }
78 
79 
80  void unmark(const Node & s)
81  {
82  if(isMarked(s))
83  {
84  list< unordered_set<Event> >::iterator it = find(_visited[s.state()][s.obsNb()].begin(),
85  _visited[s.state()][s.obsNb()].end(),s.faults());
86  _visited[s.state()][s.obsNb()].erase(it);
87  }
88  }
89 
90  };
91 
98  {
99  public:
100  typedef Transition Edge;
102  private:
103  const Graph & _model;
104  const unordered_set<Event> & _observables;
105  const vector<EventOccurrence> & _observations;
106 
107  public:
108  IncorrectPath(const Graph & model,
109  const unordered_set<Event> & observables,
110  const vector<EventOccurrence> & observations):_model(model),_observables(observables),_observations(observations){}
111  bool noGood(unsigned nbObs, const Edge & t) const
112  {
113  if(_observables.find(_model.component().getEvent(t)) == _observables.end())
114  {
115  return false;
116  }
117  return !(_observations[nbObs].second == _model.component().getEvent(t));
118  }
119 
120  };
121 
122 
131  {
132  public:
133  typedef DiagState Node;
134  typedef Transition Edge;
136 
137  private:
138  const Graph & _model;
139  const Node & _dstate;
141  public:
142 
143  struct Iterator
144  {
145  typedef Iterator self;
146  typedef ptrdiff_t difference_type;
147  typedef std::forward_iterator_tag iterator_category;
148  typedef Edge value_type;
149  typedef Edge* pointer;
150  typedef Edge& reference;
151 
154  unsigned _nbObs;
156 
157  Iterator(): _it(),_end(),_nbObs(0),_cut(nullptr){}
158 
159  explicit Iterator(const Graph::OutputTransitionIterator & it,const Graph::OutputTransitionIterator & end, unsigned nbObs, const IncorrectPath & cut) : _it(it), _end(end),_nbObs(nbObs),_cut(&cut)
160  {
161  while((_it != _end) && (_cut->noGood(_nbObs,*_it)))
162  {
163  ++_it;
164  }
165  }
166 
167 
168  reference operator*() const
169  {
170  return *_it;
171  }
172 
173  pointer operator->() const
174  {
175  return &(*_it);
176  }
177 
178  self & operator++()
179  {
180  ++_it;
181  while((_it != _end) && (_cut->noGood(_nbObs,*_it)))
182  {
183  ++_it;
184  }
185  return *this;
186  }
187 
188  self operator++(int)
189  {
190  self tmp = *this;
191  ++_it;
192  while((_it != _end) && (_cut->noGood(_nbObs,*_it)))
193  {
194  ++_it;
195  }
196  return tmp;
197  }
198 
199 
200 
201  bool operator==(const self & it) const
202  {
203  return (_it == it._it) && (_end == it._end) && (_cut == it._cut) && (_nbObs == it._nbObs);
204  }
205 
206  bool operator !=(const self & it) const
207  {
208  return !(*this == it);
209  }
210 
211  };
212 
213 
214  NextTransitions(const Graph & model, const Node & dstate, const IncorrectPath & cut):
215  _model(model), _dstate(dstate), _cut(cut){}
216  Iterator begin() const { return Iterator(_model.outputTransitionBegin(_dstate.state()),_model.outputTransitionEnd(_dstate.state()),_dstate.obsNb(),_cut); }
217  Iterator end() const { return Iterator(_model.outputTransitionEnd(_dstate.state()),_model.outputTransitionEnd(_dstate.state()),_dstate.obsNb(),_cut); }
218  };
219 
220 
228  {
229  public:
230  typedef DiagState Node;
231  typedef Transition Edge;
233 
234  private:
235  const Graph & _model;
236  const unordered_set<Event> & _observables;
237  const unordered_set<Event> & _faults;
238 
239  public:
240  TargetDiagState(const Graph & model,
241  const unordered_set<Event> & observables,
242  const unordered_set<Event> & faults):_model(model),_observables(observables),_faults(faults){}
243 
244  Node next(const Edge & t, const Node & s) const
245  {
246  Node result = s;
247  if(_faults.find(_model.component().getEvent(t)) != _faults.end())
248  {
249  result.addFault(_model.component().getEvent(t));
250  }
251  if(_observables.find(_model.component().getEvent(t)) != _observables.end())
252  {
253  result.incrObsNb();
254  }
255  result.setState(t.target());
256  return result;
257  }
258 
259 
260  };
261 
270  {
271  public:
272  typedef DiagState Node;
273  private:
274  const vector<EventOccurrence> & _observations;
275  public:
276  IsCandidate(const vector<EventOccurrence> & observations):_observations(observations){}
277  bool isSolution(const Node & s){ if(s.obsNb() == _observations.size()) { cout << "Solution part: " << s << endl; }
278  return s.obsNb() == _observations.size();
279  }
280 
281  };
282 
283 
289  template<class Algorithm>
291  {
292  private:
293  list<typename Algorithm::Search::Node> _initialDiagStates;
294  list<typename Algorithm::Search::Node> _results;
295  typename Algorithm::Search::Solution * _isCandidate;
296  typename Algorithm::Search::PathCut * _incorrectPath;
297  typename Algorithm::Search::Opposite * _targetDiagState;
301  vector<const ComposableModel *> _compModels;
302  Algorithm * _search;
303 
304  public:
305  ComposableModelSearch(const FaultDiagProblem & problem):_initialDiagStates(),_results(),_isCandidate(nullptr),
306  _incorrectPath(nullptr),_targetDiagState(nullptr),
307  _diagnosis(),_problem(problem),_model(nullptr),
308  _compModels(),_search(nullptr){}
309 
310 
311  ~ComposableModelSearch() { destroy(); }
312 
313 
314  void destroy()
315  {
316  _results.clear();
317  _initialDiagStates.clear();
318  if(_search != nullptr)
319  {
320  delete _search; _search = nullptr;
321  }
322  if(_isCandidate != nullptr)
323  {
324  delete _isCandidate; _isCandidate = nullptr;
325  }
326  if(_incorrectPath != nullptr)
327  {
328  delete _incorrectPath; _incorrectPath = nullptr;
329  }
330  if(_targetDiagState != nullptr)
331  {
332  delete _targetDiagState; _targetDiagState = nullptr;
333  }
334  if(_model != nullptr)
335  {
336  delete _model;
337  _model=nullptr;
338  }
339  if(!_compModels.empty())
340  {
341  for(unsigned i = 0; i < _compModels.size(); ++i)
342  {
343  if(_compModels[i] != nullptr)
344  {
345  delete _compModels[i];
346  _compModels[i]=nullptr;
347  }
348  }
349  _compModels.clear();
350  }
351  }
352  void initialize()
353  {
354  destroy();
355 
356  if(problem().components().size() == 1)
357  {
358  _compModels.push_back(new ComposableModel(*problem().components().begin(),problem().rules()));
359  _model =new ComposableModel(*problem().components().begin(),problem().rules());
360  }
361  else
362  {
363  // initialise the component models
364  for(const ObservableComponent & comp : problem().components())
365  {
366  _compModels.push_back(new ComposableModel(comp,problem().rules()));
367  }
368 
369  // initialise the search by creating a composable model that will be
370  // computed on the fly
371  _model = new ComposableModel(_compModels,problem().rules(),true);
372  }
373 
374  _isCandidate = new typename Algorithm::Search::Solution(problem().observations());
375  _incorrectPath = new typename Algorithm::Search::PathCut(*_model,problem().observables(),problem().observations());
376  _targetDiagState = new typename Algorithm::Search::Opposite(*_model,problem().observables(), problem().faults());
377 
379  it != _model->endOfInitialStates();
380  ++it)
381  {
382  _initialDiagStates.push_back(typename Algorithm::Search::Node(*it,unordered_set<Event>(),0));
383  }
384 
385  // create and initialise the BFS
386  _search = new Algorithm(*_model,_initialDiagStates,*_targetDiagState,*_isCandidate,*_incorrectPath,_results);
387  _search->initialize();
388  }
389 
390  bool finished() const { return (_search != nullptr) && _search->finished(); }
391  void next() { _search->next(); }
392  bool updated() const { return (_search != nullptr) && _search->updated(); }
394  {
395  if(updated())
396  {
397  _diagnosis.clear();
398  for(const typename Algorithm::Search::Node & state : _search->currentResults())
399  {
400  vector< set<Event> > faults(max((int) _model->models().size(), 1));
401  if(_model->models().size() == 0)
402  {
403  faults[0].insert(state.faults().begin(),state.faults().end());
404  }
405  else
406  {
407  for(const Event & fault: state.faults())
408  {
409  unsigned i = 0;
410  bool found =false;
411  while(!found && (i < _model->models().size()))
412  {
413  found = _model->models().operator[](i)->component().containsEvent(fault);
414  if(found)
415  {
416  faults[i].insert(fault);
417  }
418  ++i;
419  }
420  }
421  }
422  vector<Diades::Graph::Node::NodeId> stateIds;
423  for(unsigned i = 0; i < _model->vectorStateOf(state.state()).size(); ++i)
424  {
425  stateIds.push_back(_model->vectorStateOf(state.state()).operator[](i).id());
426  }
427  _diagnosis.addCandidate(Candidate(stateIds,faults));
428  }
429  }
430  return _diagnosis;
431  }
432 
433  const FaultDiagProblem & problem() const
434  {
435  return _problem;
436  }
437  };
438 
439 
440 
441 
442 
443 
444  };
445 };
446 
447 #endif
Iterator(const Graph::OutputTransitionIterator &it, const Graph::OutputTransitionIterator &end, unsigned nbObs, const IncorrectPath &cut)
IsCandidate(const vector< EventOccurrence > &observations)
ComposableModel::OutputTransitionIterator _end
Diades::Graph::Edge Transition
Definition: Component.hh:46
const unordered_set< Event > & _observables
DiagState(const DiagState &dstate)
Component::OutputTransitionIterator OutputTransitionIterator
bool noGood(unsigned nbObs, const Edge &t) const
Algorithm::Search::Solution * _isCandidate
Definition of a fault diagnosis problem in a discrete-event system.
void addCandidate(const Candidate &candidate)
ComposableModelSearch(const FaultDiagProblem &problem)
Algorithm::Search::Opposite * _targetDiagState
unordered_set< Event > _faults
An observable Component defined as a automaton.
bool operator!=(const DiagState &dstate) const
DiagState(const State &state, const unordered_set< Event > &faults, unsigned obsNb)
OutputTransitionIterator outputTransitionEnd(State s) const
VisitedDiagState(const ComposableModel &model)
Definition of a fault diagnosis problem in a discrete-event system.
Namespace of the Diades project.
Diades::Utils::ToStream< InputIterator, Diades::Utils::AlwaysTrue< typename InputIterator::reference > > toStream(InputIterator first, InputIterator last)
Definition: Verbose.hh:143
const unordered_set< Event > & _observables
ComposableModel::OutputTransitionIterator _it
TargetDiagState(const Graph &model, const unordered_set< Event > &observables, const unordered_set< Event > &faults)
const vector< ConstPointer > & models() const
bool operator==(const DiagState &dstate) const
const FaultDiagProblem & problem() const
vector< const ComposableModel * > _compModels
void setState(const State &state)
const Event & getEvent(Transition t) const
Definition: Component.hh:304
NextTransitions(const Graph &model, const Node &dstate, const IncorrectPath &cut)
const Component & component() const
const vector< EventOccurrence > & _observations
Diades::Graph::Node State
Definition: BeliefState.hh:36
ostream & operator<<(ostream &os, const DiagState &dstate)
IncorrectPath(const Graph &model, const unordered_set< Event > &observables, const vector< EventOccurrence > &observations)
OutputTransitionIterator outputTransitionBegin(State s) const
InitialStateIterator endOfInitialStates() const
const unordered_set< Event > & faults() const
Node next(const Edge &t, const Node &s) const
list< typename Algorithm::Search::Node > _initialDiagStates
unordered_set< State >::const_iterator InitialStateIterator
Diades::Graph::ConstNodeMap< vector< list< unordered_set< Event > > > > _visited
const vector< EventOccurrence > & _observations
const unordered_set< Event > & _faults
InitialStateIterator beginOfInitialStates() const
void addFault(const Event &event)
const vector< State > & vectorStateOf(State s) const
list< typename Algorithm::Search::Node > _results