Browse Source

property support for jani -- several changes throughout code, parser currently only supports probability properties

Former-commit-id: d5db0cda02 [formerly 66d55d7e43]
Former-commit-id: 1672b21b12
tempestpy_adaptions
sjunges 8 years ago
parent
commit
ed970d78b1
  1. 45
      src/cli/cli.cpp
  2. 144
      src/cli/entrypoints.h
  3. 41
      src/modelchecker/results/ExplicitQualitativeCheckResult.cpp
  4. 6
      src/modelchecker/results/ExplicitQualitativeCheckResult.h
  5. 59
      src/modelchecker/results/ExplicitQuantitativeCheckResult.cpp
  6. 6
      src/modelchecker/results/ExplicitQuantitativeCheckResult.h
  7. 32
      src/modelchecker/results/FilterType.cpp
  8. 14
      src/modelchecker/results/FilterType.h
  9. 14
      src/modelchecker/results/HybridQuantitativeCheckResult.cpp
  10. 9
      src/modelchecker/results/HybridQuantitativeCheckResult.h
  11. 4
      src/modelchecker/results/QualitativeCheckResult.h
  12. 12
      src/modelchecker/results/QuantitativeCheckResult.h
  13. 17
      src/modelchecker/results/SymbolicQualitativeCheckResult.cpp
  14. 6
      src/modelchecker/results/SymbolicQualitativeCheckResult.h
  15. 12
      src/modelchecker/results/SymbolicQuantitativeCheckResult.cpp
  16. 7
      src/modelchecker/results/SymbolicQuantitativeCheckResult.h
  17. 23
      src/parser/CSVParser.cpp
  18. 12
      src/parser/CSVParser.h
  19. 148
      src/parser/JaniParser.cpp
  20. 9
      src/parser/JaniParser.h
  21. 26
      src/parser/KeyValueParser.cpp
  22. 7
      src/parser/KeyValueParser.h
  23. 14
      src/settings/modules/IOSettings.cpp
  24. 6
      src/settings/modules/IOSettings.h
  25. 42
      src/storage/jani/JSONExporter.cpp
  26. 5
      src/storage/jani/JSONExporter.h
  27. 23
      src/storage/jani/Property.cpp
  28. 44
      src/storage/jani/Property.h
  29. 95
      src/utility/constants.cpp
  30. 15
      src/utility/constants.h
  31. 11
      src/utility/storm.cpp
  32. 1
      src/utility/storm.h

45
src/cli/cli.cpp

@ -213,22 +213,38 @@ namespace storm {
auto ioSettings = storm::settings::getModule<storm::settings::modules::IOSettings>();
if (ioSettings.isPrismOrJaniInputSet()) {
storm::storage::SymbolicModelDescription model;
std::vector<storm::jani::Property> properties;
if (ioSettings.isPrismInputSet()) {
model = storm::parseProgram(ioSettings.getPrismInputFilename());
if (ioSettings.isPrismToJaniSet()) {
model = model.toJani(true);
}
} else if (ioSettings.isJaniInputSet()) {
model = storm::parseJaniModel(ioSettings.getJaniInputFilename()).first;
auto input = storm::parseJaniModel(ioSettings.getJaniInputFilename());
model = input.first;
if (ioSettings.isJaniPropertiesSet()) {
for (auto const& propName : ioSettings.getJaniProperties()) {
STORM_LOG_THROW( input.second.count(propName) == 1, storm::exceptions::InvalidArgumentException, "No property with name " << propName << " known.");
properties.push_back(input.second.at(propName));
}
}
}
// Then proceed to parsing the properties (if given), since the model we are building may depend on the property.
std::vector<std::shared_ptr<storm::logic::Formula const>> formulas;
uint64_t i = 0;
if (storm::settings::getModule<storm::settings::modules::GeneralSettings>().isPropertySet()) {
if (model.isJaniModel()) {
formulas = storm::parseFormulasForJaniModel(storm::settings::getModule<storm::settings::modules::GeneralSettings>().getProperty(), model.asJaniModel());
for(auto const& formula : storm::parseFormulasForJaniModel(storm::settings::getModule<storm::settings::modules::GeneralSettings>().getProperty(), model.asJaniModel())) {
properties.emplace_back(std::to_string(i), formula);
++i;
}
} else {
formulas = storm::parseFormulasForPrismProgram(storm::settings::getModule<storm::settings::modules::GeneralSettings>().getProperty(), model.asPrismProgram());
for(auto const& formula :storm::parseFormulasForPrismProgram(storm::settings::getModule<storm::settings::modules::GeneralSettings>().getProperty(), model.asPrismProgram())) {
properties.emplace_back(std::to_string(i), formula);
++i;
}
}
}
@ -236,9 +252,9 @@ namespace storm {
if (storm::settings::getModule<storm::settings::modules::JaniExportSettings>().isExportAsStandardJaniSet()) {
storm::jani::Model normalisedModel = storm::jani::Model(model.asJaniModel());
normalisedModel.makeStandardJaniCompliant();
storm::jani::JsonExporter::toFile(normalisedModel, formulas, storm::settings::getModule<storm::settings::modules::JaniExportSettings>().getJaniFilename());
storm::jani::JsonExporter::toFile(normalisedModel, formulasInProperties(properties), storm::settings::getModule<storm::settings::modules::JaniExportSettings>().getJaniFilename());
} else {
storm::jani::JsonExporter::toFile(model.asJaniModel(), formulas, storm::settings::getModule<storm::settings::modules::JaniExportSettings>().getJaniFilename());
storm::jani::JsonExporter::toFile(model.asJaniModel(), formulasInProperties(properties), storm::settings::getModule<storm::settings::modules::JaniExportSettings>().getJaniFilename());
}
}
@ -250,30 +266,35 @@ namespace storm {
if (storm::settings::getModule<storm::settings::modules::GeneralSettings>().isParametricSet()) {
#ifdef STORM_HAVE_CARL
buildAndCheckSymbolicModel<storm::RationalFunction>(model, formulas, true);
buildAndCheckSymbolicModel<storm::RationalFunction>(model, properties, true);
#else
STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "No parameters are supported in this build.");
#endif
} else if (storm::settings::getModule<storm::settings::modules::GeneralSettings>().isExactSet()) {
#ifdef STORM_HAVE_CARL
buildAndCheckSymbolicModel<storm::RationalNumber>(model, formulas, true);
buildAndCheckSymbolicModel<storm::RationalNumber>(model, properties, true);
#else
STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "No exact numbers are supported in this build.");
#endif
} else {
buildAndCheckSymbolicModel<double>(model, formulas, true);
buildAndCheckSymbolicModel<double>(model, properties, true);
}
} else if (storm::settings::getModule<storm::settings::modules::IOSettings>().isExplicitSet()) {
STORM_LOG_THROW(storm::settings::getModule<storm::settings::modules::CoreSettings>().getEngine() == storm::settings::modules::CoreSettings::Engine::Sparse, storm::exceptions::InvalidSettingsException, "Only the sparse engine supports explicit model input.");
// If the model is given in an explicit format, we parse the properties without allowing expressions
// in formulas.
std::vector<std::shared_ptr<storm::logic::Formula const>> formulas;
std::vector<storm::jani::Property> properties;
if (storm::settings::getModule<storm::settings::modules::GeneralSettings>().isPropertySet()) {
formulas = storm::parseFormulasForExplicit(storm::settings::getModule<storm::settings::modules::GeneralSettings>().getProperty());
uint64_t i = 0;
for(auto const& formula : storm::parseFormulasForExplicit(storm::settings::getModule<storm::settings::modules::GeneralSettings>().getProperty())) {
properties.emplace_back(std::to_string(i), formula);
++i;
}
}
buildAndCheckExplicitModel<double>(formulas, true);
buildAndCheckExplicitModel<double>(properties, true);
} else {
STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "No input model.");
}

144
src/cli/entrypoints.h

