Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
storm-conv.cpp
Go to the documentation of this file.
1
3
11
13#include "storm/api/storm.h"
17
21
25
26namespace storm {
27namespace conv {
28
30 // Set the correct log level
32 if (general.isVerboseSet()) {
33 storm::utility::setLogLevel(l3pp::LogLevel::INFO);
34 }
35 if (general.isDebugOutputSet()) {
36 storm::utility::setLogLevel(l3pp::LogLevel::DEBUG);
37 }
38 if (general.isTraceOutputSet()) {
39 storm::utility::setLogLevel(l3pp::LogLevel::TRACE);
40 }
41}
42
43storm::utility::Stopwatch startStopwatch(std::string const& message) {
44 STORM_PRINT_AND_LOG(message);
45 return storm::utility::Stopwatch(true);
46}
47
49 stopWatch.stop();
50 STORM_PRINT_AND_LOG(" done. (" << stopWatch << " seconds).\n");
51}
52
53void processPrismInputJaniOutput(storm::prism::Program const& prismProg, std::vector<storm::jani::Property> const& properties) {
57
58 auto conversionTime = startStopwatch("Converting PRISM Program to JANI model ... ");
59
61 options.allVariablesGlobal = jani.isGlobalVarsSet();
62 options.suffix = "";
64 options.janiOptions.substituteConstants = true;
65
66 // Get the name of the output file
67 std::string outputFilename = "";
68 if (output.isJaniOutputFilenameSet()) {
69 outputFilename = output.getJaniOutputFilename();
70 } else if (input.isPrismInputSet()) {
71 outputFilename = input.getPrismInputFilename();
72 // Remove extension if present
73 auto dotPos = outputFilename.rfind('.');
74 if (dotPos != std::string::npos) {
75 outputFilename.erase(dotPos);
76 }
77 std::string suffix = "";
78 if (input.isConstantsSet()) {
79 suffix = input.getConstantDefinitionString();
80 std::replace(suffix.begin(), suffix.end(), ',', '_');
81 std::replace(suffix.begin(), suffix.end(), '=', '-');
82 }
83 suffix = suffix + ".jani";
84 outputFilename += suffix;
85 }
86
87 // Find a good model name
88 auto startOfFilename = outputFilename.rfind("/");
89 if (startOfFilename == std::string::npos) {
90 startOfFilename = 0;
91 } else {
92 ++startOfFilename;
93 }
94 auto endOfFilename = outputFilename.rfind(".");
95 if (endOfFilename == std::string::npos) {
96 endOfFilename = outputFilename.size();
97 }
98 options.janiOptions.modelName = outputFilename.substr(startOfFilename, endOfFilename - startOfFilename);
99
100 auto janiModelProperties = storm::api::convertPrismToJani(prismProg, properties, options);
101
102 stopStopwatch(conversionTime);
103 auto exportingTime = startStopwatch("Exporting JANI model ... ");
104
105 if (outputFilename != "") {
106 storm::api::exportJaniToFile(janiModelProperties.first, janiModelProperties.second, outputFilename, jani.isCompactJsonSet());
107 STORM_PRINT_AND_LOG("Stored to file '" << outputFilename << "'");
108 }
109
110 stopStopwatch(exportingTime);
111}
112
113void processPrismInputPrismOutput(storm::prism::Program const& prismProg, std::vector<storm::jani::Property> const& properties) {
117
118 auto conversionTime = startStopwatch("Processing Prism Program ... ");
119
120 // Get the name of the output file
121 std::string outputFilename = "";
122 if (output.isPrismOutputFilenameSet()) {
123 outputFilename = output.getPrismOutputFilename();
124 } else if (input.isPrismInputSet()) {
125 outputFilename = input.getPrismInputFilename();
126 // Remove extension if present
127 auto dotPos = outputFilename.rfind('.');
128 if (dotPos != std::string::npos) {
129 outputFilename.erase(dotPos);
130 }
131 std::string suffix = "";
132 if (input.isConstantsSet()) {
133 suffix = input.getConstantDefinitionString();
134 std::replace(suffix.begin(), suffix.end(), ',', '_');
135 std::replace(suffix.begin(), suffix.end(), '=', '-');
136 }
137 suffix += "_converted.prism";
138 outputFilename += suffix;
139 }
140
141 storm::prism::Program outputProgram = prismProg;
142 std::vector<storm::jani::Property> outputProperties = properties;
143 storm::api::transformPrism(outputProgram, outputProperties, prism.isSimplifySet(), prism.isExportFlattenedSet());
144
145 stopStopwatch(conversionTime);
146 auto exportingTime = startStopwatch("Exporting Prism program ... ");
147
148 if (outputFilename != "") {
149 storm::api::exportPrismToFile(outputProgram, outputProperties, outputFilename);
150 STORM_PRINT_AND_LOG("Stored to file '" << outputFilename << "'");
151 }
152
153 stopStopwatch(exportingTime);
154}
155
157 auto parsingTime = startStopwatch("Parsing PRISM input ... ");
158
160
161 // Parse the prism program
162 storm::storage::SymbolicModelDescription prismProg = storm::api::parseProgram(input.getPrismInputFilename(), input.isPrismCompatibilityEnabled(), false);
163
164 // Parse properties (if available)
165 std::vector<storm::jani::Property> properties;
166 if (input.isPropertyInputSet()) {
167 boost::optional<std::set<std::string>> propertyFilter = storm::api::parsePropertyFilter(input.getPropertyInputFilter());
168 properties = storm::api::parsePropertiesForSymbolicModelDescription(input.getPropertyInput(), prismProg, propertyFilter);
169 }
170
171 // Set constant definitions in program
172 std::string constantDefinitionString = input.getConstantDefinitionString();
173 auto constantDefinitions = prismProg.parseConstantDefinitions(constantDefinitionString);
174 prismProg = storm::storage::SymbolicModelDescription(prismProg.asPrismProgram().defineUndefinedConstants(constantDefinitions));
175 // Substitution of constants can only be done after conversion in order to preserve formula definitions in which
176 // constants appear that are renamed in some modules...
177
178 stopStopwatch(parsingTime);
179
180 // Branch on the type of output
182 if (output.isJaniOutputSet()) {
183 processPrismInputJaniOutput(prismProg.asPrismProgram(), properties);
184 } else if (output.isPrismOutputSet()) {
185 processPrismInputPrismOutput(prismProg.asPrismProgram(), properties);
186 } else {
187 STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException,
188 "There is either no outputformat specified or the provided combination of input and output format is not compatible.");
189 }
190}
191
192void processJaniInputJaniOutput(storm::jani::Model const& janiModel, std::vector<storm::jani::Property> const& properties) {
193 auto conversionTime = startStopwatch("Performing transformations on JANI model ... ");
194
198
200
201 // Get the name of the output file
202 std::string outputFilename = "";
203 if (output.isJaniOutputFilenameSet()) {
204 outputFilename = output.getJaniOutputFilename();
205 } else if (input.isJaniInputSet()) {
206 outputFilename = input.getJaniInputFilename();
207 // Remove extension if present
208 auto dotPos = outputFilename.rfind('.');
209 if (dotPos != std::string::npos) {
210 outputFilename.erase(dotPos);
211 }
212 outputFilename += "_converted.jani";
213 }
214
215 // Get a good model name from the output filename
216 auto startOfFilename = outputFilename.rfind("/");
217 if (startOfFilename == std::string::npos) {
218 startOfFilename = 0;
219 } else {
220 ++startOfFilename;
221 }
222 auto endOfFilename = outputFilename.rfind(".");
223 if (endOfFilename == std::string::npos) {
224 endOfFilename = outputFilename.size();
225 }
226 options.modelName = outputFilename.substr(startOfFilename, endOfFilename - startOfFilename);
227
228 auto transformedJaniModel = janiModel;
229 auto transformedProperties = properties;
230 storm::api::transformJani(transformedJaniModel, transformedProperties, options);
231
232 stopStopwatch(conversionTime);
233 auto exportingTime = startStopwatch("Exporting JANI model ... ");
234
235 if (outputFilename != "") {
236 storm::api::exportJaniToFile(transformedJaniModel, transformedProperties, outputFilename, jani.isCompactJsonSet());
237 STORM_PRINT_AND_LOG("Stored to file '" << outputFilename << "'");
238 }
239
240 stopStopwatch(exportingTime);
241}
242
244 auto parsingTime = startStopwatch("Parsing JANI input ... ");
245
247
248 // Parse the jani model and selected properties
249 boost::optional<std::vector<std::string>> janiPropertyFilter;
250 if (input.isJaniPropertiesSet()) {
251 if (input.areJaniPropertiesSelected()) {
252 janiPropertyFilter = input.getSelectedJaniProperties();
253 } else {
254 janiPropertyFilter = boost::none;
255 }
256 } else {
257 if (input.isPropertyInputSet()) {
258 janiPropertyFilter = std::vector<std::string>();
259 } else {
260 // If no properties are selected, take the ones from the jani file.
261 janiPropertyFilter = boost::none;
262 }
263 }
264 auto janiModelProperties = storm::api::parseJaniModel(input.getJaniInputFilename(), storm::jani::getAllKnownModelFeatures(), janiPropertyFilter);
265
266 // Parse additional properties given from command line
267 std::vector<storm::jani::Property> properties = std::move(janiModelProperties.second);
268 if (input.isPropertyInputSet()) {
269 boost::optional<std::set<std::string>> propertyFilter = storm::api::parsePropertyFilter(input.getPropertyInputFilter());
270 auto additionalProperties = storm::api::parsePropertiesForSymbolicModelDescription(input.getPropertyInput(), janiModelProperties.first, propertyFilter);
271 properties.insert(properties.end(), additionalProperties.begin(), additionalProperties.end());
272 }
273
274 storm::storage::SymbolicModelDescription symbDescr(janiModelProperties.first);
275
276 // Substitute constant definitions in model and properties.
277 std::string constantDefinitionString = input.getConstantDefinitionString();
278 auto constantDefinitions = symbDescr.parseConstantDefinitions(constantDefinitionString);
279 auto janiModel = janiModelProperties.first.defineUndefinedConstants(constantDefinitions).substituteConstants();
280 if (!properties.empty()) {
281 properties = storm::api::substituteConstantsInProperties(properties, constantDefinitions);
282 }
283 stopStopwatch(parsingTime);
284
285 // Branch on the type of output
287 if (output.isJaniOutputSet()) {
288 processJaniInputJaniOutput(janiModel, properties);
289 } else {
290 STORM_LOG_THROW(!output.isPrismOutputSet(), storm::exceptions::InvalidSettingsException, "Conversion from Jani to Prism is not supported.");
291 STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException,
292 "There is either no outputformat specified or the provided combination of input and output format is not compatible.");
293 }
294}
295
297 // Start by setting some urgent options (log levels, etc.)
298 // We cannot use the general variants used for other executables since the "GeneralSettings" module is not available in Storm-conv
300
301 // Branch on the type of input
303 STORM_LOG_THROW(!(input.isPrismInputSet() && input.isJaniInputSet()), storm::exceptions::InvalidSettingsException, "Multiple input options were set.");
304 if (input.isPrismInputSet()) {
306 } else if (input.isJaniInputSet()) {
308 }
309}
310} // namespace conv
311} // namespace storm
312
313bool parseOptions(const int argc, const char* argv[]) {
314 try {
316 } catch (storm::exceptions::OptionParserException& e) {
317 STORM_LOG_ERROR("Unable to parse command line options. Type '" + std::string(argv[0]) + " --help' or '" + std::string(argv[0]) +
318 " --help all' for help.");
319 return false;
320 }
321
323
324 // Set options from config file (if given)
325 if (general.isConfigSet()) {
326 storm::settings::mutableManager().setFromConfigurationFile(general.getConfigFilename());
327 }
328
329 bool result = true;
330 if (general.isHelpSet()) {
331 storm::settings::manager().printHelp(general.getHelpFilterExpression());
332 result = false;
333 }
334
335 if (general.isVersionSet()) {
337 result = false;
338 }
339
340 return result;
341}
342
346int main(const int argc, const char** argv) {
347 try {
349 storm::cli::printHeader("Storm-conv", argc, argv);
350
351 storm::settings::initializeConvSettings("Storm-conv", "storm-conv");
352 if (!parseOptions(argc, argv)) {
353 return -1;
354 }
355
357
359 return 0;
360 } catch (storm::exceptions::BaseException const& exception) {
361 STORM_LOG_ERROR("An exception caused Storm-conv to terminate. The message of the exception is: " << exception.what());
362 return 1;
363 } catch (std::exception const& exception) {
364 STORM_LOG_ERROR("An unexpected exception occurred and caused Storm-conv to terminate. The message of this exception is: " << exception.what());
365 return 2;
366 }
367}
This class represents the base class of all exception classes.
virtual const char * what() const NOEXCEPT override
Retrieves the message associated with this exception.
Program defineUndefinedConstants(std::map< storm::expressions::Variable, storm::expressions::Expression > const &constantDefinitions) const
Defines the undefined constants according to the given map and returns the resulting program.
Definition Program.cpp:984
void setFromCommandLine(int const argc, char const *const argv[])
This function parses the given command line arguments and sets all registered options accordingly.
void setFromConfigurationFile(std::string const &configFilename)
This function parses the given file and sets all registered options accordingly.
void printHelp(std::string const &filter="frequent") const
This function prints a help message to the standard output.
std::map< storm::expressions::Variable, storm::expressions::Expression > parseConstantDefinitions(std::string const &constantDefinitionString) const
storm::prism::Program const & asPrismProgram() const
A class that provides convenience operations to display run times.
Definition Stopwatch.h:14
void stop()
Stop stopwatch and add measured time to total time.
Definition Stopwatch.cpp:42
#define STORM_LOG_ERROR(message)
Definition logging.h:31
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
#define STORM_PRINT_AND_LOG(message)
Definition macros.h:68
storm::prism::Program parseProgram(std::string const &filename, bool prismCompatibility, bool simplify)
void transformPrism(storm::prism::Program &prismProgram, std::vector< storm::jani::Property > &properties, bool simplify, bool flatten)
std::pair< storm::jani::Model, std::vector< storm::jani::Property > > parseJaniModel(std::string const &filename, boost::optional< std::vector< std::string > > const &propertyFilter)
void exportJaniToFile(storm::jani::Model const &model, std::vector< storm::jani::Property > const &properties, std::string const &filename, bool compact)
std::vector< storm::jani::Property > parsePropertiesForSymbolicModelDescription(std::string const &inputString, storm::storage::SymbolicModelDescription const &modelDescription, boost::optional< std::set< std::string > > const &propertyFilter)
void transformJani(storm::jani::Model &janiModel, std::vector< storm::jani::Property > &properties, storm::converter::JaniConversionOptions const &options)
boost::optional< std::set< std::string > > parsePropertyFilter(std::string const &propertyFilter)
std::pair< storm::jani::Model, std::vector< storm::jani::Property > > convertPrismToJani(storm::prism::Program const &program, storm::converter::PrismToJaniConverterOptions options)
void exportPrismToFile(storm::prism::Program const &program, std::vector< storm::jani::Property > const &properties, std::string const &filename)
std::vector< storm::jani::Property > substituteConstantsInProperties(std::vector< storm::jani::Property > const &properties, std::map< storm::expressions::Variable, storm::expressions::Expression > const &substitution)
void printHeader(std::string const &name, const int argc, const char **argv)
Definition print.cpp:62
void printVersion()
Definition print.cpp:84
storm::utility::Stopwatch startStopwatch(std::string const &message)
void processOptions()
void setUrgentOptions()
void processPrismInputJaniOutput(storm::prism::Program const &prismProg, std::vector< storm::jani::Property > const &properties)
void processJaniInput()
void processPrismInputPrismOutput(storm::prism::Program const &prismProg, std::vector< storm::jani::Property > const &properties)
void stopStopwatch(storm::utility::Stopwatch &stopWatch)
void processJaniInputJaniOutput(storm::jani::Model const &janiModel, std::vector< storm::jani::Property > const &properties)
void processPrismInput()
ModelFeatures getAllKnownModelFeatures()
void initializeConvSettings(std::string const &name, std::string const &executableName)
SettingsType const & getModule()
Get module.
SettingsManager const & manager()
Retrieves the settings manager.
SettingsManager & mutableManager()
Retrieves the settings manager.
void cleanUp()
Performs some necessary clean-up.
void setLogLevel(l3pp::LogLevel level)
Set the global log level.
void setUp()
Performs some necessary initializations.
LabParser.cpp.
Definition cli.cpp:18
bool parseOptions(const int argc, const char *argv[])
int main(const int argc, const char **argv)
Main entry point of the executable storm-conv.
boost::optional< std::string > modelName
If given, the model will get this name.
bool substituteConstants
If set, constants in expressions are substituted with their definition.