Browse Source
Splitted region modelchecker in abstract class and dtmc class (to easily add an mdp class soon)
Splitted region modelchecker in abstract class and dtmc class (to easily add an mdp class soon)
Former-commit-id: e722c8f2bd
main
17 changed files with 2579 additions and 2317 deletions
-
8src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h
-
390src/modelchecker/region/AbstractSparseRegionModelChecker.cpp
-
239src/modelchecker/region/AbstractSparseRegionModelChecker.h
-
554src/modelchecker/region/ApproximationModel.cpp
-
279src/modelchecker/region/ApproximationModel.h
-
440src/modelchecker/region/ParameterRegion.cpp
-
229src/modelchecker/region/ParameterRegion.h
-
42src/modelchecker/region/RegionCheckResult.cpp
-
34src/modelchecker/region/RegionCheckResult.h
-
280src/modelchecker/region/SamplingModel.cpp
-
122src/modelchecker/region/SamplingModel.h
-
1555src/modelchecker/region/SparseDtmcRegionModelChecker.cpp
-
414src/modelchecker/region/SparseDtmcRegionModelChecker.h
-
2src/utility/region.h
-
4src/utility/regions.cpp
-
6src/utility/storm.h
-
298test/functional/modelchecker/SparseDtmcRegionModelCheckerTest.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
|
|||
|
@ -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 */ |
|||
|
@ -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; |
|||
} |
|||
} |
|||
} |
|||
} |
@ -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 */ |
|||
|
1555
src/modelchecker/region/SparseDtmcRegionModelChecker.cpp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,289 +1,155 @@ |
|||
#ifndef 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/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/solver/Smt2SmtSolver.h" |
|||
|
|||
namespace storm { |
|||
namespace modelchecker { |
|||
|
|||
template<typename ParametricSparseModelType, typename ConstantType> |
|||
class SparseDtmcRegionModelChecker { |
|||
public: |
|||
|
|||
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 */ |
|||
}; |
|||
|
|||
class ParameterRegion; |
|||
namespace region { |
|||
template<typename ParametricSparseModelType, typename ConstantType> |
|||
class SparseDtmcRegionModelChecker : public AbstractSparseRegionModelChecker<ParametricSparseModelType, ConstantType> { |
|||
public: |
|||
|
|||
typedef typename ParametricSparseModelType::ValueType ParametricType; |
|||
typedef typename ParametricSparseModelType::RewardModelType ParametricRewardModelType; |
|||
typedef typename storm::utility::region::VariableType<ParametricType> VariableType; |
|||
typedef typename storm::utility::region::CoefficientType<ParametricType> CoefficientType; |
|||
|
|||
explicit SparseDtmcRegionModelChecker(ParametricSparseModelType const& model); |
|||
|
|||
virtual ~SparseDtmcRegionModelChecker(); |
|||
|
|||
/*! |
|||
* 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; |
|||
|
|||
/*! |
|||
* Returns the reachability function. |
|||
* If it is not yet available, it is computed. |
|||
*/ |
|||
std::shared_ptr<ParametricType> const& getReachabilityFunction(); |
|||
|
|||
explicit SparseDtmcRegionModelChecker(storm::models::sparse::Dtmc<ParametricType> const& model); |
|||
|
|||
virtual ~SparseDtmcRegionModelChecker(); |
|||
/*! |
|||
* Returns the reachability Value at the specified point. |
|||
* The given flag decides whether to initialize a sampling model or to evaluate a reachability function. |
|||
* Might invoke sampling model initialization or the computation of the reachability function (if these are not available yet) |
|||
* |
|||
* @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); |
|||
|
|||
/*! |
|||
* 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. |
|||
*/ |
|||
CoefficientType evaluateReachabilityFunction(std::map<VariableType, CoefficientType>const& point); |
|||
|
|||
/*! |
|||
* Checks if the given formula can be handled by This region model checker |
|||
* @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); |
|||
protected: |
|||
|
|||
/*! |
|||
* Checks whether the approximation technique is applicable and whether the model checking result is independent of parameters (i.e., constant) |
|||
* |
|||
* Computes a model with a single target and at most one sink state. |
|||
* Eliminates all states for which the outgoing transitions are constant. |
|||
* If rewards are relevant, transition rewards are transformed to state rewards |
|||
* |
|||
* @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); |
|||
|
|||
/*! |
|||
* 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); |
|||
|
|||
/*! |
|||
* Returns the reachability function. |
|||
* If it is not yet available, it is computed. |
|||
*/ |
|||
std::shared_ptr<ParametricType> const& getReachabilityFunction(); |
|||
|
|||
/*! |
|||
* Returns the reachability Value at the specified point. |
|||
* The given flag decides whether to initialize a sampling model or to evaluate a reachability function. |
|||
* Might invoke sampling model initialization or the computation of the reachability function (if these are not available yet) |
|||
* |
|||
* @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. |
|||
*/ |
|||
template <typename ValueType> |
|||
ValueType getReachabilityValue(std::map<VariableType, CoefficientType>const& point, bool evaluateFunction=false); |
|||
|
|||
/*! |
|||
* Prints statistical information to the given stream. |
|||
*/ |
|||
void printStatisticsToStream(std::ostream& outstream); |
|||
|
|||
|
|||
|
|||
private: |
|||
|
|||
class ApproximationModel; |
|||
class SamplingModel; |
|||
|
|||
|
|||
/*! |
|||
* 1. Analyzes the formula (sets this->specifiedFormulaBound, this->specifiedFormulaCompType) |
|||
* |
|||
* 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. |
|||
* Eliminates all states for which the outgoing transitions are constant. |
|||
* If rewards are relevant, transition rewards are transformed to state rewards |
|||
* |
|||
* @note this->specifiedFormula has to be set accordingly, before calling this function |
|||
*/ |
|||
void preprocess(); |
|||
|
|||
|
|||
/*! |
|||
* Does some sanity checks and preprocessing steps on the currently specified model and |
|||
* reachability probability formula, i.e., |
|||
* * Sets some formula data and that we do not compute rewards |
|||
* * Computes maybeStates and targetStates |
|||
* * Sets the flags that state whether the result is constant and approximation is applicable |
|||
* |
|||
* @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); |
|||
|
|||
|
|||
/*! |
|||
* Does some sanity checks and preprocessing steps on the currently specified model and |
|||
* reachability reward formula, i.e. |
|||
* * Sets some formula data and that we do compute rewards |
|||
* * Computes maybeStates, targetStates |
|||
* * Computes a new stateReward vector that considers state+transition rewards of the original model. (in a sense that we can abstract away from transition rewards) |
|||
* * Sets the flags that state whether the result is constant and approximation is applicable |
|||
* |
|||
* @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); |
|||
|
|||
/*! |
|||
* Computes the reachability function via state elimination |
|||
* @note computeFlagsAndSimplifiedModel should be called before calling this |
|||
*/ |
|||
void computeReachabilityFunction(storm::models::sparse::Dtmc<ParametricType> const& simpleModel); |
|||
|
|||
/*! |
|||
* 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. |
|||
*/ |
|||
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); |
|||
|
|||
/*! |
|||
* 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 |
|||
*/ |
|||
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(); |
|||
|
|||
/*! |
|||
* 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. |
|||
*/ |
|||
bool checkFullSmt(ParameterRegion& region); |
|||
|
|||
//initializes this->smtSolver which can later be used to give an exact result regarding the whole model. |
|||
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 |
|||
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) |
|||
bool isResultInfinity; |
|||
// the smt solver that is used to prove properties with the help of the reachabilityFunction |
|||
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; |
|||
}; |
|||
|
|||
private: |
|||
/*! |
|||
* Does some sanity checks and preprocessing steps on the currently specified model and |
|||
* reachability probability formula, i.e., |
|||
* * Sets some formula data and that we do not compute rewards |
|||
* * Computes maybeStates and targetStates |
|||
* * Sets the flags that state whether the result is constant and approximation is applicable |
|||
* |
|||
* @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, bool& isApproximationApplicable, bool& isResultConstant); |
|||
|
|||
/*! |
|||
* Does some sanity checks and preprocessing steps on the currently specified model and |
|||
* reachability reward formula, i.e. |
|||
* * Sets some formula data and that we do compute rewards |
|||
* * Computes maybeStates, targetStates |
|||
* * Computes a new stateReward vector that considers state+transition rewards of the original model. (in a sense that we can abstract away from transition rewards) |
|||
* * Sets the flags that state whether the result is constant and approximation is applicable |
|||
* |
|||
* @note stateRewards.size will equal to maybeStates.numberOfSetBits |
|||
* |
|||
*/ |
|||
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 |
|||
* @note computeFlagsAndSimplifiedModel should be called before calling this |
|||
*/ |
|||
void computeReachabilityFunction(ParametricSparseModelType const& simpleModel); |
|||
|
|||
/*! |
|||
* 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); |
|||
|
|||
/*! |
|||
* 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); |
|||
|
|||
/*! |
|||
* 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. |
|||
*/ |
|||
bool checkSmt(ParameterRegion<ParametricType>& region); |
|||
|
|||
//initializes this->smtSolver which can later be used to give an exact result regarding the whole model. |
|||
void initializeSMTSolver(); |
|||
|
|||
// The function for the reachability probability (or: reachability reward) in the initial state |
|||
std::shared_ptr<ParametricType> reachabilityFunction; |
|||
// workaround to represent that the result is infinity (utility::infinity<storm::RationalFunction>() does not work at this moment) |
|||
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 |
|||
std::shared_ptr<storm::solver::Smt2SmtSolver> smtSolver; |
|||
|
|||
}; |
|||
} //namespace region |
|||
} // namespace modelchecker |
|||
} // namespace storm |
|||
|
|||
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue