#include "SparseMdpInstantiationModelChecker.h" #include "storm/logic/FragmentSpecification.h" #include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h" #include "storm/modelchecker/hints/ExplicitModelCheckerHint.h" #include "storm/exceptions/InvalidArgumentException.h" #include "storm/exceptions/InvalidStateException.h" namespace storm { namespace modelchecker { namespace parametric { template SparseMdpInstantiationModelChecker::SparseMdpInstantiationModelChecker(SparseModelType const& parametricModel) : SparseInstantiationModelChecker(parametricModel), modelInstantiator(parametricModel) { //Intentionally left empty } template std::unique_ptr SparseMdpInstantiationModelChecker::check(storm::utility::parametric::Valuation const& valuation) { STORM_LOG_THROW(this->currentCheckTask, storm::exceptions::InvalidStateException, "Checking has been invoked but no property has been specified before."); auto const& instantiatedModel = modelInstantiator.instantiate(valuation); STORM_LOG_ASSERT(instantiatedModel.getTransitionMatrix().isProbabilistic(), "Instantiated matrix is not probabilistic!"); storm::modelchecker::SparseMdpPrctlModelChecker> modelChecker(instantiatedModel); // Check if there are some optimizations implemented for the specified property if(!this->currentCheckTask->isQualitativeSet() && this->currentCheckTask->getFormula().isInFragment(storm::logic::reachability().setRewardOperatorsAllowed(true).setReachabilityRewardFormulasAllowed(true))) { return checkWithResultHint(modelChecker); } else { return modelChecker.check(*this->currentCheckTask); } } template std::unique_ptr SparseMdpInstantiationModelChecker::checkWithResultHint(storm::modelchecker::SparseMdpPrctlModelChecker>& modelchecker) { this->currentCheckTask->setProduceSchedulers(true); // Check the formula and store the result as a hint for the next call. // For qualitative properties, we still want a quantitative result hint. Hence we perform the check on the subformula if(this->currentCheckTask->getFormula().asOperatorFormula().hasQuantitativeResult()) { std::unique_ptr result = modelchecker.check(*this->currentCheckTask); storm::storage::Scheduler const& scheduler = result->template asExplicitQuantitativeCheckResult().getScheduler(); this->currentCheckTask->setHint(ExplicitModelCheckerHint(result->template asExplicitQuantitativeCheckResult().getValueVector(), dynamic_cast(scheduler))); return result; } else { std::unique_ptr quantitativeResult; auto newCheckTask = this->currentCheckTask->substituteFormula(this->currentCheckTask->getFormula().asOperatorFormula().getSubformula()).setOnlyInitialStatesRelevant(false); if(this->currentCheckTask->getFormula().isProbabilityOperatorFormula()) { quantitativeResult = modelchecker.computeProbabilities(newCheckTask); } else if (this->currentCheckTask->getFormula().isRewardOperatorFormula()) { quantitativeResult = modelchecker.computeRewards(this->currentCheckTask->getFormula().asRewardOperatorFormula().getMeasureType(), newCheckTask); } else { STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Checking with hint is only implemented for probability or reward operator formulas"); } std::unique_ptr qualitativeResult = quantitativeResult->template asExplicitQuantitativeCheckResult().compareAgainstBound(this->currentCheckTask->getFormula().asOperatorFormula().getComparisonType(), this->currentCheckTask->getFormula().asOperatorFormula().template getThresholdAs()); storm::storage::Scheduler& scheduler = quantitativeResult->template asExplicitQuantitativeCheckResult().getScheduler(); this->currentCheckTask->setHint(ExplicitModelCheckerHint(std::move(quantitativeResult->template asExplicitQuantitativeCheckResult().getValueVector()), std::move(dynamic_cast(scheduler)))); return qualitativeResult; } } template class SparseMdpInstantiationModelChecker, double>; } } }