From 3ffaa77193881d7499e0e84c09b515c0522a77da Mon Sep 17 00:00:00 2001 From: dehnert Date: Tue, 27 Jun 2017 14:27:16 +0200 Subject: [PATCH 1/5] first version of state filters in filter expressions --- src/storm/cli/cli.cpp | 76 ++++++++++++++++++----- src/storm/logic/Formula.cpp | 4 ++ src/storm/logic/Formula.h | 4 +- src/storm/parser/FormulaParserGrammar.cpp | 8 +-- src/storm/parser/FormulaParserGrammar.h | 4 +- src/storm/storage/jani/Property.cpp | 13 ++-- src/storm/storage/jani/Property.h | 17 ++++- 7 files changed, 94 insertions(+), 32 deletions(-) diff --git a/src/storm/cli/cli.cpp b/src/storm/cli/cli.cpp index 0f53aa2d3..fad3709af 100644 --- a/src/storm/cli/cli.cpp +++ b/src/storm/cli/cli.cpp @@ -353,15 +353,27 @@ namespace storm { return input; } + std::vector> createFormulasToRespect(std::vector const& properties) { + std::vector> result = storm::api::extractFormulasFromProperties(properties); + + for (auto const& property : properties) { + if (!property.getFilter().getStatesFormula()->isInitialFormula()) { + result.push_back(property.getFilter().getStatesFormula()); + } + } + + return result; + } + template std::shared_ptr buildModelDd(SymbolicInput const& input) { - return storm::api::buildSymbolicModel(input.model.get(), storm::api::extractFormulasFromProperties(input.properties)); + return storm::api::buildSymbolicModel(input.model.get(), createFormulasToRespect(input.properties)); } template std::shared_ptr buildModelSparse(SymbolicInput const& input, storm::settings::modules::IOSettings const& ioSettings) { auto counterexampleGeneratorSettings = storm::settings::getModule(); - return storm::api::buildSparseModel(input.model.get(), storm::api::extractFormulasFromProperties(input.properties), ioSettings.isBuildChoiceLabelsSet(), counterexampleGeneratorSettings.isMinimalCommandSetGenerationSet()); + return storm::api::buildSparseModel(input.model.get(), createFormulasToRespect(input.properties), ioSettings.isBuildChoiceLabelsSet(), counterexampleGeneratorSettings.isMinimalCommandSetGenerationSet()); } template @@ -379,6 +391,9 @@ namespace storm { std::shared_ptr buildModel(storm::settings::modules::CoreSettings::Engine const& engine, SymbolicInput const& input, storm::settings::modules::IOSettings const& ioSettings) { storm::utility::Stopwatch modelBuildingWatch(true); + + // Make sure that states in filter are built as label. ALso for bisimulation. + std::shared_ptr result; if (input.model) { if (engine == storm::settings::modules::CoreSettings::Engine::Dd || engine == storm::settings::modules::CoreSettings::Engine::Hybrid) { @@ -622,11 +637,11 @@ namespace storm { }; template - void verifyProperties(std::vector const& properties, std::function(std::shared_ptr const& formula)> const& verificationCallback, std::function const&)> const& postprocessingCallback = PostprocessingIdentity()) { + void verifyProperties(std::vector const& properties, std::function(std::shared_ptr const& formula, std::shared_ptr const& states)> const& verificationCallback, std::function const&)> const& postprocessingCallback = PostprocessingIdentity()) { for (auto const& property : properties) { printModelCheckingProperty(property); storm::utility::Stopwatch watch(true); - std::unique_ptr result = verificationCallback(property.getRawFormula()); + std::unique_ptr result = verificationCallback(property.getRawFormula(), property.getFilter().getStatesFormula()); watch.stop(); printInitialStatesResult(result, property, &watch); postprocessingCallback(result); @@ -636,7 +651,8 @@ namespace storm { template void verifyWithAbstractionRefinementEngine(SymbolicInput const& input) { STORM_LOG_ASSERT(input.model, "Expected symbolic model description."); - verifyProperties(input.properties, [&input] (std::shared_ptr const& formula) { + verifyProperties(input.properties, [&input] (std::shared_ptr const& formula, std::shared_ptr const& states) { + STORM_LOG_THROW(states->isInitialFormula(), storm::exceptions::NotSupportedException, "Abstraction-refinement can only filter initial states."); return storm::api::verifyWithAbstractionRefinementEngine(input.model.get(), storm::api::createTask(formula, true)); }); } @@ -645,7 +661,8 @@ namespace storm { void verifyWithExplorationEngine(SymbolicInput const& input) { STORM_LOG_ASSERT(input.model, "Expected symbolic model description."); STORM_LOG_THROW((std::is_same::value), storm::exceptions::NotSupportedException, "Exploration does not support other data-types than floating points."); - verifyProperties(input.properties, [&input] (std::shared_ptr const& formula) { + verifyProperties(input.properties, [&input] (std::shared_ptr const& formula, std::shared_ptr const& states) { + STORM_LOG_THROW(states->isInitialFormula(), storm::exceptions::NotSupportedException, "Exploration can only filter initial states."); return storm::api::verifyWithExplorationEngine(input.model.get(), storm::api::createTask(formula, true)); }); } @@ -654,9 +671,18 @@ namespace storm { void verifyWithSparseEngine(std::shared_ptr const& model, SymbolicInput const& input) { auto sparseModel = model->as>(); verifyProperties(input.properties, - [&sparseModel] (std::shared_ptr const& formula) { - std::unique_ptr result = storm::api::verifyWithSparseEngine(sparseModel, storm::api::createTask(formula, true)); - result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(sparseModel->getInitialStates())); + [&sparseModel] (std::shared_ptr const& formula, std::shared_ptr const& states) { + bool filterForInitialStates = states->isInitialFormula(); + auto task = storm::api::createTask(formula, filterForInitialStates); + std::unique_ptr result = storm::api::verifyWithSparseEngine(sparseModel, task); + + std::unique_ptr filter; + if (filterForInitialStates) { + filter = std::make_unique(sparseModel->getInitialStates()); + } else { + filter = storm::api::verifyWithSparseEngine(sparseModel, storm::api::createTask(states, false)); + } + result->filter(filter->asQualitativeCheckResult()); return result; }, [&sparseModel] (std::unique_ptr const& result) { @@ -670,20 +696,42 @@ namespace storm { template void verifyWithHybridEngine(std::shared_ptr const& model, SymbolicInput const& input) { - verifyProperties(input.properties, [&model] (std::shared_ptr const& formula) { + verifyProperties(input.properties, [&model] (std::shared_ptr const& formula, std::shared_ptr const& states) { + bool filterForInitialStates = states->isInitialFormula(); + auto task = storm::api::createTask(formula, filterForInitialStates); + auto symbolicModel = model->as>(); - std::unique_ptr result = storm::api::verifyWithHybridEngine(symbolicModel, storm::api::createTask(formula, true)); - result->filter(storm::modelchecker::SymbolicQualitativeCheckResult(symbolicModel->getReachableStates(), symbolicModel->getInitialStates())); + std::unique_ptr result = storm::api::verifyWithHybridEngine(symbolicModel, task); + + std::unique_ptr filter; + if (filterForInitialStates) { + filter = std::make_unique>(symbolicModel->getReachableStates(), symbolicModel->getInitialStates()); + } else { + filter = storm::api::verifyWithHybridEngine(symbolicModel, storm::api::createTask(states, false)); + } + + result->filter(filter->asQualitativeCheckResult()); return result; }); } template void verifyWithDdEngine(std::shared_ptr const& model, SymbolicInput const& input) { - verifyProperties(input.properties, [&model] (std::shared_ptr const& formula) { + verifyProperties(input.properties, [&model] (std::shared_ptr const& formula, std::shared_ptr const& states) { + bool filterForInitialStates = states->isInitialFormula(); + auto task = storm::api::createTask(formula, filterForInitialStates); + auto symbolicModel = model->as>(); std::unique_ptr result = storm::api::verifyWithDdEngine(model->as>(), storm::api::createTask(formula, true)); - result->filter(storm::modelchecker::SymbolicQualitativeCheckResult(symbolicModel->getReachableStates(), symbolicModel->getInitialStates())); + + std::unique_ptr filter; + if (filterForInitialStates) { + filter = std::make_unique>(symbolicModel->getReachableStates(), symbolicModel->getInitialStates()); + } else { + filter = storm::api::verifyWithDdEngine(symbolicModel, storm::api::createTask(states, false)); + } + + result->filter(filter->asQualitativeCheckResult()); return result; }); } diff --git a/src/storm/logic/Formula.cpp b/src/storm/logic/Formula.cpp index 9038a2307..3f871908e 100644 --- a/src/storm/logic/Formula.cpp +++ b/src/storm/logic/Formula.cpp @@ -175,6 +175,10 @@ namespace storm { return std::shared_ptr(new BooleanLiteralFormula(true)); } + bool Formula::isInitialFormula() const { + return this->isAtomicLabelFormula() && this->asAtomicLabelFormula().getLabel() == "init"; + } + PathFormula& Formula::asPathFormula() { return dynamic_cast(*this); } diff --git a/src/storm/logic/Formula.h b/src/storm/logic/Formula.h index 2ad5e9477..a76dd0ef7 100644 --- a/src/storm/logic/Formula.h +++ b/src/storm/logic/Formula.h @@ -93,10 +93,12 @@ namespace storm { bool isInFragment(FragmentSpecification const& fragment) const; FormulaInformation info() const; - + virtual boost::any accept(FormulaVisitor const& visitor, boost::any const& data = boost::any()) const = 0; static std::shared_ptr getTrueFormula(); + + bool isInitialFormula() const; PathFormula& asPathFormula(); PathFormula const& asPathFormula() const; diff --git a/src/storm/parser/FormulaParserGrammar.cpp b/src/storm/parser/FormulaParserGrammar.cpp index bee6b5117..78102f859 100644 --- a/src/storm/parser/FormulaParserGrammar.cpp +++ b/src/storm/parser/FormulaParserGrammar.cpp @@ -128,7 +128,7 @@ namespace storm { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Woverloaded-shift-op-parentheses" - filterProperty = (-formulaName >> qi::lit("filter") > qi::lit("(") > filterType_ > qi::lit(",") > stateFormula > -(qi::lit(",") > qi::lit("\"init\"") > qi::lit(")")))[qi::_val = phoenix::bind(&FormulaParserGrammar::createProperty, phoenix::ref(*this), qi::_1, qi::_2, qi::_3)] | (-formulaName >> stateFormula)[qi::_val = phoenix::bind(&FormulaParserGrammar::createPropertyWithDefaultFilterType, phoenix::ref(*this), qi::_1, qi::_2)]; + filterProperty = (-formulaName >> qi::lit("filter") > qi::lit("(") > filterType_ > qi::lit(",") > stateFormula > qi::lit(",") > stateFormula > qi::lit(")"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createProperty, phoenix::ref(*this), qi::_1, qi::_2, qi::_3, qi::_4)] | (-formulaName >> stateFormula)[qi::_val = phoenix::bind(&FormulaParserGrammar::createPropertyWithDefaultFilterTypeAndStates, phoenix::ref(*this), qi::_1, qi::_2)]; filterProperty.name("filter property"); #pragma clang diagnostic pop @@ -332,8 +332,8 @@ namespace storm { return std::shared_ptr(new storm::logic::MultiObjectiveFormula(subformulas)); } - storm::jani::Property FormulaParserGrammar::createProperty(boost::optional const& propertyName, storm::modelchecker::FilterType const& filterType, std::shared_ptr const& formula) { - storm::jani::FilterExpression filterExpression(formula, filterType); + storm::jani::Property FormulaParserGrammar::createProperty(boost::optional const& propertyName, storm::modelchecker::FilterType const& filterType, std::shared_ptr const& formula, std::shared_ptr const& states) { + storm::jani::FilterExpression filterExpression(formula, filterType, states); ++propertyCount; if (propertyName) { @@ -343,7 +343,7 @@ namespace storm { } } - storm::jani::Property FormulaParserGrammar::createPropertyWithDefaultFilterType(boost::optional const& propertyName, std::shared_ptr const& formula) { + storm::jani::Property FormulaParserGrammar::createPropertyWithDefaultFilterTypeAndStates(boost::optional const& propertyName, std::shared_ptr const& formula) { ++propertyCount; if (propertyName) { return storm::jani::Property(propertyName.get(), formula); diff --git a/src/storm/parser/FormulaParserGrammar.h b/src/storm/parser/FormulaParserGrammar.h index 79b272246..7ae6740b8 100644 --- a/src/storm/parser/FormulaParserGrammar.h +++ b/src/storm/parser/FormulaParserGrammar.h @@ -223,8 +223,8 @@ namespace storm { std::shared_ptr createUnaryBooleanStateFormula(std::shared_ptr const& subformula, boost::optional const& operatorType); std::shared_ptr createMultiObjectiveFormula(std::vector> const& subformulas); - storm::jani::Property createProperty(boost::optional const& propertyName, storm::modelchecker::FilterType const& filterType, std::shared_ptr const& formula); - storm::jani::Property createPropertyWithDefaultFilterType(boost::optional const& propertyName, std::shared_ptr const& formula); + storm::jani::Property createProperty(boost::optional const& propertyName, storm::modelchecker::FilterType const& filterType, std::shared_ptr const& formula, std::shared_ptr const& states); + storm::jani::Property createPropertyWithDefaultFilterTypeAndStates(boost::optional const& propertyName, std::shared_ptr const& formula); // An error handler function. phoenix::function handler; diff --git a/src/storm/storage/jani/Property.cpp b/src/storm/storage/jani/Property.cpp index e46d2ee50..73c6d0dec 100644 --- a/src/storm/storage/jani/Property.cpp +++ b/src/storm/storage/jani/Property.cpp @@ -5,19 +5,17 @@ namespace storm { std::ostream& operator<<(std::ostream& os, FilterExpression const& fe) { - return os << "Obtain " << toString(fe.getFilterType()) << " of the 'initial'-states with values described by '" << *fe.getFormula() << "'"; + return os << "Obtain " << toString(fe.getFilterType()) << " of the '" << fe.getStatesFormula() << "'-states with values described by '" << *fe.getFormula() << "'"; } Property::Property(std::string const& name, std::shared_ptr const& formula, std::string const& comment) - : name(name), comment(comment), filterExpression(FilterExpression(formula)) - { - + : name(name), comment(comment), filterExpression(FilterExpression(formula)) { + // Intentionally left empty. } Property::Property(std::string const& name, FilterExpression const& fe, std::string const& comment) - : name(name), comment(comment), filterExpression(fe) - { - + : name(name), comment(comment), filterExpression(fe) { + // Intentionally left empty. } std::string const& Property::getName() const { @@ -48,6 +46,5 @@ namespace storm { return os << "(" << p.getName() << ") : " << p.getFilter(); } - } } diff --git a/src/storm/storage/jani/Property.h b/src/storm/storage/jani/Property.h index 52db07fef..74aceab5c 100644 --- a/src/storm/storage/jani/Property.h +++ b/src/storm/storage/jani/Property.h @@ -2,6 +2,10 @@ #include "storm/modelchecker/results/FilterType.h" #include "storm/logic/Formulas.h" +#include "storm/logic/FragmentSpecification.h" + +#include "storm/utility/macros.h" +#include "storm/exceptions/InvalidArgumentException.h" namespace storm { namespace jani { @@ -30,28 +34,35 @@ namespace storm { public: FilterExpression() = default; - explicit FilterExpression(std::shared_ptr formula, storm::modelchecker::FilterType ft = storm::modelchecker::FilterType::VALUES) : formula(formula), ft(ft) {} + explicit FilterExpression(std::shared_ptr formula, storm::modelchecker::FilterType ft = storm::modelchecker::FilterType::VALUES, std::shared_ptr const& statesFormula = std::make_shared("init")) : formula(formula), ft(ft), statesFormula(statesFormula) { + STORM_LOG_THROW(statesFormula->isInFragment(storm::logic::propositional()), storm::exceptions::InvalidArgumentException, "Can only filter by propositional formula."); + } std::shared_ptr const& getFormula() const { return formula; } + std::shared_ptr const& getStatesFormula() const { + return statesFormula; + } + storm::modelchecker::FilterType getFilterType() const { return ft; } FilterExpression substitute(std::map const& substitution) const { - return FilterExpression(formula->substitute(substitution), ft); + return FilterExpression(formula->substitute(substitution), ft, statesFormula->substitute(substitution)); } FilterExpression substituteLabels(std::map const& labelSubstitution) const { - return FilterExpression(formula->substitute(labelSubstitution), ft); + return FilterExpression(formula->substitute(labelSubstitution), ft, statesFormula->substitute(labelSubstitution)); } private: // For now, we assume that the states are always the initial states. std::shared_ptr formula; storm::modelchecker::FilterType ft; + std::shared_ptr statesFormula; }; From bc373475ff34eb755931453f9b4fed82b5204a77 Mon Sep 17 00:00:00 2001 From: dehnert Date: Tue, 27 Jun 2017 14:31:26 +0200 Subject: [PATCH 2/5] respecting state filters in bisimulation --- src/storm/cli/cli.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/storm/cli/cli.cpp b/src/storm/cli/cli.cpp index fad3709af..8fea01e61 100644 --- a/src/storm/cli/cli.cpp +++ b/src/storm/cli/cli.cpp @@ -391,9 +391,6 @@ namespace storm { std::shared_ptr buildModel(storm::settings::modules::CoreSettings::Engine const& engine, SymbolicInput const& input, storm::settings::modules::IOSettings const& ioSettings) { storm::utility::Stopwatch modelBuildingWatch(true); - - // Make sure that states in filter are built as label. ALso for bisimulation. - std::shared_ptr result; if (input.model) { if (engine == storm::settings::modules::CoreSettings::Engine::Dd || engine == storm::settings::modules::CoreSettings::Engine::Hybrid) { @@ -432,7 +429,7 @@ namespace storm { } STORM_LOG_INFO("Performing bisimulation minimization..."); - return storm::api::performBisimulationMinimization(model, storm::api::extractFormulasFromProperties(input.properties), bisimType); + return storm::api::performBisimulationMinimization(model, createFormulasToRespect(input.properties), bisimType); } template From 322808db5b938ebdd896a8bb13cbd7fe5e9f10c6 Mon Sep 17 00:00:00 2001 From: TimQu Date: Tue, 4 Jul 2017 10:47:44 +0200 Subject: [PATCH 3/5] getting reward name from reward bounded until formula. --- src/storm/logic/TimeBoundType.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/storm/logic/TimeBoundType.h b/src/storm/logic/TimeBoundType.h index 2488baaaf..7200cc89d 100644 --- a/src/storm/logic/TimeBoundType.h +++ b/src/storm/logic/TimeBoundType.h @@ -36,6 +36,11 @@ namespace storm { bool isRewardBound() const { return type == TimeBoundType::Reward; } + + std::string const& getRewardName() const { + assert(isRewardBound()); + return rewardName; + } }; From d0551c1d593a9f4756d75c507c858f8cead9dd76 Mon Sep 17 00:00:00 2001 From: TimQu Date: Tue, 4 Jul 2017 10:48:26 +0200 Subject: [PATCH 4/5] getting time/step/reward bounds as rational number --- src/storm/logic/BoundedUntilFormula.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/storm/logic/BoundedUntilFormula.cpp b/src/storm/logic/BoundedUntilFormula.cpp index 66b5a29fa..b954d4720 100644 --- a/src/storm/logic/BoundedUntilFormula.cpp +++ b/src/storm/logic/BoundedUntilFormula.cpp @@ -1,5 +1,6 @@ #include "storm/logic/BoundedUntilFormula.h" +#include "storm/utility/constants.h" #include "storm/utility/macros.h" #include "storm/exceptions/InvalidArgumentException.h" @@ -80,6 +81,22 @@ namespace storm { return bound; } + template <> + storm::RationalNumber BoundedUntilFormula::getLowerBound() const { + checkNoVariablesInBound(this->getLowerBound()); + storm::RationalNumber bound = this->getLowerBound().evaluateAsRational(); + STORM_LOG_THROW(bound >= storm::utility::zero(), storm::exceptions::InvalidPropertyException, "Time-bound must not evaluate to negative number."); + return bound; + } + + template <> + storm::RationalNumber BoundedUntilFormula::getUpperBound() const { + checkNoVariablesInBound(this->getUpperBound()); + storm::RationalNumber bound = this->getLowerBound().evaluateAsRational(); + STORM_LOG_THROW(bound >= storm::utility::zero(), storm::exceptions::InvalidPropertyException, "Time-bound must not evaluate to negative number."); + return bound; + } + template <> uint64_t BoundedUntilFormula::getLowerBound() const { checkNoVariablesInBound(this->getLowerBound()); From 6471bfdcea68e60831008fbd1f806358e4a328c8 Mon Sep 17 00:00:00 2001 From: dehnert Date: Tue, 4 Jul 2017 11:17:01 +0200 Subject: [PATCH 5/5] made cli output respect filters --- src/storm/cli/cli.cpp | 8 +++++--- src/storm/modelchecker/results/CheckResult.cpp | 18 ++++++++++++++++++ src/storm/modelchecker/results/CheckResult.h | 10 +++------- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/storm/cli/cli.cpp b/src/storm/cli/cli.cpp index 8fea01e61..10f992d96 100644 --- a/src/storm/cli/cli.cpp +++ b/src/storm/cli/cli.cpp @@ -615,9 +615,11 @@ namespace storm { } template - void printInitialStatesResult(std::unique_ptr const& result, storm::jani::Property const& property, storm::utility::Stopwatch* watch = nullptr) { + void printResult(std::unique_ptr const& result, storm::jani::Property const& property, storm::utility::Stopwatch* watch = nullptr) { if (result) { - STORM_PRINT_AND_LOG("Result (initial states): "); + std::stringstream ss; + ss << "'" << *property.getFilter().getStatesFormula() << "'"; + STORM_PRINT_AND_LOG("Result (for " << (property.getFilter().getStatesFormula()->isInitialFormula() ? "initial" : ss.str()) << " states): "); printFilteredResult(result, property.getFilter().getFilterType()); if (watch) { STORM_PRINT_AND_LOG("Time for model checking: " << *watch << "." << std::endl); @@ -640,8 +642,8 @@ namespace storm { storm::utility::Stopwatch watch(true); std::unique_ptr result = verificationCallback(property.getRawFormula(), property.getFilter().getStatesFormula()); watch.stop(); - printInitialStatesResult(result, property, &watch); postprocessingCallback(result); + printResult(result, property, &watch); } } diff --git a/src/storm/modelchecker/results/CheckResult.cpp b/src/storm/modelchecker/results/CheckResult.cpp index bdcf68c8f..9155057d3 100644 --- a/src/storm/modelchecker/results/CheckResult.cpp +++ b/src/storm/modelchecker/results/CheckResult.cpp @@ -113,6 +113,15 @@ namespace storm { return dynamic_cast(*this); } + template + QuantitativeCheckResult& CheckResult::asQuantitativeCheckResult() { + return static_cast &>(*this); + } + + template + QuantitativeCheckResult const& CheckResult::asQuantitativeCheckResult() const { + return static_cast const&>(*this); + } template SymbolicQualitativeCheckResult& CheckResult::asSymbolicQualitativeCheckResult() { @@ -155,6 +164,9 @@ namespace storm { } // Explicitly instantiate the template functions. + template QuantitativeCheckResult& CheckResult::asQuantitativeCheckResult(); + template QuantitativeCheckResult const& CheckResult::asQuantitativeCheckResult() const; + template ExplicitQuantitativeCheckResult& CheckResult::asExplicitQuantitativeCheckResult(); template ExplicitQuantitativeCheckResult const& CheckResult::asExplicitQuantitativeCheckResult() const; template ExplicitParetoCurveCheckResult& CheckResult::asExplicitParetoCurveCheckResult(); @@ -184,9 +196,15 @@ namespace storm { #ifdef STORM_HAVE_CARL + template QuantitativeCheckResult& CheckResult::asQuantitativeCheckResult(); + template QuantitativeCheckResult const& CheckResult::asQuantitativeCheckResult() const; + template ExplicitQuantitativeCheckResult& CheckResult::asExplicitQuantitativeCheckResult(); template ExplicitQuantitativeCheckResult const& CheckResult::asExplicitQuantitativeCheckResult() const; + template QuantitativeCheckResult& CheckResult::asQuantitativeCheckResult(); + template QuantitativeCheckResult const& CheckResult::asQuantitativeCheckResult() const; + template ExplicitQuantitativeCheckResult& CheckResult::asExplicitQuantitativeCheckResult(); template ExplicitQuantitativeCheckResult const& CheckResult::asExplicitQuantitativeCheckResult() const; diff --git a/src/storm/modelchecker/results/CheckResult.h b/src/storm/modelchecker/results/CheckResult.h index 2cff249c9..43954a220 100644 --- a/src/storm/modelchecker/results/CheckResult.h +++ b/src/storm/modelchecker/results/CheckResult.h @@ -66,14 +66,10 @@ namespace storm { QualitativeCheckResult const& asQualitativeCheckResult() const; template - QuantitativeCheckResult& asQuantitativeCheckResult() { - return static_cast &>(*this); - } + QuantitativeCheckResult& asQuantitativeCheckResult(); + template - QuantitativeCheckResult const& asQuantitativeCheckResult() const { - return static_cast const&>(*this); - } - + QuantitativeCheckResult const& asQuantitativeCheckResult() const; ExplicitQualitativeCheckResult& asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& asExplicitQualitativeCheckResult() const;