Browse Source

Splitted region modelchecker in abstract class and dtmc class (to easily add an mdp class soon)

Former-commit-id: e722c8f2bd
main
TimQu 10 years ago
parent
commit
70dd76c08b
  1. 6
      src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h
  2. 390
      src/modelchecker/region/AbstractSparseRegionModelChecker.cpp
  3. 239
      src/modelchecker/region/AbstractSparseRegionModelChecker.h
  4. 38
      src/modelchecker/region/ApproximationModel.cpp
  5. 29
      src/modelchecker/region/ApproximationModel.h
  6. 146
      src/modelchecker/region/ParameterRegion.cpp
  7. 57
      src/modelchecker/region/ParameterRegion.h
  8. 42
      src/modelchecker/region/RegionCheckResult.cpp
  9. 34
      src/modelchecker/region/RegionCheckResult.h
  10. 34
      src/modelchecker/region/SamplingModel.cpp
  11. 26
      src/modelchecker/region/SamplingModel.h
  12. 607
      src/modelchecker/region/SparseDtmcRegionModelChecker.cpp
  13. 200
      src/modelchecker/region/SparseDtmcRegionModelChecker.h
  14. 2
      src/utility/region.h
  15. 4
      src/utility/regions.cpp
  16. 6
      src/utility/storm.h
  17. 306
      test/functional/modelchecker/SparseDtmcRegionModelCheckerTest.cpp

6
src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h

