diag_modulardiagnosis.cpp
Go to the documentation of this file.
1 /** @file diag_modulardiagnosis.cpp Functions to test modular diagnosability and compute modular diagnosers.
2 */
3 
4 /*
5 
6 Copyright Tobias Barthel, Klaus Schmidt, Thomas Moor
7 
8 */
9 
10 #include "diag_modulardiagnosis.h"
11 
12 
13 using namespace std;
14 
15 namespace faudes {
16 
17 ///////////////////////////////////////////////////////////////////////////////
18 // Functions for modular diagnosability
19 ///////////////////////////////////////////////////////////////////////////////
20 
21 
22 // IsModularDiagnosable(): RTI wrapper
23 bool IsModularDiagnosable(const SystemVector& rGsubs, const GeneratorVector& rKsubs, string& rReportString) {
24  FD_DD("IsModularDiagnosable()");
25 
26  // if the vectors have different size, the input is invalid
27  if(rGsubs.Size() != rKsubs.Size() ){
28  stringstream errstr;
29  errstr << "Number of specifications (" << rKsubs.Size() << ") does not equal number of subsystems ("<< rGsubs.Size() << ")" << endl;
30  throw Exception("IsModularDiagnosable()", errstr.str(), 304);
31  }
32 
33  // reorganize as std vector
34  std::vector<const System*> gen;
35  std::vector<const Generator*> spec;
36  Idx i;
37 
38  for(i = 0; i < rGsubs.Size(); ++i)
39  gen.push_back(&rGsubs.At(i));
40  for(i = 0; i < rKsubs.Size(); ++i)
41  spec.push_back(&rKsubs.At(i));
42 
43  // invoke function
44  return IsModularDiagnosable(gen, spec, rReportString);
45 }
46 
47 
48 
49 // IsModularDiagnosable()
50 bool IsModularDiagnosable(const vector< const System* >& rGSubs, const vector< const Generator* >& rKSubs, std::string& rReportString) {
51 
52  FD_DD("IsModularDiagnosable()");
53 
54  // clear report
55  rReportString.clear();
56  // verify dimensions
57  if(rGSubs.size() != rKSubs.size()) {
58  stringstream errstr;
59  errstr << "Number of specifications (" << rKSubs.size() << ") does not equal number of subsystems ("<< rGSubs.size() << ")" << endl;
60  throw Exception("IsModularDiagnosable()", errstr.str(), 304);
61  }
62  // assemble shared events
63  EventSet sigmaCup;
64  EventSet sigmaCap;
65  vector<EventSet> sigmaiCapVector;
66  for(unsigned int i = 0; i < rGSubs.size(); ++i) // alphabet union
67  sigmaCup.InsertSet(rGSubs.at(i)->Alphabet());
68 
69  FD_DD("all events: " + sigmaCup.ToString());
70  for(EventSet::Iterator eit=sigmaCup.Begin(); eit!=sigmaCup.End(); eit++) { // overall shared events
71  int cnt=0;
72  for(unsigned int i = 0; i < rGSubs.size(); ++i) {
73  if(rGSubs.at(i)->ExistsEvent(*eit))
74  cnt++;
75  if(cnt>1){
76  sigmaCap.Insert(*eit);
77  break;
78  }
79  }
80  }
81  sigmaCup.Name("Sigma_cup");
82  sigmaCap.Name("Sigma_cap");
83  FD_DD("Shared Events: " << sigmaCap.ToString());
84  // shared events per component
85  for(unsigned int i = 0; i < rGSubs.size(); ++i)
86  sigmaiCapVector.push_back(sigmaCap * rGSubs.at(i)->Alphabet() );
87 
88  // Compute abstraction alphabet for each component such that loop-preserving observer is fulfilled
89  vector<EventSet> sigmaAbstVector;
90  vector<System> genAbstVector;
91  EventSet sigmaAbst;
92  for(Idx i = 0; i < rGSubs.size(); ++i){
93  sigmaAbstVector.push_back(EventSet() );
94  LoopPreservingObserver(*rGSubs.at(i), sigmaiCapVector.at(i), sigmaAbstVector[i]);
95  sigmaAbst = sigmaAbst + sigmaAbstVector.at(i); // overall abstraction alphabet
96  // Compute the abstraction of each subsystem
97  genAbstVector.push_back(System() );
98  Project(*rGSubs.at(i),sigmaAbstVector.at(i),genAbstVector[i]);
99  FD_DD("AbstractionAlphabet of Automaton " + ToStringInteger(i) + " " + sigmaAbstVector.at(i).ToString());
100  }
101  // Verify modular diagnosability for each subsystem
102  EventSet obsEvents;
103  System plant, plantAbst, spec;
104  cParallel(genAbstVector,plantAbst); // abstracted plant
105  bool diagnosable = true;
106  for(unsigned int i = 0; i < rGSubs.size(); ++i){
107  plant.Clear();
108  Parallel(*rGSubs.at(i),plantAbst,plant); // plant for verification
109  Parallel(plant,*rKSubs.at(i),spec);
110  plant.ClrObservable(plant.Alphabet() );
111  plant.SetObservable(rGSubs.at(i)->ObservableEvents() ); // only observable events of the subsystem are observable
112  std::string reportString;
113  if(IsLanguageDiagnosable(plant,spec,reportString) == false ){
114  FD_DD("Plant " + ToStringInteger(i) + " fails");
115  diagnosable = false;
116  rReportString += "Subsystem " + ToStringInteger(i) + " fails ";
117  }
118  else{
119  FD_DD("Plant " + ToStringInteger(i) + " works");
120  rReportString += "Subsystem " + ToStringInteger(i) + " works ";
121  }
122  }
123  return diagnosable;
124 }
125 
126 
127 // IsModularDiagnosable(): RTI wrapper
128 bool ModularDiagnoser(const SystemVector& rGsubs, const GeneratorVector& rKsubs, GeneratorVector& rDiagSubs, string& rReportString) {
129  FD_DD("ModularDiagnoser");
130 
131  // if the vectors have different size, the input is invalid
132  if(rGsubs.Size() != rKsubs.Size() ){
133  stringstream errstr;
134  errstr << "Number of specifications (" << rKsubs.Size() << ") does not equal number of subsystems ("<< rGsubs.Size() << ")" << endl;
135  throw Exception("ModularDiagnoser()", errstr.str(), 304);
136  }
137 
138 
139  // reorganize as std vector
140  std::vector<const System*> gen;
141  std::vector<const Generator*> spec;
142  Idx i;
143  for(i = 0; i < rGsubs.Size(); ++i)
144  gen.push_back(&rGsubs.At(i));
145  for(i = 0; i < rKsubs.Size(); ++i)
146  spec.push_back(&rKsubs.At(i));
147 
148  // prepare result
149  std::vector<Diagnoser*> diag;
150 
151  // invoke function
152  bool diagnosable = ModularDiagnoser(gen, spec, diag, rReportString);
153 
154  // retrieve result (no copy, using explicit reference)
155  for(i = 0; i < diag.size(); i++)
156  rDiagSubs.Append(diag.at(i) );
157  rDiagSubs.TakeOwnership();
158 
159  // done
160  return diagnosable;
161 }
162 
163 
164 // ModularDiagnoser(rGsubs, rKsubs, rDiagsubs, rReportString)
165 bool ModularDiagnoser(const std::vector< const System* >& rGSubs, const std::vector< const Generator* >& rKSubs, std::vector<Diagnoser*>& rDiagSubs, std::string& rReportString){
166 
167  FD_DD("ModularDiagnoser()");
168 
169  // clear report
170  rReportString.clear();
171 
172  // verify dimensions
173  if(rGSubs.size() != rKSubs.size()) {
174  stringstream errstr;
175  errstr << "Number of specifications (" << rKSubs.size() << ") does not equal number of subsystems ("<< rGSubs.size() << ")" << endl;
176  throw Exception("ModularDiagnoser()", errstr.str(), 304);
177  }
178 
179  // assemble shared events
180  EventSet sigmaCup;
181  EventSet sigmaCap;
182  vector<EventSet> sigmaiCapVector;
183  for(unsigned int i = 0; i < rGSubs.size(); ++i) // alphabet union
184  sigmaCup.InsertSet(rGSubs.at(i)->Alphabet());
185 
186  FD_DD("all events: " + sigmaCup.ToString());
187  for(EventSet::Iterator eit=sigmaCup.Begin(); eit!=sigmaCup.End(); eit++) { // overall shared events
188  int cnt=0;
189  for(unsigned int i = 0; i < rGSubs.size(); ++i) {
190  if(rGSubs.at(i)->ExistsEvent(*eit))
191  cnt++;
192  if(cnt>1){
193  sigmaCap.Insert(*eit);
194  break;
195  }
196  }
197  }
198  sigmaCup.Name("Sigma_cup");
199  sigmaCap.Name("Sigma_cap");
200  FD_DD("Shared Events: " << sigmaCap.ToString());
201  // shared events per component
202  for(unsigned int i = 0; i < rGSubs.size(); ++i)
203  sigmaiCapVector.push_back(sigmaCap * rGSubs.at(i)->Alphabet() );
204 
205  // Compute abstraction alphabet for each component such that loop-preserving observer is fulfilled
206  vector<EventSet> sigmaAbstVector;
207  vector<System> genAbstVector;
208  EventSet sigmaAbst;
209  for(Idx i = 0; i < rGSubs.size(); ++i){
210  sigmaAbstVector.push_back(EventSet() );
211  LoopPreservingObserver(*rGSubs.at(i), sigmaiCapVector.at(i), sigmaAbstVector[i]);
212  sigmaAbst = sigmaAbst + sigmaAbstVector.at(i); // overall abstraction alphabet
213  // Compute the abstraction of each subsystem
214  genAbstVector.push_back(System() );
215  Project(*rGSubs.at(i),sigmaAbstVector.at(i),genAbstVector[i]);
216  FD_DD("AbstractionAlphabet of Automaton " + ToStringInteger(i) + " " + sigmaAbstVector.at(i).ToString());
217  }
218  // Verify modular diagnosability for each subsystem
219  EventSet obsEvents;
220  System plant, plantAbst, spec;
221  cParallel(genAbstVector,plantAbst); // abstracted plant
222  bool diagnosable = true;
223  for(unsigned int i = 0; i < rGSubs.size(); ++i){
224  plant.Clear();
225  Parallel(*rGSubs.at(i),plantAbst,plant); // plant for verification
226  Parallel(plant,*rKSubs.at(i),spec);
227  plant.ClrObservable(plant.Alphabet() );
228  plant.SetObservable(rGSubs.at(i)->ObservableEvents() ); // only observable events of the subsystem are observable
229  std::string reportString;
230  rDiagSubs.push_back( new Diagnoser() );
231 
232  if(IsLanguageDiagnosable(plant,spec,reportString) == false ){
233  FD_DD("Plant " + ToStringInteger(i) + " fails");
234  diagnosable = false;
235  rReportString += "Subsystem " + ToStringInteger(i) + " fails ";
236  }
237  else{
238  FD_DD("Plant " + ToStringInteger(i) + " works");
239  LanguageDiagnoser(plant,spec,*rDiagSubs[i]);
240  rReportString += "Subsystem " + ToStringInteger(i) + " works ";
241 
242  }
243  }
244  return diagnosable;
245 }
246 
247 ///////////////////////////////////////////////////////////////////////////////
248 // RTI wrapper
249 ///////////////////////////////////////////////////////////////////////////////
250 
251 // IsModularDiagnosable()
252 bool IsModularDiagnosable(const SystemVector& rGsubs, const GeneratorVector& rKsubs) {
253  std::string ignore;
254  return IsModularDiagnosable(rGsubs, rKsubs, ignore);
255 }
256 
257 
258 
259 // ModularDiagnoser()
260 bool ModularDiagnoser(const SystemVector& rGsubs, const GeneratorVector& rKsubs, GeneratorVector& rDiagsubs) {
261  std::string ignore;
262  return ModularDiagnoser(rGsubs, rKsubs, rDiagsubs, ignore);
263 }
264 
265 ///////////////////////////////////////////////////////////////////////////////
266 // Auxiliary Functions
267 ///////////////////////////////////////////////////////////////////////////////
268 
269 // cParallel()
270 void cParallel(const vector<System>& rGens, System& rResGen) {
271  unsigned int i = 0;
272  rResGen.Clear();
273  if (rGens.size() == 0) return;
274  rResGen = rGens.at(0);
275 
276  for (i = 1; i < rGens.size(); ++i) {
277  aParallel(rResGen,rGens.at(i),rResGen);
278  }
279 }
280 
281 
282 } // namespace faudes
Faudes exception class.
Set of indices with symbolic names.
Definition: cfl_nameset.h:69
virtual void InsertSet(const NameSet &rOtherSet)
Inserts all elements of rOtherSet.
bool Insert(const Idx &rIndex)
Add an element by index.
Vector template.
virtual const T & At(const Position &pos) const
Access element.
virtual void Clear(void)
Clear generator data.
const TaEventSet< EventAttr > & Alphabet(void) const
Return const reference to alphabet.
Generator with controllability attributes.
void ClrObservable(Idx index)
Mark event unobservable (by index)
void SetObservable(Idx index)
Mark event observable (by index)
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
Write configuration data to a string.
Definition: cfl_types.cpp:169
void TakeOwnership(void)
Take ownership of all entries.
virtual void Append(const Type &rElem)
Append specified entry.
Idx Size(void) const
Get size of vector.
#define FD_DD(message)
Definition: diag_debug.h:13
Functions to check a system's decentralized diagnosability.
Iterator End(void) const
Iterator to the end of set.
Definition: cfl_baseset.h:1896
Iterator Begin(void) const
Iterator to the begin of set.
Definition: cfl_baseset.h:1891
NameSet EventSet
Convenience typedef for plain event sets.
Definition: cfl_nameset.h:531
const std::string & Name(void) const
Return name of TBaseSet.
Definition: cfl_baseset.h:1755
void LanguageDiagnoser(const System &rGen, const System &rSpec, Diagnoser &rDiagGen)
Compute a standard diagnoser from an input generator and a specification.
void LoopPreservingObserver(const System &rGen, const EventSet &rInitialHighAlph, EventSet &rHighAlph)
Computes a loop-preserving observer with minimal state size of the abstraction.
TcGenerator< AttributeVoid, AttributeVoid, AttributeCFlags, AttributeVoid > System
Convenience typedef for std System.
void aParallel(const Generator &rGen1, const Generator &rGen2, Generator &rResGen)
Parallel composition.
void Project(const Generator &rGen, const EventSet &rProjectAlphabet, Generator &rResGen)
Deterministic projection.
void Parallel(const Generator &rGen1, const Generator &rGen2, Generator &rResGen)
Parallel composition.
libFAUDES resides within the namespace faudes.
uint32_t Idx
Type definition for index type (allways 32bit)
bool IsLanguageDiagnosable(const System &rGen, const System &rSpec)
Function definition for run-time interface.
TdiagGenerator< AttributeFailureTypeMap, AttributeDiagnoserState, AttributeCFlags, AttributeVoid > Diagnoser
bool IsModularDiagnosable(const SystemVector &rGsubs, const GeneratorVector &rKsubs)
Function definition for run-time interface.
bool ModularDiagnoser(const SystemVector &rGsubs, const GeneratorVector &rKsubs, GeneratorVector &rDiagsubs)
Function definition for run-time interface.
std::string ToStringInteger(Int number)
integer to string
Definition: cfl_helper.cpp:43
void cParallel(const vector< System > &rGens, System &rResGen)

libFAUDES 2.32b --- 2024.03.01 --- c++ api documentaion by doxygen