62 #include<boost/program_options.hpp> 63 #include <boost/date_time/posix_time/posix_time.hpp> 65 #include <boost/filesystem.hpp> 66 #include <boost/filesystem/fstream.hpp> 78 namespace po = boost::program_options;
79 namespace fs = boost::filesystem;
94 string description=
"Usage: dd-component-to-dot [file1.des_comp file2.des_comp file3.des_comp...] [--output template]\n\t Compute the dot graph associated to the component files. If no file as parameters,\n\t read the models from the standard input.\n\tIf --output is set with the name 'template' then the written dot files have\n\t the following names: 'template0.dot template1.dot...'\n\tIf no --output is set, write the result to the standard output ";
108 const vector<string> &
states,
113 const vector<string> & states,
123 int main(
int argc,
char * argv[])
129 std::string output =
"";
130 po::options_description desc{
"Options"};
132 (
"help,h",
"Help about the command line.")
133 (
"output,o",po::value<string>(&output),
"Output file template (if several files are exported they are written to the files template0.dot template1.dot ...) or output file name if only one file to display (not that if this option is not set, it displays the result on the standard output).")
134 (
"depth,d",po::value<int>(&depth),
"The maximal depth to visit from the given states (if depth is unset, there is no limit).")
135 (
"state,s", po::value<std::vector<std::string>>()->multitoken()->composing(),
"State from which the display can start (if this option is unset, the display starts from the initial states of the component. Many states can be added as follows: -s q1 q2 and/or -s q1 -s q2 q3...")
136 (
"component,c", po::value<std::vector<std::string>>()->multitoken()->composing(),
"Component to display (many components can be added). The option '--component/-c f1.des_comp f2.des_comp' can be simply written as 'f1.des_comp f2.des_comp'.")
137 (
"backward,b", po::bool_switch()->default_value(
false),
"Backward display (visiting source states instead of target states)");
138 po::positional_options_description posDesc;
139 posDesc.add(
"component", -1);
140 po::command_line_parser parser{argc, argv};
141 parser.options(desc).positional(posDesc).allow_unregistered();
142 po::parsed_options parsed_options = parser.run();
143 po::variables_map vm;
144 store(parsed_options, vm);
149 std::cout <<
"DIADES, LAAS-CNRS, 2006-2015, 7 avenue du Colonel Roche, Toulouse, France" << std::endl;
150 std::cout <<
"Contact: yannick.pencole@laas.fr" << std::endl;
152 std::cout <<
"This command exports the given components (des_comp format) to 'graphviz/dot' format." << std::endl << std::endl;
153 std::cout << desc << std::endl;
154 std::cout <<
"Examples: " << std::endl;
155 std::cout <<
"\t dd-component-to-dot file.des_comp" << std::endl;
156 std::cout <<
"\t Print the dot format of the component file.des_comp on the standard output" << std::endl << std::endl;
157 std::cout <<
"\t dd-component-to-dot file1.des_comp file.des_comp" << std::endl;
158 std::cout <<
"\t Print the dot format of the components file1.des_comp and file2.des_comp on the standard output" << std::endl << std::endl;
159 std::cout <<
"\t dd-component-to-dot file.des_comp -o result.dot" << std::endl;
160 std::cout <<
"\t Print the dot format of the component file.des_comp in the file result.dot" << std::endl << std::endl;
161 std::cout <<
"\t dd-component-to-dot file1.des_comp file.des_comp -o result" << std::endl;
162 std::cout <<
"\t Print the dot format of the components file1.des_comp and file2.des_comp in the files result0.dot result1.dot" << std::endl << std::endl;
164 std::cout <<
"\t dd-component-to-dot file.des_comp -d 10" << std::endl;
165 std::cout <<
"\t Print the dot format of the subpart of the component file.des_comp on the standard output from the initial states to the depth 10 " << std::endl << std::endl;
166 std::cout <<
"\t dd-component-to-dot file.des_comp -d 10 -s q1 q3" << std::endl;
167 std::cout <<
"\t Print the dot format of the subpart of the component file.des_comp on the standard output from states q1 and q3 to the depth 10 " << std::endl << std::endl;
168 std::cout <<
"\t dd-component-to-dot file.des_comp -d 10 -s q1 q3 " << std::endl;
169 std::cout <<
"\t Print the dot format of the subpart of the component file.des_comp on the standard output from states q1 and q3 to the depth 10 " << std::endl << std::endl;
170 std::cout <<
"\t dd-component-to-dot file.des_comp -d 10 -s q1 q3 -b" << std::endl;
171 std::cout <<
"\t Print the dot format of the subpart of the component file.des_comp on the standard output from states q1 and q3 to the depth 10 in backward mode (predecessors of q1 and q3) " << std::endl << std::endl;
175 if(vm.count(
"component"))
177 if(vm[
"component"].as<std::vector<std::string>>().size() > 1)
179 if(vm.count(
"state"))
181 std::cerr <<
"ERROR: option state is not allowed when there are several component files to display" << std::endl;
188 std::cerr <<
"ERROR: no component file has been found" << std::endl;
191 std::vector<std::string>
states;
192 if(vm.count(
"state"))
194 states = vm[
"state"].as<std::vector<std::string>>();
198 for(
unsigned i = 0; i < vm[
"component"].as<std::vector<std::string>>().size(); ++i)
200 checkDescompFile(vm[
"component"].as<std::vector<std::string>>().
operator[](i));
201 if(vm[
"backward"].as<bool>())
208 exportToDot(vm[
"component"].as<std::vector<std::string>>().
operator[](i),
216 for(
unsigned i = 0; i < vm[
"component"].as<std::vector<std::string>>().size(); ++i)
218 std::stringstream filename;
219 filename << output << i <<
".dot";
221 checkDescompFile(vm[
"component"].as<std::vector<std::string>>().
operator[](i));
222 fs::ofstream file(
fs::path(filename.str()));
223 if(vm[
"backward"].as<bool>())
230 exportToDot(vm[
"component"].as<std::vector<std::string>>().
operator[](i),
239 catch (
const std::exception &ex)
241 std::cerr << ex.what() <<
'\n';
253 const vector<string> & states,
254 std::vector<Diades::Automata::State> & startingStates)
256 startingStates.clear();
263 startingStates.push_back(*it);
269 for(
const std::string & stateLabel : states)
271 startingStates.push_back(component.
getState(stateLabel));
283 const vector<string> & states,
290 out <<
"digraph G {" << std::endl;
291 out <<
"\tratio=fill;" << std::endl;
292 out <<
"\tpage=\"8.5,11.6\";" << std::endl;
293 out <<
"\tsize=\"7.5,10.5\";" << std::endl;
294 std::vector<Diades::Automata::State> startingStates;
300 for(
unsigned i = 0; i < startingStates.size(); ++i)
302 out <<
"\t" << startingStates[i] <<
"\t [label=\"";
303 out << component.
getLabel(startingStates[i]);
304 out <<
"\"];" << endl;
305 out <<
"\t init" << startingStates[i] <<
"\t [label=\"\",color=white];" << endl;
306 out <<
"\t init" << startingStates[i] <<
" -> " << startingStates[i] <<
";" << endl;
307 visited[startingStates[i]] =
true;
310 for(
unsigned i = 0; i < startingStates.size(); ++i)
312 std::list< std::pair<State,ObservableComponent::OutputTransitionIterator> > queue;
317 currentDepth[startingStates[i]] = 0;
321 queue.push_back(std::make_pair(startingStates[i],component.
outputTransitionBegin(startingStates[i])));
322 while(!queue.empty())
324 State currentState = queue.front().first;
327 saturated[currentState] =
true;
332 Transition currentTransition = *queue.front().second;
333 ++queue.front().second;
334 State target = currentTransition.target();
337 out <<
"\t" << target <<
"\t [label=\"";
339 out <<
"\"];" << endl;
340 visited[target]=
true;
342 if(currentDepth[target] == -1)
344 currentDepth[target] = currentDepth[currentState] + 1;
346 if(!visitedTransition[currentTransition])
348 out <<
"\t" << currentState <<
" -> " << target;
352 out <<
"\", color=blue];" << endl;
363 out << obsIt->nickname();
373 out <<
"}\",color=blue];" << endl;
377 out <<
"}\",color=green];" << endl;
382 out <<
"\"];" << endl;
385 visitedTransition[currentTransition] =
true;
387 if(!saturated[target])
389 if((currentDepth[target] < depth) || (depth==-1))
403 std::cerr <<
"ERROR: cannot write on the select output stream" << std::endl;
412 const vector<string> & states,
419 out <<
"digraph G {" << std::endl;
420 out <<
"\tratio=fill;" << std::endl;
421 out <<
"\tpage=\"8.5,11.6\";" << std::endl;
422 out <<
"\tsize=\"7.5,10.5\";" << std::endl;
423 std::vector<Diades::Automata::State> startingStates;
429 for(
unsigned i = 0; i < startingStates.size(); ++i)
431 out <<
"\t" << startingStates[i] <<
"\t [label=\"";
432 out << component.
getLabel(startingStates[i]);
433 out <<
"\"];" << endl;
434 out <<
"\t init" << startingStates[i] <<
"\t [label=\"\",color=white];" << endl;
435 out <<
"\t init" << startingStates[i] <<
" -> " << startingStates[i] <<
";" << endl;
436 visited[startingStates[i]] =
true;
439 for(
unsigned i = 0; i < startingStates.size(); ++i)
441 std::list< std::pair<State,ObservableComponent::InputTransitionIterator> > queue;
446 currentDepth[startingStates[i]] = 0;
450 queue.push_back(std::make_pair(startingStates[i],component.
inputTransitionBegin(startingStates[i])));
451 while(!queue.empty())
453 State currentState = queue.front().first;
456 saturated[currentState] =
true;
461 Transition currentTransition = *queue.front().second;
462 ++queue.front().second;
463 State source = currentTransition.source();
466 out <<
"\t" << source <<
"\t [label=\"";
468 out <<
"\"];" << endl;
469 visited[source]=
true;
471 if(currentDepth[source] == -1)
473 currentDepth[source] = currentDepth[currentState] + 1;
475 if(!visitedTransition[currentTransition])
477 out <<
"\t" << source <<
" -> " << currentState;
481 out <<
"\", color=blue];" << endl;
492 out << obsIt->nickname();
502 out <<
"}\",color=blue];" << endl;
506 out <<
"}\",color=green];" << endl;
511 out <<
"\"];" << endl;
514 visitedTransition[currentTransition] =
true;
516 if(!saturated[source])
518 if((currentDepth[source] < depth) || (depth==-1))
531 std::cerr <<
"ERROR: cannot write on the select output stream" << std::endl;
542 if (fs::exists(filepath))
544 if (fs::is_regular_file(filepath))
550 std::cerr <<
"ERROR: " << filepath <<
" is not a regular file (maybe a directory..." << std::endl;
556 std::cerr <<
"ERROR: " << filepath <<
" does not exist" << std::endl;
561 std::cerr <<
"ERROR: " << filepath <<
" does not end with a 'des_comp' suffix. Expecting a component model in the 'des_comp' format." << std::endl;
Graph::Graph & behaviour()
void checkDescompFile(const string &filename)
Some utilities to deal with the command line.
Diades::Graph::Edge Transition
void exportBackwardToDot(const string &filename, int depth, const vector< string > &states, ostream &out)
void init(Graph &g, SizeType capacity=0, ValueType dflt=ValueType())
const Label & nickname() const
int main(int argc, char *argv[])
vector< string > fileExtensions(numberOfFileExtensions)
const StateLabel & getLabel(State state) const
InputTransitionIterator inputTransitionBegin(State s) const
set< Event >::const_iterator ObservableEventIterator
InitialStateIterator initialStateEnd() const
An observable Component defined as a automaton.
virtual bool importDesCompModel(const string &filename)
unsigned numberOfFileExtensions
InputTransitionIterator inputTransitionEnd(State s) const
InitialStateIterator initialStateBegin() const
unsigned numberOfStates() const
State getState(const StateLabel &label) const
bool fileSuffixOk(const string &modelFile, const string &suffix)
void init(Graph &g, SizeType capacity=0, ValueType dflt=ValueType())
ObservableEventIterator observableBegin() const
bool isDetectable(const Event &e) const
OutputTransitionIterator outputTransitionBegin(State s) const
bool isIdentifiable(const Event &e) const
void getStartingStates(const Component &component, const vector< string > &states, std::vector< Diades::Automata::State > &startingStates)
const ObservableMask & mask() const
vector< string > options(numberOfOptions)
ObservableEventIterator observableEnd() const
bool isObservable(const Event &e) const
const Event & getEvent(Transition t) const
Diades::Graph::Node State
void exportToDot(const string &filename, int depth, const vector< string > &states, ostream &out)
vector< bool > isSet(numberOfOptions, false)
OutputTransitionIterator outputTransitionEnd(State s) const