@ -9,17 +9,19 @@
//forward declaration of friend class //forward declaration of friend class
namespace storm { namespace storm {
namespace modelchecker { namespace modelchecker {
template<typename ParametricType, typename ConstantType>
namespace region {
template<typename ParametricModelType, typename ConstantType>
class SparseDtmcRegionModelChecker; class SparseDtmcRegionModelChecker;
} }
} }
}
namespace storm { namespace storm {
namespace modelchecker { namespace modelchecker {
template<typename SparseDtmcModelType> template<typename SparseDtmcModelType>
class SparseDtmcEliminationModelChecker : public SparsePropositionalModelChecker<SparseDtmcModelType> { class SparseDtmcEliminationModelChecker : public SparsePropositionalModelChecker<SparseDtmcModelType> {
template<typename ParametricType, typename ConstantType> friend class storm::modelchecker::SparseDtmcRegionModelChecker;
template<typename ParametricModelType, typename ConstantType> friend class storm::modelchecker::region::SparseDtmcRegionModelChecker;
public: public:
typedef typename SparseDtmcModelType::ValueType ValueType; typedef typename SparseDtmcModelType::ValueType ValueType;
typedef typename SparseDtmcModelType::RewardModelType RewardModelType; typedef typename SparseDtmcModelType::RewardModelType RewardModelType;

390
src/modelchecker/region/AbstractSparseRegionModelChecker.cpp

@ -0,0 +1,390 @@
/*
* File: AbstractSparseRegionModelChecker.cpp
* Author: tim
*
* Created on September 9, 2015, 12:34 PM
*/
#include "AbstractSparseRegionModelChecker.h"
#include "src/adapters/CarlAdapter.h"
#include "src/modelchecker/region/RegionCheckResult.h"
#include "src/logic/Formulas.h"
#include "src/models/sparse/StandardRewardModel.h"
#include "src/settings/SettingsManager.h"
#include "src/settings/modules/RegionSettings.h"
#include "src/utility/constants.h"
#include "src/utility/graph.h"
#include "src/utility/macros.h"
#include "src/exceptions/InvalidArgumentException.h"
#include "src/exceptions/InvalidPropertyException.h"
#include "src/exceptions/InvalidStateException.h"
#include "src/exceptions/InvalidSettingsException.h"
#include "src/exceptions/NotImplementedException.h"
#include "src/exceptions/UnexpectedException.h"
namespace storm {
namespace modelchecker {
namespace region {
template<typename ParametricSparseModelType, typename ConstantType>
AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>::AbstractSparseRegionModelChecker(ParametricSparseModelType const& model) :
model(model),
specifiedFormula(nullptr){
STORM_LOG_THROW(model.getInitialStates().getNumberOfSetBits() == 1, storm::exceptions::InvalidArgumentException, "Model is required to have exactly one initial state.");
}
template<typename ParametricSparseModelType, typename ConstantType>
AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>::~AbstractSparseRegionModelChecker() {
//Intentionally left empty
}
template<typename ParametricSparseModelType, typename ConstantType>
ParametricSparseModelType const& AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>::getModel() const {
return this->model;
}
template<typename ParametricSparseModelType, typename ConstantType>
bool const& AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>::isResultConstant() const {
return this->resultConstant;
}
template<typename ParametricSparseModelType, typename ConstantType>
std::shared_ptr<ParametricSparseModelType> const& AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>::getSimpleModel() const {
return this->simpleModel;
}
template<typename ParametricSparseModelType, typename ConstantType>
bool const& AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>::isComputeRewards() const {
return computeRewards;
}
template<typename ParametricSparseModelType, typename ConstantType>
std::shared_ptr<storm::logic::Formula> const& AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>::getSpecifiedFormula() const {
return specifiedFormula;
}
template<typename ParametricSparseModelType, typename ConstantType>
ConstantType const& AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>::getSpecifiedFormulaBound() const {
return specifiedFormulaBound;
}
template<typename ParametricSparseModelType, typename ConstantType>
storm::logic::ComparisonType const& AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>::getSpecifiedFormulaCompType() const {
return specifiedFormulaCompType;
}
template<typename ParametricSparseModelType, typename ConstantType>
bool AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>::specifiedFormulaHasUpperBound() const {
return !storm::logic::isLowerBound(this->getSpecifiedFormulaCompType());
}
template<typename ParametricSparseModelType, typename ConstantType>
void AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>::specifyFormula(std::shared_ptr<storm::logic::Formula> formula) {
std::chrono::high_resolution_clock::time_point timeSpecifyFormulaStart = std::chrono::high_resolution_clock::now();
STORM_LOG_THROW(this->canHandle(*formula), storm::exceptions::InvalidArgumentException, "Tried to specify a formula that can not be handled.");
//Initialize the context for this formula
this->specifiedFormula = formula;
this->resultConstant=false;
this->simpleFormula=nullptr;
this->isApproximationApplicable=false;
this->approximationModel=nullptr;
this->samplingModel=nullptr;
//stuff for statistics:
this->numOfCheckedRegions=0;
this->numOfRegionsSolvedThroughSampling=0;
this->numOfRegionsSolvedThroughApproximation=0;
this->numOfRegionsSolvedThroughSmt=0;
this->numOfRegionsExistsBoth=0;
this->numOfRegionsAllSat=0;
this->numOfRegionsAllViolated=0;
this->timeCheckRegion=std::chrono::high_resolution_clock::duration::zero();
this->timeSampling=std::chrono::high_resolution_clock::duration::zero();
this->timeApproximation=std::chrono::high_resolution_clock::duration::zero();
this->timeSmt=std::chrono::high_resolution_clock::duration::zero();
this->timeApproxModelInstantiation=std::chrono::high_resolution_clock::duration::zero();
this->timeComputeReachabilityFunction=std::chrono::high_resolution_clock::duration::zero();
this->timeApproxModelInstantiation=std::chrono::high_resolution_clock::duration::zero();
// set some information regarding the formula.
if (this->getSpecifiedFormula()->isProbabilityOperatorFormula()) {
this->computeRewards = false;
this->specifiedFormulaCompType = this->getSpecifiedFormula()->asProbabilityOperatorFormula().getComparisonType();
this->specifiedFormulaBound = storm::utility::region::convertNumber<ConstantType>(this->getSpecifiedFormula()->asProbabilityOperatorFormula().getBound());
}
else if (this->getSpecifiedFormula()->isRewardOperatorFormula()) {
this->computeRewards=true;
this->specifiedFormulaCompType = this->getSpecifiedFormula()->asRewardOperatorFormula().getComparisonType();
this->specifiedFormulaBound = this->getSpecifiedFormula()->asRewardOperatorFormula().getBound();
}
else {
STORM_LOG_THROW(false, storm::exceptions::InvalidPropertyException, "The specified property " << this->getSpecifiedFormula() << "is not supported");
}
std::chrono::high_resolution_clock::time_point timePreprocessingStart = std::chrono::high_resolution_clock::now();
this->preprocess(this->simpleModel, this->simpleFormula, isApproximationApplicable, resultConstant);
std::chrono::high_resolution_clock::time_point timePreprocessingEnd = std::chrono::high_resolution_clock::now();
//Check if the approximation and the sampling model needs to be computed
if(!this->isResultConstant()){
if(this->isApproximationApplicable && storm::settings::regionSettings().doApprox()){
initializeApproximationModel(*this->getSimpleModel(), this->simpleFormula);
}
if(storm::settings::regionSettings().getSampleMode()==storm::settings::modules::RegionSettings::SampleMode::INSTANTIATE ||
(!storm::settings::regionSettings().doSample() && storm::settings::regionSettings().getApproxMode()==storm::settings::modules::RegionSettings::ApproxMode::TESTFIRST)){
initializeSamplingModel(*this->getSimpleModel(), this->simpleFormula);
}
}
//some more information for statistics...
std::chrono::high_resolution_clock::time_point timeSpecifyFormulaEnd = std::chrono::high_resolution_clock::now();
this->timeSpecifyFormula= timeSpecifyFormulaEnd - timeSpecifyFormulaStart;
this->timePreprocessing = timePreprocessingEnd - timePreprocessingStart;
}
template<typename ParametricSparseModelType, typename ConstantType>
void AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>::initializeApproximationModel(ParametricSparseModelType const& model, std::shared_ptr<storm::logic::Formula> formula) {
std::chrono::high_resolution_clock::time_point timeInitApproxModelStart = std::chrono::high_resolution_clock::now();
STORM_LOG_THROW(this->isApproximationApplicable, storm::exceptions::UnexpectedException, "Approximation model requested but approximation is not applicable");
this->approximationModel=std::make_shared<ApproximationModel<ParametricSparseModelType, ConstantType>>(model, formula);
std::chrono::high_resolution_clock::time_point timeInitApproxModelEnd = std::chrono::high_resolution_clock::now();
this->timeInitApproxModel=timeInitApproxModelEnd - timeInitApproxModelStart;
STORM_LOG_DEBUG("Initialized Approximation Model");
}
template<typename ParametricSparseModelType, typename ConstantType>
void AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>::initializeSamplingModel(ParametricSparseModelType const& model, std::shared_ptr<storm::logic::Formula> formula) {
std::chrono::high_resolution_clock::time_point timeInitSamplingModelStart = std::chrono::high_resolution_clock::now();
this->samplingModel=std::make_shared<SamplingModel<ParametricSparseModelType, ConstantType>>(model, formula);
std::chrono::high_resolution_clock::time_point timeInitSamplingModelEnd = std::chrono::high_resolution_clock::now();
this->timeInitSamplingModel = timeInitSamplingModelEnd - timeInitSamplingModelStart;
STORM_LOG_DEBUG("Initialized Sampling Model");
}
template<typename ParametricSparseModelType, typename ConstantType>
void AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>::checkRegions(std::vector<ParameterRegion<ParametricType>>& regions) {
STORM_LOG_DEBUG("Checking " << regions.size() << "regions.");
std::cout << "Checking " << regions.size() << " regions. Progress: ";
std::cout.flush();
uint_fast64_t progress=0;
uint_fast64_t checkedRegions=0;
for(auto& region : regions){
this->checkRegion(region);
if((checkedRegions++)*10/regions.size()==progress){
std::cout << progress++;
std::cout.flush();
}
}
std::cout << " done!" << std::endl;
}
template<typename ParametricSparseModelType, typename ConstantType>
void AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>::checkRegion(ParameterRegion<ParametricType>& region) {
std::chrono::high_resolution_clock::time_point timeCheckRegionStart = std::chrono::high_resolution_clock::now();
++this->numOfCheckedRegions;
STORM_LOG_THROW(this->getSpecifiedFormula()!=nullptr, storm::exceptions::InvalidStateException, "Tried to analyze a region although no property has been specified" );
STORM_LOG_DEBUG("Analyzing the region " << region.toString());
//std::cout << "Analyzing the region " << region.toString() << std::endl;
//switches for the different steps.
bool done=false;
STORM_LOG_WARN_COND( (!storm::settings::regionSettings().doApprox() || this->isApproximationApplicable), "the approximation is only correct if the model has only linear functions. As this is not the case, approximation is deactivated");
bool doApproximation=storm::settings::regionSettings().doApprox() && this->isApproximationApplicable;
bool doSampling=storm::settings::regionSettings().doSample();
bool doSmt=storm::settings::regionSettings().doSmt();
if(!done && this->isResultConstant()){
STORM_LOG_DEBUG("Checking a region although the result is constant, i.e., independent of the region. This makes sense none.");
if(this->valueIsInBoundOfFormula(this->getReachabilityValue(region.getSomePoint()))){
region.setCheckResult(RegionCheckResult::ALLSAT);
}
else{
region.setCheckResult(RegionCheckResult::ALLVIOLATED);
}
done=true;
}
std::chrono::high_resolution_clock::time_point timeApproximationStart = std::chrono::high_resolution_clock::now();
std::vector<ConstantType> lowerBounds;
std::vector<ConstantType> upperBounds;
if(!done && doApproximation){
STORM_LOG_DEBUG("Checking approximative values...");
if(this->checkApproximativeValues(region, lowerBounds, upperBounds)){
++this->numOfRegionsSolvedThroughApproximation;
STORM_LOG_DEBUG("Result '" << region.getCheckResult() <<"' obtained through approximation.");
done=true;
}
}
std::chrono::high_resolution_clock::time_point timeApproximationEnd = std::chrono::high_resolution_clock::now();
std::chrono::high_resolution_clock::time_point timeSamplingStart = std::chrono::high_resolution_clock::now();
if(!done && doSampling){
STORM_LOG_DEBUG("Checking sample points...");
if(this->checkSamplePoints(region)){
++this->numOfRegionsSolvedThroughSampling;
STORM_LOG_DEBUG("Result '" << region.getCheckResult() <<"' obtained through sampling.");
done=true;
}
}
std::chrono::high_resolution_clock::time_point timeSamplingEnd = std::chrono::high_resolution_clock::now();
std::chrono::high_resolution_clock::time_point timeSmtStart = std::chrono::high_resolution_clock::now();
if(!done && doSmt){
STORM_LOG_DEBUG("Checking with Smt Solving...");
if(this->checkSmt(region)){
++this->numOfRegionsSolvedThroughSmt;
STORM_LOG_DEBUG("Result '" << region.getCheckResult() <<"' obtained through Smt Solving.");
done=true;
}
}
std::chrono::high_resolution_clock::time_point timeSmtEnd = std::chrono::high_resolution_clock::now();
//some information for statistics...
std::chrono::high_resolution_clock::time_point timeCheckRegionEnd = std::chrono::high_resolution_clock::now();
this->timeCheckRegion += timeCheckRegionEnd-timeCheckRegionStart;
this->timeSampling += timeSamplingEnd - timeSamplingStart;
this->timeApproximation += timeApproximationEnd - timeApproximationStart;
this->timeSmt += timeSmtEnd - timeSmtStart;
switch(region.getCheckResult()){
case RegionCheckResult::EXISTSBOTH:
++this->numOfRegionsExistsBoth;
break;
case RegionCheckResult::ALLSAT:
++this->numOfRegionsAllSat;
break;
case RegionCheckResult::ALLVIOLATED:
++this->numOfRegionsAllViolated;
break;
default:
break;
}
}
template<typename ParametricSparseModelType, typename ConstantType>
std::shared_ptr<ApproximationModel<ParametricSparseModelType, ConstantType>> const& AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>::getApproximationModel() {
if(this->approximationModel==nullptr){
STORM_LOG_WARN("Approximation model requested but it has not been initialized when specifying the formula. Will initialize it now.");
initializeApproximationModel(*this->getSimpleModel(), this->simpleFormula);
}
return this->approximationModel;
}
template<typename ParametricSparseModelType, typename ConstantType>
bool AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>::checkSamplePoints(ParameterRegion<ParametricType>& region) {
auto samplingPoints = region.getVerticesOfRegion(region.getVariables()); //test the 4 corner points
for (auto const& point : samplingPoints){
if(checkPoint(region, point)){
return true;
}
}
return false;
}
template<typename ParametricSparseModelType, typename ConstantType>
std::shared_ptr<SamplingModel<ParametricSparseModelType, ConstantType>> const& AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>::getSamplingModel() {
if(this->samplingModel==nullptr){
STORM_LOG_WARN("Sampling model requested but it has not been initialized when specifying the formula. Will initialize it now.");
initializeSamplingModel(*this->getSimpleModel(), this->simpleFormula);
}
return this->samplingModel;
}
template<typename ParametricSparseModelType, typename ConstantType>
bool AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>::valueIsInBoundOfFormula(ConstantType const& value){
STORM_LOG_THROW(this->getSpecifiedFormula()!=nullptr, storm::exceptions::InvalidStateException, "Tried to compare a value to the bound of a formula, but no formula specified.");
switch (this->getSpecifiedFormulaCompType()) {
case storm::logic::ComparisonType::Greater:
return (value > this->getSpecifiedFormulaBound());
case storm::logic::ComparisonType::GreaterEqual:
return (value >= this->getSpecifiedFormulaBound());
case storm::logic::ComparisonType::Less:
return (value < this->getSpecifiedFormulaBound());
case storm::logic::ComparisonType::LessEqual:
return (value <= this->getSpecifiedFormulaBound());
default:
STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "the comparison relation of the formula is not supported");
}
}
template<typename ParametricSparseModelType, typename ConstantType>
bool AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>::valueIsInBoundOfFormula(CoefficientType const& value){
return valueIsInBoundOfFormula(storm::utility::region::convertNumber<ConstantType>(value));
}
template<typename ParametricSparseModelType, typename ConstantType>
void AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>::printStatisticsToStream(std::ostream& outstream) {
if(this->getSpecifiedFormula()==nullptr){
outstream << "Region Model Checker Statistics Error: No formula specified." << std::endl;
return;
}
std::chrono::milliseconds timeSpecifyFormulaInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(this->timeSpecifyFormula);
std::chrono::milliseconds timePreprocessingInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(this->timePreprocessing);
std::chrono::milliseconds timeInitSamplingModelInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(this->timeInitSamplingModel);
std::chrono::milliseconds timeInitApproxModelInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(this->timeInitApproxModel);
std::chrono::milliseconds timeComputeReachabilityFunctionInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(this->timeComputeReachabilityFunction);
std::chrono::milliseconds timeCheckRegionInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(this->timeCheckRegion);
std::chrono::milliseconds timeSammplingInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(this->timeSampling);
std::chrono::milliseconds timeApproximationInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(this->timeApproximation);
std::chrono::milliseconds timeApproxModelInstantiationInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(this->timeApproxModelInstantiation);
std::chrono::milliseconds timeSmtInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(this->timeSmt);
std::chrono::high_resolution_clock::duration timeOverall = timeSpecifyFormula + timeCheckRegion; // + ...
std::chrono::milliseconds timeOverallInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(timeOverall);
uint_fast64_t numOfSolvedRegions= this->numOfRegionsExistsBoth + this->numOfRegionsAllSat + this->numOfRegionsAllViolated;
outstream << std::endl << "Region Model Checker Statistics:" << std::endl;
outstream << "-----------------------------------------------" << std::endl;
outstream << "Model: " << this->model.getNumberOfStates() << " states, " << this->model.getNumberOfTransitions() << " transitions." << std::endl;
outstream << "Formula: " << *this->getSpecifiedFormula() << std::endl;
if(this->isResultConstant()){
outstream << "The requested value is constant (i.e. independent of any parameters)" << std::endl;
}
else{
outstream << "Simple model: " << this->getSimpleModel()->getNumberOfStates() << " states, " << this->getSimpleModel()->getNumberOfTransitions() << " transitions" << std::endl;
}
outstream << "Approximation is " << (this->isApproximationApplicable ? "" : "not ") << "applicable" << std::endl;
outstream << "Number of checked regions: " << this->numOfCheckedRegions << std::endl;
if(this->numOfCheckedRegions>0){
outstream << " Number of solved regions: " << numOfSolvedRegions << "(" << numOfSolvedRegions*100/this->numOfCheckedRegions << "%)" << std::endl;
outstream << " AllSat: " << this->numOfRegionsAllSat << "(" << this->numOfRegionsAllSat*100/this->numOfCheckedRegions << "%)" << std::endl;
outstream << " AllViolated: " << this->numOfRegionsAllViolated << "(" << this->numOfRegionsAllViolated*100/this->numOfCheckedRegions << "%)" << std::endl;
outstream << " ExistsBoth: " << this->numOfRegionsExistsBoth << "(" << this->numOfRegionsExistsBoth*100/this->numOfCheckedRegions << "%)" << std::endl;
outstream << " Unsolved: " << this->numOfCheckedRegions - numOfSolvedRegions << "(" << (this->numOfCheckedRegions - numOfSolvedRegions)*100/this->numOfCheckedRegions << "%)" << std::endl;
outstream << " -- Note: %-numbers are relative to the NUMBER of regions, not the size of their area --" << std::endl;
outstream << " " << this->numOfRegionsSolvedThroughApproximation << " regions solved through Approximation" << std::endl;
outstream << " " << this->numOfRegionsSolvedThroughSampling << " regions solved through Sampling" << std::endl;
outstream << " " << this->numOfRegionsSolvedThroughSmt << " regions solved through Smt" << std::endl;
outstream << std::endl;
}
outstream << "Running times:" << std::endl;
outstream << " " << timeOverallInMilliseconds.count() << "ms overall (excluding model parsing, bisimulation (if applied))" << std::endl;
outstream << " " << timeSpecifyFormulaInMilliseconds.count() << "ms Initialization for the specified formula, including... " << std::endl;
outstream << " " << timePreprocessingInMilliseconds.count() << "ms for Preprocessing (mainly: state elimination of const transitions), including" << std::endl;
outstream << " " << timeComputeReachabilityFunctionInMilliseconds.count() << "ms to compute the reachability function" << std::endl;
outstream << " " << timeInitApproxModelInMilliseconds.count() << "ms to initialize the Approximation Model" << std::endl;
outstream << " " << timeInitSamplingModelInMilliseconds.count() << "ms to initialize the Sampling Model" << std::endl;
outstream << " " << timeCheckRegionInMilliseconds.count() << "ms Region Check including... " << std::endl;
outstream << " " << timeApproximationInMilliseconds.count() << "ms Approximation including... " << std::endl;
outstream << " " << timeApproxModelInstantiationInMilliseconds.count() << "ms for instantiation of the approximation model" << std::endl;
outstream << " " << timeSammplingInMilliseconds.count() << "ms Sampling " << std::endl;
outstream << " " << timeSmtInMilliseconds.count() << "ms Smt solving" << std::endl;
outstream << "-----------------------------------------------" << std::endl;
}
#ifdef STORM_HAVE_CARL
template class AbstractSparseRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction, storm::models::sparse::StandardRewardModel<storm::RationalFunction>>, double>;
#endif
} // namespace region
} //namespace modelchecker
} //namespace storm

239
src/modelchecker/region/AbstractSparseRegionModelChecker.h

@ -0,0 +1,239 @@
/*
* File: AbstractSparseRegionModelChecker.h
* Author: tim
*
* Created on September 9, 2015, 12:34 PM
*/
#ifndef STORM_MODELCHECKER_REGION_ABSTRACTSPARSEREGIONMODELCHECKER_H
#define STORM_MODELCHECKER_REGION_ABSTRACTSPARSEREGIONMODELCHECKER_H
#include <ostream>
#include "src/utility/region.h"
#include "src/modelchecker/region/ParameterRegion.h"
#include "src/modelchecker/region/ApproximationModel.h"
#include "src/modelchecker/region/SamplingModel.h"
#include "src/models/sparse/StandardRewardModel.h"
#include "src/models/sparse/Model.h"
#include "src/models/sparse/Dtmc.h"
#include "src/logic/Formulas.h"
namespace storm {
namespace modelchecker{
namespace region{
template<typename ParametricSparseModelType, typename ConstantType>
class AbstractSparseRegionModelChecker {
public:
typedef typename ParametricSparseModelType::ValueType ParametricType;
typedef typename storm::utility::region::VariableType<ParametricType> VariableType;
typedef typename storm::utility::region::CoefficientType<ParametricType> CoefficientType;
explicit AbstractSparseRegionModelChecker(ParametricSparseModelType const& model);
virtual ~AbstractSparseRegionModelChecker();
/*!
* Checks if the given formula can be handled by This region model checker
* @param formula the formula to be checked
*/
virtual bool canHandle(storm::logic::Formula const& formula) const = 0;
/*!
* Specifies the considered formula.
* A few preprocessing steps are performed.
* If another formula has been specified before, all 'context' regarding the old formula is lost.
*
* @param formula the formula to be considered.
*/
void specifyFormula(std::shared_ptr<storm::logic::Formula> formula);
/*!
* Checks for every given region whether the specified formula holds for all parameters that lie in that region.
* Sets the region checkresult accordingly.
* TODO: set region.satpoint and violated point correctly.
*
* @note A formula has to be specified first.
*
* @param region The considered region
*/
void checkRegions(std::vector<ParameterRegion<ParametricType>>& regions);
/*!
* Checks whether the given formula holds for all parameters that lie in the given region.
* Sets the region checkresult accordingly.
* TODO: set region.satpoint and violated point correctly.
*
* @note A formula has to be specified first.
*
* @param region The considered region
*
*/
void checkRegion(ParameterRegion<ParametricType>& region);
/*!
* Returns the reachability Value at the specified point by instantiating the sampling model.
*
* @param point The point (i.e. parameter evaluation) at which to compute the reachability value.
* @param evaluateFunction If set, the reachability function is evaluated. Otherwise, the sampling model is instantiated.
*/
virtual ConstantType getReachabilityValue(std::map<VariableType, CoefficientType>const& point, bool evaluateFunction=false) = 0;
/*!
* Returns true iff the given value satisfies the bound given by the specified property
*/
bool valueIsInBoundOfFormula(ConstantType const& value);
/*!
* Returns true iff the given value satisfies the bound given by the specified property
*/
bool valueIsInBoundOfFormula(CoefficientType const& value);
/*!
* Prints statistical information to the given stream.
*/
void printStatisticsToStream(std::ostream& outstream);
protected:
/*!
* returns the considered model
*/
ParametricSparseModelType const& getModel() const;
bool const& isResultConstant() const;
std::shared_ptr<ParametricSparseModelType> const& getSimpleModel() const;
bool const& isComputeRewards() const;
std::shared_ptr<storm::logic::Formula> const& getSpecifiedFormula() const;
ConstantType const& getSpecifiedFormulaBound() const;
storm::logic::ComparisonType const& getSpecifiedFormulaCompType() const;
bool specifiedFormulaHasUpperBound() const;
/*!
* Makes the required preprocessing steps for the specified model and formula
* Computes a simplified version of the model and formula that can be analyzed more efficiently.
* Also checks whether the approximation technique is applicable and whether the result is constant.
*
* @note this->specifiedFormula and this->computeRewards has to be set accordingly, before calling this function
*/
virtual void preprocess(std::shared_ptr<ParametricSparseModelType>& simpleModel, std::shared_ptr<storm::logic::Formula>& simpleFormula, bool& isApproximationApplicable, bool& isResultConstant) = 0;
/*!
* Instantiates the approximation model to compute bounds on the maximal/minimal reachability probability (or reachability reward).
* If the current region result is EXISTSSAT (or EXISTSVIOLATED), then this function tries to prove ALLSAT (or ALLVIOLATED).
* If this succeeded, then the region check result is changed accordingly.
* If the current region result is UNKNOWN, then this function first tries to prove ALLSAT and if that failed, it tries to prove ALLVIOLATED.
* In any case, the computed bounds are written to the given lowerBounds/upperBounds.
* However, if only the lowerBounds (or upperBounds) have been computed, the other vector is set to a vector of size 0.
* True is returned iff either ALLSAT or ALLVIOLATED could be proved.
*/
virtual bool checkApproximativeValues(ParameterRegion<ParametricType>& region, std::vector<ConstantType>& lowerBounds, std::vector<ConstantType>& upperBounds)=0;
/*!
* Returns the approximation model.
* If it is not yet available, it is computed.
*/
std::shared_ptr<ApproximationModel<ParametricSparseModelType, ConstantType>> const& getApproximationModel();
/*!
* Checks the value of the function at some sampling points within the given region.
* May set the satPoint and violatedPoint of the regions if they are not yet specified and such points are found
* Also changes the regioncheckresult of the region to EXISTSSAT, EXISTSVIOLATED, or EXISTSBOTH
*
* @return true if an violated point as well as a sat point has been found during the process
*/
bool checkSamplePoints(ParameterRegion<ParametricType>& region);
/*!
* Checks the value of the function at the given sampling point.
* May set the satPoint and violatedPoint of the regions if thy are not yet specified and such point is given.
* Also changes the regioncheckresult of the region to EXISTSSAT, EXISTSVIOLATED, or EXISTSBOTH
*
* @param favorViaFunction if not stated otherwise (e.g. in the settings), the sampling will be done via the
* reachabilityFunction if this flag is true. If the flag is false, sampling will be
* done via instantiation of the samplingmodel. Note that this argument is ignored,
* unless sampling has been turned of in the settings
*
* @return true if an violated point as well as a sat point has been found, i.e., the check result is changed to EXISTSOTH
*/
virtual bool checkPoint(ParameterRegion<ParametricType>& region, std::map<VariableType, CoefficientType>const& point, bool favorViaFunction=false) = 0;
/*!
* Returns the sampling model.
* If it is not yet available, it is computed.
*/
std::shared_ptr<SamplingModel<ParametricSparseModelType, ConstantType>> const& getSamplingModel();
/*!
* Starts the SMTSolver to get the result.
* The current regioncheckresult of the region should be EXISTSSAT or EXISTVIOLATED.
* Otherwise, a sampingPoint will be computed.
* True is returned iff the solver was successful (i.e., it returned sat or unsat)
* A Sat- or Violated point is set, if the solver has found one (not yet implemented!).
* The region checkResult of the given region is changed accordingly.
*/
virtual bool checkSmt(ParameterRegion<ParametricType>& region)=0;
private:
/*!
* initializes the Approximation Model
*
* @note does not check whether approximation can be applied
*/
void initializeApproximationModel(ParametricSparseModelType const& model, std::shared_ptr<storm::logic::Formula> formula);
/*!
* initializes the Sampling Model
*/
void initializeSamplingModel(ParametricSparseModelType const& model, std::shared_ptr<storm::logic::Formula> formula);
// The model this model checker is supposed to analyze.
ParametricSparseModelType const& model;
//The currently specified formula
std::shared_ptr<storm::logic::Formula> specifiedFormula;
storm::logic::ComparisonType specifiedFormulaCompType;
ConstantType specifiedFormulaBound;
//A flag that is true iff we are interested in rewards
bool computeRewards;
// the original model after states with constant transitions have been eliminated
std::shared_ptr<ParametricSparseModelType> simpleModel;
// a formula that can be checked on the simplified model
std::shared_ptr<storm::logic::Formula> simpleFormula;
// a flag that is true if approximation is applicable, i.e., there are only linear functions at transitions of the model
bool isApproximationApplicable;
// the model that is used to approximate the reachability values
std::shared_ptr<ApproximationModel<ParametricSparseModelType, ConstantType>> approximationModel;
// the model that can be instantiated to check the value at a certain point
std::shared_ptr<SamplingModel<ParametricSparseModelType, ConstantType>> samplingModel;
// a flag that is true iff the resulting reachability function is constant
bool resultConstant;
// runtimes and other information for statistics.
uint_fast64_t numOfCheckedRegions;
uint_fast64_t numOfRegionsSolvedThroughApproximation;
uint_fast64_t numOfRegionsSolvedThroughSampling;
uint_fast64_t numOfRegionsSolvedThroughSmt;
uint_fast64_t numOfRegionsExistsBoth;
uint_fast64_t numOfRegionsAllSat;
uint_fast64_t numOfRegionsAllViolated;
std::chrono::high_resolution_clock::duration timeSpecifyFormula;
std::chrono::high_resolution_clock::duration timePreprocessing;
std::chrono::high_resolution_clock::duration timeInitApproxModel;
std::chrono::high_resolution_clock::duration timeInitSamplingModel;
std::chrono::high_resolution_clock::duration timeCheckRegion;
std::chrono::high_resolution_clock::duration timeSampling;
std::chrono::high_resolution_clock::duration timeApproximation;
std::chrono::high_resolution_clock::duration timeSmt;
protected:
std::chrono::high_resolution_clock::duration timeComputeReachabilityFunction;
std::chrono::high_resolution_clock::duration timeApproxModelInstantiation;
};
} //namespace region
} //namespace modelchecker
} //namespace storm
#endif /* STORM_MODELCHECKER_REGION_ABSTRACTSPARSEREGIONMODELCHECKER_H */

38
src/modelchecker/region/ApproximationModel.cpp

@ -9,17 +9,18 @@
#include "src/modelchecker/region/ApproximationModel.h" #include "src/modelchecker/region/ApproximationModel.h"
#include "src/modelchecker/prctl/SparseMdpPrctlModelChecker.h" #include "src/modelchecker/prctl/SparseMdpPrctlModelChecker.h"
#include "src/modelchecker/results/ExplicitQuantitativeCheckResult.h" #include "src/modelchecker/results/ExplicitQuantitativeCheckResult.h"
#include "src/utility/macros.h"
#include "src/utility/region.h"
#include "src/utility/vector.h" #include "src/utility/vector.h"
#include "src/utility/regions.h"
#include "src/exceptions/UnexpectedException.h" #include "src/exceptions/UnexpectedException.h"
#include "src/exceptions/InvalidArgumentException.h" #include "src/exceptions/InvalidArgumentException.h"
namespace storm { namespace storm {
namespace modelchecker { namespace modelchecker {
namespace region {
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ApproximationModel::ApproximationModel(storm::models::sparse::Dtmc<ParametricType> const& parametricModel, std::shared_ptr<storm::logic::Formula> formula) : formula(formula){
ApproximationModel<ParametricSparseModelType, ConstantType>::ApproximationModel(ParametricSparseModelType const& parametricModel, std::shared_ptr<storm::logic::Formula> formula) : formula(formula){
if(this->formula->isEventuallyFormula()){ if(this->formula->isEventuallyFormula()){
this->computeRewards=false; this->computeRewards=false;
} else if(this->formula->isReachabilityRewardFormula()){ } else if(this->formula->isReachabilityRewardFormula()){
@ -61,7 +62,7 @@ namespace storm {
auto approxModelEntry = this->model->getTransitionMatrix().getRow(matrixRow).begin(); auto approxModelEntry = this->model->getTransitionMatrix().getRow(matrixRow).begin();
for(auto const& parEntry : parametricModel.getTransitionMatrix().getRow(row)){ for(auto const& parEntry : parametricModel.getTransitionMatrix().getRow(row)){
if(*tableEntry == &constantProbEntry){ if(*tableEntry == &constantProbEntry){
approxModelEntry->setValue(storm::utility::regions::convertNumber<ConstantType>(storm::utility::regions::getConstantPart(parEntry.getValue())));
approxModelEntry->setValue(storm::utility::region::convertNumber<ConstantType>(storm::utility::region::getConstantPart(parEntry.getValue())));
} else { } else {
this->probabilityMapping.emplace_back(std::make_pair(&((*tableEntry)->second), approxModelEntry)); this->probabilityMapping.emplace_back(std::make_pair(&((*tableEntry)->second), approxModelEntry));
} }
@ -93,7 +94,7 @@ namespace storm {
} }
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ApproximationModel::initializeProbabilities(storm::models::sparse::Dtmc<ParametricType>const& parametricModel,
void ApproximationModel<ParametricSparseModelType, ConstantType>::initializeProbabilities(ParametricSparseModelType const& parametricModel,
storm::storage::SparseMatrix<ConstantType>& probabilityMatrix, storm::storage::SparseMatrix<ConstantType>& probabilityMatrix,
std::vector<std::size_t>& rowSubstitutions, std::vector<std::size_t>& rowSubstitutions,
std::vector<ProbTableEntry*>& matrixEntryToEvalTableMapping, std::vector<ProbTableEntry*>& matrixEntryToEvalTableMapping,
@ -109,7 +110,7 @@ namespace storm {
// Find the different substitutions, i.e., mappings from Variables that occur in this row to {lower, upper} // Find the different substitutions, i.e., mappings from Variables that occur in this row to {lower, upper}
std::set<VariableType> occurringVariables; std::set<VariableType> occurringVariables;
for(auto const& entry : parametricModel.getTransitionMatrix().getRow(row)){ for(auto const& entry : parametricModel.getTransitionMatrix().getRow(row)){
storm::utility::regions::gatherOccurringVariables(entry.getValue(), occurringVariables);
storm::utility::region::gatherOccurringVariables(entry.getValue(), occurringVariables);
} }
std::size_t numOfSubstitutions=1ull<<occurringVariables.size(); //=2^(#variables). Note that there is still 1 substitution when #variables==0 (i.e.,the empty substitution) std::size_t numOfSubstitutions=1ull<<occurringVariables.size(); //=2^(#variables). Note that there is still 1 substitution when #variables==0 (i.e.,the empty substitution)
for(uint_fast64_t substitutionId=0; substitutionId<numOfSubstitutions; ++substitutionId){ for(uint_fast64_t substitutionId=0; substitutionId<numOfSubstitutions; ++substitutionId){
@ -151,7 +152,7 @@ namespace storm {
} }
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ApproximationModel::initializeRewards(storm::models::sparse::Dtmc<ParametricType> const& parametricModel,
void ApproximationModel<ParametricSparseModelType, ConstantType>::initializeRewards(ParametricSparseModelType const& parametricModel,
storm::storage::SparseMatrix<ConstantType> const& probabilityMatrix, storm::storage::SparseMatrix<ConstantType> const& probabilityMatrix,
std::vector<std::size_t> const& rowSubstitutions, std::vector<std::size_t> const& rowSubstitutions,
std::vector<ConstantType>& stateActionRewardVector, std::vector<ConstantType>& stateActionRewardVector,
@ -169,14 +170,14 @@ namespace storm {
std::set<VariableType> occurringRewVariables; std::set<VariableType> occurringRewVariables;
std::set<VariableType> occurringProbVariables; std::set<VariableType> occurringProbVariables;
if(storm::utility::isConstant(parametricModel.getUniqueRewardModel()->second.getStateRewardVector()[state])){ if(storm::utility::isConstant(parametricModel.getUniqueRewardModel()->second.getStateRewardVector()[state])){
ConstantType reward = storm::utility::regions::convertNumber<ConstantType>(storm::utility::regions::getConstantPart(parametricModel.getUniqueRewardModel()->second.getStateRewardVector()[state]));
ConstantType reward = storm::utility::region::convertNumber<ConstantType>(storm::utility::region::getConstantPart(parametricModel.getUniqueRewardModel()->second.getStateRewardVector()[state]));
//Add one of these entries for every row in the row group of state //Add one of these entries for every row in the row group of state
for(auto matrixRow=probabilityMatrix.getRowGroupIndices()[state]; matrixRow<probabilityMatrix.getRowGroupIndices()[state+1]; ++matrixRow){ for(auto matrixRow=probabilityMatrix.getRowGroupIndices()[state]; matrixRow<probabilityMatrix.getRowGroupIndices()[state+1]; ++matrixRow){
stateActionRewardVector.emplace_back(reward); stateActionRewardVector.emplace_back(reward);
rewardEntryToEvalTableMapping.emplace_back(constantEntry); rewardEntryToEvalTableMapping.emplace_back(constantEntry);
} }
} else { } else {
storm::utility::regions::gatherOccurringVariables(parametricModel.getUniqueRewardModel()->second.getStateRewardVector()[state], occurringRewVariables);
storm::utility::region::gatherOccurringVariables(parametricModel.getUniqueRewardModel()->second.getStateRewardVector()[state], occurringRewVariables);
//For each row in the row group of state, we get the corresponding substitution and tableIndex //For each row in the row group of state, we get the corresponding substitution and tableIndex
// We might find out that the reward is independent of the probability variables (and will thus be independent of nondeterministic choices) // We might find out that the reward is independent of the probability variables (and will thus be independent of nondeterministic choices)
// In that case, the reward function and the substitution will not change and thus we can use the same table index // In that case, the reward function and the substitution will not change and thus we can use the same table index
@ -215,17 +216,17 @@ namespace storm {
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ApproximationModel::~ApproximationModel() {
ApproximationModel<ParametricSparseModelType, ConstantType>::~ApproximationModel() {
//Intentionally left empty //Intentionally left empty
} }
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
std::shared_ptr<storm::models::sparse::Mdp<ConstantType>> const& SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ApproximationModel::getModel() const {
std::shared_ptr<storm::models::sparse::Mdp<ConstantType>> const& ApproximationModel<ParametricSparseModelType, ConstantType>::getModel() const {
return this->model; return this->model;
} }
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ApproximationModel::instantiate(const ParameterRegion& region) {
void ApproximationModel<ParametricSparseModelType, ConstantType>::instantiate(const ParameterRegion<ParametricType>& region) {
//Instantiate the substitutions //Instantiate the substitutions
std::vector<std::map<VariableType, CoefficientType>> instantiatedSubs(this->probabilitySubstitutions.size()); std::vector<std::map<VariableType, CoefficientType>> instantiatedSubs(this->probabilitySubstitutions.size());
for(uint_fast64_t substitutionIndex=0; substitutionIndex<this->probabilitySubstitutions.size(); ++substitutionIndex){ for(uint_fast64_t substitutionIndex=0; substitutionIndex<this->probabilitySubstitutions.size(); ++substitutionIndex){
@ -244,8 +245,8 @@ namespace storm {
} }
//write entries into evaluation table //write entries into evaluation table
for(auto& tableEntry : this->probabilityEvaluationTable){ for(auto& tableEntry : this->probabilityEvaluationTable){
tableEntry.second=storm::utility::regions::convertNumber<ConstantType>(
storm::utility::regions::evaluateFunction(
tableEntry.second=storm::utility::region::convertNumber<ConstantType>(
storm::utility::region::evaluateFunction(
tableEntry.first.getFunction(), tableEntry.first.getFunction(),
instantiatedSubs[tableEntry.first.getSubstitution()] instantiatedSubs[tableEntry.first.getSubstitution()]
) )
@ -290,8 +291,8 @@ namespace storm {
for(auto const& vertexSub : vertex){ for(auto const& vertexSub : vertex){
instantiatedRewardSubs[funcSub.getSubstitution()][vertexSub.first]=vertexSub.second; instantiatedRewardSubs[funcSub.getSubstitution()][vertexSub.first]=vertexSub.second;
} }
ConstantType currValue = storm::utility::regions::convertNumber<ConstantType>(
storm::utility::regions::evaluateFunction(
ConstantType currValue = storm::utility::region::convertNumber<ConstantType>(
storm::utility::region::evaluateFunction(
funcSub.getFunction(), funcSub.getFunction(),
instantiatedRewardSubs[funcSub.getSubstitution()] instantiatedRewardSubs[funcSub.getSubstitution()]
) )
@ -305,7 +306,7 @@ namespace storm {
} }
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
std::vector<ConstantType> const& SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ApproximationModel::computeValues(storm::solver::OptimizationDirection const& optDir) {
std::vector<ConstantType> const& ApproximationModel<ParametricSparseModelType, ConstantType>::computeValues(storm::solver::OptimizationDirection const& optDir) {
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<ConstantType>> modelChecker(*this->model); storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<ConstantType>> modelChecker(*this->model);
std::unique_ptr<storm::modelchecker::CheckResult> resultPtr; std::unique_ptr<storm::modelchecker::CheckResult> resultPtr;
@ -338,7 +339,8 @@ namespace storm {
#ifdef STORM_HAVE_CARL #ifdef STORM_HAVE_CARL
template class SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>;
template class ApproximationModel<storm::models::sparse::Dtmc<storm::RationalFunction, storm::models::sparse::StandardRewardModel<storm::RationalFunction>>, double>;
#endif #endif
} //namespace region
} }
} }

29
src/modelchecker/region/ApproximationModel.h

@ -9,31 +9,29 @@
#define STORM_MODELCHECKER_REGION_APPROXIMATIONMODEL_H #define STORM_MODELCHECKER_REGION_APPROXIMATIONMODEL_H
#include <unordered_map> #include <unordered_map>
#include <memory>
#include "src/utility/region.h"
#include "src/modelchecker/region/SparseDtmcRegionModelChecker.h"
#include "src/models/sparse/Mdp.h"
#include "src/logic/Formulas.h"
#include "src/modelchecker/region/ParameterRegion.h" #include "src/modelchecker/region/ParameterRegion.h"
#include "src/models/sparse/Dtmc.h"
#include "src/models/sparse/Mdp.h"
#include "src/storage/SparseMatrix.h" #include "src/storage/SparseMatrix.h"
namespace storm { namespace storm {
namespace modelchecker { namespace modelchecker {
namespace region {
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
class SparseDtmcRegionModelChecker;
template<typename ParametricSparseModelType, typename ConstantType>
class SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ApproximationModel{
class ApproximationModel{
public: public:
typedef typename ParametricSparseModelType::ValueType ParametricType; typedef typename ParametricSparseModelType::ValueType ParametricType;
typedef typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::VariableType VariableType;
typedef typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::CoefficientType CoefficientType;
typedef typename storm::utility::region::VariableType<ParametricType> VariableType;
typedef typename storm::utility::region::CoefficientType<ParametricType> CoefficientType;
/*! /*!
* @note this will not check whether approximation is applicable * @note this will not check whether approximation is applicable
*/ */
ApproximationModel(storm::models::sparse::Dtmc<ParametricType> const& parametricModel, std::shared_ptr<storm::logic::Formula> formula);
ApproximationModel(ParametricSparseModelType const& parametricModel, std::shared_ptr<storm::logic::Formula> formula);
virtual ~ApproximationModel(); virtual ~ApproximationModel();
/*! /*!
@ -44,7 +42,7 @@ namespace storm {
/*! /*!
* Instantiates the underlying model according to the given region * Instantiates the underlying model according to the given region
*/ */
void instantiate(ParameterRegion const& region);
void instantiate(ParameterRegion<ParametricType> const& region);
/*! /*!
* Returns the approximated reachability probabilities for every state. * Returns the approximated reachability probabilities for every state.
@ -125,8 +123,8 @@ namespace storm {
typedef typename std::unordered_map<FunctionSubstitution, ConstantType, FuncSubHash>::value_type ProbTableEntry; typedef typename std::unordered_map<FunctionSubstitution, ConstantType, FuncSubHash>::value_type ProbTableEntry;
typedef typename std::unordered_map<FunctionSubstitution, std::pair<ConstantType, ConstantType>, FuncSubHash>::value_type RewTableEntry; typedef typename std::unordered_map<FunctionSubstitution, std::pair<ConstantType, ConstantType>, FuncSubHash>::value_type RewTableEntry;
void initializeProbabilities(storm::models::sparse::Dtmc<ParametricType> const& parametricModel, storm::storage::SparseMatrix<ConstantType>& probabilityMatrix, std::vector<std::size_t>& rowSubstitutions, std::vector<ProbTableEntry*>& matrixEntryToEvalTableMapping, ProbTableEntry* constantEntry);
void initializeRewards(storm::models::sparse::Dtmc<ParametricType> const& parametricModel, storm::storage::SparseMatrix<ConstantType> const& probabilityMatrix, std::vector<std::size_t> const& rowSubstitutions, std::vector<ConstantType>& stateActionRewardVector, std::vector<RewTableEntry*>& rewardEntryToEvalTableMapping, RewTableEntry* constantEntry);
void initializeProbabilities(ParametricSparseModelType const& parametricModel, storm::storage::SparseMatrix<ConstantType>& probabilityMatrix, std::vector<std::size_t>& rowSubstitutions, std::vector<ProbTableEntry*>& matrixEntryToEvalTableMapping, ProbTableEntry* constantEntry);
void initializeRewards(ParametricSparseModelType const& parametricModel, storm::storage::SparseMatrix<ConstantType> const& probabilityMatrix, std::vector<std::size_t> const& rowSubstitutions, std::vector<ConstantType>& stateActionRewardVector, std::vector<RewTableEntry*>& rewardEntryToEvalTableMapping, RewTableEntry* constantEntry);
//The Model with which we work //The Model with which we work
std::shared_ptr<storm::models::sparse::Mdp<ConstantType>> model; std::shared_ptr<storm::models::sparse::Mdp<ConstantType>> model;
@ -160,6 +158,7 @@ namespace storm {
std::vector<std::tuple<ConstantType*, ConstantType*, typename std::vector<ConstantType>::iterator>> rewardMapping; std::vector<std::tuple<ConstantType*, ConstantType*, typename std::vector<ConstantType>::iterator>> rewardMapping;
}; };
} //namespace region
} }
} }

146
src/modelchecker/region/ParameterRegion.cpp

@ -7,30 +7,30 @@
#include "src/modelchecker/region/ParameterRegion.h" #include "src/modelchecker/region/ParameterRegion.h"
#include "src/utility/regions.h"
#include "src/utility/region.h"
#include "src/utility/macros.h"
#include "src/parser/MappedFile.h"
#include "src/settings/SettingsManager.h" #include "src/settings/SettingsManager.h"
#include "src/settings/modules/RegionSettings.h" #include "src/settings/modules/RegionSettings.h"
#include "src/exceptions/UnexpectedException.h"
#include "exceptions/InvalidSettingsException.h"
#include "exceptions/InvalidArgumentException.h"
#include "parser/MappedFile.h"
#include "src/exceptions/InvalidSettingsException.h"
#include "src/exceptions/InvalidArgumentException.h"
namespace storm { namespace storm {
namespace modelchecker { namespace modelchecker {
namespace region {
template<typename ParametricSparseModelType, typename ConstantType>
SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::ParameterRegion(std::map<VariableType, CoefficientType> const& lowerBounds, std::map<VariableType, CoefficientType> const& upperBounds) : lowerBounds(lowerBounds), upperBounds(upperBounds), checkResult(RegionCheckResult::UNKNOWN) {
template<typename ParametricType>
ParameterRegion<ParametricType>::ParameterRegion(VariableSubstitutionType const& lowerBounds, VariableSubstitutionType const& upperBounds) : lowerBounds(lowerBounds), upperBounds(upperBounds), checkResult(RegionCheckResult::UNKNOWN) {
init(); init();
} }
template<typename ParametricSparseModelType, typename ConstantType>
SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::ParameterRegion(std::map<VariableType, CoefficientType>&& lowerBounds, std::map<VariableType, CoefficientType>&& upperBounds) : lowerBounds(std::move(lowerBounds)), upperBounds(std::move(upperBounds)), checkResult(RegionCheckResult::UNKNOWN) {
template<typename ParametricType>
ParameterRegion<ParametricType>::ParameterRegion(VariableSubstitutionType&& lowerBounds, VariableSubstitutionType&& upperBounds) : lowerBounds(std::move(lowerBounds)), upperBounds(std::move(upperBounds)), checkResult(RegionCheckResult::UNKNOWN) {
init(); init();
} }
template<typename ParametricSparseModelType, typename ConstantType>
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::init() {
template<typename ParametricType>
void ParameterRegion<ParametricType>::init() {
//check whether both mappings map the same variables, check that lowerbound <= upper bound, and pre-compute the set of variables //check whether both mappings map the same variables, check that lowerbound <= upper bound, and pre-compute the set of variables
for (auto const& variableWithLowerBound : this->lowerBounds) { for (auto const& variableWithLowerBound : this->lowerBounds) {
auto variableWithUpperBound = this->upperBounds.find(variableWithLowerBound.first); auto variableWithUpperBound = this->upperBounds.find(variableWithLowerBound.first);
@ -43,45 +43,45 @@ namespace storm {
} }
} }
template<typename ParametricSparseModelType, typename ConstantType>
SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::~ParameterRegion() {
template<typename ParametricType>
ParameterRegion<ParametricType>::~ParameterRegion() {
//Intentionally left empty //Intentionally left empty
} }
template<typename ParametricSparseModelType, typename ConstantType>
std::set<typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::VariableType> SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::getVariables() const {
template<typename ParametricType>
std::set<typename ParameterRegion<ParametricType>::VariableType> ParameterRegion<ParametricType>::getVariables() const {
return this->variables; return this->variables;
} }
template<typename ParametricSparseModelType, typename ConstantType>
typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::CoefficientType const& SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::getLowerBound(VariableType const& variable) const {
template<typename ParametricType>
typename ParameterRegion<ParametricType>::CoefficientType const& ParameterRegion<ParametricType>::getLowerBound(VariableType const& variable) const {
auto const& result = lowerBounds.find(variable); auto const& result = lowerBounds.find(variable);
STORM_LOG_THROW(result != lowerBounds.end(), storm::exceptions::InvalidArgumentException, "tried to find a lower bound of a variable that is not specified by this region"); STORM_LOG_THROW(result != lowerBounds.end(), storm::exceptions::InvalidArgumentException, "tried to find a lower bound of a variable that is not specified by this region");
return (*result).second; return (*result).second;
} }
template<typename ParametricSparseModelType, typename ConstantType>
typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::CoefficientType const& SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::getUpperBound(VariableType const& variable) const {
template<typename ParametricType>
typename ParameterRegion<ParametricType>::CoefficientType const& ParameterRegion<ParametricType>::getUpperBound(VariableType const& variable) const {
auto const& result = upperBounds.find(variable); auto const& result = upperBounds.find(variable);
STORM_LOG_THROW(result != upperBounds.end(), storm::exceptions::InvalidArgumentException, "tried to find an upper bound of a variable that is not specified by this region"); STORM_LOG_THROW(result != upperBounds.end(), storm::exceptions::InvalidArgumentException, "tried to find an upper bound of a variable that is not specified by this region");
return (*result).second; return (*result).second;
} }
template<typename ParametricSparseModelType, typename ConstantType>
const std::map<typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::VariableType, typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::CoefficientType> SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::getUpperBounds() const {
template<typename ParametricType>
const typename ParameterRegion<ParametricType>::VariableSubstitutionType ParameterRegion<ParametricType>::getUpperBounds() const {
return upperBounds; return upperBounds;
} }
template<typename ParametricSparseModelType, typename ConstantType>
const std::map<typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::VariableType, typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::CoefficientType> SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::getLowerBounds() const {
template<typename ParametricType>
const typename ParameterRegion<ParametricType>::VariableSubstitutionType ParameterRegion<ParametricType>::getLowerBounds() const {
return lowerBounds; return lowerBounds;
} }
template<typename ParametricSparseModelType, typename ConstantType>
std::vector<std::map<typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::VariableType, typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::CoefficientType>> SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::getVerticesOfRegion(std::set<VariableType> const& consideredVariables) const {
template<typename ParametricType>
std::vector<typename ParameterRegion<ParametricType>::VariableSubstitutionType> ParameterRegion<ParametricType>::getVerticesOfRegion(std::set<VariableType> const& consideredVariables) const {
std::size_t const numOfVariables = consideredVariables.size(); std::size_t const numOfVariables = consideredVariables.size();
std::size_t const numOfVertices = std::pow(2, numOfVariables); std::size_t const numOfVertices = std::pow(2, numOfVariables);
std::vector<std::map<VariableType, CoefficientType >> resultingVector(numOfVertices, std::map<VariableType, CoefficientType>());
std::vector<VariableSubstitutionType> resultingVector(numOfVertices, VariableSubstitutionType());
if (numOfVertices == 1) { if (numOfVertices == 1) {
//no variables are given, the returned vector should still contain an empty map //no variables are given, the returned vector should still contain an empty map
return resultingVector; return resultingVector;
@ -104,18 +104,18 @@ namespace storm {
return resultingVector; return resultingVector;
} }
template<typename ParametricSparseModelType, typename ConstantType>
std::map<typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::VariableType, typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::CoefficientType> SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::getSomePoint() const {
template<typename ParametricType>
typename ParameterRegion<ParametricType>::VariableSubstitutionType ParameterRegion<ParametricType>::getSomePoint() const {
return this->getLowerBounds(); return this->getLowerBounds();
} }
template<typename ParametricSparseModelType, typename ConstantType>
typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::RegionCheckResult SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::getCheckResult() const {
template<typename ParametricType>
RegionCheckResult ParameterRegion<ParametricType>::getCheckResult() const {
return checkResult; return checkResult;
} }
template<typename ParametricSparseModelType, typename ConstantType>
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::setCheckResult(RegionCheckResult checkResult) {
template<typename ParametricType>
void ParameterRegion<ParametricType>::setCheckResult(RegionCheckResult checkResult) {
//a few sanity checks //a few sanity checks
STORM_LOG_THROW((this->checkResult == RegionCheckResult::UNKNOWN || checkResult != RegionCheckResult::UNKNOWN), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from something known to UNKNOWN "); STORM_LOG_THROW((this->checkResult == RegionCheckResult::UNKNOWN || checkResult != RegionCheckResult::UNKNOWN), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from something known to UNKNOWN ");
STORM_LOG_THROW((this->checkResult != RegionCheckResult::EXISTSSAT || checkResult != RegionCheckResult::EXISTSVIOLATED), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from EXISTSSAT to EXISTSVIOLATED"); STORM_LOG_THROW((this->checkResult != RegionCheckResult::EXISTSSAT || checkResult != RegionCheckResult::EXISTSVIOLATED), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from EXISTSSAT to EXISTSVIOLATED");
@ -129,55 +129,35 @@ namespace storm {
this->checkResult = checkResult; this->checkResult = checkResult;
} }
template<typename ParametricSparseModelType, typename ConstantType>
std::map<typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::VariableType, typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::CoefficientType> SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::getViolatedPoint() const {
template<typename ParametricType>
typename ParameterRegion<ParametricType>::VariableSubstitutionType ParameterRegion<ParametricType>::getViolatedPoint() const {
return violatedPoint; return violatedPoint;
} }
template<typename ParametricSparseModelType, typename ConstantType>
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::setViolatedPoint(std::map<VariableType, CoefficientType> const& violatedPoint) {
template<typename ParametricType>
void ParameterRegion<ParametricType>::setViolatedPoint(VariableSubstitutionType const& violatedPoint) {
this->violatedPoint = violatedPoint; this->violatedPoint = violatedPoint;
} }
template<typename ParametricSparseModelType, typename ConstantType>
std::map<typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::VariableType, typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::CoefficientType> SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::getSatPoint() const {
template<typename ParametricType>
typename ParameterRegion<ParametricType>::VariableSubstitutionType ParameterRegion<ParametricType>::getSatPoint() const {
return satPoint; return satPoint;
} }
template<typename ParametricSparseModelType, typename ConstantType>
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::setSatPoint(std::map<VariableType, CoefficientType> const& satPoint) {
template<typename ParametricType>
void ParameterRegion<ParametricType>::setSatPoint(VariableSubstitutionType const& satPoint) {
this->satPoint = satPoint; this->satPoint = satPoint;
} }
template<typename ParametricSparseModelType, typename ConstantType>
std::string SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::checkResultToString() const {
switch (this->checkResult) {
case RegionCheckResult::UNKNOWN:
return "unknown";
case RegionCheckResult::EXISTSSAT:
return "ExistsSat";
case RegionCheckResult::EXISTSVIOLATED:
return "ExistsViolated";
case RegionCheckResult::EXISTSBOTH:
return "ExistsBoth";
case RegionCheckResult::ALLSAT:
return "allSat";
case RegionCheckResult::ALLVIOLATED:
return "allViolated";
}
STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Could not identify check result")
return "ERROR";
}
template<typename ParametricSparseModelType, typename ConstantType>
std::string SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::toString() const {
template<typename ParametricType>
std::string ParameterRegion<ParametricType>::toString() const {
std::stringstream regionstringstream; std::stringstream regionstringstream;
for (auto var : this->getVariables()) { for (auto var : this->getVariables()) {
regionstringstream << storm::utility::regions::convertNumber<double>(this->getLowerBound(var));
regionstringstream << storm::utility::region::convertNumber<double>(this->getLowerBound(var));
regionstringstream << "<="; regionstringstream << "<=";
regionstringstream << storm::utility::regions::getVariableName(var);
regionstringstream << storm::utility::region::getVariableName(var);
regionstringstream << "<="; regionstringstream << "<=";
regionstringstream << storm::utility::regions::convertNumber<double>(this->getUpperBound(var));
regionstringstream << storm::utility::region::convertNumber<double>(this->getUpperBound(var));
regionstringstream << ","; regionstringstream << ",";
} }
std::string regionstring = regionstringstream.str(); std::string regionstring = regionstringstream.str();
@ -188,10 +168,10 @@ namespace storm {
template<typename ParametricSparseModelType, typename ConstantType>
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::parseParameterBounds(
std::map<VariableType, CoefficientType>& lowerBounds,
std::map<VariableType, CoefficientType>& upperBounds,
template<typename ParametricType>
void ParameterRegion<ParametricType>::parseParameterBounds(
VariableSubstitutionType& lowerBounds,
VariableSubstitutionType& upperBounds,
std::string const& parameterBoundsString){ std::string const& parameterBoundsString){
std::string::size_type positionOfFirstRelation = parameterBoundsString.find("<="); std::string::size_type positionOfFirstRelation = parameterBoundsString.find("<=");
@ -204,18 +184,18 @@ namespace storm {
parameter.erase(std::remove_if(parameter.begin(), parameter.end(), ::isspace), parameter.end()); parameter.erase(std::remove_if(parameter.begin(), parameter.end(), ::isspace), parameter.end());
STORM_LOG_THROW(parameter.length()>0, storm::exceptions::InvalidArgumentException, "When parsing the region" << parameterBoundsString << " I could not find a parameter"); STORM_LOG_THROW(parameter.length()>0, storm::exceptions::InvalidArgumentException, "When parsing the region" << parameterBoundsString << " I could not find a parameter");
VariableType var = storm::utility::regions::getVariableFromString<VariableType>(parameter);
CoefficientType lb = storm::utility::regions::convertNumber<CoefficientType>(parameterBoundsString.substr(0,positionOfFirstRelation));
CoefficientType ub = storm::utility::regions::convertNumber<CoefficientType>(parameterBoundsString.substr(positionOfSecondRelation+2));
VariableType var = storm::utility::region::getVariableFromString<VariableType>(parameter);
CoefficientType lb = storm::utility::region::convertNumber<CoefficientType>(parameterBoundsString.substr(0,positionOfFirstRelation));
CoefficientType ub = storm::utility::region::convertNumber<CoefficientType>(parameterBoundsString.substr(positionOfSecondRelation+2));
lowerBounds.emplace(std::make_pair(var, lb)); lowerBounds.emplace(std::make_pair(var, lb));
upperBounds.emplace(std::make_pair(var, ub)); upperBounds.emplace(std::make_pair(var, ub));
} }
template<typename ParametricSparseModelType, typename ConstantType>
typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::parseRegion(
template<typename ParametricType>
ParameterRegion<ParametricType> ParameterRegion<ParametricType>::parseRegion(
std::string const& regionString){ std::string const& regionString){
std::map<VariableType, CoefficientType> lowerBounds;
std::map<VariableType, CoefficientType> upperBounds;
VariableSubstitutionType lowerBounds;
VariableSubstitutionType upperBounds;
std::vector<std::string> parameterBounds; std::vector<std::string> parameterBounds;
boost::split(parameterBounds, regionString, boost::is_any_of(",")); boost::split(parameterBounds, regionString, boost::is_any_of(","));
for(auto const& parameterBound : parameterBounds){ for(auto const& parameterBound : parameterBounds){
@ -226,8 +206,8 @@ namespace storm {
return ParameterRegion(std::move(lowerBounds), std::move(upperBounds)); return ParameterRegion(std::move(lowerBounds), std::move(upperBounds));
} }
template<typename ParametricSparseModelType, typename ConstantType>
std::vector<typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion> SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::parseMultipleRegions(
template<typename ParametricType>
std::vector<ParameterRegion<ParametricType>> ParameterRegion<ParametricType>::parseMultipleRegions(
std::string const& regionsString){ std::string const& regionsString){
std::vector<ParameterRegion> result; std::vector<ParameterRegion> result;
std::vector<std::string> regionsStrVec; std::vector<std::string> regionsStrVec;
@ -240,8 +220,8 @@ namespace storm {
return result; return result;
} }
template<typename ParametricSparseModelType, typename ConstantType>
std::vector<typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion> SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion::getRegionsFromSettings(){
template<typename ParametricType>
std::vector<ParameterRegion<ParametricType>> ParameterRegion<ParametricType>::getRegionsFromSettings(){
STORM_LOG_THROW(storm::settings::regionSettings().isRegionsSet() || storm::settings::regionSettings().isRegionFileSet(), storm::exceptions::InvalidSettingsException, "Tried to obtain regions from the settings but no regions are specified."); STORM_LOG_THROW(storm::settings::regionSettings().isRegionsSet() || storm::settings::regionSettings().isRegionFileSet(), storm::exceptions::InvalidSettingsException, "Tried to obtain regions from the settings but no regions are specified.");
STORM_LOG_THROW(!(storm::settings::regionSettings().isRegionsSet() && storm::settings::regionSettings().isRegionFileSet()), storm::exceptions::InvalidSettingsException, "Regions are specified via file AND cmd line. Only one option is allowed."); STORM_LOG_THROW(!(storm::settings::regionSettings().isRegionsSet() && storm::settings::regionSettings().isRegionFileSet()), storm::exceptions::InvalidSettingsException, "Regions are specified via file AND cmd line. Only one option is allowed.");
@ -258,9 +238,9 @@ namespace storm {
return parseMultipleRegions(regionsString); return parseMultipleRegions(regionsString);
} }
#ifdef STORM_HAVE_CARL #ifdef STORM_HAVE_CARL
template class SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>;
template class ParameterRegion<storm::RationalFunction>;
#endif #endif
} //namespace region
} }
} }

57
src/modelchecker/region/ParameterRegion.h

@ -8,30 +8,31 @@
#ifndef STORM_MODELCHECKER_REGION_PARAMETERREGION_H #ifndef STORM_MODELCHECKER_REGION_PARAMETERREGION_H
#define STORM_MODELCHECKER_REGION_PARAMETERREGION_H #define STORM_MODELCHECKER_REGION_PARAMETERREGION_H
#include "src/modelchecker/region/SparseDtmcRegionModelChecker.h"
#include <map>
namespace storm {
namespace modelchecker{
#include "src/modelchecker/region/RegionCheckResult.h"
#include "src/utility/region.h"
template<typename ParametricSparseModelType, typename ConstantType>
class SparseDtmcRegionModelChecker;
template<typename ParametricSparseModelType, typename ConstantType>
class SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParameterRegion{
namespace storm {
namespace modelchecker{
namespace region {
template<typename ParametricType>
class ParameterRegion{
public: public:
typedef typename ParametricSparseModelType::ValueType ParametricType;
typedef typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::VariableType VariableType;
typedef typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::CoefficientType CoefficientType;
typedef typename storm::utility::region::VariableType<ParametricType> VariableType;
typedef typename storm::utility::region::CoefficientType<ParametricType> CoefficientType;
typedef typename std::map<VariableType, CoefficientType> VariableSubstitutionType;
ParameterRegion(std::map<VariableType, CoefficientType> const& lowerBounds, std::map<VariableType, CoefficientType> const& upperBounds);
ParameterRegion(std::map<VariableType, CoefficientType>&& lowerBounds, std::map<VariableType, CoefficientType>&& upperBounds);
ParameterRegion(VariableSubstitutionType const& lowerBounds, VariableSubstitutionType const& upperBounds);
ParameterRegion(VariableSubstitutionType&& lowerBounds, VariableSubstitutionType&& upperBounds);
virtual ~ParameterRegion(); virtual ~ParameterRegion();
std::set<VariableType> getVariables() const; std::set<VariableType> getVariables() const;
CoefficientType const& getLowerBound(VariableType const& variable) const; CoefficientType const& getLowerBound(VariableType const& variable) const;
CoefficientType const& getUpperBound(VariableType const& variable) const; CoefficientType const& getUpperBound(VariableType const& variable) const;
const std::map<VariableType, CoefficientType> getUpperBounds() const;
const std::map<VariableType, CoefficientType> getLowerBounds() const;
const VariableSubstitutionType getUpperBounds() const;
const VariableSubstitutionType getLowerBounds() const;
/*! /*!
* Returns a vector of all possible combinations of lower and upper bounds of the given variables. * Returns a vector of all possible combinations of lower and upper bounds of the given variables.
@ -42,12 +43,12 @@ namespace storm {
* *
* If the given set of variables is empty, the returned vector will contain an empty map * If the given set of variables is empty, the returned vector will contain an empty map
*/ */
std::vector<std::map<VariableType, CoefficientType>> getVerticesOfRegion(std::set<VariableType> const& consideredVariables) const;
std::vector<VariableSubstitutionType> getVerticesOfRegion(std::set<VariableType> const& consideredVariables) const;
/*! /*!
* Returns some point that lies within this region * Returns some point that lies within this region
*/ */
std::map<VariableType, CoefficientType> getSomePoint() const;
VariableSubstitutionType getSomePoint() const;
RegionCheckResult getCheckResult() const; RegionCheckResult getCheckResult() const;
void setCheckResult(RegionCheckResult checkResult); void setCheckResult(RegionCheckResult checkResult);
@ -56,26 +57,23 @@ namespace storm {
* Retrieves a point in the region for which is considered property is not satisfied. * Retrieves a point in the region for which is considered property is not satisfied.
* If such a point is not known, the returned map is empty. * If such a point is not known, the returned map is empty.
*/ */
std::map<VariableType, CoefficientType> getViolatedPoint() const;
VariableSubstitutionType getViolatedPoint() const;
/*! /*!
* Sets a point in the region for which the considered property is not satisfied. * Sets a point in the region for which the considered property is not satisfied.
*/ */
void setViolatedPoint(std::map<VariableType, CoefficientType> const& violatedPoint);
void setViolatedPoint(VariableSubstitutionType const& violatedPoint);
/*! /*!
* Retrieves a point in the region for which is considered property is satisfied. * Retrieves a point in the region for which is considered property is satisfied.
* If such a point is not known, the returned map is empty. * If such a point is not known, the returned map is empty.
*/ */
std::map<VariableType, CoefficientType> getSatPoint() const;
VariableSubstitutionType getSatPoint() const;
/*! /*!
* Sets a point in the region for which the considered property is satisfied. * Sets a point in the region for which the considered property is satisfied.
*/ */
void setSatPoint(std::map<VariableType, CoefficientType> const& satPoint);
//returns the currently set check result as a string
std::string checkResultToString() const;
void setSatPoint(VariableSubstitutionType const& satPoint);
//returns the region as string in the format 0.3<=p<=0.4,0.2<=q<=0.5; //returns the region as string in the format 0.3<=p<=0.4,0.2<=q<=0.5;
std::string toString() const; std::string toString() const;
@ -87,8 +85,8 @@ namespace storm {
* *
*/ */
static void parseParameterBounds( static void parseParameterBounds(
std::map<VariableType, CoefficientType>& lowerBounds,
std::map<VariableType, CoefficientType>& upperBounds,
VariableSubstitutionType& lowerBounds,
VariableSubstitutionType& upperBounds,
std::string const& parameterBoundsString std::string const& parameterBoundsString
); );
@ -120,13 +118,14 @@ namespace storm {
void init(); void init();
std::map<VariableType, CoefficientType> const lowerBounds;
std::map<VariableType, CoefficientType> const upperBounds;
VariableSubstitutionType const lowerBounds;
VariableSubstitutionType const upperBounds;
std::set<VariableType> variables; std::set<VariableType> variables;
RegionCheckResult checkResult; RegionCheckResult checkResult;
std::map<VariableType, CoefficientType> satPoint;
std::map<VariableType, CoefficientType> violatedPoint;
VariableSubstitutionType satPoint;
VariableSubstitutionType violatedPoint;
}; };
} //namespace region
} }
} }

42
src/modelchecker/region/RegionCheckResult.cpp

@ -0,0 +1,42 @@
/*
* File: RegionCheckResult.cpp
* Author: tim
*
* Created on September 9, 2015, 1:56 PM
*/
#include "RegionCheckResult.h"
#include "src/utility/macros.h"
#include "src/exceptions/NotImplementedException.h"
namespace storm {
namespace modelchecker {
namespace region {
std::ostream& operator<<(std::ostream& os, RegionCheckResult const& regionCheckResult) {
switch (regionCheckResult) {
case RegionCheckResult::UNKNOWN:
os << "Unknown";
break;
case RegionCheckResult::EXISTSSAT:
os << "ExistsSat";
break;
case RegionCheckResult::EXISTSVIOLATED:
os << "ExistsViolated";
break;
case RegionCheckResult::EXISTSBOTH:
os << "ExistsBoth";
break;
case RegionCheckResult::ALLSAT:
os << "AllSat";
break;
case RegionCheckResult::ALLVIOLATED:
os << "AllViolated";
break;
default:
STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Could not get a string from the region check result. The case has not been implemented");
}
return os;
}
}
}
}

34
src/modelchecker/region/RegionCheckResult.h

@ -0,0 +1,34 @@
/*
* File: RegionCheckResult.h
* Author: tim
*
* Created on September 9, 2015, 1:56 PM
*/
#ifndef STORM_MODELCHECKER_REGION_REGIONCHECKRESULT_H
#define STORM_MODELCHECKER_REGION_REGIONCHECKRESULT_H
#include <ostream>
namespace storm {
namespace modelchecker {
namespace region {
/*!
* The possible results for a single Parameter region
*/
enum class RegionCheckResult {
UNKNOWN, /*!< the result is unknown */
EXISTSSAT, /*!< the formula is satisfied for at least one parameter evaluation that lies in the given region */
EXISTSVIOLATED, /*!< the formula is violated for at least one parameter evaluation that lies in the given region */
EXISTSBOTH, /*!< the formula is satisfied for some parameters but also violated for others */
ALLSAT, /*!< the formula is satisfied for all parameters in the given region */
ALLVIOLATED /*!< the formula is violated for all parameters in the given region */
};
std::ostream& operator<<(std::ostream& os, RegionCheckResult const& regionCheckResult);
}
}
}
#endif /* STORM_MODELCHECKER_REGION_REGIONCHECKRESULT_H */

34
src/modelchecker/region/SamplingModel.cpp

@ -8,18 +8,19 @@
#include "src/modelchecker/region/SamplingModel.h" #include "src/modelchecker/region/SamplingModel.h"
#include "src/modelchecker/prctl/SparseDtmcPrctlModelChecker.h" #include "src/modelchecker/prctl/SparseDtmcPrctlModelChecker.h"
#include "src/modelchecker/results/ExplicitQuantitativeCheckResult.h" #include "src/modelchecker/results/ExplicitQuantitativeCheckResult.h"
#include "src/utility/macros.h"
#include "src/utility/region.h"
#include "src/utility/vector.h" #include "src/utility/vector.h"
#include "src/utility/regions.h"
#include "src/exceptions/UnexpectedException.h" #include "src/exceptions/UnexpectedException.h"
#include "src/exceptions/InvalidArgumentException.h" #include "src/exceptions/InvalidArgumentException.h"
#include "models/sparse/StandardRewardModel.h" #include "models/sparse/StandardRewardModel.h"
namespace storm { namespace storm {
namespace modelchecker { namespace modelchecker {
namespace region {
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::SamplingModel::SamplingModel(storm::models::sparse::Dtmc<ParametricType> const& parametricModel, std::shared_ptr<storm::logic::Formula> formula) : formula(formula){
SamplingModel<ParametricSparseModelType, ConstantType>::SamplingModel(ParametricSparseModelType const& parametricModel, std::shared_ptr<storm::logic::Formula> formula) : formula(formula){
if(this->formula->isEventuallyFormula()){ if(this->formula->isEventuallyFormula()){
this->computeRewards=false; this->computeRewards=false;
} else if(this->formula->isReachabilityRewardFormula()){ } else if(this->formula->isReachabilityRewardFormula()){
@ -57,7 +58,7 @@ namespace storm {
for(auto tableEntry : matrixEntryToEvalTableMapping){ for(auto tableEntry : matrixEntryToEvalTableMapping){
STORM_LOG_THROW(sampleModelEntry->getColumn()==parModelEntry->getColumn(), storm::exceptions::UnexpectedException, "The entries of the given parametric model and the constructed sampling model do not match"); STORM_LOG_THROW(sampleModelEntry->getColumn()==parModelEntry->getColumn(), storm::exceptions::UnexpectedException, "The entries of the given parametric model and the constructed sampling model do not match");
if(tableEntry == &constantEntry){ if(tableEntry == &constantEntry){
sampleModelEntry->setValue(storm::utility::regions::convertNumber<ConstantType>(storm::utility::regions::getConstantPart(parModelEntry->getValue())));
sampleModelEntry->setValue(storm::utility::region::convertNumber<ConstantType>(storm::utility::region::getConstantPart(parModelEntry->getValue())));
} else { } else {
this->probabilityMapping.emplace_back(std::make_pair(&(tableEntry->second), sampleModelEntry)); this->probabilityMapping.emplace_back(std::make_pair(&(tableEntry->second), sampleModelEntry));
} }
@ -77,7 +78,7 @@ namespace storm {
} }
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::SamplingModel::initializeProbabilities(storm::models::sparse::Dtmc<ParametricType> const& parametricModel,
void SamplingModel<ParametricSparseModelType, ConstantType>::initializeProbabilities(ParametricSparseModelType const& parametricModel,
storm::storage::SparseMatrix<ConstantType>& probabilityMatrix, storm::storage::SparseMatrix<ConstantType>& probabilityMatrix,
std::vector<TableEntry*>& matrixEntryToEvalTableMapping, std::vector<TableEntry*>& matrixEntryToEvalTableMapping,
TableEntry* constantEntry) { TableEntry* constantEntry) {
@ -104,7 +105,7 @@ namespace storm {
} }
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::SamplingModel::initializeRewards(storm::models::sparse::Dtmc<ParametricType> const& parametricModel,
void SamplingModel<ParametricSparseModelType, ConstantType>::initializeRewards(ParametricSparseModelType const& parametricModel,
boost::optional<std::vector<ConstantType>>& stateRewards, boost::optional<std::vector<ConstantType>>& stateRewards,
std::vector<TableEntry*>& rewardEntryToEvalTableMapping, std::vector<TableEntry*>& rewardEntryToEvalTableMapping,
TableEntry* constantEntry) { TableEntry* constantEntry) {
@ -114,7 +115,7 @@ namespace storm {
std::size_t numOfNonConstEntries=0; std::size_t numOfNonConstEntries=0;
for(std::size_t state=0; state<parametricModel.getNumberOfStates(); ++state){ for(std::size_t state=0; state<parametricModel.getNumberOfStates(); ++state){
if(storm::utility::isConstant(parametricModel.getUniqueRewardModel()->second.getStateRewardVector()[state])){ if(storm::utility::isConstant(parametricModel.getUniqueRewardModel()->second.getStateRewardVector()[state])){
stateRewardsAsVector[state] = storm::utility::regions::convertNumber<ConstantType>(storm::utility::regions::getConstantPart(parametricModel.getUniqueRewardModel()->second.getStateRewardVector()[state]));
stateRewardsAsVector[state] = storm::utility::region::convertNumber<ConstantType>(storm::utility::region::getConstantPart(parametricModel.getUniqueRewardModel()->second.getStateRewardVector()[state]));
rewardEntryToEvalTableMapping.emplace_back(constantEntry); rewardEntryToEvalTableMapping.emplace_back(constantEntry);
} else { } else {
++numOfNonConstEntries; ++numOfNonConstEntries;
@ -127,25 +128,25 @@ namespace storm {
} }
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::SamplingModel::~SamplingModel() {
SamplingModel<ParametricSparseModelType, ConstantType>::~SamplingModel() {
//Intentionally left empty //Intentionally left empty
} }
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
std::shared_ptr<storm::models::sparse::Dtmc<ConstantType>> const& SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::SamplingModel::getModel() const {
std::shared_ptr<storm::models::sparse::Dtmc<ConstantType>> const& SamplingModel<ParametricSparseModelType, ConstantType>::getModel() const {
return this->model; return this->model;
} }
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::SamplingModel::instantiate(std::map<VariableType, CoefficientType>const& point) {
void SamplingModel<ParametricSparseModelType, ConstantType>::instantiate(std::map<VariableType, CoefficientType>const& point) {
//write entries into evaluation tables //write entries into evaluation tables
for(auto& tableEntry : this->probabilityEvaluationTable){ for(auto& tableEntry : this->probabilityEvaluationTable){
tableEntry.second=storm::utility::regions::convertNumber<ConstantType>(
storm::utility::regions::evaluateFunction(tableEntry.first, point));
tableEntry.second=storm::utility::region::convertNumber<ConstantType>(
storm::utility::region::evaluateFunction(tableEntry.first, point));
} }
for(auto& tableEntry : this->rewardEvaluationTable){ for(auto& tableEntry : this->rewardEvaluationTable){
tableEntry.second=storm::utility::regions::convertNumber<ConstantType>(
storm::utility::regions::evaluateFunction(tableEntry.first, point));
tableEntry.second=storm::utility::region::convertNumber<ConstantType>(
storm::utility::region::evaluateFunction(tableEntry.first, point));
} }
//write the instantiated values to the matrix according to the mappings //write the instantiated values to the matrix according to the mappings
@ -160,7 +161,7 @@ namespace storm {
} }
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
std::vector<ConstantType> const& SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::SamplingModel::computeValues() {
std::vector<ConstantType> const& SamplingModel<ParametricSparseModelType, ConstantType>::computeValues() {
storm::modelchecker::SparseDtmcPrctlModelChecker<storm::models::sparse::Dtmc<ConstantType>> modelChecker(*this->model); storm::modelchecker::SparseDtmcPrctlModelChecker<storm::models::sparse::Dtmc<ConstantType>> modelChecker(*this->model);
std::unique_ptr<storm::modelchecker::CheckResult> resultPtr; std::unique_ptr<storm::modelchecker::CheckResult> resultPtr;
//perform model checking on the dtmc //perform model checking on the dtmc
@ -174,7 +175,8 @@ namespace storm {
} }
#ifdef STORM_HAVE_CARL #ifdef STORM_HAVE_CARL
template class SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>;
template class SamplingModel<storm::models::sparse::Dtmc<storm::RationalFunction, storm::models::sparse::StandardRewardModel<storm::RationalFunction>>, double>;
#endif #endif
} //namespace region
} }
} }

26
src/modelchecker/region/SamplingModel.h

@ -9,27 +9,25 @@
#define STORM_MODELCHECKER_REGION_SAMPLINGMODEL_H #define STORM_MODELCHECKER_REGION_SAMPLINGMODEL_H
#include <unordered_map> #include <unordered_map>
#include <memory>
#include "src/modelchecker/region/SparseDtmcRegionModelChecker.h"
#include "src/utility/region.h"
#include "src/logic/Formulas.h"
#include "src/models/sparse/Dtmc.h" #include "src/models/sparse/Dtmc.h"
#include "src/storage/SparseMatrix.h" #include "src/storage/SparseMatrix.h"
namespace storm { namespace storm {
namespace modelchecker{ namespace modelchecker{
template<typename ParametricSparseModelType, typename ConstantType>
class SparseDtmcRegionModelChecker;
namespace region {
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
class SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::SamplingModel {
class SamplingModel {
public: public:
typedef typename ParametricSparseModelType::ValueType ParametricType; typedef typename ParametricSparseModelType::ValueType ParametricType;
typedef typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::VariableType VariableType;
typedef typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::CoefficientType CoefficientType;
typedef typename storm::utility::region::VariableType<ParametricType> VariableType;
typedef typename storm::utility::region::CoefficientType<ParametricType> CoefficientType;
SamplingModel(storm::models::sparse::Dtmc<ParametricType> const& parametricModel, std::shared_ptr<storm::logic::Formula> formula);
SamplingModel(ParametricSparseModelType const& parametricModel, std::shared_ptr<storm::logic::Formula> formula);
virtual ~SamplingModel(); virtual ~SamplingModel();
/*! /*!
@ -53,8 +51,8 @@ namespace storm {
typedef typename std::unordered_map<ParametricType, ConstantType>::value_type TableEntry; typedef typename std::unordered_map<ParametricType, ConstantType>::value_type TableEntry;
void initializeProbabilities(storm::models::sparse::Dtmc<ParametricType> const& parametricModel, storm::storage::SparseMatrix<ConstantType>& probabilityMatrix, std::vector<TableEntry*>& matrixEntryToEvalTableMapping, TableEntry* constantEntry);
void initializeRewards(storm::models::sparse::Dtmc<ParametricType> const& parametricModel, boost::optional<std::vector<ConstantType>>& stateRewards, std::vector<TableEntry*>& rewardEntryToEvalTableMapping, TableEntry* constantEntry);
void initializeProbabilities(ParametricSparseModelType const& parametricModel, storm::storage::SparseMatrix<ConstantType>& probabilityMatrix, std::vector<TableEntry*>& matrixEntryToEvalTableMapping, TableEntry* constantEntry);
void initializeRewards(ParametricSparseModelType const& parametricModel, boost::optional<std::vector<ConstantType>>& stateRewards, std::vector<TableEntry*>& rewardEntryToEvalTableMapping, TableEntry* constantEntry);
//The model with which we work //The model with which we work
std::shared_ptr<storm::models::sparse::Dtmc<ConstantType>> model; std::shared_ptr<storm::models::sparse::Dtmc<ConstantType>> model;
@ -77,7 +75,7 @@ namespace storm {
std::vector<std::pair<ConstantType*, typename std::vector<ConstantType>::iterator>> stateRewardMapping; std::vector<std::pair<ConstantType*, typename std::vector<ConstantType>::iterator>> stateRewardMapping;
}; };
} //namespace region
} }
} }
#endif /* STORM_MODELCHECKER_REGION_SAMPLINGMODEL_H */ #endif /* STORM_MODELCHECKER_REGION_SAMPLINGMODEL_H */

607
src/modelchecker/region/SparseDtmcRegionModelChecker.cpp

@ -1,20 +1,22 @@
#include "src/modelchecker/region/SparseDtmcRegionModelChecker.h" #include "src/modelchecker/region/SparseDtmcRegionModelChecker.h"
#include <chrono> #include <chrono>
#include <memory>
#include <boost/optional.hpp>
#include "src/adapters/CarlAdapter.h" #include "src/adapters/CarlAdapter.h"
#include "src/modelchecker/region/ParameterRegion.h"
#include "src/modelchecker/region/ApproximationModel.h"
#include "src/modelchecker/region/SamplingModel.h"
#include "src/logic/Formulas.h"
#include "src/modelchecker/results/ExplicitQualitativeCheckResult.h" #include "src/modelchecker/results/ExplicitQualitativeCheckResult.h"
#include "src/modelchecker/region/RegionCheckResult.h"
#include "src/models/sparse/StandardRewardModel.h" #include "src/models/sparse/StandardRewardModel.h"
#include "src/utility/graph.h"
#include "src/utility/vector.h"
#include "src/utility/macros.h"
#include "src/settings/SettingsManager.h" #include "src/settings/SettingsManager.h"
#include "src/settings/modules/RegionSettings.h" #include "src/settings/modules/RegionSettings.h"
#include "src/solver/OptimizationDirection.h"
#include "src/storage/sparse/StateType.h"
#include "src/utility/constants.h"
#include "src/utility/graph.h"
#include "src/utility/macros.h"
#include "src/utility/vector.h"
#include "src/exceptions/InvalidArgumentException.h" #include "src/exceptions/InvalidArgumentException.h"
#include "src/exceptions/InvalidPropertyException.h" #include "src/exceptions/InvalidPropertyException.h"
@ -22,19 +24,18 @@
#include "src/exceptions/InvalidSettingsException.h" #include "src/exceptions/InvalidSettingsException.h"
#include "src/exceptions/NotImplementedException.h" #include "src/exceptions/NotImplementedException.h"
#include "src/exceptions/UnexpectedException.h" #include "src/exceptions/UnexpectedException.h"
#include "exceptions/InvalidAccessException.h"
#include "exceptions/NotSupportedException.h"
namespace storm { namespace storm {
namespace modelchecker { namespace modelchecker {
namespace region {
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::SparseDtmcRegionModelChecker(storm::models::sparse::Dtmc<ParametricType> const& model) :
model(model),
eliminationModelChecker(model),
specifiedFormula(nullptr){
STORM_LOG_THROW(model.getInitialStates().getNumberOfSetBits() == 1, storm::exceptions::InvalidArgumentException, "Model is required to have exactly one initial state.");
SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::SparseDtmcRegionModelChecker(ParametricSparseModelType const& model) :
AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType>(model),
eliminationModelChecker(model){
//intentionally left empty
} }
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
@ -72,90 +73,33 @@ namespace storm {
} }
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::specifyFormula(std::shared_ptr<storm::logic::Formula> formula) {
std::chrono::high_resolution_clock::time_point timeSpecifyFormulaStart = std::chrono::high_resolution_clock::now();
STORM_LOG_THROW(this->canHandle(*formula), storm::exceptions::InvalidArgumentException, "Tried to specify a formula that can not be handled.");
//Note: canHandle already ensures that the formula has the right shape.
this->specifiedFormula = formula;
this->isResultConstant=false;
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::preprocess(std::shared_ptr<ParametricSparseModelType>& simpleModel, std::shared_ptr<storm::logic::Formula>& simpleFormula, bool& isApproximationApplicable, bool& isResultConstant){
STORM_LOG_THROW(this->getModel().getInitialStates().getNumberOfSetBits() == 1, storm::exceptions::InvalidArgumentException, "Input model is required to have exactly one initial state.");
//Reset some data
this->isResultInfinity=false; this->isResultInfinity=false;
this->simpleFormula=nullptr;
this->isApproximationApplicable=false;
this->smtSolver=nullptr; this->smtSolver=nullptr;
this->approximationModel=nullptr;
this->samplingModel=nullptr;
this->reachabilityFunction=nullptr; this->reachabilityFunction=nullptr;
// set some information regarding the formula and model. Also computes a more simple version of the model
preprocess();
if(!this->isResultConstant){
//now create the model used for Approximation (if required)
if(storm::settings::regionSettings().doApprox()){
initializeApproximationModel(*this->simpleModel, this->simpleFormula);
}
//now create the model used for Sampling (if required)
if(storm::settings::regionSettings().getSampleMode()==storm::settings::modules::RegionSettings::SampleMode::INSTANTIATE ||
(!storm::settings::regionSettings().doSample() && storm::settings::regionSettings().getApproxMode()==storm::settings::modules::RegionSettings::ApproxMode::TESTFIRST)){
initializeSamplingModel(*this->simpleModel, this->simpleFormula);
}
//Check if the reachability function needs to be computed
if((storm::settings::regionSettings().getSmtMode()==storm::settings::modules::RegionSettings::SmtMode::FUNCTION) ||
(storm::settings::regionSettings().getSampleMode()==storm::settings::modules::RegionSettings::SampleMode::EVALUATE)){
computeReachabilityFunction(*this->simpleModel);
}
} else {
//for a constant result we just compute the reachability function
if(this->reachabilityFunction==nullptr){
computeReachabilityFunction(*this->simpleModel);
}
}
//some information for statistics...
std::chrono::high_resolution_clock::time_point timeSpecifyFormulaEnd = std::chrono::high_resolution_clock::now();
this->timeSpecifyFormula= timeSpecifyFormulaEnd - timeSpecifyFormulaStart;
this->numOfCheckedRegions=0;
this->numOfRegionsSolvedThroughSampling=0;
this->numOfRegionsSolvedThroughApproximation=0;
this->numOfRegionsSolvedThroughFullSmt=0;
this->numOfRegionsExistsBoth=0;
this->numOfRegionsAllSat=0;
this->numOfRegionsAllViolated=0;
this->timeCheckRegion=std::chrono::high_resolution_clock::duration::zero();
this->timeSampling=std::chrono::high_resolution_clock::duration::zero();
this->timeApproximation=std::chrono::high_resolution_clock::duration::zero();
this->timeMDPBuild=std::chrono::high_resolution_clock::duration::zero();
this->timeFullSmt=std::chrono::high_resolution_clock::duration::zero();
}
template<typename ParametricSparseModelType, typename ConstantType>
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::preprocess(){
std::chrono::high_resolution_clock::time_point timePreprocessingStart = std::chrono::high_resolution_clock::now();
STORM_LOG_THROW(this->model.getInitialStates().getNumberOfSetBits() == 1, storm::exceptions::InvalidArgumentException, "Input model is required to have exactly one initial state.");
//first some preprocessing depending on the type of the considered formula
//Preprocessing depending on the type of the considered formula
storm::storage::BitVector maybeStates, targetStates; storm::storage::BitVector maybeStates, targetStates;
boost::optional<std::vector<ParametricType>> stateRewards; boost::optional<std::vector<ParametricType>> stateRewards;
if (this->specifiedFormula->isProbabilityOperatorFormula()) {
preprocessForProbabilities(maybeStates, targetStates);
}
else if (this->specifiedFormula->isRewardOperatorFormula()) {
if (this->isComputeRewards()) {
std::vector<ParametricType> stateRewardsAsVector; std::vector<ParametricType> stateRewardsAsVector;
preprocessForRewards(maybeStates, targetStates, stateRewardsAsVector);
preprocessForRewards(maybeStates, targetStates, stateRewardsAsVector, isApproximationApplicable, isResultConstant);
stateRewards=std::move(stateRewardsAsVector); stateRewards=std::move(stateRewardsAsVector);
}
else {
STORM_LOG_THROW(false, storm::exceptions::InvalidPropertyException, "The specified property " << this->specifiedFormula << "is not supported");
} else {
preprocessForProbabilities(maybeStates, targetStates, isApproximationApplicable, isResultConstant);
} }
// Determine the set of states that is reachable from the initial state without jumping over a target state. // Determine the set of states that is reachable from the initial state without jumping over a target state.
storm::storage::BitVector reachableStates = storm::utility::graph::getReachableStates(this->model.getTransitionMatrix(), this->model.getInitialStates(), maybeStates, targetStates);
storm::storage::BitVector reachableStates = storm::utility::graph::getReachableStates(this->getModel().getTransitionMatrix(), this->getModel().getInitialStates(), maybeStates, targetStates);
// Subtract from the maybe states the set of states that is not reachable (on a path from the initial to a target state). // Subtract from the maybe states the set of states that is not reachable (on a path from the initial to a target state).
maybeStates &= reachableStates; maybeStates &= reachableStates;
// Create a vector for the probabilities to go to a target state in one step. // Create a vector for the probabilities to go to a target state in one step.
std::vector<ParametricType> oneStepProbabilities = this->model.getTransitionMatrix().getConstrainedRowSumVector(maybeStates, targetStates);
std::vector<ParametricType> oneStepProbabilities = this->getModel().getTransitionMatrix().getConstrainedRowSumVector(maybeStates, targetStates);
// Determine the initial state of the sub-model. // Determine the initial state of the sub-model.
storm::storage::sparse::state_type initialState = *(this->model.getInitialStates() % maybeStates).begin();
storm::storage::sparse::state_type initialState = *(this->getModel().getInitialStates() % maybeStates).begin();
// We then build the submatrix that only has the transitions of the maybe states. // We then build the submatrix that only has the transitions of the maybe states.
storm::storage::SparseMatrix<ParametricType> submatrix = this->model.getTransitionMatrix().getSubmatrix(false, maybeStates, maybeStates);
storm::storage::SparseMatrix<ParametricType> submatrix = this->getModel().getTransitionMatrix().getSubmatrix(false, maybeStates, maybeStates);
// Eliminate all states with only constant outgoing transitions // Eliminate all states with only constant outgoing transitions
// Convert the reduced matrix to a more flexible format to be able to perform state elimination more easily. // Convert the reduced matrix to a more flexible format to be able to perform state elimination more easily.
auto flexibleTransitions = this->eliminationModelChecker.getFlexibleSparseMatrix(submatrix); auto flexibleTransitions = this->eliminationModelChecker.getFlexibleSparseMatrix(submatrix);
@ -176,18 +120,18 @@ namespace storm {
if(!storm::utility::isConstant(oneStepProbabilities[state])){ if(!storm::utility::isConstant(oneStepProbabilities[state])){
eliminateThisState=false; eliminateThisState=false;
} }
if(this->computeRewards && eliminateThisState && !storm::utility::isConstant(stateRewards.get()[state])){
if(this->isComputeRewards() && eliminateThisState && !storm::utility::isConstant(stateRewards.get()[state])){
//Note: The state reward does not need to be constant but we need to make sure that //Note: The state reward does not need to be constant but we need to make sure that
//no parameter of this reward function occurs as a parameter in the probability functions of the predecessors //no parameter of this reward function occurs as a parameter in the probability functions of the predecessors
// (otherwise, more complex functions might occur in our simple model) // (otherwise, more complex functions might occur in our simple model)
std::set<VariableType> probVars; std::set<VariableType> probVars;
for(auto const& predecessor : flexibleBackwardTransitions.getRow(state)){ for(auto const& predecessor : flexibleBackwardTransitions.getRow(state)){
for(auto const& predecessorTransition : flexibleTransitions.getRow(predecessor.getColumn())){ for(auto const& predecessorTransition : flexibleTransitions.getRow(predecessor.getColumn())){
storm::utility::regions::gatherOccurringVariables(predecessorTransition.getValue(), probVars);
storm::utility::region::gatherOccurringVariables(predecessorTransition.getValue(), probVars);
} }
} }
std::set<VariableType> rewardVars; std::set<VariableType> rewardVars;
storm::utility::regions::gatherOccurringVariables(stateRewards.get()[state], rewardVars);
storm::utility::region::gatherOccurringVariables(stateRewards.get()[state], rewardVars);
for(auto const& rewardVar : rewardVars){ for(auto const& rewardVar : rewardVars){
if(probVars.find(rewardVar)!=probVars.end()){ if(probVars.find(rewardVar)!=probVars.end()){
eliminateThisState=false; eliminateThisState=false;
@ -218,14 +162,14 @@ namespace storm {
//We can now fill in the data. //We can now fill in the data.
storm::storage::SparseMatrixBuilder<ParametricType> matrixBuilder(numStates, numStates); storm::storage::SparseMatrixBuilder<ParametricType> matrixBuilder(numStates, numStates);
for(storm::storage::sparse::state_type oldStateIndex : subsystem){ for(storm::storage::sparse::state_type oldStateIndex : subsystem){
ParametricType missingProbability=storm::utility::regions::getNewFunction<ParametricType, CoefficientType>(storm::utility::one<CoefficientType>());
ParametricType missingProbability=storm::utility::region::getNewFunction<ParametricType, CoefficientType>(storm::utility::one<CoefficientType>());
//go through columns: //go through columns:
for(auto& entry: flexibleTransitions.getRow(oldStateIndex)){ for(auto& entry: flexibleTransitions.getRow(oldStateIndex)){
STORM_LOG_THROW(newStateIndexMap[entry.getColumn()]!=flexibleTransitions.getNumberOfRows(), storm::exceptions::UnexpectedException, "There is a transition to a state that should have been eliminated."); STORM_LOG_THROW(newStateIndexMap[entry.getColumn()]!=flexibleTransitions.getNumberOfRows(), storm::exceptions::UnexpectedException, "There is a transition to a state that should have been eliminated.");
missingProbability-=entry.getValue(); missingProbability-=entry.getValue();
matrixBuilder.addNextValue(newStateIndexMap[oldStateIndex],newStateIndexMap[entry.getColumn()], storm::utility::simplify(entry.getValue())); matrixBuilder.addNextValue(newStateIndexMap[oldStateIndex],newStateIndexMap[entry.getColumn()], storm::utility::simplify(entry.getValue()));
} }
if(this->computeRewards){
if(this->isComputeRewards()){
// the missing probability always leads to target // the missing probability always leads to target
if(!storm::utility::isZero(missingProbability)){ if(!storm::utility::isZero(missingProbability)){
matrixBuilder.addNextValue(newStateIndexMap[oldStateIndex], targetState, storm::utility::simplify(missingProbability)); matrixBuilder.addNextValue(newStateIndexMap[oldStateIndex], targetState, storm::utility::simplify(missingProbability));
@ -257,8 +201,8 @@ namespace storm {
sinkLabel.set(sinkState, true); sinkLabel.set(sinkState, true);
labeling.addLabel("sink", std::move(sinkLabel)); labeling.addLabel("sink", std::move(sinkLabel));
// other ingredients // other ingredients
std::unordered_map<std::string, storm::models::sparse::StandardRewardModel<ParametricType>> rewardModels;
if(this->computeRewards){
std::unordered_map<std::string, ParametricRewardModelType> rewardModels;
if(this->isComputeRewards()){
std::size_t newState = 0; std::size_t newState = 0;
for (auto oldstate : subsystem) { for (auto oldstate : subsystem) {
if(oldstate!=newState){ if(oldstate!=newState){
@ -270,98 +214,89 @@ namespace storm {
stateRewards.get()[newState++] = storm::utility::zero<ParametricType>(); //target state stateRewards.get()[newState++] = storm::utility::zero<ParametricType>(); //target state
stateRewards.get()[newState++] = storm::utility::zero<ParametricType>(); //sink state stateRewards.get()[newState++] = storm::utility::zero<ParametricType>(); //sink state
stateRewards.get().resize(newState); stateRewards.get().resize(newState);
rewardModels.insert(std::pair<std::string, storm::models::sparse::StandardRewardModel<ParametricType>>("", storm::models::sparse::StandardRewardModel<ParametricType>(std::move(stateRewards))));
rewardModels.insert(std::pair<std::string, ParametricRewardModelType>("", ParametricRewardModelType(std::move(stateRewards))));
} }
boost::optional<std::vector<boost::container::flat_set<uint_fast64_t>>> noChoiceLabeling; boost::optional<std::vector<boost::container::flat_set<uint_fast64_t>>> noChoiceLabeling;
// the final model // the final model
this->simpleModel = std::make_shared<storm::models::sparse::Dtmc<ParametricType>>(matrixBuilder.build(), std::move(labeling), std::move(rewardModels), std::move(noChoiceLabeling));
simpleModel = std::make_shared<ParametricSparseModelType>(matrixBuilder.build(), std::move(labeling), std::move(rewardModels), std::move(noChoiceLabeling));
// the corresponding formula // the corresponding formula
std::shared_ptr<storm::logic::Formula> targetFormulaPtr(new storm::logic::AtomicLabelFormula("target")); std::shared_ptr<storm::logic::Formula> targetFormulaPtr(new storm::logic::AtomicLabelFormula("target"));
if(this->computeRewards){
this->simpleFormula = std::shared_ptr<storm::logic::Formula>(new storm::logic::ReachabilityRewardFormula(targetFormulaPtr));
if(this->isComputeRewards()){
simpleFormula = std::shared_ptr<storm::logic::Formula>(new storm::logic::ReachabilityRewardFormula(targetFormulaPtr));
} else { } else {
this->simpleFormula = std::shared_ptr<storm::logic::Formula>(new storm::logic::EventuallyFormula(targetFormulaPtr));
simpleFormula = std::shared_ptr<storm::logic::Formula>(new storm::logic::EventuallyFormula(targetFormulaPtr));
}
//Check if the reachability function needs to be computed
if((isResultConstant && this->reachabilityFunction==nullptr) || //If the result is constant, we can already compute it now.
(storm::settings::regionSettings().getSmtMode()==storm::settings::modules::RegionSettings::SmtMode::FUNCTION) || //The smt solver will need it
(storm::settings::regionSettings().getSampleMode()==storm::settings::modules::RegionSettings::SampleMode::EVALUATE)){ //The sampling will need it
this->computeReachabilityFunction(*simpleModel);
} }
std::chrono::high_resolution_clock::time_point timePreprocessingEnd = std::chrono::high_resolution_clock::now();
this->timePreprocessing = timePreprocessingEnd - timePreprocessingStart;
} }
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::preprocessForProbabilities(storm::storage::BitVector& maybeStates, storm::storage::BitVector& targetStates) {
this->computeRewards=false;
//Get bounds, comparison type, target states
storm::logic::ProbabilityOperatorFormula const& probabilityOperatorFormula = this->specifiedFormula->asProbabilityOperatorFormula();
this->specifiedFormulaCompType=probabilityOperatorFormula.getComparisonType();
this->specifiedFormulaBound=probabilityOperatorFormula.getBound();
storm::modelchecker::SparsePropositionalModelChecker<storm::models::sparse::Dtmc<ParametricType>> modelChecker(this->model);
std::unique_ptr<CheckResult> targetStatesResultPtr= modelChecker.checkAtomicLabelFormula(probabilityOperatorFormula.getSubformula().asEventuallyFormula().getSubformula().asAtomicLabelFormula());
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::preprocessForProbabilities(storm::storage::BitVector& maybeStates, storm::storage::BitVector& targetStates, bool& isApproximationApplicable /* = 0 */, bool& isResultConstant /* = 0 */) {
//Get Target States
storm::logic::AtomicLabelFormula const& labelFormula = this->getSpecifiedFormula()->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula().getSubformula().asAtomicLabelFormula();
storm::modelchecker::SparsePropositionalModelChecker<ParametricSparseModelType> modelChecker(this->getModel());
std::unique_ptr<CheckResult> targetStatesResultPtr = modelChecker.checkAtomicLabelFormula(labelFormula);
targetStates = std::move(targetStatesResultPtr->asExplicitQualitativeCheckResult().getTruthValuesVector()); targetStates = std::move(targetStatesResultPtr->asExplicitQualitativeCheckResult().getTruthValuesVector());
//maybeStates: Compute the subset of states that have a probability of 0 or 1, respectively and reduce the considered states accordingly. //maybeStates: Compute the subset of states that have a probability of 0 or 1, respectively and reduce the considered states accordingly.
std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01 = storm::utility::graph::performProb01(this->model, storm::storage::BitVector(this->model.getNumberOfStates(),true), targetStates);
std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01 = storm::utility::graph::performProb01(this->getModel(), storm::storage::BitVector(this->getModel().getNumberOfStates(),true), targetStates);
maybeStates = ~(statesWithProbability01.first | statesWithProbability01.second); maybeStates = ~(statesWithProbability01.first | statesWithProbability01.second);
// If the initial state is known to have either probability 0 or 1, we can directly set the reachProbFunction. // If the initial state is known to have either probability 0 or 1, we can directly set the reachProbFunction.
storm::storage::sparse::state_type initialState = *this->model.getInitialStates().begin();
storm::storage::sparse::state_type initialState = *this->getModel().getInitialStates().begin();
if (!maybeStates.get(initialState)) { if (!maybeStates.get(initialState)) {
STORM_LOG_WARN("The probability of the initial state is constant (zero or one)"); STORM_LOG_WARN("The probability of the initial state is constant (zero or one)");
this->reachabilityFunction = std::make_shared<ParametricType>(statesWithProbability01.first.get(initialState) ? storm::utility::zero<ParametricType>() : storm::utility::one<ParametricType>()); this->reachabilityFunction = std::make_shared<ParametricType>(statesWithProbability01.first.get(initialState) ? storm::utility::zero<ParametricType>() : storm::utility::one<ParametricType>());
this->isResultConstant=true;
isResultConstant=true;
return; //nothing else to do... return; //nothing else to do...
} }
//extend target states //extend target states
targetStates=statesWithProbability01.second; targetStates=statesWithProbability01.second;
//check if approximation is applicable and whether the result is constant //check if approximation is applicable and whether the result is constant
this->isApproximationApplicable=true;
this->isResultConstant=true;
for (auto state=maybeStates.begin(); (state!=maybeStates.end()) && this->isApproximationApplicable; ++state) {
for(auto const& entry : this->model.getTransitionMatrix().getRow(*state)){
isApproximationApplicable=true;
isResultConstant=true;
for (auto state=maybeStates.begin(); (state!=maybeStates.end()) && isApproximationApplicable; ++state) {
for(auto const& entry : this->getModel().getTransitionMatrix().getRow(*state)){
if(!storm::utility::isConstant(entry.getValue())){ if(!storm::utility::isConstant(entry.getValue())){
this->isResultConstant=false;
if(!storm::utility::regions::functionIsLinear(entry.getValue())){
this->isApproximationApplicable=false;
isResultConstant=false;
if(!storm::utility::region::functionIsLinear(entry.getValue())){
isApproximationApplicable=false;
break; break;
} }
} }
} }
} }
STORM_LOG_WARN_COND(!this->isResultConstant, "For the given property, the reachability Value is constant, i.e., independent of the region");
STORM_LOG_WARN_COND(!isResultConstant, "For the given property, the reachability Value is constant, i.e., independent of the region");
} }
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::preprocessForRewards(storm::storage::BitVector& maybeStates, storm::storage::BitVector& targetStates, std::vector<ParametricType>& stateRewards) {
this->computeRewards=true;
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::preprocessForRewards(storm::storage::BitVector& maybeStates, storm::storage::BitVector& targetStates, std::vector<ParametricType>& stateRewards, bool& isApproximationApplicable /* = true */, bool& isResultConstant /* = false */) {
//get the correct reward model //get the correct reward model
storm::models::sparse::StandardRewardModel<ParametricType> const* rewardModel;
if(this->specifiedFormula->asRewardOperatorFormula().hasRewardModelName()){
std::string const& rewardModelName = this->specifiedFormula->asRewardOperatorFormula().getRewardModelName();
STORM_LOG_THROW(this->model.hasRewardModel(rewardModelName), storm::exceptions::InvalidPropertyException, "The Property specifies refers to the reward model '" << rewardModelName << "which is not defined by the given model");
rewardModel=&(this->model.getRewardModel(rewardModelName));
ParametricRewardModelType const* rewardModel;
if(this->getSpecifiedFormula()->asRewardOperatorFormula().hasRewardModelName()){
std::string const& rewardModelName = this->getSpecifiedFormula()->asRewardOperatorFormula().getRewardModelName();
STORM_LOG_THROW(this->getModel().hasRewardModel(rewardModelName), storm::exceptions::InvalidPropertyException, "The Property specifies refers to the reward model '" << rewardModelName << "which is not defined by the given model");
rewardModel=&(this->getModel().getRewardModel(rewardModelName));
} else { } else {
STORM_LOG_THROW(this->model.hasRewardModel(), storm::exceptions::InvalidArgumentException, "No reward model specified");
STORM_LOG_THROW(this->model.hasUniqueRewardModel(), storm::exceptions::InvalidArgumentException, "Ambiguous reward model. Specify it in the formula!");
rewardModel=&(this->model.getUniqueRewardModel()->second);
}
//Get bounds, comparison type, target states
storm::logic::RewardOperatorFormula const& rewardOperatorFormula = this->specifiedFormula->asRewardOperatorFormula();
this->specifiedFormulaCompType=rewardOperatorFormula.getComparisonType();
this->specifiedFormulaBound=rewardOperatorFormula.getBound();
storm::modelchecker::SparsePropositionalModelChecker<storm::models::sparse::Dtmc<ParametricType>> modelChecker(this->model);
std::unique_ptr<CheckResult> targetStatesResultPtr= modelChecker.checkAtomicLabelFormula(rewardOperatorFormula.getSubformula().asReachabilityRewardFormula().getSubformula().asAtomicLabelFormula());
STORM_LOG_THROW(this->getModel().hasRewardModel(), storm::exceptions::InvalidArgumentException, "No reward model specified");
STORM_LOG_THROW(this->getModel().hasUniqueRewardModel(), storm::exceptions::InvalidArgumentException, "Ambiguous reward model. Specify it in the formula!");
rewardModel=&(this->getModel().getUniqueRewardModel()->second);
}
//Get target states
storm::logic::AtomicLabelFormula const& labelFormula = this->getSpecifiedFormula()->asRewardOperatorFormula().getSubformula().asReachabilityRewardFormula().getSubformula().asAtomicLabelFormula();
storm::modelchecker::SparsePropositionalModelChecker<ParametricSparseModelType> modelChecker(this->getModel());
std::unique_ptr<CheckResult> targetStatesResultPtr= modelChecker.checkAtomicLabelFormula(labelFormula);
targetStates = std::move(targetStatesResultPtr->asExplicitQualitativeCheckResult().getTruthValuesVector()); targetStates = std::move(targetStatesResultPtr->asExplicitQualitativeCheckResult().getTruthValuesVector());
//maybeStates: Compute the subset of states that has a reachability reward less than infinity. //maybeStates: Compute the subset of states that has a reachability reward less than infinity.
storm::storage::BitVector statesWithProbability1 = storm::utility::graph::performProb1(this->model.getBackwardTransitions(), storm::storage::BitVector(this->model.getNumberOfStates(), true), targetStates);
storm::storage::BitVector statesWithProbability1 = storm::utility::graph::performProb1(this->getModel().getBackwardTransitions(), storm::storage::BitVector(this->getModel().getNumberOfStates(), true), targetStates);
maybeStates = ~targetStates & statesWithProbability1; maybeStates = ~targetStates & statesWithProbability1;
//Compute the new state reward vector //Compute the new state reward vector
stateRewards=rewardModel->getTotalRewardVector(maybeStates.getNumberOfSetBits(), this->model.getTransitionMatrix(), maybeStates);
stateRewards=rewardModel->getTotalRewardVector(maybeStates.getNumberOfSetBits(), this->getModel().getTransitionMatrix(), maybeStates);
// If the initial state is known to have 0 reward or an infinite reachability reward value, we can directly set the reachRewardFunction. // If the initial state is known to have 0 reward or an infinite reachability reward value, we can directly set the reachRewardFunction.
storm::storage::sparse::state_type initialState = *this->model.getInitialStates().begin();
storm::storage::sparse::state_type initialState = *this->getModel().getInitialStates().begin();
if (!maybeStates.get(initialState)) { if (!maybeStates.get(initialState)) {
STORM_LOG_WARN("The expected reward of the initial state is constant (infinity or zero)"); STORM_LOG_WARN("The expected reward of the initial state is constant (infinity or zero)");
if(statesWithProbability1.get(initialState)){ if(statesWithProbability1.get(initialState)){
@ -370,46 +305,45 @@ namespace storm {
this->reachabilityFunction = std::make_shared<ParametricType>(storm::utility::one<ParametricType>()); this->reachabilityFunction = std::make_shared<ParametricType>(storm::utility::one<ParametricType>());
this->isResultInfinity=true; this->isResultInfinity=true;
} }
this->isResultConstant=true;
isResultConstant=true;
return; //nothing else to do... return; //nothing else to do...
} }
//check if approximation is applicable and whether the result is constant //check if approximation is applicable and whether the result is constant
this->isApproximationApplicable=true;
this->isResultConstant=true;
isApproximationApplicable=true;
isResultConstant=true;
std::set<VariableType> rewardPars; //the set of parameters that occur on a reward function std::set<VariableType> rewardPars; //the set of parameters that occur on a reward function
std::set<VariableType> probPars; //the set of parameters that occur on a probability function std::set<VariableType> probPars; //the set of parameters that occur on a probability function
for (auto state=maybeStates.begin(); state!=maybeStates.end() && this->isApproximationApplicable; ++state) {
for (auto state=maybeStates.begin(); state!=maybeStates.end() && isApproximationApplicable; ++state) {
//Constant/Linear probability functions //Constant/Linear probability functions
for(auto const& entry : this->model.getTransitionMatrix().getRow(*state)){
for(auto const& entry : this->getModel().getTransitionMatrix().getRow(*state)){
if(!storm::utility::isConstant(entry.getValue())){ if(!storm::utility::isConstant(entry.getValue())){
this->isResultConstant=false;
if(!storm::utility::regions::functionIsLinear(entry.getValue())){
this->isApproximationApplicable=false;
isResultConstant=false;
if(!storm::utility::region::functionIsLinear(entry.getValue())){
isApproximationApplicable=false;
break; break;
} }
storm::utility::regions::gatherOccurringVariables(entry.getValue(), probPars);
storm::utility::region::gatherOccurringVariables(entry.getValue(), probPars);
} }
} }
//Constant/Linear state rewards //Constant/Linear state rewards
if(rewardModel->hasStateRewards() && !storm::utility::isConstant(rewardModel->getStateRewardVector()[*state])){ if(rewardModel->hasStateRewards() && !storm::utility::isConstant(rewardModel->getStateRewardVector()[*state])){
this->isResultConstant=false;
if(!storm::utility::regions::functionIsLinear(rewardModel->getStateRewardVector()[*state])){
this->isApproximationApplicable=false;
isResultConstant=false;
if(!storm::utility::region::functionIsLinear(rewardModel->getStateRewardVector()[*state])){
isApproximationApplicable=false;
break; break;
} }
storm::utility::regions::gatherOccurringVariables(rewardModel->getStateRewardVector()[*state], rewardPars);
storm::utility::region::gatherOccurringVariables(rewardModel->getStateRewardVector()[*state], rewardPars);
} }
//Constant/Linear transition rewards //Constant/Linear transition rewards
if(rewardModel->hasTransitionRewards()){ if(rewardModel->hasTransitionRewards()){
for(auto const& entry : rewardModel->getTransitionRewardMatrix().getRow(*state)) { for(auto const& entry : rewardModel->getTransitionRewardMatrix().getRow(*state)) {
if(!storm::utility::isConstant(entry.getValue())){ if(!storm::utility::isConstant(entry.getValue())){
this->isResultConstant=false;
if(!storm::utility::regions::functionIsLinear(entry.getValue())){
this->isApproximationApplicable=false;
isResultConstant=false;
if(!storm::utility::region::functionIsLinear(entry.getValue())){
isApproximationApplicable=false;
break; break;
} }
storm::utility::regions::gatherOccurringVariables(entry.getValue(), rewardPars);
storm::utility::region::gatherOccurringVariables(entry.getValue(), rewardPars);
} }
} }
} }
@ -419,35 +353,15 @@ namespace storm {
//This is to avoid getting functions with local maxima like p * (1-p) //This is to avoid getting functions with local maxima like p * (1-p)
for(auto const& rewardVar : rewardPars){ for(auto const& rewardVar : rewardPars){
if(probPars.find(rewardVar)!=probPars.end()){ if(probPars.find(rewardVar)!=probPars.end()){
this->isApproximationApplicable=false;
isApproximationApplicable=false;
break; break;
} }
} }
STORM_LOG_WARN_COND(!this->isResultConstant, "For the given property, the reachability Value is constant, i.e., independent of the region");
STORM_LOG_WARN_COND(!isResultConstant, "For the given property, the reachability Value is constant, i.e., independent of the region");
} }
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::initializeApproximationModel(storm::models::sparse::Dtmc<ParametricType> const& model, std::shared_ptr<storm::logic::Formula> formula) {
std::chrono::high_resolution_clock::time_point timeInitApproxModelStart = std::chrono::high_resolution_clock::now();
this->approximationModel=std::make_shared<ApproximationModel>(model, formula);
std::chrono::high_resolution_clock::time_point timeInitApproxModelEnd = std::chrono::high_resolution_clock::now();
this->timeInitApproxModel=timeInitApproxModelEnd - timeInitApproxModelStart;
STORM_LOG_DEBUG("Initialized Approximation Model");
}
template<typename ParametricSparseModelType, typename ConstantType>
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::initializeSamplingModel(storm::models::sparse::Dtmc<ParametricType> const& model, std::shared_ptr<storm::logic::Formula> formula) {
std::chrono::high_resolution_clock::time_point timeInitSamplingModelStart = std::chrono::high_resolution_clock::now();
this->samplingModel=std::make_shared<SamplingModel>(model, formula);
std::chrono::high_resolution_clock::time_point timeInitSamplingModelEnd = std::chrono::high_resolution_clock::now();
this->timeInitSamplingModel = timeInitSamplingModelEnd - timeInitSamplingModelStart;
STORM_LOG_DEBUG("Initialized Sampling Model");
}
template<typename ParametricSparseModelType, typename ConstantType>
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::computeReachabilityFunction(storm::models::sparse::Dtmc<ParametricType> const& simpleModel){
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::computeReachabilityFunction(ParametricSparseModelType const& simpleModel){
std::chrono::high_resolution_clock::time_point timeComputeReachabilityFunctionStart = std::chrono::high_resolution_clock::now(); std::chrono::high_resolution_clock::time_point timeComputeReachabilityFunctionStart = std::chrono::high_resolution_clock::now();
//get the one step probabilities and the transition matrix of the simple model without target/sink state //get the one step probabilities and the transition matrix of the simple model without target/sink state
storm::storage::SparseMatrix<ParametricType> backwardTransitions(simpleModel.getBackwardTransitions()); storm::storage::SparseMatrix<ParametricType> backwardTransitions(simpleModel.getBackwardTransitions());
@ -464,7 +378,7 @@ namespace storm {
storm::storage::BitVector newInitialStates = simpleModel.getInitialStates() % maybeStates; storm::storage::BitVector newInitialStates = simpleModel.getInitialStates() % maybeStates;
storm::storage::BitVector phiStates(simpleModel.getNumberOfStates(), true); storm::storage::BitVector phiStates(simpleModel.getNumberOfStates(), true);
boost::optional<std::vector<ParametricType>> stateRewards; boost::optional<std::vector<ParametricType>> stateRewards;
if(this->computeRewards){
if(this->isComputeRewards()){
stateRewards = simpleModel.getUniqueRewardModel()->second.getTotalRewardVector(maybeStates.getNumberOfSetBits(), simpleModel.getTransitionMatrix(), maybeStates); stateRewards = simpleModel.getUniqueRewardModel()->second.getTotalRewardVector(maybeStates.getNumberOfSetBits(), simpleModel.getTransitionMatrix(), maybeStates);
} }
std::vector<std::size_t> statePriorities = this->eliminationModelChecker.getStatePriorities(forwardTransitions,backwardTransitions,newInitialStates,oneStepProbabilities); std::vector<std::size_t> statePriorities = this->eliminationModelChecker.getStatePriorities(forwardTransitions,backwardTransitions,newInitialStates,oneStepProbabilities);
@ -480,118 +394,13 @@ namespace storm {
} }
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::checkRegions(std::vector<ParameterRegion>& regions) {
STORM_LOG_DEBUG("Checking " << regions.size() << "regions.");
std::cout << "Checking " << regions.size() << " regions. Progress: ";
std::cout.flush();
uint_fast64_t progress=0;
uint_fast64_t checkedRegions=0;
for(auto& region : regions){
checkRegion(region);
if((checkedRegions++)*10/regions.size()==progress){
std::cout << progress++;
std::cout.flush();
}
}
std::cout << " done!" << std::endl;
}
template<typename ParametricSparseModelType, typename ConstantType>
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::checkRegion(ParameterRegion& region) {
std::chrono::high_resolution_clock::time_point timeCheckRegionStart = std::chrono::high_resolution_clock::now();
++this->numOfCheckedRegions;
STORM_LOG_THROW(this->specifiedFormula!=nullptr, storm::exceptions::InvalidStateException, "Tried to analyze a region although no property has been specified" );
STORM_LOG_DEBUG("Analyzing the region " << region.toString());
//std::cout << "Analyzing the region " << region.toString() << std::endl;
//switches for the different steps.
bool done=false;
STORM_LOG_WARN_COND( (!storm::settings::regionSettings().doApprox() || this->isApproximationApplicable), "the approximation is only correct if the model has only linear functions. As this is not the case, approximation is deactivated");
bool doApproximation=storm::settings::regionSettings().doApprox() && this->isApproximationApplicable;
bool doSampling=storm::settings::regionSettings().doSample();
bool doFullSmt=storm::settings::regionSettings().doSmt();
if(!done && this->isResultConstant){
STORM_LOG_DEBUG("Checking a region although the result is constant, i.e., independent of the region. This makes sense none.");
if(valueIsInBoundOfFormula(this->getReachabilityValue<ConstantType>(region.getSomePoint(), true))){
region.setCheckResult(RegionCheckResult::ALLSAT);
}
else{
region.setCheckResult(RegionCheckResult::ALLVIOLATED);
}
done=true;
}
std::chrono::high_resolution_clock::time_point timeApproximationStart = std::chrono::high_resolution_clock::now();
std::vector<ConstantType> lowerBounds;
std::vector<ConstantType> upperBounds;
if(!done && doApproximation){
STORM_LOG_DEBUG("Checking approximative values...");
if(checkApproximativeValues(region, lowerBounds, upperBounds)){
++this->numOfRegionsSolvedThroughApproximation;
STORM_LOG_DEBUG("Result '" << region.checkResultToString() <<"' obtained through approximation.");
done=true;
}
}
std::chrono::high_resolution_clock::time_point timeApproximationEnd = std::chrono::high_resolution_clock::now();
std::chrono::high_resolution_clock::time_point timeSamplingStart = std::chrono::high_resolution_clock::now();
if(!done && doSampling){
STORM_LOG_DEBUG("Checking sample points...");
if(checkSamplePoints(region)){
++this->numOfRegionsSolvedThroughSampling;
STORM_LOG_DEBUG("Result '" << region.checkResultToString() <<"' obtained through sampling.");
done=true;
}
}
std::chrono::high_resolution_clock::time_point timeSamplingEnd = std::chrono::high_resolution_clock::now();
std::chrono::high_resolution_clock::time_point timeFullSmtStart = std::chrono::high_resolution_clock::now();
if(!done && doFullSmt){
STORM_LOG_DEBUG("Checking with Smt Solving...");
if(checkFullSmt(region)){
++this->numOfRegionsSolvedThroughFullSmt;
STORM_LOG_DEBUG("Result '" << region.checkResultToString() <<"' obtained through Smt Solving.");
done=true;
}
}
std::chrono::high_resolution_clock::time_point timeFullSmtEnd = std::chrono::high_resolution_clock::now();
//some information for statistics...
std::chrono::high_resolution_clock::time_point timeCheckRegionEnd = std::chrono::high_resolution_clock::now();
this->timeCheckRegion += timeCheckRegionEnd-timeCheckRegionStart;
this->timeSampling += timeSamplingEnd - timeSamplingStart;
this->timeApproximation += timeApproximationEnd - timeApproximationStart;
this->timeFullSmt += timeFullSmtEnd - timeFullSmtStart;
switch(region.getCheckResult()){
case RegionCheckResult::EXISTSBOTH:
++this->numOfRegionsExistsBoth;
break;
case RegionCheckResult::ALLSAT:
++this->numOfRegionsAllSat;
break;
case RegionCheckResult::ALLVIOLATED:
++this->numOfRegionsAllViolated;
break;
default:
break;
}
}
template<typename ParametricSparseModelType, typename ConstantType>
bool SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::checkApproximativeValues(ParameterRegion& region, std::vector<ConstantType>& lowerBounds, std::vector<ConstantType>& upperBounds) {
STORM_LOG_THROW(this->isApproximationApplicable, storm::exceptions::UnexpectedException, "Tried to perform approximative method (only applicable if all functions are linear), but there are nonlinear functions.");
bool SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::checkApproximativeValues(ParameterRegion<ParametricType>& region, std::vector<ConstantType>& lowerBounds, std::vector<ConstantType>& upperBounds) {
std::chrono::high_resolution_clock::time_point timeMDPBuildStart = std::chrono::high_resolution_clock::now(); std::chrono::high_resolution_clock::time_point timeMDPBuildStart = std::chrono::high_resolution_clock::now();
getApproximationModel()->instantiate(region);
this->getApproximationModel()->instantiate(region);
std::chrono::high_resolution_clock::time_point timeMDPBuildEnd = std::chrono::high_resolution_clock::now(); std::chrono::high_resolution_clock::time_point timeMDPBuildEnd = std::chrono::high_resolution_clock::now();
this->timeMDPBuild += timeMDPBuildEnd-timeMDPBuildStart;
this->timeApproxModelInstantiation += timeMDPBuildEnd-timeMDPBuildStart;
// Decide whether the formula has an upper or a lower bond ({<, <=} or {>, >=}) and whether to prove allsat or allviolated. (Hence, there are 4 cases)
bool formulaHasUpperBound = this->specifiedFormulaCompType==storm::logic::ComparisonType::Less || this->specifiedFormulaCompType==storm::logic::ComparisonType::LessEqual;
STORM_LOG_THROW((formulaHasUpperBound != (this->specifiedFormulaCompType==storm::logic::ComparisonType::Greater || this->specifiedFormulaCompType==storm::logic::ComparisonType::GreaterEqual)),
storm::exceptions::UnexpectedException, "Unexpected comparison Type of formula");
// Decide whether to prove allsat or allviolated. (Hence, there are 4 cases)
bool proveAllSat; bool proveAllSat;
switch (region.getCheckResult()){ switch (region.getCheckResult()){
case RegionCheckResult::UNKNOWN: case RegionCheckResult::UNKNOWN:
@ -629,17 +438,17 @@ namespace storm {
} }
bool formulaSatisfied; bool formulaSatisfied;
if((formulaHasUpperBound && proveAllSat) || (!formulaHasUpperBound && !proveAllSat)){
if((this->specifiedFormulaHasUpperBound() && proveAllSat) || (!this->specifiedFormulaHasUpperBound() && !proveAllSat)){
//these are the cases in which we need to compute upper bounds //these are the cases in which we need to compute upper bounds
upperBounds = getApproximationModel()->computeValues(storm::solver::OptimizationDirection::Maximize);
upperBounds = this->getApproximationModel()->computeValues(storm::solver::OptimizationDirection::Maximize);
lowerBounds = std::vector<ConstantType>(); lowerBounds = std::vector<ConstantType>();
formulaSatisfied = valueIsInBoundOfFormula(upperBounds[*getApproximationModel()->getModel()->getInitialStates().begin()]);
formulaSatisfied = this->valueIsInBoundOfFormula(upperBounds[*this->getApproximationModel()->getModel()->getInitialStates().begin()]);
} }
else{ else{
//for the remaining cases we compute lower bounds //for the remaining cases we compute lower bounds
lowerBounds = getApproximationModel()->computeValues(storm::solver::OptimizationDirection::Minimize);
lowerBounds = this->getApproximationModel()->computeValues(storm::solver::OptimizationDirection::Minimize);
upperBounds = std::vector<ConstantType>(); upperBounds = std::vector<ConstantType>();
formulaSatisfied = valueIsInBoundOfFormula(lowerBounds[*getApproximationModel()->getModel()->getInitialStates().begin()]);
formulaSatisfied = this->valueIsInBoundOfFormula(lowerBounds[*this->getApproximationModel()->getModel()->getInitialStates().begin()]);
} }
//check if approximation was conclusive //check if approximation was conclusive
@ -657,12 +466,12 @@ namespace storm {
proveAllSat=!proveAllSat; proveAllSat=!proveAllSat;
if(lowerBounds.empty()){ if(lowerBounds.empty()){
lowerBounds = getApproximationModel()->computeValues(storm::solver::OptimizationDirection::Minimize);
formulaSatisfied=valueIsInBoundOfFormula(lowerBounds[*getApproximationModel()->getModel()->getInitialStates().begin()]);
lowerBounds = this->getApproximationModel()->computeValues(storm::solver::OptimizationDirection::Minimize);
formulaSatisfied=this->valueIsInBoundOfFormula(lowerBounds[*this->getApproximationModel()->getModel()->getInitialStates().begin()]);
} }
else{ else{
upperBounds = getApproximationModel()->computeValues(storm::solver::OptimizationDirection::Maximize);
formulaSatisfied=valueIsInBoundOfFormula(upperBounds[*getApproximationModel()->getModel()->getInitialStates().begin()]);
upperBounds = this->getApproximationModel()->computeValues(storm::solver::OptimizationDirection::Maximize);
formulaSatisfied=this->valueIsInBoundOfFormula(upperBounds[*this->getApproximationModel()->getModel()->getInitialStates().begin()]);
} }
//check if approximation was conclusive //check if approximation was conclusive
@ -680,36 +489,16 @@ namespace storm {
} }
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
std::shared_ptr<typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ApproximationModel> const& SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::getApproximationModel() {
if(this->approximationModel==nullptr){
STORM_LOG_WARN("Approximation model requested but it has not been initialized when specifying the formula. Will initialize it now.");
initializeApproximationModel(*this->simpleModel, this->simpleFormula);
}
return this->approximationModel;
}
template<typename ParametricSparseModelType, typename ConstantType>
bool SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::checkSamplePoints(ParameterRegion& region) {
auto samplingPoints = region.getVerticesOfRegion(region.getVariables()); //test the 4 corner points
for (auto const& point : samplingPoints){
if(checkPoint(region, point)){
return true;
}
}
return false;
}
template<typename ParametricSparseModelType, typename ConstantType>
bool SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::checkPoint(ParameterRegion& region, std::map<VariableType, CoefficientType>const& point, bool favorViaFunction) {
bool SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::checkPoint(ParameterRegion<ParametricType>& region, std::map<VariableType, CoefficientType>const& point, bool favorViaFunction) {
bool valueInBoundOfFormula; bool valueInBoundOfFormula;
if((storm::settings::regionSettings().getSampleMode()==storm::settings::modules::RegionSettings::SampleMode::EVALUATE) || if((storm::settings::regionSettings().getSampleMode()==storm::settings::modules::RegionSettings::SampleMode::EVALUATE) ||
(!storm::settings::regionSettings().doSample() && favorViaFunction)){ (!storm::settings::regionSettings().doSample() && favorViaFunction)){
//evaluate the reachability function //evaluate the reachability function
valueInBoundOfFormula = this->valueIsInBoundOfFormula(this->getReachabilityValue<CoefficientType>(point, true));
valueInBoundOfFormula = this->valueIsInBoundOfFormula(this->getReachabilityValue(point, true));
} }
else{ else{
//instantiate the sampling model //instantiate the sampling model
valueInBoundOfFormula = this->valueIsInBoundOfFormula(this->getReachabilityValue<ConstantType>(point, false));
valueInBoundOfFormula = this->valueIsInBoundOfFormula(this->getReachabilityValue(point, false));
} }
if(valueInBoundOfFormula){ if(valueInBoundOfFormula){
@ -735,46 +524,47 @@ namespace storm {
return false; return false;
} }
template<typename ParametricSparseModelType, typename ConstantType>
std::shared_ptr<typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::SamplingModel> const& SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::getSamplingModel() {
if(this->samplingModel==nullptr){
STORM_LOG_WARN("Sampling model requested but it has not been initialized when specifying the formula. Will initialize it now.");
initializeSamplingModel(*this->simpleModel, this->simpleFormula);
}
return this->samplingModel;
}
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
std::shared_ptr<typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParametricType> const& SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::getReachabilityFunction() { std::shared_ptr<typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::ParametricType> const& SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::getReachabilityFunction() {
if(this->reachabilityFunction==nullptr){ if(this->reachabilityFunction==nullptr){
STORM_LOG_WARN("Reachability Function requested but it has not been computed when specifying the formula. Will compute it now."); STORM_LOG_WARN("Reachability Function requested but it has not been computed when specifying the formula. Will compute it now.");
computeReachabilityFunction(*this->simpleModel);
computeReachabilityFunction(*this->getSimpleModel());
} }
return this->reachabilityFunction; return this->reachabilityFunction;
} }
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
template<typename ValueType>
ValueType SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::getReachabilityValue(std::map<VariableType, CoefficientType> const& point, bool evaluateFunction) {
if(this->isResultConstant){
//Todo: remove workaround (infinity<storm::RationalFunction() does not work)
ConstantType SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::getReachabilityValue(std::map<VariableType, CoefficientType> const& point, bool evaluateFunction) {
if(this->isResultConstant()){
//Todo: remove workaround (infinity<storm::RationalNumber>() does not work)
if(this->isResultInfinity){ if(this->isResultInfinity){
return storm::utility::infinity<ValueType>();
return storm::utility::infinity<ConstantType>();
} }
STORM_LOG_THROW(storm::utility::isConstant(*getReachabilityFunction()), storm::exceptions::UnexpectedException, "The result was assumed to be constant but it isn't."); STORM_LOG_THROW(storm::utility::isConstant(*getReachabilityFunction()), storm::exceptions::UnexpectedException, "The result was assumed to be constant but it isn't.");
return storm::utility::regions::convertNumber<ValueType>(storm::utility::regions::getConstantPart(*getReachabilityFunction()));
return storm::utility::region::convertNumber<ConstantType>(storm::utility::region::getConstantPart(*getReachabilityFunction()));
} }
if(evaluateFunction){ if(evaluateFunction){
return storm::utility::regions::convertNumber<ValueType>(storm::utility::regions::evaluateFunction(*getReachabilityFunction(), point));
return storm::utility::region::convertNumber<ConstantType>(this->evaluateReachabilityFunction(point));
} else { } else {
getSamplingModel()->instantiate(point);
return storm::utility::regions::convertNumber<ValueType>(getSamplingModel()->computeValues()[*getSamplingModel()->getModel()->getInitialStates().begin()]);
this->getSamplingModel()->instantiate(point);
return storm::utility::region::convertNumber<ConstantType>(this->getSamplingModel()->computeValues()[*this->getSamplingModel()->getModel()->getInitialStates().begin()]);
} }
} }
template<typename ParametricSparseModelType, typename ConstantType>
typename SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::CoefficientType SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::evaluateReachabilityFunction(std::map<VariableType, CoefficientType> const& point) {
if(this->isResultConstant()){
//Todo: remove workaround (infinity<storm::RationalNumber>() does not work)
STORM_LOG_THROW(!this->isResultInfinity, storm::exceptions::NotSupportedException, "Requested the reachability value but can not represent it as a Coefficient type (The value is infinity)");
STORM_LOG_THROW(storm::utility::isConstant(*getReachabilityFunction()), storm::exceptions::UnexpectedException, "The result was assumed to be constant but it isn't.");
return storm::utility::region::convertNumber<ConstantType>(storm::utility::region::getConstantPart(*getReachabilityFunction()));
}
return storm::utility::region::evaluateFunction(*getReachabilityFunction(), point);
}
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
bool SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::checkFullSmt(ParameterRegion& region) {
bool SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::checkSmt(ParameterRegion<ParametricType>& region) {
STORM_LOG_THROW((storm::settings::regionSettings().getSmtMode()==storm::settings::modules::RegionSettings::SmtMode::FUNCTION), storm::exceptions::NotImplementedException, "Selected SMT mode has not been implemented."); STORM_LOG_THROW((storm::settings::regionSettings().getSmtMode()==storm::settings::modules::RegionSettings::SmtMode::FUNCTION), storm::exceptions::NotImplementedException, "Selected SMT mode has not been implemented.");
if (region.getCheckResult()==RegionCheckResult::UNKNOWN){ if (region.getCheckResult()==RegionCheckResult::UNKNOWN){
//Sampling needs to be done (on a single point) //Sampling needs to be done (on a single point)
@ -789,30 +579,30 @@ namespace storm {
//add constraints for the region //add constraints for the region
for(auto const& variable : region.getVariables()) { for(auto const& variable : region.getVariables()) {
storm::utility::regions::addParameterBoundsToSmtSolver(this->smtSolver, variable, storm::logic::ComparisonType::GreaterEqual, region.getLowerBound(variable));
storm::utility::regions::addParameterBoundsToSmtSolver(this->smtSolver, variable, storm::logic::ComparisonType::LessEqual, region.getUpperBound(variable));
storm::utility::region::addParameterBoundsToSmtSolver(this->smtSolver, variable, storm::logic::ComparisonType::GreaterEqual, region.getLowerBound(variable));
storm::utility::region::addParameterBoundsToSmtSolver(this->smtSolver, variable, storm::logic::ComparisonType::LessEqual, region.getUpperBound(variable));
} }
//add constraint that states what we want to prove //add constraint that states what we want to prove
VariableType proveAllSatVar=storm::utility::regions::getVariableFromString<VariableType>("storm_proveAllSat");
VariableType proveAllViolatedVar=storm::utility::regions::getVariableFromString<VariableType>("storm_proveAllViolated");
VariableType proveAllSatVar=storm::utility::region::getVariableFromString<VariableType>("storm_proveAllSat");
VariableType proveAllViolatedVar=storm::utility::region::getVariableFromString<VariableType>("storm_proveAllViolated");
switch(region.getCheckResult()){ switch(region.getCheckResult()){
case RegionCheckResult::EXISTSBOTH: case RegionCheckResult::EXISTSBOTH:
STORM_LOG_WARN_COND((region.getCheckResult()!=RegionCheckResult::EXISTSBOTH), "checkFullSmt invoked although the result is already clear (EXISTSBOTH). Will validate this now...");
STORM_LOG_WARN_COND((region.getCheckResult()!=RegionCheckResult::EXISTSBOTH), "checkSmt invoked although the result is already clear (EXISTSBOTH). Will validate this now...");
case RegionCheckResult::ALLSAT: case RegionCheckResult::ALLSAT:
STORM_LOG_WARN_COND((region.getCheckResult()!=RegionCheckResult::ALLSAT), "checkFullSmt invoked although the result is already clear (ALLSAT). Will validate this now...");
STORM_LOG_WARN_COND((region.getCheckResult()!=RegionCheckResult::ALLSAT), "checkSmt invoked although the result is already clear (ALLSAT). Will validate this now...");
case RegionCheckResult::EXISTSSAT: case RegionCheckResult::EXISTSSAT:
storm::utility::regions::addBoolVariableToSmtSolver(this->smtSolver, proveAllSatVar, true);
storm::utility::regions::addBoolVariableToSmtSolver(this->smtSolver, proveAllViolatedVar, false);
storm::utility::region::addBoolVariableToSmtSolver(this->smtSolver, proveAllSatVar, true);
storm::utility::region::addBoolVariableToSmtSolver(this->smtSolver, proveAllViolatedVar, false);
break; break;
case RegionCheckResult::ALLVIOLATED: case RegionCheckResult::ALLVIOLATED:
STORM_LOG_WARN_COND((region.getCheckResult()!=RegionCheckResult::ALLVIOLATED), "checkFullSmt invoked although the result is already clear (ALLVIOLATED). Will validate this now...");
STORM_LOG_WARN_COND((region.getCheckResult()!=RegionCheckResult::ALLVIOLATED), "checkSmt invoked although the result is already clear (ALLVIOLATED). Will validate this now...");
case RegionCheckResult::EXISTSVIOLATED: case RegionCheckResult::EXISTSVIOLATED:
storm::utility::regions::addBoolVariableToSmtSolver(this->smtSolver, proveAllSatVar, false);
storm::utility::regions::addBoolVariableToSmtSolver(this->smtSolver, proveAllViolatedVar, true);
storm::utility::region::addBoolVariableToSmtSolver(this->smtSolver, proveAllSatVar, false);
storm::utility::region::addBoolVariableToSmtSolver(this->smtSolver, proveAllViolatedVar, true);
break; break;
default: default:
STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Could not handle the current region CheckResult: " << region.checkResultToString());
STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Could not handle the current region CheckResult: " << region.getCheckResult());
} }
storm::solver::SmtSolver::CheckResult solverResult= this->smtSolver->check(); storm::solver::SmtSolver::CheckResult solverResult= this->smtSolver->check();
@ -875,12 +665,12 @@ namespace storm {
storm::expressions::ExpressionManager manager; //this manager will do nothing as we will use carl expressions.. storm::expressions::ExpressionManager manager; //this manager will do nothing as we will use carl expressions..
this->smtSolver = std::shared_ptr<storm::solver::Smt2SmtSolver>(new storm::solver::Smt2SmtSolver(manager, true)); this->smtSolver = std::shared_ptr<storm::solver::Smt2SmtSolver>(new storm::solver::Smt2SmtSolver(manager, true));
ParametricType bound= storm::utility::regions::convertNumber<ParametricType>(this->specifiedFormulaBound);
ParametricType bound= storm::utility::region::convertNumber<ParametricType>(this->getSpecifiedFormulaBound());
// To prove that the property is satisfied in the initial state for all parameters, // To prove that the property is satisfied in the initial state for all parameters,
// we ask the solver whether the negation of the property is satisfiable and invert the answer. // we ask the solver whether the negation of the property is satisfiable and invert the answer.
// In this case, assert that this variable is true: // In this case, assert that this variable is true:
VariableType proveAllSatVar=storm::utility::regions::getNewVariable<VariableType>("storm_proveAllSat", storm::utility::regions::VariableSort::VS_BOOL);
VariableType proveAllSatVar=storm::utility::region::getNewVariable<VariableType>("storm_proveAllSat", storm::utility::region::VariableSort::VS_BOOL);
//Example: //Example:
//Property: P<=p [ F 'target' ] holds iff... //Property: P<=p [ F 'target' ] holds iff...
@ -888,7 +678,7 @@ namespace storm {
// Hence: If f(x) > p is unsat, the property is satisfied for all parameters. // Hence: If f(x) > p is unsat, the property is satisfied for all parameters.
storm::logic::ComparisonType proveAllSatRel; //the relation from the property needs to be inverted storm::logic::ComparisonType proveAllSatRel; //the relation from the property needs to be inverted
switch (this->specifiedFormulaCompType) {
switch (this->getSpecifiedFormulaCompType()) {
case storm::logic::ComparisonType::Greater: case storm::logic::ComparisonType::Greater:
proveAllSatRel=storm::logic::ComparisonType::LessEqual; proveAllSatRel=storm::logic::ComparisonType::LessEqual;
break; break;
@ -904,108 +694,27 @@ namespace storm {
default: default:
STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "the comparison relation of the formula is not supported"); STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "the comparison relation of the formula is not supported");
} }
storm::utility::regions::addGuardedConstraintToSmtSolver(this->smtSolver, proveAllSatVar, *getReachabilityFunction(), proveAllSatRel, bound);
storm::utility::region::addGuardedConstraintToSmtSolver(this->smtSolver, proveAllSatVar, *getReachabilityFunction(), proveAllSatRel, bound);
// To prove that the property is violated in the initial state for all parameters, // To prove that the property is violated in the initial state for all parameters,
// we ask the solver whether the the property is satisfiable and invert the answer. // we ask the solver whether the the property is satisfiable and invert the answer.
// In this case, assert that this variable is true: // In this case, assert that this variable is true:
VariableType proveAllViolatedVar=storm::utility::regions::getNewVariable<VariableType>("storm_proveAllViolated", storm::utility::regions::VariableSort::VS_BOOL);
VariableType proveAllViolatedVar=storm::utility::region::getNewVariable<VariableType>("storm_proveAllViolated", storm::utility::region::VariableSort::VS_BOOL);
//Example: //Example:
//Property: P<=p [ F 'target' ] holds iff... //Property: P<=p [ F 'target' ] holds iff...
// f(x) <= p // f(x) <= p
// Hence: If f(x) <= p is unsat, the property is violated for all parameters. // Hence: If f(x) <= p is unsat, the property is violated for all parameters.
storm::logic::ComparisonType proveAllViolatedRel = this->specifiedFormulaCompType;
storm::utility::regions::addGuardedConstraintToSmtSolver(this->smtSolver, proveAllViolatedVar, *getReachabilityFunction(), proveAllViolatedRel, bound);
}
template<typename ParametricSparseModelType, typename ConstantType>
template<typename ValueType>
bool SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::valueIsInBoundOfFormula(ValueType const& value){
STORM_LOG_THROW(this->specifiedFormula!=nullptr, storm::exceptions::InvalidStateException, "Tried to compare a value to the bound of a formula, but no formula specified.");
double valueAsDouble = storm::utility::regions::convertNumber<double>(value);
switch (this->specifiedFormulaCompType) {
case storm::logic::ComparisonType::Greater:
return (valueAsDouble > this->specifiedFormulaBound);
case storm::logic::ComparisonType::GreaterEqual:
return (valueAsDouble >= this->specifiedFormulaBound);
case storm::logic::ComparisonType::Less:
return (valueAsDouble < this->specifiedFormulaBound);
case storm::logic::ComparisonType::LessEqual:
return (valueAsDouble <= this->specifiedFormulaBound);
default:
STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "the comparison relation of the formula is not supported");
}
}
template<typename ParametricSparseModelType, typename ConstantType>
void SparseDtmcRegionModelChecker<ParametricSparseModelType, ConstantType>::printStatisticsToStream(std::ostream& outstream) {
if(this->specifiedFormula==nullptr){
outstream << "Region Model Checker Statistics Error: No formula specified." << std::endl;
return;
storm::logic::ComparisonType proveAllViolatedRel = this->getSpecifiedFormulaCompType();
storm::utility::region::addGuardedConstraintToSmtSolver(this->smtSolver, proveAllViolatedVar, *getReachabilityFunction(), proveAllViolatedRel, bound);
} }
std::chrono::milliseconds timeSpecifyFormulaInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(this->timeSpecifyFormula);
std::chrono::milliseconds timePreprocessingInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(this->timePreprocessing);
std::chrono::milliseconds timeInitSamplingModelInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(this->timeInitSamplingModel);
std::chrono::milliseconds timeInitApproxModelInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(this->timeInitApproxModel);
std::chrono::milliseconds timeComputeReachabilityFunctionInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(this->timeComputeReachabilityFunction);
std::chrono::milliseconds timeCheckRegionInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(this->timeCheckRegion);
std::chrono::milliseconds timeSammplingInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(this->timeSampling);
std::chrono::milliseconds timeApproximationInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(this->timeApproximation);
std::chrono::milliseconds timeMDPBuildInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(this->timeMDPBuild);
std::chrono::milliseconds timeFullSmtInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(this->timeFullSmt);
std::chrono::high_resolution_clock::duration timeOverall = timeSpecifyFormula + timeCheckRegion; // + ...
std::chrono::milliseconds timeOverallInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(timeOverall);
uint_fast64_t numOfSolvedRegions= this->numOfRegionsExistsBoth + this->numOfRegionsAllSat + this->numOfRegionsAllViolated;
outstream << std::endl << "Region Model Checker Statistics:" << std::endl;
outstream << "-----------------------------------------------" << std::endl;
outstream << "Model: " << this->model.getNumberOfStates() << " states, " << this->model.getNumberOfTransitions() << " transitions." << std::endl;
outstream << "Formula: " << *this->specifiedFormula << std::endl;
if(this->isResultConstant){
outstream << "The requested value is constant (i.e. independent of any parameters)" << std::endl;
}
else{
outstream << "Simple model: " << this->simpleModel->getNumberOfStates() << " states, " << this->simpleModel->getNumberOfTransitions() << " transitions" << std::endl;
}
outstream << "Approximation is " << (this->isApproximationApplicable ? "" : "not ") << "applicable" << std::endl;
outstream << "Number of checked regions: " << this->numOfCheckedRegions << std::endl;
if(this->numOfCheckedRegions>0){
outstream << " Number of solved regions: " << numOfSolvedRegions << "(" << numOfSolvedRegions*100/this->numOfCheckedRegions << "%)" << std::endl;
outstream << " AllSat: " << this->numOfRegionsAllSat << "(" << this->numOfRegionsAllSat*100/this->numOfCheckedRegions << "%)" << std::endl;
outstream << " AllViolated: " << this->numOfRegionsAllViolated << "(" << this->numOfRegionsAllViolated*100/this->numOfCheckedRegions << "%)" << std::endl;
outstream << " ExistsBoth: " << this->numOfRegionsExistsBoth << "(" << this->numOfRegionsExistsBoth*100/this->numOfCheckedRegions << "%)" << std::endl;
outstream << " Unsolved: " << this->numOfCheckedRegions - numOfSolvedRegions << "(" << (this->numOfCheckedRegions - numOfSolvedRegions)*100/this->numOfCheckedRegions << "%)" << std::endl;
outstream << " -- Note: %-numbers are relative to the NUMBER of regions, not the size of their area --" << std::endl;
outstream << " " << this->numOfRegionsSolvedThroughApproximation << " regions solved through Approximation" << std::endl;
outstream << " " << this->numOfRegionsSolvedThroughSampling << " regions solved through Sampling" << std::endl;
outstream << " " << this->numOfRegionsSolvedThroughFullSmt << " regions solved through FullSmt" << std::endl;
outstream << std::endl;
}
outstream << "Running times:" << std::endl;
outstream << " " << timeOverallInMilliseconds.count() << "ms overall (excluding model parsing, bisimulation (if applied))" << std::endl;
outstream << " " << timeSpecifyFormulaInMilliseconds.count() << "ms Initialization for the specified formula, including... " << std::endl;
outstream << " " << timePreprocessingInMilliseconds.count() << "ms for Preprocessing (mainly: state elimination of const transitions)" << std::endl;
outstream << " " << timeInitApproxModelInMilliseconds.count() << "ms to initialize the Approximation Model" << std::endl;
outstream << " " << timeInitSamplingModelInMilliseconds.count() << "ms to initialize the Sampling Model" << std::endl;
outstream << " " << timeComputeReachabilityFunctionInMilliseconds.count() << "ms to compute the reachability function" << std::endl;
outstream << " " << timeCheckRegionInMilliseconds.count() << "ms Region Check including... " << std::endl;
outstream << " " << timeApproximationInMilliseconds.count() << "ms Approximation including... " << std::endl;
outstream << " " << timeMDPBuildInMilliseconds.count() << "ms to build the MDP" << std::endl;
outstream << " " << timeSammplingInMilliseconds.count() << "ms Sampling " << std::endl;
outstream << " " << timeFullSmtInMilliseconds.count() << "ms Smt solving" << std::endl;
outstream << "-----------------------------------------------" << std::endl;
}
#ifdef STORM_HAVE_CARL #ifdef STORM_HAVE_CARL
template class SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>;
template class SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction, storm::models::sparse::StandardRewardModel<storm::RationalFunction>>, double>;
#endif #endif
//note: for other template instantiations, add rules for the typedefs of VariableType and CoefficientType in utility/regions.h //note: for other template instantiations, add rules for the typedefs of VariableType and CoefficientType in utility/regions.h
} // namespace region
} // namespace modelchecker } // namespace modelchecker
} // namespace storm } // namespace storm

200
src/modelchecker/region/SparseDtmcRegionModelChecker.h

@ -1,42 +1,27 @@
#ifndef STORM_MODELCHECKER_REACHABILITY_SPARSEDTMCREGIONMODELCHECKER_H_ #ifndef STORM_MODELCHECKER_REACHABILITY_SPARSEDTMCREGIONMODELCHECKER_H_
#define STORM_MODELCHECKER_REACHABILITY_SPARSEDTMCREGIONMODELCHECKER_H_ #define STORM_MODELCHECKER_REACHABILITY_SPARSEDTMCREGIONMODELCHECKER_H_
#include<memory>
#include "src/modelchecker/region/AbstractSparseRegionModelChecker.h"
#include "src/storage/sparse/StateType.h"
#include "src/models/sparse/Dtmc.h"
#include "src/models/sparse/StandardRewardModel.h" #include "src/models/sparse/StandardRewardModel.h"
#include "src/utility/constants.h"
#include "src/utility/regions.h"
#include "src/solver/Smt2SmtSolver.h"
#include "src/models/sparse/Dtmc.h"
#include "src/utility/region.h"
#include "src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h" #include "src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h"
#include "src/solver/Smt2SmtSolver.h"
namespace storm { namespace storm {
namespace modelchecker { namespace modelchecker {
namespace region {
template<typename ParametricSparseModelType, typename ConstantType> template<typename ParametricSparseModelType, typename ConstantType>
class SparseDtmcRegionModelChecker {
class SparseDtmcRegionModelChecker : public AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType> {
public: public:
typedef typename ParametricSparseModelType::ValueType ParametricType; typedef typename ParametricSparseModelType::ValueType ParametricType;
typedef typename storm::utility::regions::VariableType<ParametricType> VariableType;
typedef typename storm::utility::regions::CoefficientType<ParametricType> CoefficientType;
/*!
* The possible results for a single Parameter region
*/
enum class RegionCheckResult {
UNKNOWN, /*!< the result is unknown */
EXISTSSAT, /*!< the formula is satisfied for at least one parameter evaluation that lies in the given region */
EXISTSVIOLATED, /*!< the formula is violated for at least one parameter evaluation that lies in the given region */
EXISTSBOTH, /*!< the formula is satisfied for some parameters but also violated for others */
ALLSAT, /*!< the formula is satisfied for all parameters in the given region */
ALLVIOLATED /*!< the formula is violated for all parameters in the given region */
};
typedef typename ParametricSparseModelType::RewardModelType ParametricRewardModelType;
typedef typename storm::utility::region::VariableType<ParametricType> VariableType;
typedef typename storm::utility::region::CoefficientType<ParametricType> CoefficientType;
class ParameterRegion;
explicit SparseDtmcRegionModelChecker(storm::models::sparse::Dtmc<ParametricType> const& model);
explicit SparseDtmcRegionModelChecker(ParametricSparseModelType const& model);
virtual ~SparseDtmcRegionModelChecker(); virtual ~SparseDtmcRegionModelChecker();
@ -44,37 +29,7 @@ namespace storm {
* Checks if the given formula can be handled by This region model checker * Checks if the given formula can be handled by This region model checker
* @param formula the formula to be checked * @param formula the formula to be checked
*/ */
bool canHandle(storm::logic::Formula const& formula) const;
/*!
* Specifies the considered formula.
* A few preprocessing steps are performed.
* If another formula has been specified before, all 'context' regarding the old formula is lost.
*
* @param formula the formula to be considered.
*/
void specifyFormula(std::shared_ptr<storm::logic::Formula> formula);
/*!
* Checks for every given region whether the specified formula holds for all parameters that lie in that region.
* Sets the region checkresult accordingly. Moreover, region.satPoint and/or an region.violatedPoint will be set.
*
* @note A formula has to be specified first.
*
* @param region The considered region
*/
void checkRegions(std::vector<ParameterRegion>& regions);
/*!
* Checks whether the given formula holds for all parameters that lie in the given region.
* Sets the region checkresult accordingly. Moreover, region.satPoint and/or an region.violatedPoint will be set.
*
* @note A formula has to be specified first.
*
* @param region The considered region
*
*/
void checkRegion(ParameterRegion& region);
virtual bool canHandle(storm::logic::Formula const& formula) const;
/*! /*!
* Returns the reachability function. * Returns the reachability function.
@ -90,37 +45,29 @@ namespace storm {
* @param point The point (i.e. parameter evaluation) at which to compute the reachability value. * @param point The point (i.e. parameter evaluation) at which to compute the reachability value.
* @param evaluateFunction If set, the reachability function is evaluated. Otherwise, the sampling model is instantiated. * @param evaluateFunction If set, the reachability function is evaluated. Otherwise, the sampling model is instantiated.
*/ */
template <typename ValueType>
ValueType getReachabilityValue(std::map<VariableType, CoefficientType>const& point, bool evaluateFunction=false);
virtual ConstantType getReachabilityValue(std::map<VariableType, CoefficientType>const& point, bool evaluateFunction=false);
/*! /*!
* Prints statistical information to the given stream.
* Evaluates the reachability function with the given substitution.
* Makes some checks for the case that the result should be constant.
* @param point The point (i.e. parameter evaluation) at which to compute the reachability value.
*/ */
void printStatisticsToStream(std::ostream& outstream);
private:
class ApproximationModel;
class SamplingModel;
CoefficientType evaluateReachabilityFunction(std::map<VariableType, CoefficientType>const& point);
protected:
/*! /*!
* 1. Analyzes the formula (sets this->specifiedFormulaBound, this->specifiedFormulaCompType)
* Checks whether the approximation technique is applicable and whether the model checking result is independent of parameters (i.e., constant)
* *
* 2. Checks whether the approximation technique is applicable and whether the model checking result is independent of parameters (i.e., constant)
* The flags of This model checker are set accordingly.
*
* 3. Computes a model with a single target and at most one sink state.
* Computes a model with a single target and at most one sink state.
* Eliminates all states for which the outgoing transitions are constant. * Eliminates all states for which the outgoing transitions are constant.
* If rewards are relevant, transition rewards are transformed to state rewards * If rewards are relevant, transition rewards are transformed to state rewards
* *
* @note this->specifiedFormula has to be set accordingly, before calling this function
* @note this->specifiedFormula and this->computeRewards has to be set accordingly before calling this function
*/ */
void preprocess();
virtual void preprocess(std::shared_ptr<ParametricSparseModelType>& simpleModel, std::shared_ptr<storm::logic::Formula>& simpleFormula, bool& isApproximationApplicable, bool& isResultConstant);
private:
/*! /*!
* Does some sanity checks and preprocessing steps on the currently specified model and * Does some sanity checks and preprocessing steps on the currently specified model and
* reachability probability formula, i.e., * reachability probability formula, i.e.,
@ -131,8 +78,7 @@ namespace storm {
* @note The returned set of target states also includes states where an 'actual' target state is reached with probability 1 * @note The returned set of target states also includes states where an 'actual' target state is reached with probability 1
* *
*/ */
void preprocessForProbabilities(storm::storage::BitVector& maybeStates, storm::storage::BitVector& targetStates);
void preprocessForProbabilities(storm::storage::BitVector& maybeStates, storm::storage::BitVector& targetStates, bool& isApproximationApplicable, bool& isResultConstant);
/*! /*!
* Does some sanity checks and preprocessing steps on the currently specified model and * Does some sanity checks and preprocessing steps on the currently specified model and
@ -145,25 +91,13 @@ namespace storm {
* @note stateRewards.size will equal to maybeStates.numberOfSetBits * @note stateRewards.size will equal to maybeStates.numberOfSetBits
* *
*/ */
void preprocessForRewards(storm::storage::BitVector& maybeStates, storm::storage::BitVector& targetStates, std::vector<ParametricType>& stateRewards);
/*!
* initializes the Approximation Model
*
* @note does not check whether approximation can be applied
*/
void initializeApproximationModel(storm::models::sparse::Dtmc<ParametricType> const& model, std::shared_ptr<storm::logic::Formula> formula);
/*!
* initializes the Sampling Model
*/
void initializeSamplingModel(storm::models::sparse::Dtmc<ParametricType> const& model, std::shared_ptr<storm::logic::Formula> formula);
void preprocessForRewards(storm::storage::BitVector& maybeStates, storm::storage::BitVector& targetStates, std::vector<ParametricType>& stateRewards, bool& isApproximationApplicable, bool& isResultConstant);
/*! /*!
* Computes the reachability function via state elimination * Computes the reachability function via state elimination
* @note computeFlagsAndSimplifiedModel should be called before calling this * @note computeFlagsAndSimplifiedModel should be called before calling this
*/ */
void computeReachabilityFunction(storm::models::sparse::Dtmc<ParametricType> const& simpleModel);
void computeReachabilityFunction(ParametricSparseModelType const& simpleModel);
/*! /*!
* Instantiates the approximation model to compute bounds on the maximal/minimal reachability probability (or reachability reward). * Instantiates the approximation model to compute bounds on the maximal/minimal reachability probability (or reachability reward).
@ -174,22 +108,7 @@ namespace storm {
* However, if only the lowerBounds (or upperBounds) have been computed, the other vector is set to a vector of size 0. * However, if only the lowerBounds (or upperBounds) have been computed, the other vector is set to a vector of size 0.
* True is returned iff either ALLSAT or ALLVIOLATED could be proved. * True is returned iff either ALLSAT or ALLVIOLATED could be proved.
*/ */
bool checkApproximativeValues(ParameterRegion& region, std::vector<ConstantType>& lowerBounds, std::vector<ConstantType>& upperBounds);
/*!
* Returns the approximation model.
* If it is not yet available, it is computed.
*/
std::shared_ptr<ApproximationModel> const& getApproximationModel();
/*!
* Checks the value of the function at some sampling points within the given region.
* May set the satPoint and violatedPoint of the regions if they are not yet specified and such points are found
* Also changes the regioncheckresult of the region to EXISTSSAT, EXISTSVIOLATED, or EXISTSBOTH
*
* @return true if an violated point as well as a sat point has been found during the process
*/
bool checkSamplePoints(ParameterRegion& region);
virtual bool checkApproximativeValues(ParameterRegion<ParametricType>& region, std::vector<ConstantType>& lowerBounds, std::vector<ConstantType>& upperBounds);
/*! /*!
* Checks the value of the function at the given sampling point. * Checks the value of the function at the given sampling point.
@ -203,13 +122,7 @@ namespace storm {
* *
* @return true if an violated point as well as a sat point has been found, i.e., the check result is changed to EXISTSOTH * @return true if an violated point as well as a sat point has been found, i.e., the check result is changed to EXISTSOTH
*/ */
bool checkPoint(ParameterRegion& region, std::map<VariableType, CoefficientType>const& point, bool favorViaFunction=false);
/*!
* Returns the sampling model.
* If it is not yet available, it is computed.
*/
std::shared_ptr<SamplingModel> const& getSamplingModel();
virtual bool checkPoint(ParameterRegion<ParametricType>& region, std::map<VariableType, CoefficientType>const& point, bool favorViaFunction=false);
/*! /*!
* Starts the SMTSolver to get the result. * Starts the SMTSolver to get the result.
@ -219,71 +132,24 @@ namespace storm {
* A Sat- or Violated point is set, if the solver has found one (not yet implemented!). * A Sat- or Violated point is set, if the solver has found one (not yet implemented!).
* The region checkResult of the given region is changed accordingly. * The region checkResult of the given region is changed accordingly.
*/ */
bool checkFullSmt(ParameterRegion& region);
bool checkSmt(ParameterRegion<ParametricType>& region);
//initializes this->smtSolver which can later be used to give an exact result regarding the whole model. //initializes this->smtSolver which can later be used to give an exact result regarding the whole model.
void initializeSMTSolver(); void initializeSMTSolver();
/*!
* Returns true iff the given value satisfies the bound given by the specified property
*/
template <typename ValueType>
bool valueIsInBoundOfFormula(ValueType const& value);
// The model this model checker is supposed to analyze.
storm::models::sparse::Dtmc<ParametricType> const& model;
//classes that provide auxilliary functions
// Instance of an elimination model checker to access its functions
storm::modelchecker::SparseDtmcEliminationModelChecker<storm::models::sparse::Dtmc<ParametricType>> eliminationModelChecker;
//the following members depend on the currently specified formula:
//the currently specified formula, the bound and the comparison type
std::shared_ptr<storm::logic::Formula> specifiedFormula;
bool computeRewards;
storm::logic::ComparisonType specifiedFormulaCompType;
double specifiedFormulaBound;
// the original model after states with constant transitions have been eliminated
std::shared_ptr<storm::models::sparse::Dtmc<ParametricType>> simpleModel;
// a formula that can be checked on the simplified model
std::shared_ptr<storm::logic::Formula> simpleFormula;
// the model that is used to approximate the reachability values
std::shared_ptr<ApproximationModel> approximationModel;
// the model that can be instantiated to check the value at a certain point
std::shared_ptr<SamplingModel> samplingModel;
// The function for the reachability probability (or: reachability reward) in the initial state // The function for the reachability probability (or: reachability reward) in the initial state
std::shared_ptr<ParametricType> reachabilityFunction; std::shared_ptr<ParametricType> reachabilityFunction;
// a flag that is true if there are only linear functions at transitions of the model
bool isApproximationApplicable;
// a flag that is true iff the resulting reachability function is constant
bool isResultConstant;
// workaround to represent that the result is infinity (utility::infinity<storm::RationalFunction>() does not work at this moment) // workaround to represent that the result is infinity (utility::infinity<storm::RationalFunction>() does not work at this moment)
bool isResultInfinity; bool isResultInfinity;
// Instance of an elimination model checker to access its functions
storm::modelchecker::SparseDtmcEliminationModelChecker<storm::models::sparse::Dtmc<ParametricType>> eliminationModelChecker;
// the smt solver that is used to prove properties with the help of the reachabilityFunction // the smt solver that is used to prove properties with the help of the reachabilityFunction
std::shared_ptr<storm::solver::Smt2SmtSolver> smtSolver; std::shared_ptr<storm::solver::Smt2SmtSolver> smtSolver;
// runtimes and other information for statistics.
uint_fast64_t numOfCheckedRegions;
uint_fast64_t numOfRegionsSolvedThroughApproximation;
uint_fast64_t numOfRegionsSolvedThroughSampling;
uint_fast64_t numOfRegionsSolvedThroughFullSmt;
uint_fast64_t numOfRegionsExistsBoth;
uint_fast64_t numOfRegionsAllSat;
uint_fast64_t numOfRegionsAllViolated;
std::chrono::high_resolution_clock::duration timeSpecifyFormula;
std::chrono::high_resolution_clock::duration timePreprocessing;
std::chrono::high_resolution_clock::duration timeInitApproxModel;
std::chrono::high_resolution_clock::duration timeInitSamplingModel;
std::chrono::high_resolution_clock::duration timeComputeReachabilityFunction;
std::chrono::high_resolution_clock::duration timeCheckRegion;
std::chrono::high_resolution_clock::duration timeSampling;
std::chrono::high_resolution_clock::duration timeApproximation;
std::chrono::high_resolution_clock::duration timeMDPBuild;
std::chrono::high_resolution_clock::duration timeFullSmt;
}; };
} //namespace region
} // namespace modelchecker } // namespace modelchecker
} // namespace storm } // namespace storm

2
src/utility/regions.h → src/utility/region.h

@ -30,7 +30,7 @@
namespace storm { namespace storm {
namespace utility{ namespace utility{
namespace regions {
namespace region {
#ifdef STORM_HAVE_CARL #ifdef STORM_HAVE_CARL
template<typename FunctionType> template<typename FunctionType>

4
src/utility/regions.cpp

@ -7,7 +7,7 @@
#include <string> #include <string>
#include "src/utility/regions.h"
#include "src/utility/region.h"
#include "src/utility/constants.h" #include "src/utility/constants.h"
#include "src/utility/macros.h" #include "src/utility/macros.h"
#include "src/settings/SettingsManager.h" #include "src/settings/SettingsManager.h"
@ -21,7 +21,7 @@
namespace storm { namespace storm {
namespace utility{ namespace utility{
namespace regions {
namespace region {
template<> template<>
double convertNumber<double, double>(double const& number){ double convertNumber<double, double>(double const& number){

6
src/utility/storm.h

@ -249,8 +249,8 @@ namespace storm {
if(storm::settings::generalSettings().isParametricRegionSet()){ if(storm::settings::generalSettings().isParametricRegionSet()){
std::cout << std::endl << "Model checking property: " << *formula << " for all parameters in the given regions." << std::endl; std::cout << std::endl << "Model checking property: " << *formula << " for all parameters in the given regions." << std::endl;
auto regions=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::getRegionsFromSettings();
storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double> modelchecker(*dtmc);
auto regions=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::getRegionsFromSettings();
storm::modelchecker::region::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double> modelchecker(*dtmc);
if (modelchecker.canHandle(*formula.get())) { if (modelchecker.canHandle(*formula.get())) {
modelchecker.specifyFormula(formula); modelchecker.specifyFormula(formula);
modelchecker.checkRegions(regions); modelchecker.checkRegions(regions);
@ -259,7 +259,7 @@ namespace storm {
STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "The parametric region check engine currently does not support this property."); STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "The parametric region check engine currently does not support this property.");
} }
// for(auto const& reg : regions){ // for(auto const& reg : regions){
// std::cout << reg.toString() << " Result: " << reg.checkResultToString() << std::endl;
// std::cout << reg.toString() << " Result: " << reg.getCheckResult() << std::endl;
// } // }
modelchecker.printStatisticsToStream(std::cout); modelchecker.printStatisticsToStream(std::cout);

306
test/functional/modelchecker/SparseDtmcRegionModelCheckerTest.cpp

@ -37,27 +37,27 @@ TEST(SparseDtmcRegionModelCheckerTest, Brp_Prob) {
std::shared_ptr<storm::models::sparse::Model<storm::RationalFunction>> model = storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::translateProgram(program.get(), options)->as<storm::models::sparse::Model<storm::RationalFunction>>(); std::shared_ptr<storm::models::sparse::Model<storm::RationalFunction>> model = storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::translateProgram(program.get(), options)->as<storm::models::sparse::Model<storm::RationalFunction>>();
ASSERT_EQ(storm::models::ModelType::Dtmc, model->getType()); ASSERT_EQ(storm::models::ModelType::Dtmc, model->getType());
std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> dtmc = model->template as<storm::models::sparse::Dtmc<storm::RationalFunction>>(); std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> dtmc = model->template as<storm::models::sparse::Dtmc<storm::RationalFunction>>();
storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double> modelchecker(*dtmc);
storm::modelchecker::region::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double> modelchecker(*dtmc);
ASSERT_TRUE(modelchecker.canHandle(*formulas[0])); ASSERT_TRUE(modelchecker.canHandle(*formulas[0]));
modelchecker.specifyFormula(formulas[0]); modelchecker.specifyFormula(formulas[0]);
//start testing //start testing
auto allSatRegion=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.7<=pL<=0.9,0.75<=pK<=0.95");
auto exBothRegion=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.4<=pL<=0.65,0.75<=pK<=0.95");
auto allVioRegion=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.1<=pL<=0.9,0.2<=pK<=0.5");
EXPECT_NEAR(0.8369631407, modelchecker.getReachabilityValue<double>(allSatRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(0.8369631407, modelchecker.getReachabilityValue<double>(allSatRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.0476784174, modelchecker.getReachabilityValue<double>(allSatRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.0476784174, modelchecker.getReachabilityValue<double>(allSatRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.9987948367, modelchecker.getReachabilityValue<double>(exBothRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(0.9987948367, modelchecker.getReachabilityValue<double>(exBothRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.6020480995, modelchecker.getReachabilityValue<double>(exBothRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.6020480995, modelchecker.getReachabilityValue<double>(exBothRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(1.0000000000, modelchecker.getReachabilityValue<double>(allVioRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(1.0000000000, modelchecker.getReachabilityValue<double>(allVioRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.9456084185, modelchecker.getReachabilityValue<double>(allVioRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.9456084185, modelchecker.getReachabilityValue<double>(allVioRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
auto allSatRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.7<=pL<=0.9,0.75<=pK<=0.95");
auto exBothRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.4<=pL<=0.65,0.75<=pK<=0.95");
auto allVioRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.1<=pL<=0.9,0.2<=pK<=0.5");
EXPECT_NEAR(0.8369631407, modelchecker.getReachabilityValue(allSatRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(0.8369631407, modelchecker.getReachabilityValue(allSatRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.0476784174, modelchecker.getReachabilityValue(allSatRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.0476784174, modelchecker.getReachabilityValue(allSatRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.9987948367, modelchecker.getReachabilityValue(exBothRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(0.9987948367, modelchecker.getReachabilityValue(exBothRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.6020480995, modelchecker.getReachabilityValue(exBothRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.6020480995, modelchecker.getReachabilityValue(exBothRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(1.0000000000, modelchecker.getReachabilityValue(allVioRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(1.0000000000, modelchecker.getReachabilityValue(allVioRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.9456084185, modelchecker.getReachabilityValue(allVioRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.9456084185, modelchecker.getReachabilityValue(allVioRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
//test approximative method //test approximative method
storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::TESTFIRST, storm::settings::modules::RegionSettings::SampleMode::INSTANTIATE, storm::settings::modules::RegionSettings::SmtMode::OFF); storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::TESTFIRST, storm::settings::modules::RegionSettings::SampleMode::INSTANTIATE, storm::settings::modules::RegionSettings::SmtMode::OFF);
@ -65,26 +65,26 @@ TEST(SparseDtmcRegionModelCheckerTest, Brp_Prob) {
ASSERT_TRUE(storm::settings::regionSettings().doSample()); ASSERT_TRUE(storm::settings::regionSettings().doSample());
ASSERT_FALSE(storm::settings::regionSettings().doSmt()); ASSERT_FALSE(storm::settings::regionSettings().doSmt());
modelchecker.checkRegion(allSatRegion); modelchecker.checkRegion(allSatRegion);
EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLSAT), allSatRegion.getCheckResult());
EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLSAT), allSatRegion.getCheckResult());
modelchecker.checkRegion(exBothRegion); modelchecker.checkRegion(exBothRegion);
EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::EXISTSBOTH), exBothRegion.getCheckResult());
EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::EXISTSBOTH), exBothRegion.getCheckResult());
modelchecker.checkRegion(allVioRegion); modelchecker.checkRegion(allVioRegion);
EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLVIOLATED), allVioRegion.getCheckResult());
EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLVIOLATED), allVioRegion.getCheckResult());
//test smt method (the regions need to be created again, because the old ones have some information stored in their internal state) //test smt method (the regions need to be created again, because the old ones have some information stored in their internal state)
auto allSatRegionSmt=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.7<=pL<=0.9,0.75<=pK<=0.95");
auto exBothRegionSmt=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.4<=pL<=0.65,0.75<=pK<=0.95");
auto allVioRegionSmt=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.1<=pL<=0.9,0.2<=pK<=0.5");
auto allSatRegionSmt=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.7<=pL<=0.9,0.75<=pK<=0.95");
auto exBothRegionSmt=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.4<=pL<=0.65,0.75<=pK<=0.95");
auto allVioRegionSmt=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.1<=pL<=0.9,0.2<=pK<=0.5");
storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::OFF, storm::settings::modules::RegionSettings::SampleMode::EVALUATE, storm::settings::modules::RegionSettings::SmtMode::FUNCTION); storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::OFF, storm::settings::modules::RegionSettings::SampleMode::EVALUATE, storm::settings::modules::RegionSettings::SmtMode::FUNCTION);
ASSERT_FALSE(storm::settings::regionSettings().doApprox()); ASSERT_FALSE(storm::settings::regionSettings().doApprox());
ASSERT_TRUE(storm::settings::regionSettings().doSample()); ASSERT_TRUE(storm::settings::regionSettings().doSample());
ASSERT_TRUE(storm::settings::regionSettings().doSmt()); ASSERT_TRUE(storm::settings::regionSettings().doSmt());
modelchecker.checkRegion(allSatRegionSmt); modelchecker.checkRegion(allSatRegionSmt);
//smt EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLSAT), allSatRegionSmt.getCheckResult());
//smt EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLSAT), allSatRegionSmt.getCheckResult());
modelchecker.checkRegion(exBothRegionSmt); modelchecker.checkRegion(exBothRegionSmt);
//smt EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::EXISTSBOTH), exBothRegionSmt.getCheckResult());
//smt EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::EXISTSBOTH), exBothRegionSmt.getCheckResult());
modelchecker.checkRegion(allVioRegionSmt); modelchecker.checkRegion(allVioRegionSmt);
//smt EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLVIOLATED), allVioRegionSmt.getCheckResult());
//smt EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLVIOLATED), allVioRegionSmt.getCheckResult());
storm::settings::mutableRegionSettings().resetModes(); storm::settings::mutableRegionSettings().resetModes();
} }
@ -106,32 +106,32 @@ TEST(SparseDtmcRegionModelCheckerTest, Brp_Rew) {
std::shared_ptr<storm::models::sparse::Model<storm::RationalFunction>> model = storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::translateProgram(program.get(), options)->as<storm::models::sparse::Model<storm::RationalFunction>>(); std::shared_ptr<storm::models::sparse::Model<storm::RationalFunction>> model = storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::translateProgram(program.get(), options)->as<storm::models::sparse::Model<storm::RationalFunction>>();
ASSERT_EQ(storm::models::ModelType::Dtmc, model->getType()); ASSERT_EQ(storm::models::ModelType::Dtmc, model->getType());
std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> dtmc = model->template as<storm::models::sparse::Dtmc<storm::RationalFunction>>(); std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> dtmc = model->template as<storm::models::sparse::Dtmc<storm::RationalFunction>>();
storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double> modelchecker(*dtmc);
storm::modelchecker::region::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double> modelchecker(*dtmc);
ASSERT_TRUE(modelchecker.canHandle(*formulas[0])); ASSERT_TRUE(modelchecker.canHandle(*formulas[0]));
modelchecker.specifyFormula(formulas[0]); modelchecker.specifyFormula(formulas[0]);
//start testing //start testing
auto allSatRegion=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.7<=pK<=0.875,0.75<=TOMsg<=0.95");
auto exBothRegion=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.6<=pK<=0.9,0.5<=TOMsg<=0.95");
auto exBothHardRegion=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.5<=pK<=0.75,0.3<=TOMsg<=0.4"); //this region has a local maximum!
auto allVioRegion=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.1<=pK<=0.3,0.2<=TOMsg<=0.3");
EXPECT_NEAR(4.367791292, modelchecker.getReachabilityValue<double>(allSatRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(4.367791292, modelchecker.getReachabilityValue<double>(allSatRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(3.044795147, modelchecker.getReachabilityValue<double>(allSatRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(3.044795147, modelchecker.getReachabilityValue<double>(allSatRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(3.182535759, modelchecker.getReachabilityValue<double>(exBothRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(3.182535759, modelchecker.getReachabilityValue<double>(exBothRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(2.609602197, modelchecker.getReachabilityValue<double>(exBothRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(2.609602197, modelchecker.getReachabilityValue<double>(exBothRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(1.842551039, modelchecker.getReachabilityValue<double>(exBothHardRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(1.842551039, modelchecker.getReachabilityValue<double>(exBothHardRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(2.453500364, modelchecker.getReachabilityValue<double>(exBothHardRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(2.453500364, modelchecker.getReachabilityValue<double>(exBothHardRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.6721974438, modelchecker.getReachabilityValue<double>(allVioRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(0.6721974438, modelchecker.getReachabilityValue<double>(allVioRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(1.308324558, modelchecker.getReachabilityValue<double>(allVioRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(1.308324558, modelchecker.getReachabilityValue<double>(allVioRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
auto allSatRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.7<=pK<=0.875,0.75<=TOMsg<=0.95");
auto exBothRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.6<=pK<=0.9,0.5<=TOMsg<=0.95");
auto exBothHardRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.5<=pK<=0.75,0.3<=TOMsg<=0.4"); //this region has a local maximum!
auto allVioRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.1<=pK<=0.3,0.2<=TOMsg<=0.3");
EXPECT_NEAR(4.367791292, modelchecker.getReachabilityValue(allSatRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(4.367791292, modelchecker.getReachabilityValue(allSatRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(3.044795147, modelchecker.getReachabilityValue(allSatRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(3.044795147, modelchecker.getReachabilityValue(allSatRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(3.182535759, modelchecker.getReachabilityValue(exBothRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(3.182535759, modelchecker.getReachabilityValue(exBothRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(2.609602197, modelchecker.getReachabilityValue(exBothRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(2.609602197, modelchecker.getReachabilityValue(exBothRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(1.842551039, modelchecker.getReachabilityValue(exBothHardRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(1.842551039, modelchecker.getReachabilityValue(exBothHardRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(2.453500364, modelchecker.getReachabilityValue(exBothHardRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(2.453500364, modelchecker.getReachabilityValue(exBothHardRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.6721974438, modelchecker.getReachabilityValue(allVioRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(0.6721974438, modelchecker.getReachabilityValue(allVioRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(1.308324558, modelchecker.getReachabilityValue(allVioRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(1.308324558, modelchecker.getReachabilityValue(allVioRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
//test approximative method //test approximative method
storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::TESTFIRST, storm::settings::modules::RegionSettings::SampleMode::INSTANTIATE, storm::settings::modules::RegionSettings::SmtMode::OFF); storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::TESTFIRST, storm::settings::modules::RegionSettings::SampleMode::INSTANTIATE, storm::settings::modules::RegionSettings::SmtMode::OFF);
@ -139,44 +139,44 @@ TEST(SparseDtmcRegionModelCheckerTest, Brp_Rew) {
ASSERT_TRUE(storm::settings::regionSettings().doSample()); ASSERT_TRUE(storm::settings::regionSettings().doSample());
ASSERT_FALSE(storm::settings::regionSettings().doSmt()); ASSERT_FALSE(storm::settings::regionSettings().doSmt());
modelchecker.checkRegion(allSatRegion); modelchecker.checkRegion(allSatRegion);
EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLSAT), allSatRegion.getCheckResult());
EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLSAT), allSatRegion.getCheckResult());
modelchecker.checkRegion(exBothRegion); modelchecker.checkRegion(exBothRegion);
EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::EXISTSBOTH), exBothRegion.getCheckResult());
EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::EXISTSBOTH), exBothRegion.getCheckResult());
modelchecker.checkRegion(exBothHardRegion); modelchecker.checkRegion(exBothHardRegion);
//At this moment, Approximation should not be able to get a result for this region. (However, it is not wrong if it can) //At this moment, Approximation should not be able to get a result for this region. (However, it is not wrong if it can)
EXPECT_TRUE( EXPECT_TRUE(
(exBothHardRegion.getCheckResult()==(storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::EXISTSBOTH)) ||
(exBothHardRegion.getCheckResult()==(storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::EXISTSVIOLATED))
(exBothHardRegion.getCheckResult()==(storm::modelchecker::region::RegionCheckResult::EXISTSBOTH)) ||
(exBothHardRegion.getCheckResult()==(storm::modelchecker::region::RegionCheckResult::EXISTSVIOLATED))
); );
modelchecker.checkRegion(allVioRegion); modelchecker.checkRegion(allVioRegion);
EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLVIOLATED), allVioRegion.getCheckResult());
EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLVIOLATED), allVioRegion.getCheckResult());
//test smt method (the regions need to be created again, because the old ones have some information stored in their internal state) //test smt method (the regions need to be created again, because the old ones have some information stored in their internal state)
auto allSatRegionSmt=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.7<=pK<=0.9,0.75<=TOMsg<=0.95");
auto exBothRegionSmt=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.3<=pK<=0.5,0.5<=TOMsg<=0.75");
auto exBothHardRegionSmt=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.5<=pK<=0.75,0.3<=TOMsg<=0.4"); //this region has a local maximum!
auto allVioRegionSmt=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.1<=pK<=0.3,0.2<=TOMsg<=0.3");
auto allSatRegionSmt=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.7<=pK<=0.9,0.75<=TOMsg<=0.95");
auto exBothRegionSmt=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.3<=pK<=0.5,0.5<=TOMsg<=0.75");
auto exBothHardRegionSmt=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.5<=pK<=0.75,0.3<=TOMsg<=0.4"); //this region has a local maximum!
auto allVioRegionSmt=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.1<=pK<=0.3,0.2<=TOMsg<=0.3");
storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::OFF, storm::settings::modules::RegionSettings::SampleMode::EVALUATE, storm::settings::modules::RegionSettings::SmtMode::FUNCTION); storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::OFF, storm::settings::modules::RegionSettings::SampleMode::EVALUATE, storm::settings::modules::RegionSettings::SmtMode::FUNCTION);
ASSERT_FALSE(storm::settings::regionSettings().doApprox()); ASSERT_FALSE(storm::settings::regionSettings().doApprox());
ASSERT_TRUE(storm::settings::regionSettings().doSample()); ASSERT_TRUE(storm::settings::regionSettings().doSample());
ASSERT_TRUE(storm::settings::regionSettings().doSmt()); ASSERT_TRUE(storm::settings::regionSettings().doSmt());
modelchecker.checkRegion(allSatRegionSmt); modelchecker.checkRegion(allSatRegionSmt);
//smt EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLSAT), allSatRegionSmt.getCheckResult());
//smt EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLSAT), allSatRegionSmt.getCheckResult());
modelchecker.checkRegion(exBothRegionSmt); modelchecker.checkRegion(exBothRegionSmt);
//smt EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::EXISTSBOTH), exBothRegionSmt.getCheckResult());
//smt EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::EXISTSBOTH), exBothRegionSmt.getCheckResult());
modelchecker.checkRegion(exBothHardRegionSmt); modelchecker.checkRegion(exBothHardRegionSmt);
//smt EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::EXISTSBOTH), exBothHardRegionSmt.getCheckResult());
//smt EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::EXISTSBOTH), exBothHardRegionSmt.getCheckResult());
modelchecker.checkRegion(allVioRegionSmt); modelchecker.checkRegion(allVioRegionSmt);
//smt EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLVIOLATED), allVioRegionSmt.getCheckResult());
//smt EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLVIOLATED), allVioRegionSmt.getCheckResult());
//test smt + approx //test smt + approx
auto exBothHardRegionSmtApp=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.5<=pK<=0.75,0.3<=TOMsg<=0.4"); //this region has a local maximum!
auto exBothHardRegionSmtApp=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.5<=pK<=0.75,0.3<=TOMsg<=0.4"); //this region has a local maximum!
storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::TESTFIRST, storm::settings::modules::RegionSettings::SampleMode::EVALUATE, storm::settings::modules::RegionSettings::SmtMode::FUNCTION); storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::TESTFIRST, storm::settings::modules::RegionSettings::SampleMode::EVALUATE, storm::settings::modules::RegionSettings::SmtMode::FUNCTION);
ASSERT_TRUE(storm::settings::regionSettings().doApprox()); ASSERT_TRUE(storm::settings::regionSettings().doApprox());
ASSERT_TRUE(storm::settings::regionSettings().doSample()); ASSERT_TRUE(storm::settings::regionSettings().doSample());
ASSERT_TRUE(storm::settings::regionSettings().doSmt()); ASSERT_TRUE(storm::settings::regionSettings().doSmt());
modelchecker.checkRegion(exBothHardRegionSmt); modelchecker.checkRegion(exBothHardRegionSmt);
//smt EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::EXISTSBOTH), exBothHardRegionSmtApp.getCheckResult());
//smt EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::EXISTSBOTH), exBothHardRegionSmtApp.getCheckResult());
storm::settings::mutableRegionSettings().resetModes(); storm::settings::mutableRegionSettings().resetModes();
@ -199,15 +199,15 @@ TEST(SparseDtmcRegionModelCheckerTest, Brp_Rew_Infty) {
std::shared_ptr<storm::models::sparse::Model<storm::RationalFunction>> model = storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::translateProgram(program.get(), options)->as<storm::models::sparse::Model<storm::RationalFunction>>(); std::shared_ptr<storm::models::sparse::Model<storm::RationalFunction>> model = storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::translateProgram(program.get(), options)->as<storm::models::sparse::Model<storm::RationalFunction>>();
ASSERT_EQ(storm::models::ModelType::Dtmc, model->getType()); ASSERT_EQ(storm::models::ModelType::Dtmc, model->getType());
std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> dtmc = model->template as<storm::models::sparse::Dtmc<storm::RationalFunction>>(); std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> dtmc = model->template as<storm::models::sparse::Dtmc<storm::RationalFunction>>();
storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double> modelchecker(*dtmc);
storm::modelchecker::region::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double> modelchecker(*dtmc);
ASSERT_TRUE(modelchecker.canHandle(*formulas[0])); ASSERT_TRUE(modelchecker.canHandle(*formulas[0]));
modelchecker.specifyFormula(formulas[0]); modelchecker.specifyFormula(formulas[0]);
//start testing //start testing
auto allSatRegion=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("");
auto allSatRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("");
EXPECT_EQ(storm::utility::infinity<double>(), modelchecker.getReachabilityValue<double>(allSatRegion.getLowerBounds(), false)); //instantiation of sampling model
EXPECT_EQ(storm::utility::infinity<double>(), modelchecker.getReachabilityValue<double>(allSatRegion.getLowerBounds(), true)); //instantiation of sampling model
EXPECT_EQ(storm::utility::infinity<double>(), modelchecker.getReachabilityValue(allSatRegion.getLowerBounds(), false)); //instantiation of sampling model
EXPECT_EQ(storm::utility::infinity<double>(), modelchecker.getReachabilityValue(allSatRegion.getLowerBounds(), true)); //instantiation of sampling model
//test approximative method //test approximative method
storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::TESTFIRST, storm::settings::modules::RegionSettings::SampleMode::INSTANTIATE, storm::settings::modules::RegionSettings::SmtMode::OFF); storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::TESTFIRST, storm::settings::modules::RegionSettings::SampleMode::INSTANTIATE, storm::settings::modules::RegionSettings::SmtMode::OFF);
@ -215,16 +215,16 @@ TEST(SparseDtmcRegionModelCheckerTest, Brp_Rew_Infty) {
ASSERT_TRUE(storm::settings::regionSettings().doSample()); ASSERT_TRUE(storm::settings::regionSettings().doSample());
ASSERT_FALSE(storm::settings::regionSettings().doSmt()); ASSERT_FALSE(storm::settings::regionSettings().doSmt());
modelchecker.checkRegion(allSatRegion); modelchecker.checkRegion(allSatRegion);
EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLSAT), allSatRegion.getCheckResult());
EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLSAT), allSatRegion.getCheckResult());
//test smt method (the regions need to be created again, because the old ones have some information stored in their internal state) //test smt method (the regions need to be created again, because the old ones have some information stored in their internal state)
auto allSatRegionSmt=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("");
auto allSatRegionSmt=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("");
storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::OFF, storm::settings::modules::RegionSettings::SampleMode::EVALUATE, storm::settings::modules::RegionSettings::SmtMode::FUNCTION); storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::OFF, storm::settings::modules::RegionSettings::SampleMode::EVALUATE, storm::settings::modules::RegionSettings::SmtMode::FUNCTION);
ASSERT_FALSE(storm::settings::regionSettings().doApprox()); ASSERT_FALSE(storm::settings::regionSettings().doApprox());
ASSERT_TRUE(storm::settings::regionSettings().doSample()); ASSERT_TRUE(storm::settings::regionSettings().doSample());
ASSERT_TRUE(storm::settings::regionSettings().doSmt()); ASSERT_TRUE(storm::settings::regionSettings().doSmt());
modelchecker.checkRegion(allSatRegionSmt); modelchecker.checkRegion(allSatRegionSmt);
//smt EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLSAT), allSatRegionSmt.getCheckResult());
//smt EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLSAT), allSatRegionSmt.getCheckResult());
storm::settings::mutableRegionSettings().resetModes(); storm::settings::mutableRegionSettings().resetModes();
} }
@ -246,21 +246,21 @@ TEST(SparseDtmcRegionModelCheckerTest, Brp_Rew_4Par) {
std::shared_ptr<storm::models::sparse::Model<storm::RationalFunction>> model = storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::translateProgram(program.get(), options)->as<storm::models::sparse::Model<storm::RationalFunction>>(); std::shared_ptr<storm::models::sparse::Model<storm::RationalFunction>> model = storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::translateProgram(program.get(), options)->as<storm::models::sparse::Model<storm::RationalFunction>>();
ASSERT_EQ(storm::models::ModelType::Dtmc, model->getType()); ASSERT_EQ(storm::models::ModelType::Dtmc, model->getType());
std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> dtmc = model->template as<storm::models::sparse::Dtmc<storm::RationalFunction>>(); std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> dtmc = model->template as<storm::models::sparse::Dtmc<storm::RationalFunction>>();
storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double> modelchecker(*dtmc);
storm::modelchecker::region::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double> modelchecker(*dtmc);
ASSERT_TRUE(modelchecker.canHandle(*formulas[0])); ASSERT_TRUE(modelchecker.canHandle(*formulas[0]));
modelchecker.specifyFormula(formulas[0]); modelchecker.specifyFormula(formulas[0]);
//start testing //start testing
auto allSatRegion=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.7<=pK<=0.9,0.6<=pL<=0.85,0.9<=TOMsg<=0.95,0.85<=TOAck<=0.9");
auto exBothRegion=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.1<=pK<=0.7,0.2<=pL<=0.8,0.15<=TOMsg<=0.65,0.3<=TOAck<=0.9");
auto allVioRegion=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.1<=pK<=0.4,0.2<=pL<=0.3,0.15<=TOMsg<=0.3,0.1<=TOAck<=0.2");
auto allSatRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.7<=pK<=0.9,0.6<=pL<=0.85,0.9<=TOMsg<=0.95,0.85<=TOAck<=0.9");
auto exBothRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.1<=pK<=0.7,0.2<=pL<=0.8,0.15<=TOMsg<=0.65,0.3<=TOAck<=0.9");
auto allVioRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.1<=pK<=0.4,0.2<=pL<=0.3,0.15<=TOMsg<=0.3,0.1<=TOAck<=0.2");
EXPECT_NEAR(4.834779705, modelchecker.getReachabilityValue<double>(allSatRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(4.834779705, modelchecker.getReachabilityValue<double>(allSatRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(4.674651623, modelchecker.getReachabilityValue<double>(exBothRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(4.674651623, modelchecker.getReachabilityValue<double>(exBothRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.4467496536, modelchecker.getReachabilityValue<double>(allVioRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(0.4467496536, modelchecker.getReachabilityValue<double>(allVioRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(4.834779705, modelchecker.getReachabilityValue(allSatRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(4.834779705, modelchecker.getReachabilityValue(allSatRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(4.674651623, modelchecker.getReachabilityValue(exBothRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(4.674651623, modelchecker.getReachabilityValue(exBothRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.4467496536, modelchecker.getReachabilityValue(allVioRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(0.4467496536, modelchecker.getReachabilityValue(allVioRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
//test approximative method //test approximative method
storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::TESTFIRST, storm::settings::modules::RegionSettings::SampleMode::INSTANTIATE, storm::settings::modules::RegionSettings::SmtMode::OFF); storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::TESTFIRST, storm::settings::modules::RegionSettings::SampleMode::INSTANTIATE, storm::settings::modules::RegionSettings::SmtMode::OFF);
@ -268,26 +268,26 @@ TEST(SparseDtmcRegionModelCheckerTest, Brp_Rew_4Par) {
ASSERT_TRUE(storm::settings::regionSettings().doSample()); ASSERT_TRUE(storm::settings::regionSettings().doSample());
ASSERT_FALSE(storm::settings::regionSettings().doSmt()); ASSERT_FALSE(storm::settings::regionSettings().doSmt());
modelchecker.checkRegion(allSatRegion); modelchecker.checkRegion(allSatRegion);
EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLSAT), allSatRegion.getCheckResult());
EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLSAT), allSatRegion.getCheckResult());
modelchecker.checkRegion(exBothRegion); modelchecker.checkRegion(exBothRegion);
EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::EXISTSBOTH), exBothRegion.getCheckResult());
EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::EXISTSBOTH), exBothRegion.getCheckResult());
modelchecker.checkRegion(allVioRegion); modelchecker.checkRegion(allVioRegion);
EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLVIOLATED), allVioRegion.getCheckResult());
EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLVIOLATED), allVioRegion.getCheckResult());
//test smt method (the regions need to be created again, because the old ones have some information stored in their internal state) //test smt method (the regions need to be created again, because the old ones have some information stored in their internal state)
auto allSatRegionSmt=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.7<=pK<=0.9,0.6<=pL<=0.85,0.9<=TOMsg<=0.95,0.85<=TOAck<=0.9");
auto exBothRegionSmt=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.1<=pK<=0.7,0.2<=pL<=0.8,0.15<=TOMsg<=0.65,0.3<=TOAck<=0.9");
auto allVioRegionSmt=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.1<=pK<=0.4,0.2<=pL<=0.3,0.15<=TOMsg<=0.3,0.1<=TOAck<=0.2");
auto allSatRegionSmt=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.7<=pK<=0.9,0.6<=pL<=0.85,0.9<=TOMsg<=0.95,0.85<=TOAck<=0.9");
auto exBothRegionSmt=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.1<=pK<=0.7,0.2<=pL<=0.8,0.15<=TOMsg<=0.65,0.3<=TOAck<=0.9");
auto allVioRegionSmt=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.1<=pK<=0.4,0.2<=pL<=0.3,0.15<=TOMsg<=0.3,0.1<=TOAck<=0.2");
storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::OFF, storm::settings::modules::RegionSettings::SampleMode::EVALUATE, storm::settings::modules::RegionSettings::SmtMode::FUNCTION); storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::OFF, storm::settings::modules::RegionSettings::SampleMode::EVALUATE, storm::settings::modules::RegionSettings::SmtMode::FUNCTION);
ASSERT_FALSE(storm::settings::regionSettings().doApprox()); ASSERT_FALSE(storm::settings::regionSettings().doApprox());
ASSERT_TRUE(storm::settings::regionSettings().doSample()); ASSERT_TRUE(storm::settings::regionSettings().doSample());
ASSERT_TRUE(storm::settings::regionSettings().doSmt()); ASSERT_TRUE(storm::settings::regionSettings().doSmt());
modelchecker.checkRegion(allSatRegionSmt); modelchecker.checkRegion(allSatRegionSmt);
//smt EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLSAT), allSatRegionSmt.getCheckResult());
//smt EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLSAT), allSatRegionSmt.getCheckResult());
modelchecker.checkRegion(exBothRegionSmt); modelchecker.checkRegion(exBothRegionSmt);
//smt EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::EXISTSBOTH), exBothRegionSmt.getCheckResult());
//smt EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::EXISTSBOTH), exBothRegionSmt.getCheckResult());
modelchecker.checkRegion(allVioRegionSmt); modelchecker.checkRegion(allVioRegionSmt);
//smt EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLVIOLATED), allVioRegionSmt.getCheckResult());
//smt EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLVIOLATED), allVioRegionSmt.getCheckResult());
storm::settings::mutableRegionSettings().resetModes(); storm::settings::mutableRegionSettings().resetModes();
} }
@ -309,28 +309,28 @@ TEST(SparseDtmcRegionModelCheckerTest, Crowds_Prob) {
std::shared_ptr<storm::models::sparse::Model<storm::RationalFunction>> model = storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::translateProgram(program.get(), options)->as<storm::models::sparse::Model<storm::RationalFunction>>(); std::shared_ptr<storm::models::sparse::Model<storm::RationalFunction>> model = storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::translateProgram(program.get(), options)->as<storm::models::sparse::Model<storm::RationalFunction>>();
ASSERT_EQ(storm::models::ModelType::Dtmc, model->getType()); ASSERT_EQ(storm::models::ModelType::Dtmc, model->getType());
std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> dtmc = model->template as<storm::models::sparse::Dtmc<storm::RationalFunction>>(); std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> dtmc = model->template as<storm::models::sparse::Dtmc<storm::RationalFunction>>();
storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double> modelchecker(*dtmc);
storm::modelchecker::region::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double> modelchecker(*dtmc);
ASSERT_TRUE(modelchecker.canHandle(*formulas[0])); ASSERT_TRUE(modelchecker.canHandle(*formulas[0]));
modelchecker.specifyFormula(formulas[0]); modelchecker.specifyFormula(formulas[0]);
//start testing //start testing
auto allSatRegion=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.1<=PF<=0.75,0.15<=badC<=0.2");
auto exBothRegion=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.75<=PF<=0.8,0.2<=badC<=0.3");
auto allVioRegion=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.8<=PF<=0.95,0.2<=badC<=0.2");
auto allVioHardRegion=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.8<=PF<=0.95,0.2<=badC<=0.9");
EXPECT_NEAR(0.1734086422, modelchecker.getReachabilityValue<double>(allSatRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(0.1734086422, modelchecker.getReachabilityValue<double>(allSatRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.47178, modelchecker.getReachabilityValue<double>(allSatRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.47178, modelchecker.getReachabilityValue<double>(allSatRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.7085157883, modelchecker.getReachabilityValue<double>(exBothRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.7085157883, modelchecker.getReachabilityValue<double>(exBothRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.5095205203, modelchecker.getReachabilityValue<double>(allVioRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(0.5095205203, modelchecker.getReachabilityValue<double>(allVioRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.6819701472, modelchecker.getReachabilityValue<double>(allVioRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(0.6819701472, modelchecker.getReachabilityValue<double>(allVioRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.999895897, modelchecker.getReachabilityValue<double>(allVioHardRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.999895897, modelchecker.getReachabilityValue<double>(allVioHardRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
auto allSatRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.1<=PF<=0.75,0.15<=badC<=0.2");
auto exBothRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.75<=PF<=0.8,0.2<=badC<=0.3");
auto allVioRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.8<=PF<=0.95,0.2<=badC<=0.2");
auto allVioHardRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.8<=PF<=0.95,0.2<=badC<=0.9");
EXPECT_NEAR(0.1734086422, modelchecker.getReachabilityValue(allSatRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(0.1734086422, modelchecker.getReachabilityValue(allSatRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.47178, modelchecker.getReachabilityValue(allSatRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.47178, modelchecker.getReachabilityValue(allSatRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.7085157883, modelchecker.getReachabilityValue(exBothRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.7085157883, modelchecker.getReachabilityValue(exBothRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.5095205203, modelchecker.getReachabilityValue(allVioRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(0.5095205203, modelchecker.getReachabilityValue(allVioRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.6819701472, modelchecker.getReachabilityValue(allVioRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(0.6819701472, modelchecker.getReachabilityValue(allVioRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.999895897, modelchecker.getReachabilityValue(allVioHardRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.999895897, modelchecker.getReachabilityValue(allVioHardRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
//test approximative method //test approximative method
storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::TESTFIRST, storm::settings::modules::RegionSettings::SampleMode::INSTANTIATE, storm::settings::modules::RegionSettings::SmtMode::OFF); storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::TESTFIRST, storm::settings::modules::RegionSettings::SampleMode::INSTANTIATE, storm::settings::modules::RegionSettings::SmtMode::OFF);
@ -338,44 +338,44 @@ TEST(SparseDtmcRegionModelCheckerTest, Crowds_Prob) {
ASSERT_TRUE(storm::settings::regionSettings().doSample()); ASSERT_TRUE(storm::settings::regionSettings().doSample());
ASSERT_FALSE(storm::settings::regionSettings().doSmt()); ASSERT_FALSE(storm::settings::regionSettings().doSmt());
modelchecker.checkRegion(allSatRegion); modelchecker.checkRegion(allSatRegion);
EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLSAT), allSatRegion.getCheckResult());
EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLSAT), allSatRegion.getCheckResult());
modelchecker.checkRegion(exBothRegion); modelchecker.checkRegion(exBothRegion);
EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::EXISTSBOTH), exBothRegion.getCheckResult());
EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::EXISTSBOTH), exBothRegion.getCheckResult());
modelchecker.checkRegion(allVioRegion); modelchecker.checkRegion(allVioRegion);
EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLVIOLATED), allVioRegion.getCheckResult());
EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLVIOLATED), allVioRegion.getCheckResult());
modelchecker.checkRegion(allVioHardRegion); modelchecker.checkRegion(allVioHardRegion);
//At this moment, Approximation should not be able to get a result for this region. (However, it is not wrong if it can) //At this moment, Approximation should not be able to get a result for this region. (However, it is not wrong if it can)
EXPECT_TRUE( EXPECT_TRUE(
(allVioHardRegion.getCheckResult()==(storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLVIOLATED)) ||
(allVioHardRegion.getCheckResult()==(storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::EXISTSVIOLATED))
(allVioHardRegion.getCheckResult()==(storm::modelchecker::region::RegionCheckResult::ALLVIOLATED)) ||
(allVioHardRegion.getCheckResult()==(storm::modelchecker::region::RegionCheckResult::EXISTSVIOLATED))
); );
//test smt method (the regions need to be created again, because the old ones have some information stored in their internal state) //test smt method (the regions need to be created again, because the old ones have some information stored in their internal state)
auto allSatRegionSmt=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.1<=PF<=0.75,0.15<=badC<=0.2");
auto exBothRegionSmt=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.75<=PF<=0.8,0.2<=badC<=0.3");
auto allVioRegionSmt=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.8<=PF<=0.95,0.2<=badC<=0.2");
auto allVioHardRegionSmt=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.8<=PF<=0.95,0.2<=badC<=0.9");
auto allSatRegionSmt=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.1<=PF<=0.75,0.15<=badC<=0.2");
auto exBothRegionSmt=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.75<=PF<=0.8,0.2<=badC<=0.3");
auto allVioRegionSmt=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.8<=PF<=0.95,0.2<=badC<=0.2");
auto allVioHardRegionSmt=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.8<=PF<=0.95,0.2<=badC<=0.9");
storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::OFF, storm::settings::modules::RegionSettings::SampleMode::EVALUATE, storm::settings::modules::RegionSettings::SmtMode::FUNCTION); storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::OFF, storm::settings::modules::RegionSettings::SampleMode::EVALUATE, storm::settings::modules::RegionSettings::SmtMode::FUNCTION);
ASSERT_FALSE(storm::settings::regionSettings().doApprox()); ASSERT_FALSE(storm::settings::regionSettings().doApprox());
ASSERT_TRUE(storm::settings::regionSettings().doSample()); ASSERT_TRUE(storm::settings::regionSettings().doSample());
ASSERT_TRUE(storm::settings::regionSettings().doSmt()); ASSERT_TRUE(storm::settings::regionSettings().doSmt());
modelchecker.checkRegion(allSatRegionSmt); modelchecker.checkRegion(allSatRegionSmt);
//smt EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLSAT), allSatRegionSmt.getCheckResult());
//smt EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLSAT), allSatRegionSmt.getCheckResult());
modelchecker.checkRegion(exBothRegionSmt); modelchecker.checkRegion(exBothRegionSmt);
//smt EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::EXISTSBOTH), exBothRegionSmt.getCheckResult());
//smt EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::EXISTSBOTH), exBothRegionSmt.getCheckResult());
modelchecker.checkRegion(allVioRegionSmt); modelchecker.checkRegion(allVioRegionSmt);
//smt EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLVIOLATED), allVioRegionSmt.getCheckResult());
//smt EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLVIOLATED), allVioRegionSmt.getCheckResult());
modelchecker.checkRegion(allVioHardRegionSmt); modelchecker.checkRegion(allVioHardRegionSmt);
//smt EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLVIOLATED), allVioHardRegionSmt.getCheckResult());
//smt EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLVIOLATED), allVioHardRegionSmt.getCheckResult());
//test smt + approx //test smt + approx
auto allVioHardRegionSmtApp=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.8<=PF<=0.95,0.2<=badC<=0.9");
auto allVioHardRegionSmtApp=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.8<=PF<=0.95,0.2<=badC<=0.9");
storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::TESTFIRST, storm::settings::modules::RegionSettings::SampleMode::EVALUATE, storm::settings::modules::RegionSettings::SmtMode::FUNCTION); storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::TESTFIRST, storm::settings::modules::RegionSettings::SampleMode::EVALUATE, storm::settings::modules::RegionSettings::SmtMode::FUNCTION);
ASSERT_TRUE(storm::settings::regionSettings().doApprox()); ASSERT_TRUE(storm::settings::regionSettings().doApprox());
ASSERT_TRUE(storm::settings::regionSettings().doSample()); ASSERT_TRUE(storm::settings::regionSettings().doSample());
ASSERT_TRUE(storm::settings::regionSettings().doSmt()); ASSERT_TRUE(storm::settings::regionSettings().doSmt());
modelchecker.checkRegion(allVioHardRegionSmt); modelchecker.checkRegion(allVioHardRegionSmt);
//smt EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLVIOLATED), allVioHardRegionSmtApp.getCheckResult());
//smt EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLVIOLATED), allVioHardRegionSmtApp.getCheckResult());
storm::settings::mutableRegionSettings().resetModes(); storm::settings::mutableRegionSettings().resetModes();
} }
@ -397,23 +397,23 @@ TEST(SparseDtmcRegionModelCheckerTest, Crowds_Prob_1Par) {
std::shared_ptr<storm::models::sparse::Model<storm::RationalFunction>> model = storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::translateProgram(program.get(), options)->as<storm::models::sparse::Model<storm::RationalFunction>>(); std::shared_ptr<storm::models::sparse::Model<storm::RationalFunction>> model = storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::translateProgram(program.get(), options)->as<storm::models::sparse::Model<storm::RationalFunction>>();
ASSERT_EQ(storm::models::ModelType::Dtmc, model->getType()); ASSERT_EQ(storm::models::ModelType::Dtmc, model->getType());
std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> dtmc = model->template as<storm::models::sparse::Dtmc<storm::RationalFunction>>(); std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> dtmc = model->template as<storm::models::sparse::Dtmc<storm::RationalFunction>>();
storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double> modelchecker(*dtmc);
storm::modelchecker::region::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double> modelchecker(*dtmc);
ASSERT_TRUE(modelchecker.canHandle(*formulas[0])); ASSERT_TRUE(modelchecker.canHandle(*formulas[0]));
modelchecker.specifyFormula(formulas[0]); modelchecker.specifyFormula(formulas[0]);
//start testing //start testing
auto allSatRegion=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.9<=PF<=0.99");
auto exBothRegion=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.8<=PF<=0.9");
auto allVioRegion=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.01<=PF<=0.8");
EXPECT_NEAR(0.8430128158, modelchecker.getReachabilityValue<double>(allSatRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.8430128158, modelchecker.getReachabilityValue<double>(allSatRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.7731321947, modelchecker.getReachabilityValue<double>(exBothRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.7731321947, modelchecker.getReachabilityValue<double>(exBothRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.4732302663, modelchecker.getReachabilityValue<double>(allVioRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(0.4732302663, modelchecker.getReachabilityValue<double>(allVioRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.7085157883, modelchecker.getReachabilityValue<double>(allVioRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(0.7085157883, modelchecker.getReachabilityValue<double>(allVioRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
auto allSatRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.9<=PF<=0.99");
auto exBothRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.8<=PF<=0.9");
auto allVioRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.01<=PF<=0.8");
EXPECT_NEAR(0.8430128158, modelchecker.getReachabilityValue(allSatRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.8430128158, modelchecker.getReachabilityValue(allSatRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.7731321947, modelchecker.getReachabilityValue(exBothRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.7731321947, modelchecker.getReachabilityValue(exBothRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.4732302663, modelchecker.getReachabilityValue(allVioRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(0.4732302663, modelchecker.getReachabilityValue(allVioRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.7085157883, modelchecker.getReachabilityValue(allVioRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //instantiation of sampling model
EXPECT_NEAR(0.7085157883, modelchecker.getReachabilityValue(allVioRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
//test approximative method //test approximative method
storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::TESTFIRST, storm::settings::modules::RegionSettings::SampleMode::INSTANTIATE, storm::settings::modules::RegionSettings::SmtMode::OFF); storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::TESTFIRST, storm::settings::modules::RegionSettings::SampleMode::INSTANTIATE, storm::settings::modules::RegionSettings::SmtMode::OFF);
@ -421,26 +421,26 @@ TEST(SparseDtmcRegionModelCheckerTest, Crowds_Prob_1Par) {
ASSERT_TRUE(storm::settings::regionSettings().doSample()); ASSERT_TRUE(storm::settings::regionSettings().doSample());
ASSERT_FALSE(storm::settings::regionSettings().doSmt()); ASSERT_FALSE(storm::settings::regionSettings().doSmt());
modelchecker.checkRegion(allSatRegion); modelchecker.checkRegion(allSatRegion);
EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLSAT), allSatRegion.getCheckResult());
EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLSAT), allSatRegion.getCheckResult());
modelchecker.checkRegion(exBothRegion); modelchecker.checkRegion(exBothRegion);
EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::EXISTSBOTH), exBothRegion.getCheckResult());
EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::EXISTSBOTH), exBothRegion.getCheckResult());
modelchecker.checkRegion(allVioRegion); modelchecker.checkRegion(allVioRegion);
EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLVIOLATED), allVioRegion.getCheckResult());
EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLVIOLATED), allVioRegion.getCheckResult());
//test smt method (the regions need to be created again, because the old ones have some information stored in their internal state) //test smt method (the regions need to be created again, because the old ones have some information stored in their internal state)
auto allSatRegionSmt=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.9<=PF<=0.99");
auto exBothRegionSmt=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.8<=PF<=0.9");
auto allVioRegionSmt=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("0.01<=PF<=0.8");
auto allSatRegionSmt=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.9<=PF<=0.99");
auto exBothRegionSmt=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.8<=PF<=0.9");
auto allVioRegionSmt=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.01<=PF<=0.8");
storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::OFF, storm::settings::modules::RegionSettings::SampleMode::EVALUATE, storm::settings::modules::RegionSettings::SmtMode::FUNCTION); storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::OFF, storm::settings::modules::RegionSettings::SampleMode::EVALUATE, storm::settings::modules::RegionSettings::SmtMode::FUNCTION);
ASSERT_FALSE(storm::settings::regionSettings().doApprox()); ASSERT_FALSE(storm::settings::regionSettings().doApprox());
ASSERT_TRUE(storm::settings::regionSettings().doSample()); ASSERT_TRUE(storm::settings::regionSettings().doSample());
ASSERT_TRUE(storm::settings::regionSettings().doSmt()); ASSERT_TRUE(storm::settings::regionSettings().doSmt());
modelchecker.checkRegion(allSatRegionSmt); modelchecker.checkRegion(allSatRegionSmt);
//smt EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLSAT), allSatRegionSmt.getCheckResult());
//smt EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLSAT), allSatRegionSmt.getCheckResult());
modelchecker.checkRegion(exBothRegionSmt); modelchecker.checkRegion(exBothRegionSmt);
//smt EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::EXISTSBOTH), exBothRegionSmt.getCheckResult());
//smt EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::EXISTSBOTH), exBothRegionSmt.getCheckResult());
modelchecker.checkRegion(allVioRegionSmt); modelchecker.checkRegion(allVioRegionSmt);
//smt EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLVIOLATED), allVioRegionSmt.getCheckResult());
//smt EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLVIOLATED), allVioRegionSmt.getCheckResult());
storm::settings::mutableRegionSettings().resetModes(); storm::settings::mutableRegionSettings().resetModes();
} }
@ -462,17 +462,17 @@ TEST(SparseDtmcRegionModelCheckerTest, Crowds_Prob_Const) {
std::shared_ptr<storm::models::sparse::Model<storm::RationalFunction>> model = storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::translateProgram(program.get(), options)->as<storm::models::sparse::Model<storm::RationalFunction>>(); std::shared_ptr<storm::models::sparse::Model<storm::RationalFunction>> model = storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::translateProgram(program.get(), options)->as<storm::models::sparse::Model<storm::RationalFunction>>();
ASSERT_EQ(storm::models::ModelType::Dtmc, model->getType()); ASSERT_EQ(storm::models::ModelType::Dtmc, model->getType());
std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> dtmc = model->template as<storm::models::sparse::Dtmc<storm::RationalFunction>>(); std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> dtmc = model->template as<storm::models::sparse::Dtmc<storm::RationalFunction>>();
storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double> modelchecker(*dtmc);
storm::modelchecker::region::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double> modelchecker(*dtmc);
ASSERT_TRUE(modelchecker.canHandle(*formulas[0])); ASSERT_TRUE(modelchecker.canHandle(*formulas[0]));
modelchecker.specifyFormula(formulas[0]); modelchecker.specifyFormula(formulas[0]);
//start testing //start testing
auto allSatRegion=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("");
auto allSatRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("");
EXPECT_NEAR(0.6119660237, modelchecker.getReachabilityValue<double>(allSatRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.6119660237, modelchecker.getReachabilityValue<double>(allSatRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.6119660237, modelchecker.getReachabilityValue<double>(allSatRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.6119660237, modelchecker.getReachabilityValue<double>(allSatRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.6119660237, modelchecker.getReachabilityValue(allSatRegion.getUpperBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.6119660237, modelchecker.getReachabilityValue(allSatRegion.getUpperBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.6119660237, modelchecker.getReachabilityValue(allSatRegion.getLowerBounds(), false), storm::settings::generalSettings().getPrecision()); //evaluation of function
EXPECT_NEAR(0.6119660237, modelchecker.getReachabilityValue(allSatRegion.getLowerBounds(), true), storm::settings::generalSettings().getPrecision()); //evaluation of function
//test approximative method //test approximative method
storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::TESTFIRST, storm::settings::modules::RegionSettings::SampleMode::INSTANTIATE, storm::settings::modules::RegionSettings::SmtMode::OFF); storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::TESTFIRST, storm::settings::modules::RegionSettings::SampleMode::INSTANTIATE, storm::settings::modules::RegionSettings::SmtMode::OFF);
@ -480,16 +480,16 @@ TEST(SparseDtmcRegionModelCheckerTest, Crowds_Prob_Const) {
ASSERT_TRUE(storm::settings::regionSettings().doSample()); ASSERT_TRUE(storm::settings::regionSettings().doSample());
ASSERT_FALSE(storm::settings::regionSettings().doSmt()); ASSERT_FALSE(storm::settings::regionSettings().doSmt());
modelchecker.checkRegion(allSatRegion); modelchecker.checkRegion(allSatRegion);
EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLSAT), allSatRegion.getCheckResult());
EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLSAT), allSatRegion.getCheckResult());
//test smt method (the regions need to be created again, because the old ones have some information stored in their internal state) //test smt method (the regions need to be created again, because the old ones have some information stored in their internal state)
auto allSatRegionSmt=storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::ParameterRegion::parseRegion("");
auto allSatRegionSmt=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("");
storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::OFF, storm::settings::modules::RegionSettings::SampleMode::EVALUATE, storm::settings::modules::RegionSettings::SmtMode::FUNCTION); storm::settings::mutableRegionSettings().modifyModes(storm::settings::modules::RegionSettings::ApproxMode::OFF, storm::settings::modules::RegionSettings::SampleMode::EVALUATE, storm::settings::modules::RegionSettings::SmtMode::FUNCTION);
ASSERT_FALSE(storm::settings::regionSettings().doApprox()); ASSERT_FALSE(storm::settings::regionSettings().doApprox());
ASSERT_TRUE(storm::settings::regionSettings().doSample()); ASSERT_TRUE(storm::settings::regionSettings().doSample());
ASSERT_TRUE(storm::settings::regionSettings().doSmt()); ASSERT_TRUE(storm::settings::regionSettings().doSmt());
modelchecker.checkRegion(allSatRegionSmt); modelchecker.checkRegion(allSatRegionSmt);
//smt EXPECT_EQ((storm::modelchecker::SparseDtmcRegionModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double>::RegionCheckResult::ALLSAT), allSatRegionSmt.getCheckResult());
//smt EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLSAT), allSatRegionSmt.getCheckResult());
storm::settings::mutableRegionSettings().resetModes(); storm::settings::mutableRegionSettings().resetModes();
} }

Loading…
Cancel
Save