19 #include <boost/program_options/options_description.hpp> 20 #include <boost/program_options/positional_options.hpp> 21 #include <boost/program_options/variables_map.hpp> 22 #include <boost/program_options/parsers.hpp> 27 #include <sdmdl/SdmdlParser.hpp> 28 #include <sdmdl/SdmdlLexer.hpp> 31 namespace po = boost::program_options;
60 case SpecialisedActiveDiagnoser::Tag::Undiscriminable:
64 case SpecialisedActiveDiagnoser::Tag::Discriminable:
68 case SpecialisedActiveDiagnoser::Tag::Safe:
72 case SpecialisedActiveDiagnoser::Tag::Sure:
124 stringstream logStream;
125 ofstream file(filename.c_str());
131 logStream <<
"cannot open file '" << filename <<
"'.";
139 logStream <<
"cannot write the number of states in file " << filename <<
".";
143 file << diagnoser.
events().size() << endl;
147 logStream <<
"cannot write the number of observable events in file " << filename <<
".";
158 stringstream streamStates;
162 string initial = streamStates.str();
163 streamStates << endl;
167 for(SpecialisedActiveDiagnoser::StateIterator stateIt = diagnoser.
stateBegin();
173 if(!diagnoser.
isHole(*stateIt))
175 states.push_back(*stateIt);
176 indexOf[*stateIt] = index;
178 streamStates <<
" (" << (indexOf[*stateIt]+1) <<
"," <<
tag(diagnoser.
tag(*stateIt)) <<
")";
182 file << streamStates.str() << endl;
186 logStream <<
"cannot write the list of belief states in file " << filename <<
".";
190 string observationLabels;
191 vector<Diades::Automata::Event> observations;
195 observations.push_back(evt);
196 observationLabels += evt.nickname() +
" ";
198 file << observationLabels << endl;
202 logStream <<
"cannot write the list of observations in file " << filename <<
".";
207 vector<Diades::Automata::Event>::size_type i = 0;
208 while((result==0) && (i < observations.size()))
210 stringstream matrixLine;
211 for(vector<State>::size_type j = 0; j < states.size(); ++j)
213 SpecialisedActiveDiagnoser::OutputEventTransitionIterator transIt = diagnoser.
outputEventTransitionBegin(states[j],observations[i]);
216 if(!diagnoser.
isHole(transIt->target()))
218 matrixLine << indexOf[transIt->target()] <<
" ";
222 matrixLine << -1 <<
" ";
227 matrixLine << -1 <<
" ";
231 file << matrixLine.str() << endl;
235 logStream <<
"cannot write the line " << i <<
" of the incidence matrix in file " << filename <<
".";
248 cerr <<
"Export to HyDiag: " + logStream.str() << endl;
272 const set<string> & shortNameFaults,
273 unordered_map<string,string> & dictionary,
274 set<string> & faults,
275 set<string> & nominals)
281 if( ! globalModel.
import(filename.c_str()))
283 cerr <<
"Model import: problem, see the log below: " << endl;
284 cerr <<
"LOG START:" << endl;
286 cerr <<
"LOG END" << endl;
293 dictionary[evt.label()]= evt.nickname();
294 if(shortNameFaults.find(evt.nickname()) != shortNameFaults.end())
296 faults.insert(evt.label());
300 nominals.insert(evt.label());
305 catch(std::exception & e)
331 VariableFactory & factory,
332 const set<string> & shortNameIgnored,
333 const set<string> & shortNameFaults,
334 unordered_map<string,string> & dictionary,
335 set<string> & faults,
336 set<string> & nominals)
339 map<string,ComponentType *> results;
342 ifstream file(filename);
343 SdmdlLexer lexer(file);
345 SdmdlParser parser(lexer);
346 stringstream parsingLog;
347 parser.libraryUnit(results,factory,verbose,parsingLog);
351 cerr <<
"Error: no model is loaded." << endl;
352 cerr << parsingLog.str() << endl;
357 ComponentType & component = *results.begin()->second;
358 set<string> nonNominalEvents;
361 for(set<string>::const_iterator it = shortNameIgnored.begin();
362 it != shortNameIgnored.end();
365 if(component.containsSpontaneousEventOfLabel(*it))
367 nonNominalEvents.insert(component.spontaneousPort().label() +
"." + *it);
371 nonNominalEvents.insert(*it);
375 for(set<string>::const_iterator it = shortNameFaults.begin();
376 it != shortNameFaults.end();
379 if(component.containsSpontaneousEventOfLabel(*it))
381 nonNominalEvents.insert(component.spontaneousPort().label() +
"." + *it);
382 faults.insert(component.spontaneousPort().label() +
"." + *it);
386 nonNominalEvents.insert(*it);
391 for(ComponentType::EventIterator it = component.beginOfInputEvents();
392 it != component.endOfInputEvents();
395 if(nonNominalEvents.find((*it)->label()) == nonNominalEvents.end())
397 nominals.insert((*it)->label());
401 set<string> triggers = nominals;
402 for(set<string>::const_iterator faultIt = faults.begin();
403 faultIt != faults.end();
406 triggers.insert(*faultIt);
408 Unfolding unfold2(component,triggers,dictionary,
"global_model");
410 string globalModelFileName (
"global_model.des_comp");
411 if( ! globalModel.
import(globalModelFileName.c_str()))
413 cerr <<
"Model import: problem, see the log below: " << endl;
414 cerr <<
"LOG START:" << endl;
416 cerr <<
"LOG END" << endl;
421 catch(std::exception & e)
425 for(std::pair<const string,ComponentType *> & p : results)
427 if(p.second !=
nullptr)
450 unordered_map<string,string> & dictionnary,
451 unordered_map<string,SpecialisedActiveDiagnoser *> & activeDiagnoser)
454 for(set<string>::const_iterator faultIt = faults.begin();
455 faultIt != faults.end();
458 std::cout <<
"Computation of the diagnoser..." << (model.
name()+
"." + dictionnary[*faultIt]) << std::endl;
460 std::cout <<
"this is done" << std::endl;
462 if(!activeDiagnoser[*faultIt]->sanityCheck(log))
464 cout <<
"SANITY CHECK ERROR of the active diagnoser of fault " << *faultIt <<
":" << endl;
483 cout <<
"Diades: active diagnoser" << endl;
484 cout <<
"LAAS, CNRS, Univ. Toulouse, FRANCE. Copyright 2006-2014" << endl;
485 cout <<
"Contact: ypencole@laas.fr" << endl << endl;
487 cout << desc << endl;
488 cout <<
"Compute the active diagnoser of the file 'file.sdmdl' or the file" << endl;
489 cout <<
"'file.des_comp'. The events listed after '--faults' are considered" << endl;
490 cout <<
"as fault events. The events listed after '--ignored' are simply" << endl;
491 cout <<
"ignored INPUT events in the model 'file.sdmdl' (this option is" << endl;
492 cout <<
"simply ignored if the model is in 'des_comp' format. Any event" << endl;
493 cout <<
"that is in the model but not listed as a fault or as an ignored" << endl;
494 cout <<
"event is considered as a normal event." << endl;
511 po::options_description desc(
"Allowed options");
513 (
"help",
"produce this help message")
514 (
"model-file", po::value<string>(),
"model file")
515 (
"fault", po::value< vector<string> >(),
"fault event")
516 (
"ignored", po::value< vector<string> >(),
"ignored input event (sdmdl model only)")
517 (
"had", po::value<string>(),
"Hydiag Active Diagnoser format")
518 (
"dot", po::value<string>(),
"dot (graphviz) format")
520 po::positional_options_description p;
521 p.add(
"model-file", -1);
522 po::variables_map vm;
523 po::store(po::command_line_parser(ac, av).
524 options(desc).positional(p).run(), vm);
527 if (vm.count(
"help"))
533 if(vm.count(
"model-file"))
535 filename = vm[
"model-file"].as<
string>();
539 cout <<
"ERROR: expecting a model file (sdmdl or des_comp extensions)" << endl << endl;
543 vector<string>
suffixes = {
"sdmdl",
"des_comp" };
545 if(it == suffixes.end())
547 cout <<
"ERROR: wrong suffix in the name of the model file. Expecting 'sdmdl' or 'des_comp' formats." << endl << endl;
551 bool isSdmdl = (*it ==
"sdmdl");
552 set<string> shortNameFaults;
553 if(vm.count(
"fault"))
555 const vector<string> & vtr = vm[
"fault"].as<vector<string>>();
556 for(
size_t i = 0; i < vtr.size(); ++i)
558 shortNameFaults.insert(vtr[i]);
561 set<string> shortNameIgnored;
564 if(vm.count(
"ignored"))
566 const vector<string> & vtr = vm[
"ignored"].as<vector<string>>();
567 for(
size_t i = 0; i < vtr.size(); ++i)
569 shortNameIgnored.insert(vtr[i]);
573 bool had = vm.count(
"had");
574 bool dot = vm.count(
"dot");
579 hadfilename = vm[
"had"].as<
string>();
583 dotfilename = vm[
"dot"].as<
string>();
590 unordered_map<string,string> dictionary;
591 set<string> faultEvents;
592 set<string> nominalEvents;
595 VariableFactory * factory =
new VariableFactory();
596 int result =
initialiseModelFromSdmdl(filename,globalModel,*factory,shortNameIgnored,shortNameFaults,dictionary,faultEvents,nominalEvents);
599 cout <<
"ERROR: the generation of the global model (automaton) from the sdmdl description has failed. Check your model." << endl;
609 cout <<
"ERROR: the import of the global model (automaton) from the des_comp file has failed. Check your model." << endl;
613 unordered_map<string,SpecialisedActiveDiagnoser *> activeDiagnoser;
617 cout <<
"ERROR: the sanity check of the active diagnosers has failed." << endl;
622 if(faultEvents.size()==1)
624 for(std::pair<const string,SpecialisedActiveDiagnoser *> & p : activeDiagnoser)
626 p.second->diagnoser2Dot(dotfilename);
631 string dotfilenameprefix;
632 unsigned found = dotfilename.find_last_of(
".dot");
633 if(found!= string::npos)
635 if(found+1 == dotfilename.size())
637 dotfilenameprefix = dotfilename.substr(0,found-3);
641 dotfilenameprefix = dotfilename;
644 for(std::pair<const string,SpecialisedActiveDiagnoser *> & p : activeDiagnoser)
646 string filename = dotfilenameprefix + p.first.substr(p.first.find_first_of(
".")+1,p.first.size()) +
".dot";
647 p.second->diagnoser2Dot(filename);
653 if(faultEvents.size()==1)
655 for(std::pair<const string,SpecialisedActiveDiagnoser *> & p : activeDiagnoser)
660 cout <<
"ERROR: abort." << endl;
666 string hadfilenameprefix;
667 unsigned found = hadfilename.find_last_of(
".had");
668 if(found!= string::npos)
670 if(found+1 == hadfilename.size())
672 hadfilenameprefix = hadfilename.substr(0,found-3);
676 hadfilenameprefix = hadfilename;
679 for(std::pair<const string,SpecialisedActiveDiagnoser *> & p : activeDiagnoser)
681 string filename = hadfilenameprefix + p.first.substr(p.first.find_first_of(
".")+1,p.first.size()) +
".had";
685 cout <<
"ERROR: abort." << endl;
int initialiseModelFromSdmdl(const string &filename, ObservableComponent &globalModel, VariableFactory &factory, const set< string > &shortNameIgnored, const set< string > &shortNameFaults, unordered_map< string, string > &dictionary, set< string > &faults, set< string > &nominals)
Graph::Graph & behaviour()
OutputEventTransitionIterator outputEventTransitionBegin(State s, Event e) const
InputIterator getFileExtension(const std::basic_string< CharType, CharTraits > &fileName, InputIterator begin, InputIterator end)
int initialiseDiagnosers(const ObservableComponent &model, const set< string > &faults, unordered_map< string, string > &dictionnary, unordered_map< string, SpecialisedActiveDiagnoser *> &activeDiagnoser)
StateIterator stateBegin() const
int main(int ac, char **av)
vector< string > options(numberOfOptions)
StateIterator stateEnd() const
OutputEventTransitionIterator outputEventTransitionEnd(State s, Event e) const
int export2Hydiag(const SpecialisedActiveDiagnoser &diagnoser, const string &filename)
An observable Component defined as a automaton.
bool isHole(State state) const
int initialiseModelFromDesComp(const string &filename, ObservableComponent &globalModel, const set< string > &shortNameFaults, unordered_map< string, string > &dictionary, set< string > &faults, set< string > &nominals)
const string & name() const
unsigned numberOfStates() const
string tag(SpecialisedActiveDiagnoser::Tag tag)
Diades::Utils::Verbose verbose(const char *msg)
FileSuffixes suffixes({"aut","ddaut"})
Log log(Logger logger, const string &msg)
Diades::Graph::Node State
virtual bool import(const string &filename)
const set< Event > & events() const
State initialState() const
void printUsage(const po::options_description &desc)