@ -12,15 +12,72 @@ namespace storm {
namespace cli {
template<typename ValueType>
void verifySparseModel(std::shared_ptr<storm::models::sparse::Model<ValueType>> model, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, bool onlyInitialStatesRelevant = false) {
for (auto const& formula : formulas) {
std::cout << std::endl << "Model checking property: " << *formula << " ...";
std::unique_ptr<storm::modelchecker::CheckResult> result(storm::verifySparseModel(model, formula, onlyInitialStatesRelevant));
void applyFilterFunctionAndOutput(std::unique_ptr<storm::modelchecker::CheckResult> const& result, storm::modelchecker::FilterType ft) {
if(result->isQuantitative()) {
switch(ft) {
case storm::modelchecker::FilterType::VALUES:
std::cout << *result << std::endl;
return;
case storm::modelchecker::FilterType::SUM:
std::cout << result->asQuantitativeCheckResult<ValueType>().sum();
return;
case storm::modelchecker::FilterType::AVG:
std::cout << result->asQuantitativeCheckResult<ValueType>().average();
return;
case storm::modelchecker::FilterType::MIN:
std::cout << result->asQuantitativeCheckResult<ValueType>().getMin();
return;
case storm::modelchecker::FilterType::MAX:
std::cout << result->asQuantitativeCheckResult<ValueType>().getMax();
return;
case storm::modelchecker::FilterType::ARGMIN:
case storm::modelchecker::FilterType::ARGMAX:
STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Outputting states is not supported");
case storm::modelchecker::FilterType::EXISTS:
case storm::modelchecker::FilterType::FORALL:
case storm::modelchecker::FilterType::COUNT:
STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "FilterType only defined for qualitative results");
}
} else {
switch(ft) {
case storm::modelchecker::FilterType::VALUES:
std::cout << *result << std::endl;
return;
case storm::modelchecker::FilterType::EXISTS:
std::cout << result->asQualitativeCheckResult().existsTrue();
return;
case storm::modelchecker::FilterType::FORALL:
std::cout << result->asQualitativeCheckResult().forallTrue();
return;
case storm::modelchecker::FilterType::COUNT:
std::cout << result->asQualitativeCheckResult().count();
return;
case storm::modelchecker::FilterType::ARGMIN:
case storm::modelchecker::FilterType::ARGMAX:
STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Outputting states is not supported");
case storm::modelchecker::FilterType::SUM:
case storm::modelchecker::FilterType::AVG:
case storm::modelchecker::FilterType::MIN:
case storm::modelchecker::FilterType::MAX:
STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "FilterType only defined for quantitative results");
}
}
}
template<typename ValueType>
void verifySparseModel(std::shared_ptr<storm::models::sparse::Model<ValueType>> model, std::vector<storm::jani::Property> const& properties, bool onlyInitialStatesRelevant = false) {
for (auto const& property : properties) {
std::cout << std::endl << "Model checking property: " << property << " ...";
std::unique_ptr<storm::modelchecker::CheckResult> result(storm::verifySparseModel(model, property.getFilter().getFormula(), onlyInitialStatesRelevant));
if (result) {
std::cout << " done." << std::endl;
std::cout << "Result (initial states): ";
result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates()));
std::cout << *result << std::endl;
applyFilterFunctionAndOutput<ValueType>(result, property.getFilter().getFilterType());
std::cout << std::endl;
} else {
std::cout << " skipped, because the modelling formalism is currently unsupported." << std::endl;
}
@ -29,17 +86,18 @@ namespace storm {
#ifdef STORM_HAVE_CARL
template<>
inline void verifySparseModel(std::shared_ptr<storm::models::sparse::Model<storm::RationalFunction>> model, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, bool onlyInitialStatesRelevant) {
inline void verifySparseModel(std::shared_ptr<storm::models::sparse::Model<storm::RationalFunction>> model, std::vector<storm::jani::Property> const& properties, bool onlyInitialStatesRelevant) {
for (auto const& formula : formulas) {
for (auto const& property : properties) {
STORM_LOG_THROW(model->getType() == storm::models::ModelType::Dtmc || model->getType() == storm::models::ModelType::Ctmc, storm::exceptions::InvalidSettingsException, "Currently parametric verification is only available for DTMCs and CTMCs.");
std::cout << std::endl << "Model checking property: " << *formula << " ...";
std::unique_ptr<storm::modelchecker::CheckResult> result(storm::verifySparseModel(model, formula, onlyInitialStatesRelevant));
std::cout << std::endl << "Model checking property: " << property << " ...";
std::unique_ptr<storm::modelchecker::CheckResult> result(storm::verifySparseModel(model, property.getFilter().getFormula(), onlyInitialStatesRelevant));
if (result) {
std::cout << " done." << std::endl;
std::cout << "Result (initial states): ";
result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates()));
std::cout << *result << std::endl;
applyFilterFunctionAndOutput<storm::RationalFunction>(result, property.getFilter().getFilterType());
std::cout << std::endl;
} else {
std::cout << " skipped, because the modelling formalism is currently unsupported." << std::endl;
}
@ -52,24 +110,24 @@ namespace storm {
#endif
template<storm::dd::DdType DdType>
void verifySymbolicModelWithAbstractionRefinementEngine(storm::storage::SymbolicModelDescription const& model, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, bool onlyInitialStatesRelevant = false) {
void verifySymbolicModelWithAbstractionRefinementEngine(storm::storage::SymbolicModelDescription const& model, std::vector<storm::jani::Property> const& formulas, bool onlyInitialStatesRelevant = false) {
STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Abstraction Refinement is not yet implemented.");
}
template<typename ValueType>
void verifySymbolicModelWithExplorationEngine(storm::storage::SymbolicModelDescription const& model, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, bool onlyInitialStatesRelevant = false) {
void verifySymbolicModelWithExplorationEngine(storm::storage::SymbolicModelDescription const& model, std::vector<storm::jani::Property> const& formulas, bool onlyInitialStatesRelevant = false) {
STORM_LOG_THROW(model.isPrismProgram(), storm::exceptions::InvalidSettingsException, "Exploration engine is currently only applicable to PRISM models.");
storm::prism::Program const& program = model.asPrismProgram();
STORM_LOG_THROW(program.getModelType() == storm::prism::Program::ModelType::DTMC || program.getModelType() == storm::prism::Program::ModelType::MDP, storm::exceptions::InvalidSettingsException, "Currently exploration-based verification is only available for DTMCs and MDPs.");
for (auto const& formula : formulas) {
std::cout << std::endl << "Model checking property: " << *formula << " ...";
for (auto const& property : formulas) {
std::cout << std::endl << "Model checking property: " << property << " ...";
bool supportFormula;
std::unique_ptr<storm::modelchecker::CheckResult> result;
if(program.getModelType() == storm::prism::Program::ModelType::DTMC) {
storm::modelchecker::SparseExplorationModelChecker<storm::models::sparse::Dtmc<ValueType>> checker(program);
storm::modelchecker::CheckTask<storm::logic::Formula> task(*formula, onlyInitialStatesRelevant);
storm::modelchecker::CheckTask<storm::logic::Formula> task(*property.getFilter().getFormula(), onlyInitialStatesRelevant);
supportFormula = checker.canHandle(task);
if (supportFormula) {
@ -77,7 +135,7 @@ namespace storm {
}
} else if(program.getModelType() == storm::prism::Program::ModelType::MDP) {
storm::modelchecker::SparseExplorationModelChecker<storm::models::sparse::Mdp<ValueType>> checker(program);
storm::modelchecker::CheckTask<storm::logic::Formula> task(*formula, onlyInitialStatesRelevant);
storm::modelchecker::CheckTask<storm::logic::Formula> task(*property.getFilter().getFormula(), onlyInitialStatesRelevant);
supportFormula = checker.canHandle(task);
if (supportFormula) {
@ -94,7 +152,8 @@ namespace storm {
if (result) {
std::cout << " done." << std::endl;
std::cout << "Result (initial states): ";
std::cout << *result << std::endl;
applyFilterFunctionAndOutput<ValueType>(result, property.getFilter().getFilterType());
std::cout << std::endl;
} else {
std::cout << " skipped, because the modelling formalism is currently unsupported." << std::endl;
}
@ -103,22 +162,23 @@ namespace storm {
#ifdef STORM_HAVE_CARL
template<>
void verifySymbolicModelWithExplorationEngine<storm::RationalFunction>(storm::storage::SymbolicModelDescription const& model, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, bool onlyInitialStatesRelevant) {
void verifySymbolicModelWithExplorationEngine<storm::RationalFunction>(storm::storage::SymbolicModelDescription const& model, std::vector<storm::jani::Property> const& formulas, bool onlyInitialStatesRelevant) {
STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "Exploration-based verification does currently not support parametric models.");
}
#endif
template<storm::dd::DdType DdType>
void verifySymbolicModelWithHybridEngine(std::shared_ptr<storm::models::symbolic::Model<DdType>> model, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, bool onlyInitialStatesRelevant = false) {
for (auto const& formula : formulas) {
std::cout << std::endl << "Model checking property: " << *formula << " ...";
std::unique_ptr<storm::modelchecker::CheckResult> result(storm::verifySymbolicModelWithHybridEngine(model, formula, onlyInitialStatesRelevant));
void verifySymbolicModelWithHybridEngine(std::shared_ptr<storm::models::symbolic::Model<DdType>> model, std::vector<storm::jani::Property> const& formulas, bool onlyInitialStatesRelevant = false) {
for (auto const& property : formulas) {
std::cout << std::endl << "Model checking property: " << property << " ...";
std::unique_ptr<storm::modelchecker::CheckResult> result(storm::verifySymbolicModelWithHybridEngine(model, property.getFilter().getFormula(), onlyInitialStatesRelevant));
if (result) {
std::cout << " done." << std::endl;
std::cout << "Result (initial states): ";
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<DdType>(model->getReachableStates(), model->getInitialStates()));
std::cout << *result << std::endl;
applyFilterFunctionAndOutput<double>(result, property.getFilter().getFilterType());
std::cout << std::endl;
} else {
std::cout << " skipped, because the modelling formalism is currently unsupported." << std::endl;
}
@ -126,15 +186,16 @@ namespace storm {
}
template<storm::dd::DdType DdType>
void verifySymbolicModelWithDdEngine(std::shared_ptr<storm::models::symbolic::Model<DdType>> model, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, bool onlyInitialStatesRelevant = false) {
for (auto const& formula : formulas) {
std::cout << std::endl << "Model checking property: " << *formula << " ...";
std::unique_ptr<storm::modelchecker::CheckResult> result(storm::verifySymbolicModelWithDdEngine(model, formula, onlyInitialStatesRelevant));
void verifySymbolicModelWithDdEngine(std::shared_ptr<storm::models::symbolic::Model<DdType>> model, std::vector<storm::jani::Property> const& formulas, bool onlyInitialStatesRelevant = false) {
for (auto const& property : formulas) {
std::cout << std::endl << "Model checking property: " << property << " ...";
std::unique_ptr<storm::modelchecker::CheckResult> result(storm::verifySymbolicModelWithDdEngine(model, property.getFilter().getFormula(), onlyInitialStatesRelevant));
if (result) {
std::cout << " done." << std::endl;
std::cout << "Result (initial states): ";
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<DdType>(model->getReachableStates(), model->getInitialStates()));
std::cout << *result << std::endl;
applyFilterFunctionAndOutput<double>(result, property.getFilter().getFilterType());
std::cout << std::endl;
} else {
std::cout << " skipped, because the modelling formalism is currently unsupported." << std::endl;
}
@ -182,23 +243,24 @@ namespace storm {
}
template<storm::dd::DdType LibraryType>
void buildAndCheckSymbolicModelWithSymbolicEngine(bool hybrid, storm::storage::SymbolicModelDescription const& model, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, bool onlyInitialStatesRelevant = false) {
void buildAndCheckSymbolicModelWithSymbolicEngine(bool hybrid, storm::storage::SymbolicModelDescription const& model, std::vector<storm::jani::Property> const& properties, bool onlyInitialStatesRelevant = false) {
// Start by building the model.
auto markovModel = buildSymbolicModel<double, LibraryType>(model, formulas);
auto markovModel = buildSymbolicModel<double, LibraryType>(model, formulasInProperties(properties));
// Print some information about the model.
markovModel->printModelInformationToStream(std::cout);
// Then select the correct engine.
if (hybrid) {
verifySymbolicModelWithHybridEngine(markovModel, formulas, onlyInitialStatesRelevant);
verifySymbolicModelWithHybridEngine(markovModel, properties, onlyInitialStatesRelevant);
} else {
verifySymbolicModelWithDdEngine(markovModel, formulas, onlyInitialStatesRelevant);
verifySymbolicModelWithDdEngine(markovModel, properties, onlyInitialStatesRelevant);
}
}
template<typename ValueType>
void buildAndCheckSymbolicModelWithSparseEngine(storm::storage::SymbolicModelDescription const& model, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, bool onlyInitialStatesRelevant = false) {
void buildAndCheckSymbolicModelWithSparseEngine(storm::storage::SymbolicModelDescription const& model, std::vector<storm::jani::Property> const& properties, bool onlyInitialStatesRelevant = false) {
auto formulas = formulasInProperties(properties);
// Start by building the model.
std::shared_ptr<storm::models::ModelBase> markovModel = buildSparseModel<ValueType>(model, formulas);
@ -214,12 +276,12 @@ namespace storm {
if (storm::settings::getModule<storm::settings::modules::CoreSettings>().isCounterexampleSet()) {
generateCounterexamples<ValueType>(model, sparseModel, formulas);
} else {
verifySparseModel<ValueType>(sparseModel, formulas, onlyInitialStatesRelevant);
verifySparseModel<ValueType>(sparseModel, properties, onlyInitialStatesRelevant);
}
}
template<typename ValueType>
void buildAndCheckSymbolicModel(storm::storage::SymbolicModelDescription const& model, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, bool onlyInitialStatesRelevant = false) {
void buildAndCheckSymbolicModel(storm::storage::SymbolicModelDescription const& model, std::vector<storm::jani::Property> const& formulas, bool onlyInitialStatesRelevant = false) {
if (storm::settings::getModule<storm::settings::modules::CoreSettings>().getEngine() == storm::settings::modules::CoreSettings::Engine::AbstractionRefinement) {
auto ddlib = storm::settings::getModule<storm::settings::modules::CoreSettings>().getDdLibraryType();
if (ddlib == storm::dd::DdType::CUDD) {
@ -247,35 +309,35 @@ namespace storm {
#ifdef STORM_HAVE_CARL
template<>
void buildAndCheckSymbolicModel<storm::RationalNumber>(storm::storage::SymbolicModelDescription const& model, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, bool onlyInitialStatesRelevant) {
void buildAndCheckSymbolicModel<storm::RationalNumber>(storm::storage::SymbolicModelDescription const& model, std::vector<storm::jani::Property> const& formulas, bool onlyInitialStatesRelevant) {
STORM_LOG_THROW(storm::settings::getModule<storm::settings::modules::CoreSettings>().getEngine() == storm::settings::modules::CoreSettings::Engine::Sparse, storm::exceptions::InvalidSettingsException, "Cannot use this data type with an engine different than the sparse one.");
buildAndCheckSymbolicModelWithSparseEngine<storm::RationalNumber>(model, formulas, onlyInitialStatesRelevant);
}
template<>
void buildAndCheckSymbolicModel<storm::RationalFunction>(storm::storage::SymbolicModelDescription const& model, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, bool onlyInitialStatesRelevant) {
void buildAndCheckSymbolicModel<storm::RationalFunction>(storm::storage::SymbolicModelDescription const& model, std::vector<storm::jani::Property> const& formulas, bool onlyInitialStatesRelevant) {
STORM_LOG_THROW(storm::settings::getModule<storm::settings::modules::CoreSettings>().getEngine() == storm::settings::modules::CoreSettings::Engine::Sparse, storm::exceptions::InvalidSettingsException, "Cannot use this data type with an engine different than the sparse one.");
buildAndCheckSymbolicModelWithSparseEngine<storm::RationalFunction>(model, formulas, onlyInitialStatesRelevant);
}
#endif
template<typename ValueType>
void buildAndCheckExplicitModel(std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, bool onlyInitialStatesRelevant = false) {
void buildAndCheckExplicitModel(std::vector<storm::jani::Property> const& properties, bool onlyInitialStatesRelevant = false) {
storm::settings::modules::IOSettings const& settings = storm::settings::getModule<storm::settings::modules::IOSettings>();
STORM_LOG_THROW(settings.isExplicitSet(), storm::exceptions::InvalidStateException, "Unable to build explicit model without model files.");
std::shared_ptr<storm::models::ModelBase> model = buildExplicitModel<ValueType>(settings.getTransitionFilename(), settings.getLabelingFilename(), settings.isStateRewardsSet() ? boost::optional<std::string>(settings.getStateRewardsFilename()) : boost::none, settings.isTransitionRewardsSet() ? boost::optional<std::string>(settings.getTransitionRewardsFilename()) : boost::none, settings.isChoiceLabelingSet() ? boost::optional<std::string>(settings.getChoiceLabelingFilename()) : boost::none);
// Preprocess the model if needed.
BRANCH_ON_MODELTYPE(model, model, ValueType, storm::dd::DdType::CUDD, preprocessModel, formulas);
BRANCH_ON_MODELTYPE(model, model, ValueType, storm::dd::DdType::CUDD, preprocessModel, formulasInProperties(properties));
// Print some information about the model.
model->printModelInformationToStream(std::cout);
// Verify the model, if a formula was given.
if (!formulas.empty()) {
if (!properties.empty()) {
STORM_LOG_THROW(model->isSparseModel(), storm::exceptions::InvalidStateException, "Expected sparse model.");
verifySparseModel<ValueType>(model->as<storm::models::sparse::Model<ValueType>>(), formulas, onlyInitialStatesRelevant);
verifySparseModel<ValueType>(model->as<storm::models::sparse::Model<ValueType>>(), properties, onlyInitialStatesRelevant);
}
}
}

41
src/modelchecker/results/ExplicitQualitativeCheckResult.cpp

@ -70,6 +70,47 @@ namespace storm {
return *this;
}
bool ExplicitQualitativeCheckResult::existsTrue() const {
if (this->isResultForAllStates()) {
return !boost::get<vector_type>(truthValues).empty();
} else {
for (auto& element : boost::get<map_type>(truthValues)) {
if(element.second) {
return true;
}
}
return false;
}
}
bool ExplicitQualitativeCheckResult::forallTrue() const {
if (this->isResultForAllStates()) {
return boost::get<vector_type>(truthValues).full();
} else {
for (auto& element : boost::get<map_type>(truthValues)) {
if(!element.second) {
return false;
}
}
return true;
}
}
uint64_t ExplicitQualitativeCheckResult::count() const {
if (this->isResultForAllStates()) {
return boost::get<vector_type>(truthValues).getNumberOfSetBits();
} else {
uint64_t result = 0;
for (auto& element : boost::get<map_type>(truthValues)) {
if(element.second) {
++result;
}
}
return result;
}
}
bool ExplicitQualitativeCheckResult::operator[](storm::storage::sparse::state_type state) const {
if (this->isResultForAllStates()) {
return boost::get<vector_type>(truthValues).get(state);

6
src/modelchecker/results/ExplicitQualitativeCheckResult.h

@ -47,6 +47,12 @@ namespace storm {
vector_type const& getTruthValuesVector() const;
map_type const& getTruthValuesVectorMap() const;
virtual bool existsTrue() const override;
virtual bool forallTrue() const override;
virtual uint64_t count() const override;
virtual std::ostream& writeToStream(std::ostream& out) const override;
virtual void filter(QualitativeCheckResult const& filter) override;

59
src/modelchecker/results/ExplicitQuantitativeCheckResult.cpp

@ -3,6 +3,7 @@
#include "src/modelchecker/results/ExplicitQualitativeCheckResult.h"
#include "src/storage/BitVector.h"
#include "src/utility/macros.h"
#include "src/utility/constants.h"
#include "src/utility/vector.h"
#include "src/exceptions/InvalidOperationException.h"
#include "src/exceptions/InvalidAccessException.h"
@ -81,6 +82,64 @@ namespace storm {
}
}
template<typename ValueType>
ValueType ExplicitQuantitativeCheckResult<ValueType>::getMin() const {
STORM_LOG_THROW(!values.empty(),storm::exceptions::InvalidOperationException, "Minimum of empty set is not defined");
if (this->isResultForAllStates()) {
return storm::utility::minimum(boost::get<vector_type>(values));
} else {
return storm::utility::minimum(boost::get<map_type>(values));
}
}
template<typename ValueType>
ValueType ExplicitQuantitativeCheckResult<ValueType>::getMax() const {
STORM_LOG_THROW(!values.empty(),storm::exceptions::InvalidOperationException, "Minimum of empty set is not defined");
if (this->isResultForAllStates()) {
return storm::utility::maximum(boost::get<vector_type>(values));
} else {
return storm::utility::maximum(boost::get<map_type>(values));
}
}
template<typename ValueType>
ValueType ExplicitQuantitativeCheckResult<ValueType>::sum() const {
STORM_LOG_THROW(!values.empty(),storm::exceptions::InvalidOperationException, "Minimum of empty set is not defined");
ValueType sum = storm::utility::zero<ValueType>();
if (this->isResultForAllStates()) {
for (auto& element : boost::get<vector_type>(values)) {
sum += element;
}
} else {
for (auto& element : boost::get<map_type>(values)) {
sum += element.second;
}
}
return sum;
}
template<typename ValueType>
ValueType ExplicitQuantitativeCheckResult<ValueType>::average() const {
STORM_LOG_THROW(!values.empty(),storm::exceptions::InvalidOperationException, "Minimum of empty set is not defined");
ValueType sum = storm::utility::zero<ValueType>();
if (this->isResultForAllStates()) {
for (auto& element : boost::get<vector_type>(values)) {
sum += element;
}
return sum / boost::get<vector_type>(values).size();
} else {
for (auto& element : boost::get<map_type>(values)) {
sum += element.second;
}
return sum / boost::get<map_type>(values).size();
}
}
template<typename ValueType>
bool ExplicitQuantitativeCheckResult<ValueType>::hasScheduler() const {
return static_cast<bool>(scheduler);

6
src/modelchecker/results/ExplicitQuantitativeCheckResult.h

@ -53,6 +53,12 @@ namespace storm {
virtual void oneMinus() override;
virtual ValueType getMin() const override;
virtual ValueType getMax() const override;
virtual ValueType average() const override;
virtual ValueType sum() const override;
bool hasScheduler() const;
void setScheduler(std::unique_ptr<storm::storage::Scheduler>&& scheduler);
storm::storage::Scheduler const& getScheduler() const;

32
src/modelchecker/results/FilterType.cpp

@ -0,0 +1,32 @@
#include "FilterType.h"
namespace storm {
namespace modelchecker {
std::string toString(FilterType ft) {
switch(ft) {
case FilterType::ARGMAX:
return "the argmax";
case FilterType::ARGMIN:
return "the argmin";
case FilterType::AVG:
return "the average";
case FilterType::COUNT:
return "the number of";
case FilterType::EXISTS:
return "whether there exists a state in";
case FilterType::FORALL:
return "whether for all states in";
case FilterType::MAX:
return "the maximum";
case FilterType::MIN:
return "the minumum";
case FilterType::SUM:
return "the sum";
case FilterType::VALUES:
return "the values";
}
}
}
}

14
src/modelchecker/results/FilterType.h

@ -0,0 +1,14 @@
#pragma once
#include <string>
namespace storm {
namespace modelchecker {
enum class StateFilter { ARGMIN, ARGMAX };
enum class FilterType { MIN, MAX, SUM, AVG, COUNT, FORALL, EXISTS, ARGMIN, ARGMAX, VALUES };
std::string toString(FilterType);
bool isStateFilter(FilterType);
}
}

14
src/modelchecker/results/HybridQuantitativeCheckResult.cpp

@ -5,9 +5,12 @@
#include "src/storage/dd/cudd/CuddAddIterator.h"
#include "src/exceptions/InvalidOperationException.h"
#include "src/exceptions/NotImplementedException.h"
#include "src/utility/macros.h"
#include "src/utility/constants.h"
namespace storm {
namespace modelchecker {
template<storm::dd::DdType Type, typename ValueType>
@ -164,6 +167,16 @@ namespace storm {
return max;
}
template<storm::dd::DdType Type, typename ValueType>
ValueType HybridQuantitativeCheckResult<Type, ValueType>::sum() const {
STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Sum not implemented for hybrid results");
}
template<storm::dd::DdType Type, typename ValueType>
ValueType HybridQuantitativeCheckResult<Type, ValueType>::average() const {
STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Average not implemented for hybrid results");
}
template<storm::dd::DdType Type, typename ValueType>
void HybridQuantitativeCheckResult<Type, ValueType>::oneMinus() {
storm::dd::Add<Type> one = symbolicValues.getDdManager().template getAddOne<ValueType>();
@ -175,6 +188,7 @@ namespace storm {
}
}
// Explicitly instantiate the class.
template class HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>;
template class HybridQuantitativeCheckResult<storm::dd::DdType::Sylvan>;

9
src/modelchecker/results/HybridQuantitativeCheckResult.h

@ -46,9 +46,14 @@ namespace storm {
virtual void filter(QualitativeCheckResult const& filter) override;
virtual ValueType getMin() const;
virtual ValueType getMin() const override;
virtual ValueType getMax() const;
virtual ValueType getMax() const override;
virtual ValueType sum() const override;
virtual ValueType average() const override;
virtual void oneMinus() override;

4
src/modelchecker/results/QualitativeCheckResult.h

@ -12,6 +12,10 @@ namespace storm {
virtual QualitativeCheckResult& operator|=(QualitativeCheckResult const& other);
virtual void complement();
virtual bool existsTrue() const = 0;
virtual bool forallTrue() const = 0;
virtual uint64_t count() const = 0;
virtual bool isQualitative() const override;
};
}

12
src/modelchecker/results/QuantitativeCheckResult.h

@ -1,5 +1,4 @@
#ifndef STORM_MODELCHECKER_QUANTITATIVECHECKRESULT_H_
#define STORM_MODELCHECKER_QUANTITATIVECHECKRESULT_H_
#pragma once
#include "src/modelchecker/results/CheckResult.h"
@ -14,9 +13,16 @@ namespace storm {
virtual void oneMinus() = 0;
virtual ValueType getMin() const = 0;
virtual ValueType getMax() const = 0;
virtual ValueType average() const = 0;
virtual ValueType sum() const = 0;
virtual bool isQuantitative() const override;
};
}
}
#endif /* STORM_MODELCHECKER_QUANTITATIVECHECKRESULT_H_ */

17
src/modelchecker/results/SymbolicQualitativeCheckResult.cpp

@ -3,6 +3,8 @@
#include "src/utility/macros.h"
#include "src/exceptions/InvalidOperationException.h"
#include "src/exceptions/NotImplementedException.h"
namespace storm {
namespace modelchecker {
template <storm::dd::DdType Type>
@ -49,6 +51,21 @@ namespace storm {
return truthValues;
}
template <storm::dd::DdType Type>
bool SymbolicQualitativeCheckResult<Type>::existsTrue() const {
STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Exists not implemented for symbolic results");
}
template <storm::dd::DdType Type>
bool SymbolicQualitativeCheckResult<Type>::forallTrue() const {
STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Forall not implemented for symbolic results");
}
template <storm::dd::DdType Type>
uint64_t SymbolicQualitativeCheckResult<Type>::count() const {
STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Count not implemented for symbolic results");
}
template <storm::dd::DdType Type>
std::ostream& SymbolicQualitativeCheckResult<Type>::writeToStream(std::ostream& out) const {
if (this->truthValues.isZero()) {

6
src/modelchecker/results/SymbolicQualitativeCheckResult.h

@ -30,6 +30,12 @@ namespace storm {
virtual QualitativeCheckResult& operator|=(QualitativeCheckResult const& other) override;
virtual void complement() override;
virtual bool existsTrue() const override;
virtual bool forallTrue() const override;
virtual uint64_t count() const override;
storm::dd::Bdd<Type> const& getTruthValuesVector() const;
virtual std::ostream& writeToStream(std::ostream& out) const override;

12
src/modelchecker/results/SymbolicQuantitativeCheckResult.cpp

@ -5,6 +5,8 @@
#include "src/storage/dd/cudd/CuddAddIterator.h"
#include "src/exceptions/InvalidOperationException.h"
#include "src/exceptions/NotImplementedException.h"
#include "src/utility/macros.h"
#include "src/utility/constants.h"
@ -89,6 +91,16 @@ namespace storm {
return this->values.getMax();
}
template<storm::dd::DdType Type, typename ValueType>
ValueType SymbolicQuantitativeCheckResult<Type, ValueType>::average() const {
STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Average not implemented for symbolic results");
}
template<storm::dd::DdType Type, typename ValueType>
ValueType SymbolicQuantitativeCheckResult<Type, ValueType>::sum() const {
STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Sum not implemented for symbolic results");
}
template<storm::dd::DdType Type, typename ValueType>
void SymbolicQuantitativeCheckResult<Type, ValueType>::oneMinus() {
storm::dd::Add<Type> one = values.getDdManager().template getAddOne<ValueType>();

7
src/modelchecker/results/SymbolicQuantitativeCheckResult.h

@ -35,9 +35,12 @@ namespace storm {
virtual void filter(QualitativeCheckResult const& filter) override;
virtual ValueType getMin() const;
virtual ValueType getMin() const override;
virtual ValueType getMax() const;
virtual ValueType getMax() const override;
virtual ValueType average() const override;
virtual ValueType sum() const override;
virtual void oneMinus() override;

23
src/parser/CSVParser.cpp

@ -0,0 +1,23 @@
#include "src/parser/CSVParser.h"
#include <boost/any.hpp>
#include <boost/algorithm/string.hpp>
#include "src/utility/macros.h"
#include "src/exceptions/InvalidArgumentException.h"
namespace storm {
namespace parser {
std::vector<std::string> parseCommaSeperatedValues(std::string const& input) {
std::vector<std::string> values;
std::vector<std::string> definitions;
boost::split(definitions, input, boost::is_any_of(","));
for (auto& definition : definitions) {
boost::trim(definition);
values.push_back(definition);
}
return values;
}
}
}

12
src/parser/CSVParser.h

@ -0,0 +1,12 @@
#include <vector>
#include <string>
namespace storm {
namespace parser {
/**
* Given a string seperated by commas, returns the values.
*/
std::vector<std::string> parseCommaSeperatedValues(std::string const& input);
}
}

148
src/parser/JaniParser.cpp

@ -10,6 +10,7 @@
#include "src/exceptions/NotImplementedException.h"
#include "src/storage/jani/ModelType.h"
#include "src/modelchecker/results/FilterType.h"
#include <iostream>
#include <sstream>
@ -153,11 +154,41 @@ namespace storm {
return { parseFormula(propertyStructure.at("left"), "Operand of operator " + opstring), parseFormula(propertyStructure.at("right"), "Operand of operator " + opstring) };
}
storm::jani::PropertyInterval JaniParser::parsePropertyInterval(json const& piStructure) {
storm::jani::PropertyInterval pi;
if (piStructure.count("lower") > 0) {
pi.lowerBound = parseExpression(piStructure.at("lower"), "Lower bound for property interval");
// TODO substitute constants.
STORM_LOG_THROW(!pi.lowerBound.containsVariables(), storm::exceptions::NotSupportedException, "Only constant expressions are supported as lower bounds");
}
if (piStructure.count("lower-exclusive") > 0) {
STORM_LOG_THROW(pi.lowerBound.isInitialized(), storm::exceptions::InvalidJaniException, "Lower-exclusive can only be set if a lower bound is present");
pi.lowerBoundStrict = piStructure.at("lower-exclusive");
}
if (piStructure.count("upper") > 0) {
pi.upperBound = parseExpression(piStructure.at("upper"), "Upper bound for property interval");
// TODO substitute constants.
STORM_LOG_THROW(!pi.upperBound.containsVariables(), storm::exceptions::NotSupportedException, "Only constant expressions are supported as upper bounds");
}
if (piStructure.count("upper-exclusive") > 0) {
STORM_LOG_THROW(pi.lowerBound.isInitialized(), storm::exceptions::InvalidJaniException, "Lower-exclusive can only be set if a lower bound is present");
pi.lowerBoundStrict = piStructure.at("upper-exclusive");
}
STORM_LOG_THROW(pi.lowerBound.isInitialized() || pi.upperBound.isInitialized(), storm::exceptions::InvalidJaniException, "Bounded operators must be bounded");
return pi;
}
std::shared_ptr<storm::logic::Formula const> JaniParser::parseFormula(json const& propertyStructure, std::string const& context) {
storm::expressions::Expression expr = parseExpression(propertyStructure, "Expression in property", {}, true);
std::shared_ptr<storm::logic::Formula const> JaniParser::parseFormula(json const& propertyStructure, std::string const& context, boost::optional<storm::logic::Bound<storm::RationalNumber>> bound) {
storm::expressions::Expression expr = parseExpression(propertyStructure, "expression in property", {}, true);
if(expr.isInitialized()) {
assert(bound == boost::none);
return std::make_shared<storm::logic::AtomicExpressionFormula>(expr);
} else if(propertyStructure.count("op") == 1) {
std::string opString = getString(propertyStructure.at("op"), "Operation description");
@ -167,9 +198,11 @@ namespace storm {
assert(args.size() == 1);
storm::logic::OperatorInformation opInfo;
opInfo.optimalityType = opString == "Pmin" ? storm::solver::OptimizationDirection::Minimize : storm::solver::OptimizationDirection::Maximize;
opInfo.bound = bound;
return std::make_shared<storm::logic::ProbabilityOperatorFormula>(args[0], opInfo);
} else if (opString == "" || opString == "") {
assert(bound == boost::none);
STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Forall and Exists are currently not supported");
} else if (opString == "Emin" || opString == "Emax") {
STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Emin and Emax are currently not supported");
@ -177,29 +210,84 @@ namespace storm {
std::vector<std::shared_ptr<storm::logic::Formula const>> args = parseUnaryFormulaArgument(propertyStructure, opString, "");
STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Smin and Smax are currently not supported");
} else if (opString == "U") {
assert(bound == boost::none);
std::vector<std::shared_ptr<storm::logic::Formula const>> args = parseBinaryFormulaArguments(propertyStructure, opString, "");
if (propertyStructure.count("step-bounds") > 0) {
storm::jani::PropertyInterval pi = parsePropertyInterval(propertyStructure.at("step-bounds"));
STORM_LOG_THROW(pi.hasUpperBound(), storm::exceptions::NotSupportedException, "Storm only supports step-bounded until with an upper bound");
if(pi.hasLowerBound()) {
STORM_LOG_THROW(pi.lowerBound.evaluateAsInt() == 0, storm::exceptions::NotSupportedException, "Storm only supports step-bounded until without a (non-trivial) lower-bound");
}
int64_t upperBound = pi.upperBound.evaluateAsInt();
if(pi.upperBoundStrict) {
upperBound--;
}
STORM_LOG_THROW(upperBound >= 0, storm::exceptions::InvalidJaniException, "Step-bounds cannot be negative");
return std::make_shared<storm::logic::BoundedUntilFormula const>(args[0], args[1], upperBound);
} else if (propertyStructure.count("time-bounds") > 0) {
storm::jani::PropertyInterval pi = parsePropertyInterval(propertyStructure.at("time-bounds"));
STORM_LOG_THROW(pi.hasUpperBound(), storm::exceptions::NotSupportedException, "Storm only supports time-bounded until with an upper bound.");
double lowerBound = 0.0;
if(pi.hasLowerBound()) {
lowerBound = pi.lowerBound.evaluateAsDouble();
}
double upperBound = pi.upperBound.evaluateAsDouble();
STORM_LOG_THROW(lowerBound >= 0, storm::exceptions::InvalidJaniException, "(Lower) time-bounds cannot be negative");
STORM_LOG_THROW(upperBound >= 0, storm::exceptions::InvalidJaniException, "(Upper) time-bounds cannot be negative");
return std::make_shared<storm::logic::BoundedUntilFormula const>(args[0], args[1], upperBound);
} else if (propertyStructure.count("reward-bounds") > 0 ) {
STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Reward bounded properties are not supported by Storm");
}
return std::make_shared<storm::logic::UntilFormula const>(args[0], args[1]);
if (args[0]->isTrueFormula()) {
return std::make_shared<storm::logic::EventuallyFormula const>(args[1]);
} else {
return std::make_shared<storm::logic::UntilFormula const>(args[0], args[1]);
}
} else if (opString == "W") {
assert(bound == boost::none);
STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Weak until is not supported");
} else if (opString == "" || opString == "") {
assert(bound == boost::none);
std::vector<std::shared_ptr<storm::logic::Formula const>> args = parseBinaryFormulaArguments(propertyStructure, opString, "");
assert(args.size() == 2);
storm::logic::BinaryBooleanStateFormula::OperatorType oper = opString == "" ? storm::logic::BinaryBooleanStateFormula::OperatorType::And : storm::logic::BinaryBooleanStateFormula::OperatorType::Or;
return std::make_shared<storm::logic::BinaryBooleanStateFormula const>(oper, args[0], args[1]);
} else if (opString == "¬") {
assert(bound == boost::none);
std::vector<std::shared_ptr<storm::logic::Formula const>> args = parseUnaryFormulaArgument(propertyStructure, opString, "");
assert(args.size() == 1);
return std::make_shared<storm::logic::UnaryBooleanStateFormula const>(storm::logic::UnaryBooleanStateFormula::OperatorType::Not, args[0]);
} else if (opString == "" || opString == "" || opString == "<" || opString == ">") {
assert(bound == boost::none);
storm::logic::ComparisonType ct;
if(opString == "") {
ct = storm::logic::ComparisonType::GreaterEqual;
} else if (opString == "") {
ct = storm::logic::ComparisonType::LessEqual;
} else if (opString == "<") {
ct = storm::logic::ComparisonType::Less;
} else if (opString == ">") {
ct = storm::logic::ComparisonType::Greater;
}
if (propertyStructure.at("left").count("op") > 0 && (propertyStructure.at("left").at("op") == "Pmin" || propertyStructure.at("left").at("op") == "Pmax" || propertyStructure.at("left").at("op") == "Emin" || propertyStructure.at("left").at("op") == "Emax" || propertyStructure.at("left").at("op") == "Smin" || propertyStructure.at("left").at("op") == "Smax")) {
auto expr = parseExpression(propertyStructure.at("right"), "Threshold for operator " + propertyStructure.at("left").at("op").get<std::string>());
STORM_LOG_THROW(expr.getVariables().empty(), storm::exceptions::NotSupportedException, "Only constant thresholds supported");
// TODO evaluate this expression directly as rational number
return parseFormula(propertyStructure.at("left"), "", storm::logic::Bound<storm::RationalNumber>(ct, storm::utility::convertNumber<storm::RationalNumber>(expr.evaluateAsDouble())));
} else if(propertyStructure.at("right").count("op") > 0 && (propertyStructure.at("right").at("op") == "Pmin" || propertyStructure.at("right").at("op") == "Pmax" || propertyStructure.at("right").at("op") == "Emin" || propertyStructure.at("right").at("op") == "Emax" || propertyStructure.at("right").at("op") == "Smin" || propertyStructure.at("right").at("op") == "Smax")) {
auto expr = parseExpression(propertyStructure.at("left"), "Threshold for operator " + propertyStructure.at("right").at("op").get<std::string>());
STORM_LOG_THROW(expr.getVariables().empty(), storm::exceptions::NotSupportedException, "Only constant thresholds supported");
// TODO evaluate this expression directly as rational number
return parseFormula(propertyStructure.at("right"), "", storm::logic::Bound<storm::RationalNumber>(ct, storm::utility::convertNumber<storm::RationalNumber>(expr.evaluateAsDouble())));
} else {
STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "No complex comparisons are allowed.");
}
} else {
STORM_LOG_THROW(false, storm::exceptions::InvalidJaniException, "Unknown operator " << opString);
}
}
}
@ -220,38 +308,38 @@ namespace storm {
STORM_LOG_THROW(expressionStructure.at("op") == "filter", storm::exceptions::InvalidJaniException, "Top level operation of a property must be a filter");
STORM_LOG_THROW(expressionStructure.count("fun") == 1, storm::exceptions::InvalidJaniException, "Filter must have a function descritpion");
std::string funDescr = getString(expressionStructure.at("fun"), "Filter function in property named " + name);
storm::jani::FilterType ft;
storm::modelchecker::FilterType ft;
if (funDescr == "min") {
ft = storm::jani::FilterType::MIN;
ft = storm::modelchecker::FilterType::MIN;
} else if (funDescr == "max") {
ft = storm::jani::FilterType::MAX;
ft = storm::modelchecker::FilterType::MAX;
} else if (funDescr == "sum") {
ft = storm::jani::FilterType::SUM;
ft = storm::modelchecker::FilterType::SUM;
} else if (funDescr == "avg") {
ft = storm::jani::FilterType::AVG;
ft = storm::modelchecker::FilterType::AVG;
} else if (funDescr == "count") {
ft = storm::jani::FilterType::COUNT;
ft = storm::modelchecker::FilterType::COUNT;
} else if (funDescr == "") {
ft = storm::jani::FilterType::FORALL;
ft = storm::modelchecker::FilterType::FORALL;
} else if (funDescr == "") {
ft = storm::jani::FilterType::EXISTS;
ft = storm::modelchecker::FilterType::EXISTS;
} else if (funDescr == "argmin") {
ft = storm::jani::FilterType::ARGMIN;
ft = storm::modelchecker::FilterType::ARGMIN;
} else if (funDescr == "argmax") {
ft = storm::jani::FilterType::ARGMAX;
ft = storm::modelchecker::FilterType::ARGMAX;
} else if (funDescr == "values") {
ft = storm::jani::FilterType::VALUES;
ft = storm::modelchecker::FilterType::VALUES;
} else {
STORM_LOG_THROW(false, storm::exceptions::InvalidJaniException, "Unknown filter description " << funDescr << " in property named " << name);
}
STORM_LOG_THROW(expressionStructure.count("states") == 1, storm::exceptions::InvalidJaniException, "Filter must have a states description");
STORM_LOG_THROW(expressionStructure.at("states").is_string(), storm::exceptions::NotImplementedException, "We only support properties where the filter has a non-complex description of the states");
std::string statesDescr = getString(expressionStructure.at("states"), "Filtered states in property named " + name);
STORM_LOG_THROW(expressionStructure.at("states").count("op") > 0, storm::exceptions::NotImplementedException, "We only support properties where the filter has initial states");
std::string statesDescr = getString(expressionStructure.at("states").at("op"), "Filtered states in property named " + name);
STORM_LOG_THROW(statesDescr == "initial", storm::exceptions::NotImplementedException, "Only initial states are allowed as set of states we are interested in.");
STORM_LOG_THROW(expressionStructure.count("values") == 1, storm::exceptions::InvalidJaniException, "Values as input for a filter must be given");
auto formula = parseFormula(expressionStructure.at("values"), "Values of property " + name);
return storm::jani::Property(name, formula, comment);
return storm::jani::Property(name, storm::jani::FilterExpression(formula, ft), comment);
}
std::shared_ptr<storm::jani::Constant> JaniParser::parseConstant(json const& constantStructure, std::string const& scopeDescription) {
@ -567,26 +655,38 @@ namespace storm {
return arguments[0] != arguments[1];
}
} else if (opstring == "<") {
arguments = parseBinaryExpressionArguments(expressionStructure, opstring, scopeDescription, localVars);
arguments = parseBinaryExpressionArguments(expressionStructure, opstring, scopeDescription, localVars, returnNoneInitializedOnUnknownOperator);
assert(arguments.size() == 2);
if(!arguments[0].isInitialized() || !arguments[1].isInitialized()) {
return storm::expressions::Expression();
}
ensureNumericalType(arguments[0], opstring, 0, scopeDescription);
ensureNumericalType(arguments[1], opstring, 1, scopeDescription);
return arguments[0] < arguments[1];
} else if (opstring == "") {
arguments = parseBinaryExpressionArguments(expressionStructure, opstring, scopeDescription, localVars);
arguments = parseBinaryExpressionArguments(expressionStructure, opstring, scopeDescription, localVars, returnNoneInitializedOnUnknownOperator);
assert(arguments.size() == 2);
if(!arguments[0].isInitialized() || !arguments[1].isInitialized()) {
return storm::expressions::Expression();
}
ensureNumericalType(arguments[0], opstring, 0, scopeDescription);
ensureNumericalType(arguments[1], opstring, 1, scopeDescription);
return arguments[0] <= arguments[1];
} else if (opstring == ">") {
arguments = parseBinaryExpressionArguments(expressionStructure, opstring, scopeDescription, localVars);
arguments = parseBinaryExpressionArguments(expressionStructure, opstring, scopeDescription, localVars, returnNoneInitializedOnUnknownOperator);
assert(arguments.size() == 2);
if(!arguments[0].isInitialized() || !arguments[1].isInitialized()) {
return storm::expressions::Expression();
}
ensureNumericalType(arguments[0], opstring, 0, scopeDescription);
ensureNumericalType(arguments[1], opstring, 1, scopeDescription);
return arguments[0] > arguments[1];
} else if (opstring == "") {
arguments = parseBinaryExpressionArguments(expressionStructure, opstring, scopeDescription, localVars);
arguments = parseBinaryExpressionArguments(expressionStructure, opstring, scopeDescription, localVars, returnNoneInitializedOnUnknownOperator);
assert(arguments.size() == 2);
if(!arguments[0].isInitialized() || !arguments[1].isInitialized()) {
return storm::expressions::Expression();
}
ensureNumericalType(arguments[0], opstring, 0, scopeDescription);
ensureNumericalType(arguments[1], opstring, 1, scopeDescription);
return arguments[0] >= arguments[1];

9
src/parser/JaniParser.h

@ -1,9 +1,11 @@
#pragma once
#include <src/storage/jani/Constant.h>
#include <src/logic/Formula.h>
#include "src/logic/Formula.h"
#include "src/logic/Bound.h"
#include "src/exceptions/FileIoException.h"
#include "src/storage/expressions/ExpressionManager.h"
// JSON parser
#include "json.hpp"
@ -16,6 +18,7 @@ namespace storm {
class Variable;
class Composition;
class Property;
class PropertyInterval;
}
@ -51,13 +54,13 @@ namespace storm {
* Helper for parsing the actions of a model.
*/
void parseActions(json const& actionStructure, storm::jani::Model& parentModel);
std::shared_ptr<storm::logic::Formula const> parseFormula(json const& propertyStructure, std::string const& context);
std::shared_ptr<storm::logic::Formula const> parseFormula(json const& propertyStructure, std::string const& context, boost::optional<storm::logic::Bound<storm::RationalNumber>> bound = boost::none);
std::vector<storm::expressions::Expression> parseUnaryExpressionArguments(json const& expressionStructure, std::string const& opstring, std::string const& scopeDescription, std::unordered_map<std::string, std::shared_ptr<storm::jani::Variable>> const& localVars = {}, bool returnNoneOnUnknownOpString = false);
std::vector<storm::expressions::Expression> parseBinaryExpressionArguments(json const& expressionStructure, std::string const& opstring, std::string const& scopeDescription, std::unordered_map<std::string, std::shared_ptr<storm::jani::Variable>> const& localVars = {}, bool returnNoneOnUnknownOpString = false);
std::vector<std::shared_ptr<storm::logic::Formula const>> parseUnaryFormulaArgument(json const& propertyStructure, std::string const& opstring, std::string const& context);
std::vector<std::shared_ptr<storm::logic::Formula const>> parseBinaryFormulaArguments(json const& propertyStructure, std::string const& opstring, std::string const& context);
storm::jani::PropertyInterval parsePropertyInterval(json const& piStructure);
std::shared_ptr<storm::jani::Composition> parseComposition(json const& compositionStructure);

26
src/parser/KeyValueParser.cpp

@ -0,0 +1,26 @@
#include "KeyValueParser.h"
namespace storm {
namespace parser {
std::unordered_map<std::string, std::string> parseKeyValueString(std::string const& keyValueString) {
std::unordered_map<std::string, std::string> keyValueMap;
std::vector<std::string> definitions;
boost::split(definitions, keyValueString, boost::is_any_of(","));
for (auto& definition : definitions) {
boost::trim(definition);
// Check whether the token could be a legal constant definition.
std::size_t positionOfAssignmentOperator = definition.find('=');
STORM_LOG_THROW(positionOfAssignmentOperator != std::string::npos, storm::exceptions::InvalidArgumentException, "Illegal key value string: syntax error.");
// Now extract the variable name and the value from the string.
std::string key = definition.substr(0, positionOfAssignmentOperator);
boost::trim(key);
std::string value = definition.substr(positionOfAssignmentOperator + 1);
boost::trim(value);
keyValueMap.emplace(key, value);
}
}
}
}

7
src/parser/KeyValueParser.h

@ -0,0 +1,7 @@
#pragma once
namespace storm {
namespace parser {
std::unordered_map<std::string, std::string> parseKeyValueString(std::string const& keyValueString);
}
}

14
src/settings/modules/IOSettings.cpp

@ -7,6 +7,7 @@
#include "src/settings/ArgumentBuilder.h"
#include "src/settings/Argument.h"
#include "src/exceptions/InvalidSettingsException.h"
#include "src/parser/CSVParser.h"
namespace storm {
namespace settings {
@ -29,6 +30,8 @@ namespace storm {
const std::string IOSettings::constantsOptionShortName = "const";
const std::string IOSettings::prismCompatibilityOptionName = "prismcompat";
const std::string IOSettings::prismCompatibilityOptionShortName = "pc";
const std::string IOSettings::janiPropertyOptionName = "janiproperty";
const std::string IOSettings::janiPropertyOptionShortName = "jprop";
IOSettings::IOSettings() : ModuleSettings(moduleName) {
this->addOption(storm::settings::OptionBuilder(moduleName, prismCompatibilityOptionName, false, "Enables PRISM compatibility. This may be necessary to process some PRISM models.").setShortName(prismCompatibilityOptionShortName).build());
@ -57,6 +60,8 @@ namespace storm {
.addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The file from which to read the choice labels.").addValidationFunctionString(storm::settings::ArgumentValidators::existingReadableFileValidator()).build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName, constantsOptionName, false, "Specifies the constant replacements to use in symbolic models. Note that this requires the model to be given as an symbolic model (i.e., via --" + prismInputOptionName + " or --" + janiInputOptionName + ").").setShortName(constantsOptionShortName)
.addArgument(storm::settings::ArgumentBuilder::createStringArgument("values", "A comma separated list of constants and their value, e.g. a=1,b=2,c=3.").setDefaultValueString("").build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName, janiPropertyOptionName, false, "Specifies the properties from the jani model (given by --" + janiInputOptionName + ") to be checked.").setShortName(janiPropertyOptionShortName)
.addArgument(storm::settings::ArgumentBuilder::createStringArgument("values", "A comma separated list of properties to be checked").setDefaultValueString("").build()).build());
}
bool IOSettings::isExportDotSet() const {
@ -153,6 +158,15 @@ namespace storm {
return this->getOption(constantsOptionName).getArgumentByName("values").getValueAsString();
}
bool IOSettings::isJaniPropertiesSet() const {
return this->getOption(janiPropertyOptionName).getHasOptionBeenSet();
}
std::vector<std::string> IOSettings::getJaniProperties() const {
return storm::parser::parseCommaSeperatedValues(this->getOption(janiPropertyOptionName).getArgumentByName("values").getValueAsString());
}
bool IOSettings::isPrismCompatibilityEnabled() const {
return this->getOption(prismCompatibilityOptionName).getHasOptionBeenSet();
}

6
src/settings/modules/IOSettings.h

@ -183,6 +183,10 @@ namespace storm {
* @return The string that defines the constants of a symbolic model.
*/
std::string getConstantDefinitionString() const;
bool isJaniPropertiesSet() const;
std::vector<std::string> getJaniProperties() const;
/*!
* Retrieves whether the PRISM compatibility mode was enabled.
@ -215,6 +219,8 @@ namespace storm {
static const std::string constantsOptionShortName;
static const std::string prismCompatibilityOptionName;
static const std::string prismCompatibilityOptionShortName;
static const std::string janiPropertyOptionName;
static const std::string janiPropertyOptionShortName;
};
} // namespace modules

42
src/storage/jani/JSONExporter.cpp

@ -105,13 +105,17 @@ namespace storm {
modernjson::json numberToJson(storm::RationalNumber rn) {
modernjson::json numDecl;
if(carl::isOne(carl::getDenom(rn))) {
numDecl = modernjson::json(carl::toString(carl::getNum(rn)));
} else {
numDecl["op"] = "/";
numDecl["left"] = carl::toString(carl::getNum(rn));
numDecl["right"] = carl::toString(carl::getDenom(rn));
}
numDecl = storm::utility::convertNumber<double>(rn);
// if(carl::isOne(carl::getDenom(rn))) {
// numDecl = modernjson::json(carl::toString(carl::getNum(rn)));
// } else {
// numDecl["op"] = "/";
// // TODO set json lib to work with arbitrary precision ints.
// assert(carl::toInt<int64_t>(carl::getNum(rn)) == carl::getNum(rn));
// assert(carl::toInt<int64_t>(carl::getDenom(rn)) == carl::getDenom(rn));
// numDecl["left"] = carl::toInt<int64_t>(carl::getNum(rn));
// numDecl["right"] = carl::toInt<int64_t>(carl::getDenom(rn));
// }
return numDecl;
}
@ -689,27 +693,27 @@ namespace storm {
}
std::string janiFilterTypeString(storm::jani::FilterType const& ft) {
std::string janiFilterTypeString(storm::modelchecker::FilterType const& ft) {
switch(ft) {
case storm::jani::FilterType::MIN:
case storm::modelchecker::FilterType::MIN:
return "min";
case storm::jani::FilterType::MAX:
case storm::modelchecker::FilterType::MAX:
return "max";
case storm::jani::FilterType::SUM:
case storm::modelchecker::FilterType::SUM:
return "sum";
case storm::jani::FilterType::AVG:
case storm::modelchecker::FilterType::AVG:
return "avg";
case storm::jani::FilterType::COUNT:
case storm::modelchecker::FilterType::COUNT:
return "count";
case storm::jani::FilterType::EXISTS:
case storm::modelchecker::FilterType::EXISTS:
return "";
case storm::jani::FilterType::FORALL:
case storm::modelchecker::FilterType::FORALL:
return "";
case storm::jani::FilterType::ARGMIN:
case storm::modelchecker::FilterType::ARGMIN:
return "argmin";
case storm::jani::FilterType::ARGMAX:
case storm::modelchecker::FilterType::ARGMAX:
return "argmax";
case storm::jani::FilterType::VALUES:
case storm::modelchecker::FilterType::VALUES:
return "values";
}
@ -717,7 +721,7 @@ namespace storm {
modernjson::json convertFilterExpression(storm::jani::FilterExpression const& fe, bool continuousModel) {
modernjson::json propDecl;
propDecl["states"] = "initial";
propDecl["states"]["op"] = "initial";
propDecl["op"] = "filter";
propDecl["fun"] = janiFilterTypeString(fe.getFilterType());
propDecl["values"] = FormulaToJaniJson::translate(*fe.getFormula(), continuousModel);

5
src/storage/jani/JSONExporter.h

@ -4,9 +4,12 @@
#include "src/storage/expressions/ExpressionVisitor.h"
#include "src/logic/FormulaVisitor.h"
#include "Model.h"
#include "src/adapters/NumberAdapter.h"
// JSON parser
#include "json.hpp"
namespace modernjson = nlohmann;
namespace modernjson {
using json = nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, double, std::allocator>;
};
namespace storm {
namespace jani {

23
src/storage/jani/Property.cpp

@ -1,10 +1,23 @@
#include "Property.h"
namespace storm {
namespace jani {
std::ostream& operator<<(std::ostream& os, FilterExpression const& fe) {
return os << "Obtain " << toString(fe.getFilterType()) << " the 'initial'-states with values described by '" << *fe.getFormula() << "'";
}
Property::Property(std::string const& name, std::shared_ptr<storm::logic::Formula const> const& formula, std::string const& comment)
: name(name), filterExpression(FilterExpression(formula)), comment(comment)
: name(name), comment(comment), filterExpression(FilterExpression(formula))
{
}
Property::Property(std::string const& name, FilterExpression const& fe, std::string const& comment)
: name(name), comment(comment), filterExpression(fe)
{
}
std::string const& Property::getName() const {
@ -15,6 +28,14 @@ namespace storm {
return this->comment;
}
FilterExpression const& Property::getFilter() const {
return this->filterExpression;
}
std::ostream& operator<<(std::ostream& os, Property const& p) {
return os << "(" << p.getName() << ") : " << p.getFilter();
}
}
}

44
src/storage/jani/Property.h

@ -1,33 +1,52 @@
#pragma once
#include "src/logic/formulas.h"
#include "src/modelchecker/results/FilterType.h"
namespace storm {
namespace jani {
enum class FilterType { MIN, MAX, SUM, AVG, COUNT, FORALL, EXISTS, ARGMIN, ARGMAX, VALUES };
/**
* Property intervals as per Jani Specification.
* Currently mainly used to help parsing.
*/
struct PropertyInterval {
storm::expressions::Expression lowerBound;
bool lowerBoundStrict = false;
storm::expressions::Expression upperBound;
bool upperBoundStrict = false;
bool hasLowerBound() {
return lowerBound.isInitialized();
}
bool hasUpperBound() {
return upperBound.isInitialized();
}
};
class FilterExpression {
public:
explicit FilterExpression(std::shared_ptr<storm::logic::Formula const> formula) : values(formula) {}
explicit FilterExpression(std::shared_ptr<storm::logic::Formula const> formula, storm::modelchecker::FilterType ft = storm::modelchecker::FilterType::VALUES) : values(formula), ft(ft) {}
std::shared_ptr<storm::logic::Formula const> const& getFormula() const {
return values;
}
FilterType getFilterType() const {
storm::modelchecker::FilterType getFilterType() const {
return ft;
}
private:
// For now, we assume that the states are always the initial states.
std::shared_ptr<storm::logic::Formula const> values;
FilterType ft = FilterType::VALUES;
storm::modelchecker::FilterType ft;
};
std::ostream& operator<<(std::ostream& os, FilterExpression const& fe);
class Property {
@ -39,6 +58,13 @@ namespace storm {
* @param comment An optional comment
*/
Property(std::string const& name, std::shared_ptr<storm::logic::Formula const> const& formula, std::string const& comment = "");
/**
* Constructs the property
* @param name the name
* @param formula the formula representation
* @param comment An optional comment
*/
Property(std::string const& name, FilterExpression const& fe, std::string const& comment = "");
/**
* Get the provided name
* @return the name
@ -50,13 +76,15 @@ namespace storm {
*/
std::string const& getComment() const;
FilterExpression const& getFilter() const;
private:
std::string name;
std::string comment;
FilterExpression filterExpression;
};
std::ostream& operator<<(std::ostream& os, Property const& p);
}
}

95
src/utility/constants.cpp

@ -5,7 +5,10 @@
#include "src/settings/SettingsManager.h"
#include "src/settings/modules/GeneralSettings.h"
#include "src/exceptions/InvalidArgumentException.h"
#include "src/adapters/CarlAdapter.h"
#include "src/utility/macros.h"
namespace storm {
namespace utility {
@ -143,6 +146,80 @@ namespace storm {
return std::fabs(number);
}
template<>
storm::RationalFunction minimum(std::vector<storm::RationalFunction> const& values)
{
STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Minimum for rational functions is not defined");
}
template<typename ValueType>
ValueType minimum(std::vector<ValueType> const& values) {
assert(!values.empty());
ValueType min = values.front();
for (auto const& vt : values) {
if (vt < min) {
min = vt;
}
}
return min;
}
template<>
storm::RationalFunction maximum(std::vector<storm::RationalFunction> const& values)
{
STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Maximum for rational functions is not defined");
}
template<typename ValueType>
ValueType maximum(std::vector<ValueType> const& values) {
assert(!values.empty());
ValueType max = values.front();
for (auto const& vt : values) {
if (vt > max) {
max = vt;
}
}
return max;
}
template<>
storm::RationalFunction minimum(std::map<uint64_t, storm::RationalFunction> const& values)
{
STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Minimum for rational functions is not defined");
}
template< typename K, typename ValueType>
ValueType minimum(std::map<K, ValueType> const& values) {
assert(!values.empty());
ValueType min = values.begin()->second;
for (auto const& vt : values) {
if (vt.second < min) {
min = vt.second;
}
}
return min;
}
template<>
storm::RationalFunction maximum(std::map<uint64_t, storm::RationalFunction> const& values)
{
STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Maximum for rational functions is not defined");
}
template<typename K, typename ValueType>
ValueType maximum(std::map<K, ValueType> const& values) {
assert(!values.empty());
ValueType max = values.begin()->second;
for (auto const& vt : values) {
if (vt.second > max) {
max = vt.second;
}
}
return max;
}
#ifdef STORM_HAVE_CARL
template<>
RationalFunction& simplify(RationalFunction& value);
@ -317,6 +394,24 @@ namespace storm {
template storm::storage::MatrixEntry<storm::storage::sparse::state_type, storm::storage::sparse::state_type>& simplify(storm::storage::MatrixEntry<storm::storage::sparse::state_type, storm::storage::sparse::state_type>& matrixEntry);
template storm::storage::MatrixEntry<storm::storage::sparse::state_type, storm::storage::sparse::state_type>&& simplify(storm::storage::MatrixEntry<storm::storage::sparse::state_type, storm::storage::sparse::state_type>&& matrixEntry);
template double minimum(std::vector<double> const&);
template double maximum(std::vector<double> const&);
template storm::RationalNumber minimum(std::vector<storm::RationalNumber> const&);
template storm::RationalNumber maximum(std::vector<storm::RationalNumber> const&);
template storm::RationalFunction minimum(std::vector<storm::RationalFunction> const&);
template storm::RationalFunction maximum(std::vector<storm::RationalFunction> const&);
template double minimum(std::map<uint64_t, double> const&);
template double maximum(std::map<uint64_t, double> const&);
template storm::RationalNumber minimum(std::map<uint64_t, storm::RationalNumber> const&);
template storm::RationalNumber maximum(std::map<uint64_t, storm::RationalNumber> const&);
template storm::RationalFunction minimum(std::map<uint64_t, storm::RationalFunction> const&);
template storm::RationalFunction maximum(std::map<uint64_t, storm::RationalFunction> const&);
#ifdef STORM_HAVE_CARL
// Instantiations for rational number.
template bool isOne(storm::RationalNumber const& value);

15
src/utility/constants.h

@ -11,6 +11,8 @@
#include <limits>
#include <cstdint>
#include <vector>
#include <map>
namespace storm {
@ -45,6 +47,19 @@ namespace storm {
template<typename ValueType>
ValueType simplify(ValueType value);
template<typename ValueType>
ValueType minimum(std::vector<ValueType> const& values);
template<typename ValueType>
ValueType maximum(std::vector<ValueType> const& values);
template< typename K, typename ValueType>
ValueType minimum(std::map<K, ValueType> const& values);
template<typename K, typename ValueType>
ValueType maximum(std::map<K, ValueType> const& values);
template<typename IndexType, typename ValueType>
storm::storage::MatrixEntry<IndexType, ValueType>& simplify(storm::storage::MatrixEntry<IndexType, ValueType>& matrixEntry);

11
src/utility/storm.cpp

@ -7,7 +7,16 @@
#include "src/utility/macros.h"
#include "src/storage/jani/Property.h"
namespace storm {
namespace storm{
std::vector<std::shared_ptr<storm::logic::Formula const>> formulasInProperties(std::vector<storm::jani::Property> const& properties) {
std::vector<std::shared_ptr<storm::logic::Formula const>> formulas;
for (auto const& prop : properties) {
formulas.push_back(prop.getFilter().getFormula());
}
return formulas;
}
storm::prism::Program parseProgram(std::string const& path) {
storm::prism::Program program = storm::parser::PrismParser::parse(path).simplify().simplify();

1
src/utility/storm.h

@ -100,6 +100,7 @@ namespace storm {
return storm::parser::AutoParser<>::parseModel(transitionsFile, labelingFile, stateRewardsFile ? stateRewardsFile.get() : "", transitionRewardsFile ? transitionRewardsFile.get() : "", choiceLabelingFile ? choiceLabelingFile.get() : "" );
}
std::vector<std::shared_ptr<storm::logic::Formula const>> formulasInProperties(std::vector<storm::jani::Property> const& properties);
std::pair<storm::jani::Model, std::map<std::string, storm::jani::Property>> parseJaniModel(std::string const& path);
storm::prism::Program parseProgram(std::string const& path);
std::vector<std::shared_ptr<storm::logic::Formula const>> parseFormulasForExplicit(std::string const& inputString);
Loading…
Cancel
Save