Browse Source

fix for approximation model, additional test for mdps, minor changes

Former-commit-id: cc837ddf3e
main
TimQu 10 years ago
parent
commit
77c2f397a9
  1. 69
      examples/pmdp/consensus/4pars/coin4_2.nm
  2. 69
      examples/pmdp/consensus/4pars/coin4_8.nm
  3. 45
      examples/pmdp/two_dice/two_dice.nm
  4. 12
      src/modelchecker/region/AbstractSparseRegionModelChecker.cpp
  5. 1
      src/modelchecker/region/AbstractSparseRegionModelChecker.h
  6. 35
      src/modelchecker/region/ApproximationModel.cpp
  7. 23
      src/modelchecker/region/ApproximationModel.h
  8. 6
      src/modelchecker/region/SamplingModel.cpp
  9. 11
      src/modelchecker/region/SamplingModel.h
  10. 8
      test/functional/modelchecker/SparseDtmcRegionModelCheckerTest.cpp
  11. 60
      test/functional/modelchecker/SparseMdpRegionModelCheckerTest.cpp

69
examples/pmdp/consensus/4pars/coin4_2.nm

@ -0,0 +1,69 @@
// COIN FLIPPING PROTOCOL FOR POLYNOMIAL RANDOMIZED CONSENSUS [AH90]
// gxn/dxp 20/11/00
mdp
// constants
const int N=4;
const int K=2;
const int range = 2*(K+1)*N;
const int counter_init = (K+1)*N;
const int left = N;
const int right = 2*(K+1)*N - N;
//Coin Probabilities
const double p1;
const double p2;
const double p3;
const double p4;
// shared coin
global counter : [0..range] init counter_init;
module process1
// program counter
pc1 : [0..3];
// 0 - flip
// 1 - write
// 2 - check
// 3 - finished
// local coin
coin1 : [0..1];
// flip coin
[] (pc1=0) -> p1 : (coin1'=0) & (pc1'=1) + 1-p1 : (coin1'=1) & (pc1'=1);
// write tails -1 (reset coin to add regularity)
[] (pc1=1) & (coin1=0) & (counter>0) -> 1 : (counter'=counter-1) & (pc1'=2) & (coin1'=0);
// write heads +1 (reset coin to add regularity)
[] (pc1=1) & (coin1=1) & (counter<range) -> 1 : (counter'=counter+1) & (pc1'=2) & (coin1'=0);
// check
// decide tails
[] (pc1=2) & (counter<=left) -> 1 : (pc1'=3) & (coin1'=0);
// decide heads
[] (pc1=2) & (counter>=right) -> 1 : (pc1'=3) & (coin1'=1);
// flip again
[] (pc1=2) & (counter>left) & (counter<right) -> 1 : (pc1'=0);
// loop (all loop together when done)
[done] (pc1=3) -> 1 : (pc1'=3);
endmodule
// construct remaining processes through renaming
module process2 = process1[pc1=pc2,coin1=coin2,p1=p2] endmodule
module process3 = process1[pc1=pc3,coin1=coin3,p1=p3] endmodule
module process4 = process1[pc1=pc4,coin1=coin4,p1=p4] endmodule
// labels
label "finished" = pc1=3 & pc2=3 & pc3=3 & pc4=3 ;
label "all_coins_equal_0" = coin1=0 & coin2=0 & coin3=0 & coin4=0 ;
label "all_coins_equal_1" = coin1=1 & coin2=1 & coin3=1 & coin4=1 ;
label "agree" = coin1=coin2 & coin2=coin3 & coin3=coin4 ;
label "finish_with_1" = pc1=3 & pc2=3 & pc3=3 & pc4=3 & coin1=1 & coin2=1 & coin3=1 & coin4=1 ;
// rewards
rewards "steps"
true : 1;
endrewards

69
examples/pmdp/consensus/4pars/coin4_8.nm

@ -0,0 +1,69 @@
// COIN FLIPPING PROTOCOL FOR POLYNOMIAL RANDOMIZED CONSENSUS [AH90]
// gxn/dxp 20/11/00
mdp
// constants
const int N=4;
const int K=8;
const int range = 2*(K+1)*N;
const int counter_init = (K+1)*N;
const int left = N;
const int right = 2*(K+1)*N - N;
//Coin Probabilities
const double p1;
const double p2;
const double p3;
const double p4;
// shared coin
global counter : [0..range] init counter_init;
module process1
// program counter
pc1 : [0..3];
// 0 - flip
// 1 - write
// 2 - check
// 3 - finished
// local coin
coin1 : [0..1];
// flip coin
[] (pc1=0) -> p1 : (coin1'=0) & (pc1'=1) + 1-p1 : (coin1'=1) & (pc1'=1);
// write tails -1 (reset coin to add regularity)
[] (pc1=1) & (coin1=0) & (counter>0) -> 1 : (counter'=counter-1) & (pc1'=2) & (coin1'=0);
// write heads +1 (reset coin to add regularity)
[] (pc1=1) & (coin1=1) & (counter<range) -> 1 : (counter'=counter+1) & (pc1'=2) & (coin1'=0);
// check
// decide tails
[] (pc1=2) & (counter<=left) -> 1 : (pc1'=3) & (coin1'=0);
// decide heads
[] (pc1=2) & (counter>=right) -> 1 : (pc1'=3) & (coin1'=1);
// flip again
[] (pc1=2) & (counter>left) & (counter<right) -> 1 : (pc1'=0);
// loop (all loop together when done)
[done] (pc1=3) -> 1 : (pc1'=3);
endmodule
// construct remaining processes through renaming
module process2 = process1[pc1=pc2,coin1=coin2,p1=p2] endmodule
module process3 = process1[pc1=pc3,coin1=coin3,p1=p3] endmodule
module process4 = process1[pc1=pc4,coin1=coin4,p1=p4] endmodule
// labels
label "finished" = pc1=3 & pc2=3 & pc3=3 & pc4=3 ;
label "all_coins_equal_0" = coin1=0 & coin2=0 & coin3=0 & coin4=0 ;
label "all_coins_equal_1" = coin1=1 & coin2=1 & coin3=1 & coin4=1 ;
label "agree" = coin1=coin2 & coin2=coin3 & coin3=coin4 ;
label "finish_with_1" = pc1=3 & pc2=3 & pc3=3 & pc4=3 & coin1=1 & coin2=1 & coin3=1 & coin4=1 ;
// rewards
rewards "steps"
true : 1;
endrewards

45
examples/pmdp/two_dice/two_dice.nm

@ -0,0 +1,45 @@
// sum of two dice as the asynchronous parallel composition of
// two copies of Knuth's model of a fair die using only fair coins
mdp
//Coin Probabilities
const double p1;
const double p2;
module die1
// local state
s1 : [0..7] init 0;
// value of the dice
d1 : [0..6] init 0;
[] s1=0 -> p1 : (s1'=1) + 1-p1 : (s1'=2);
[] s1=1 -> p1 : (s1'=3) + 1-p1 : (s1'=4);
[] s1=2 -> p1 : (s1'=5) + 1-p1 : (s1'=6);
[] s1=3 -> p1 : (s1'=1) + 1-p1 : (s1'=7) & (d1'=1);
[] s1=4 -> p1 : (s1'=7) & (d1'=2) + 1-p1 : (s1'=7) & (d1'=3);
[] s1=5 -> p1 : (s1'=7) & (d1'=4) + 1-p1 : (s1'=7) & (d1'=5);
[] s1=6 -> p1 : (s1'=2) + 1-p1 : (s1'=7) & (d1'=6);
[] s1=7 & s2=7 -> 1: (s1'=7);
endmodule
module die2 = die1 [ s1=s2, s2=s1, d1=d2, p1=p2 ] endmodule
rewards "coinflips"
[] s1<7 | s2<7 : 1;
endrewards
label "done" = s1=7 & s2=7;
label "two" = s1=7 & s2=7 & d1+d2=2;
label "three" = s1=7 & s2=7 & d1+d2=3;
label "four" = s1=7 & s2=7 & d1+d2=4;
label "five" = s1=7 & s2=7 & d1+d2=5;
label "six" = s1=7 & s2=7 & d1+d2=6;
label "seven" = s1=7 & s2=7 & d1+d2=7;
label "eight" = s1=7 & s2=7 & d1+d2=8;
label "nine" = s1=7 & s2=7 & d1+d2=9;
label "ten" = s1=7 & s2=7 & d1+d2=10;
label "eleven" = s1=7 & s2=7 & d1+d2=11;
label "twelve" = s1=7 & s2=7 & d1+d2=12;
label "doubles" = s1=7 & s2=7 & d1=d2;

12
src/modelchecker/region/AbstractSparseRegionModelChecker.cpp

@ -118,9 +118,7 @@ namespace storm {
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();
std::chrono::high_resolution_clock::time_point timePreprocessingStart = std::chrono::high_resolution_clock::now();
@ -140,8 +138,7 @@ namespace storm {
STORM_LOG_DEBUG("The Result is constant and will be computed now.");
initializeSamplingModel(*this->getSimpleModel(), this->getSimpleFormula());
std::map<VariableType, CoefficientType> emptySubstitution;
this->getSamplingModel()->instantiate(emptySubstitution);
this->constantResult = this->getSamplingModel()->computeInitialStateValue();
this->constantResult = this->getSamplingModel()->computeInitialStateValue(emptySubstitution);
}
//some more information for statistics...
@ -371,8 +368,7 @@ namespace storm {
if(this->isResultConstant()){
return this->constantResult.get();
}
this->getSamplingModel()->instantiate(point);
return this->getSamplingModel()->computeInitialStateValue();
return this->getSamplingModel()->computeInitialStateValue(point);
}
template<typename ParametricSparseModelType, typename ConstantType>
@ -423,7 +419,6 @@ namespace storm {
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; // + ...
@ -463,8 +458,7 @@ namespace storm {
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 << " " << timeApproximationInMilliseconds.count() << "ms Approximation" << std::endl;
outstream << " " << timeSammplingInMilliseconds.count() << "ms Sampling " << std::endl;
outstream << " " << timeSmtInMilliseconds.count() << "ms Smt solving" << std::endl;
outstream << "-----------------------------------------------" << std::endl;

1
src/modelchecker/region/AbstractSparseRegionModelChecker.h

@ -223,7 +223,6 @@ namespace storm {
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 timeApproxModelInstantiation;
std::chrono::high_resolution_clock::duration timeSmt;
protected:
std::chrono::high_resolution_clock::duration timeComputeReachabilityFunction;

35
src/modelchecker/region/ApproximationModel.cpp

@ -4,6 +4,8 @@
*
* Created on August 7, 2015, 9:29 AM
*/
#include <stdint.h>
#include "src/modelchecker/region/ApproximationModel.h"
#include "src/models/sparse/Dtmc.h"
@ -79,14 +81,14 @@ namespace storm {
* We also store the substitution that needs to be applied for each row.
*/
ConstantType dummyValue = storm::utility::one<ConstantType>();
auto numOfMaybeStates = this->maybeStates.getNumberOfSetBits();
storm::storage::SparseMatrixBuilder<ConstantType> matrixBuilder(numOfMaybeStates, //exact number of rows is unknown at this point, but at least this many
numOfMaybeStates, //columns
storm::storage::SparseMatrixBuilder<ConstantType> matrixBuilder(0, //Unknown number of rows
this->maybeStates.getNumberOfSetBits(), //columns
0, //Unknown number of entries
false, // no force dimensions
true, // force dimensions
true, //will have custom row grouping
numOfMaybeStates); //exact number of rowgroups is unknown at this point, but at least this many
rowSubstitutions.reserve(numOfMaybeStates);
0); //Unknown number of rowgroups
rowSubstitutions.reserve(this->maybeStates.getNumberOfSetBits());
storm::storage::BitVector relevantColumns = this->computeRewards ? this->maybeStates : (this->maybeStates | this->targetStates);
std::size_t curRow = 0;
for (auto oldRowGroup : this->maybeStates){
for (std::size_t oldRow = parametricModel.getTransitionMatrix().getRowGroupIndices()[oldRowGroup]; oldRow < parametricModel.getTransitionMatrix().getRowGroupIndices()[oldRowGroup+1]; ++oldRow){
@ -94,12 +96,12 @@ namespace storm {
// Find the different substitutions, i.e., mappings from Variables that occur in this row to {lower, upper}
std::set<VariableType> occurringVariables;
for(auto const& oldEntry : parametricModel.getTransitionMatrix().getRow(oldRow)){
if(this->maybeStates.get(oldEntry.getColumn())){
if(relevantColumns.get(oldEntry.getColumn())){
storm::utility::region::gatherOccurringVariables(oldEntry.getValue(), occurringVariables);
}
}
std::size_t numOfSubstitutions=1ull<<occurringVariables.size(); //=2^(#variables). Note that there is still 1 substitution when #variables==0 (the empty substitution)
for(uint_fast64_t substitutionId=0; substitutionId<numOfSubstitutions; ++substitutionId){
uint_fast64_t numOfSubstitutions=1ull<<occurringVariables.size(); //=2^(#variables). Note that there is still 1 substitution when #variables==0 (the empty substitution)
for(uint_fast64_t substitutionId=0ull; substitutionId<numOfSubstitutions; ++substitutionId){
//compute actual substitution from substitutionId by interpreting the Id as a bit sequence.
//the occurringVariables.size() least significant bits of substitutionId will represent the substitution that we have to consider
//(00...0 = lower bounds for all parameters, 11...1 = upper bounds for all parameters)
@ -127,7 +129,8 @@ namespace storm {
}
}
}
this->matrixData.matrix=matrixBuilder.build();
//Build the matrix. Override the row count (required e.g. when there are only transitions to target for the last matrixrow)
this->matrixData.matrix=matrixBuilder.build(rowSubstitutions.size());
//Now run again through both matrices to get the remaining ingredients of the matrixData and vectorData
this->matrixData.assignment.reserve(this->matrixData.matrix.getEntryCount());
@ -156,7 +159,7 @@ namespace storm {
eqSysMatrixEntry->setValue(storm::utility::region::convertNumber<ConstantType>(storm::utility::region::getConstantPart(oldEntry.getValue())));
} else {
auto functionsIt = this->funcSubData.functions.insert(FunctionEntry(FunctionSubstitution(oldEntry.getValue(), rowSubstitutions[curRow]), dummyValue)).first;
this->matrixData.assignment.emplace_back(std::make_pair(eqSysMatrixEntry, &(functionsIt->second)));
this->matrixData.assignment.emplace_back(eqSysMatrixEntry, functionsIt->second);
//Note that references to elements of an unordered map remain valid after calling unordered_map::insert.
}
++eqSysMatrixEntry;
@ -167,7 +170,7 @@ namespace storm {
*vectorIt = storm::utility::region::convertNumber<ConstantType>(storm::utility::region::getConstantPart(targetProbability));
} else {
auto functionsIt = this->funcSubData.functions.insert(FunctionEntry(FunctionSubstitution(targetProbability, rowSubstitutions[curRow]), dummyValue)).first;
this->vectorData.assignment.emplace_back(std::make_pair(vectorIt, &(functionsIt->second)));
this->vectorData.assignment.emplace_back(vectorIt, functionsIt->second);
*vectorIt = dummyValue;
}
}
@ -230,7 +233,7 @@ namespace storm {
functionsIt = this->funcSubData.functions.insert(FunctionEntry(FunctionSubstitution(parametricModel.getUniqueRewardModel()->second.getStateRewardVector()[oldState], substitutionIndex), dummyValue)).first;
}
//insert assignment and dummy data
this->vectorData.assignment.emplace_back(std::make_pair(vectorIt, &(functionsIt->second)));
this->vectorData.assignment.emplace_back(vectorIt, functionsIt->second);
*vectorIt = dummyValue;
++vectorIt;
}
@ -281,7 +284,7 @@ namespace storm {
ConstantType ApproximationModel<ParametricSparseModelType, ConstantType>::computeInitialStateValue(ParameterRegion<ParametricType> const& region, bool computeLowerBounds) {
instantiate(region, computeLowerBounds);
invokeSolver(computeLowerBounds);
// std::cout << "initialStateValue is " << this->eqSysResult[this->eqSysInitIndex] << std::endl;
// std::cout << "initialStateValue is " << this->eqSysResult[this->eqSysInitIndex] << std::endl;
return this->eqSysResult[this->eqSysInitIndex];
}
@ -335,10 +338,10 @@ namespace storm {
//write the instantiated values to the matrix and the vector according to the assignment
for(auto& assignment : this->matrixData.assignment){
assignment.first->setValue(*(assignment.second));
assignment.first->setValue(assignment.second);
}
for(auto& assignment : this->vectorData.assignment){
*assignment.first=*assignment.second;
*assignment.first = assignment.second;
}
}

23
src/modelchecker/region/ApproximationModel.h

@ -10,6 +10,7 @@
#include <unordered_map>
#include <memory>
#include <boost/functional/hash.hpp>
#include "src/utility/region.h"
#include "src/modelchecker/region/ParameterRegion.h"
@ -63,7 +64,7 @@ namespace storm {
};
//A class that represents a function and how it should be substituted (i.e. which variables should be replaced with lower and which with upper bounds of the region)
//The substitution is given as an index in probability or reward substitutions. (This allows to instantiate the substitutions more easily)
//The substitution is given as an index in funcSubData.substitutions (allowing to instantiate the substitutions more easily).
class FunctionSubstitution {
public:
FunctionSubstitution(ParametricType const& fun, std::size_t const& sub) : hash(computeHash(fun,sub)), function(fun), substitution(sub) {
@ -105,9 +106,10 @@ namespace storm {
private:
static std::size_t computeHash(ParametricType const& fun, std::size_t const& sub) {
std::size_t hf = std::hash<ParametricType>()(fun);
std::size_t hs = std::hash<std::size_t>()(sub);
return hf ^(hs << 1);
std::size_t seed = 0;
boost::hash_combine(seed, fun);
boost::hash_combine(seed, sub);
return seed;
}
std::size_t hash;
@ -123,7 +125,6 @@ namespace storm {
};
typedef typename std::unordered_map<FunctionSubstitution, ConstantType, FuncSubHash>::value_type FunctionEntry;
// typedef typename std::unordered_map<FunctionSubstitution, std::pair<ConstantType, ConstantType>, FuncSubHash>::value_type RewTableEntry;
void initializeProbabilities(ParametricSparseModelType const& parametricModel, std::vector<std::size_t> const& newIndices, std::vector<std::size_t>& rowSubstitutions);
void initializeRewards(ParametricSparseModelType const& parametricModel, std::vector<std::size_t> const& newIndices, std::vector<std::size_t> const& rowSubstitutions);
@ -156,24 +157,18 @@ namespace storm {
* This way, it is avoided that the same function is evaluated multiple times.
*/
struct FuncSubData{
// the occurring probability functions together with the corresponding placeholders for the result
// the occurring (function,substitution)-pairs together with the corresponding placeholders for the result
std::unordered_map<FunctionSubstitution, ConstantType, FuncSubHash> functions;
// the occurring reward functions together with the corresponding placeholders for the minimal and maximal result
// //std::unordered_map<FunctionSubstitution, std::pair<ConstantType, ConstantType>, FuncSubHash> rewFunctions;
//Vector has one entry for every required substitution (=replacement of parameters with lower/upper bounds of region)
std::vector<std::map<VariableType, TypeOfBound>> substitutions;
//For rewards, we also store the parameters for which the correct substitution depends on the region and whether to minimize/maximize (i.e. TypeOfBound==CHOSEOPTIMAL)
// // std::vector<std::map<VariableType, TypeOfBound>> rewSubs;
// //std::vector<std::set<VariableType>> choseOptimalRewardPars;
} funcSubData;
struct MatrixData {
storm::storage::SparseMatrix<ConstantType> matrix; //The matrix itself.
std::vector<std::pair<typename storm::storage::SparseMatrix<ConstantType>::iterator, ConstantType*>> assignment; // Connection of matrix entries with placeholders
// std::vector<std::tuple<ConstantType*, ConstantType*, typename std::vector<ConstantType>::iterator>> rewardMapping;
std::vector<std::pair<typename storm::storage::SparseMatrix<ConstantType>::iterator, ConstantType&>> assignment; // Connection of matrix entries with placeholders
} matrixData;
struct VectorData {
std::vector<ConstantType> vector; //The vector itself.
std::vector<std::pair<typename std::vector<ConstantType>::iterator, ConstantType*>> assignment; // Connection of vector entries with placeholders
std::vector<std::pair<typename std::vector<ConstantType>::iterator, ConstantType&>> assignment; // Connection of vector entries with placeholders
} vectorData;
};

6
src/modelchecker/region/SamplingModel.cpp

@ -205,7 +205,8 @@ namespace storm {
}
template<typename ParametricSparseModelType, typename ConstantType>
std::vector<ConstantType> SamplingModel<ParametricSparseModelType, ConstantType>::computeValues() {
std::vector<ConstantType> SamplingModel<ParametricSparseModelType, ConstantType>::computeValues(std::map<VariableType, CoefficientType>const& point) {
instantiate(point);
invokeSolver();
std::vector<ConstantType> result(this->maybeStates.size());
storm::utility::vector::setVectorValues(result, this->maybeStates, this->eqSysResult);
@ -216,7 +217,8 @@ namespace storm {
}
template<typename ParametricSparseModelType, typename ConstantType>
ConstantType SamplingModel<ParametricSparseModelType, ConstantType>::computeInitialStateValue() {
ConstantType SamplingModel<ParametricSparseModelType, ConstantType>::computeInitialStateValue(std::map<VariableType, CoefficientType>const& point) {
instantiate(point);
invokeSolver();
return this->eqSysResult[this->eqSysInitIndex];
}

11
src/modelchecker/region/SamplingModel.h

@ -39,26 +39,23 @@ namespace storm {
/*!
* Instantiates the underlying model according to the given point
*/
void instantiate(std::map<VariableType, CoefficientType>const& point);
/*!
* Returns the reachability probabilities (or the expected rewards) for every state according to the current instantiation.
* Undefined behavior if model has not been instantiated first!
*/
std::vector<ConstantType> computeValues();
std::vector<ConstantType> computeValues(std::map<VariableType, CoefficientType>const& point);
/*!
* Instantiates the underlying model according to the given point
* Returns the reachability probability (or the expected rewards) of the initial state.
* Undefined behavior if model has not been instantiated first!
*/
ConstantType computeInitialStateValue();
ConstantType computeInitialStateValue(std::map<VariableType, CoefficientType>const& point);
private:
typedef typename std::unordered_map<ParametricType, ConstantType>::value_type FunctionEntry;
void initializeProbabilities(ParametricSparseModelType const& parametricModel, std::vector<std::size_t> const& newIndices);
void initializeRewards(ParametricSparseModelType const& parametricModel, std::vector<std::size_t> const& newIndices);
void instantiate(std::map<VariableType, CoefficientType>const& point);
void invokeSolver();
//Some designated states in the original model

8
test/functional/modelchecker/SparseDtmcRegionModelCheckerTest.cpp

@ -23,7 +23,7 @@
TEST(SparseDtmcRegionModelCheckerTest, Brp_Prob) {
std::string const& programFile = STORM_CPP_BASE_PATH "/examples/pdtmc/brp/brp_16_2.pm";
std::string const& formulaAsString = "P<=0.85 [F \"target\" ]";
std::string const& formulaAsString = "P<=0.84 [F \"target\" ]";
std::string const& constantsAsString = ""; //e.g. pL=0.9,TOACK=0.5
//Build model, formula, region model checker
@ -44,7 +44,7 @@ TEST(SparseDtmcRegionModelCheckerTest, Brp_Prob) {
//start testing
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");
auto allVioRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.1<=pL<=0.73,0.2<=pK<=0.715");
EXPECT_NEAR(0.8369631407, modelchecker.getReachabilityValue(allSatRegion.getLowerBounds()), storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(0.8369631407, storm::utility::region::convertNumber<double>(modelchecker.evaluateReachabilityFunction(allSatRegion.getLowerBounds())), storm::settings::generalSettings().getPrecision());
@ -56,8 +56,8 @@ TEST(SparseDtmcRegionModelCheckerTest, Brp_Prob) {
EXPECT_NEAR(0.6020480995, storm::utility::region::convertNumber<double>(modelchecker.evaluateReachabilityFunction(exBothRegion.getUpperBounds())), storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(1.0000000000, modelchecker.getReachabilityValue(allVioRegion.getLowerBounds()), storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(1.0000000000, storm::utility::region::convertNumber<double>(modelchecker.evaluateReachabilityFunction(allVioRegion.getLowerBounds())), storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(0.9456084185, modelchecker.getReachabilityValue(allVioRegion.getUpperBounds()), storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(0.9456084185, storm::utility::region::convertNumber<double>(modelchecker.evaluateReachabilityFunction(allVioRegion.getUpperBounds())), storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(0.8429289733, modelchecker.getReachabilityValue(allVioRegion.getUpperBounds()), storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(0.8429289733, storm::utility::region::convertNumber<double>(modelchecker.evaluateReachabilityFunction(allVioRegion.getUpperBounds())), storm::settings::generalSettings().getPrecision());
//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);

60
test/functional/modelchecker/SparseMdpRegionModelCheckerTest.cpp

@ -20,6 +20,54 @@
#include "modelchecker/region/SparseMdpRegionModelChecker.h"
#include "modelchecker/region/ParameterRegion.h"
TEST(SparseMdpRegionModelCheckerTest, two_dice_Prob) {
std::string const& programFile = STORM_CPP_BASE_PATH "/examples/pmdp/two_dice/two_dice.nm";
std::string const& formulaAsString = "P<=0.17 [F \"doubles\" ]";
std::string const& constantsAsString = ""; //e.g. pL=0.9,TOACK=0.5
//Build model, formula, region model checker
boost::optional<storm::prism::Program> program=storm::parser::PrismParser::parse(programFile).simplify().simplify();
program->checkValidity();
storm::parser::FormulaParser formulaParser(program.get().getManager().getSharedPointer());
std::vector<std::shared_ptr<storm::logic::Formula>> formulas = formulaParser.parseFromString(formulaAsString);
typename storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::Options options=storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::Options(*formulas[0]);
options.addConstantDefinitionsFromString(program.get(), constantsAsString);
options.preserveFormula(*formulas[0]);
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::Mdp, model->getType());
std::shared_ptr<storm::models::sparse::Mdp<storm::RationalFunction>> mdp = model->template as<storm::models::sparse::Mdp<storm::RationalFunction>>();
storm::modelchecker::region::SparseMdpRegionModelChecker<storm::models::sparse::Mdp<storm::RationalFunction>, double> modelchecker(*mdp);
ASSERT_TRUE(modelchecker.canHandle(*formulas[0]));
modelchecker.specifyFormula(formulas[0]);
//start testing
auto allSatRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.495<=p1<=0.5,0.5<=p2<=0.505");
auto exBothRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.45<=p1<=0.55,0.45<=p2<=0.55");
auto allVioRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.6<=p1<=0.7,0.6<=p2<=0.6");
EXPECT_NEAR(0.1666665285, modelchecker.getReachabilityValue(allSatRegion.getLowerBounds()), storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(0.1666665529, modelchecker.getReachabilityValue(allSatRegion.getUpperBounds()), storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(0.1716553235, modelchecker.getReachabilityValue(exBothRegion.getLowerBounds()), storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(0.1709666953, modelchecker.getReachabilityValue(exBothRegion.getUpperBounds()), storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(0.1826972576, modelchecker.getReachabilityValue(allVioRegion.getLowerBounds()), storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(0.1964429282, modelchecker.getReachabilityValue(allVioRegion.getUpperBounds()), storm::settings::generalSettings().getPrecision());
//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);
ASSERT_TRUE(storm::settings::regionSettings().doApprox());
ASSERT_TRUE(storm::settings::regionSettings().doSample());
ASSERT_FALSE(storm::settings::regionSettings().doSmt());
modelchecker.checkRegion(allSatRegion);
EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLSAT), allSatRegion.getCheckResult());
modelchecker.checkRegion(exBothRegion);
EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::EXISTSBOTH), exBothRegion.getCheckResult());
modelchecker.checkRegion(allVioRegion);
EXPECT_EQ((storm::modelchecker::region::RegionCheckResult::ALLVIOLATED), allVioRegion.getCheckResult());
storm::settings::mutableRegionSettings().resetModes();
}
TEST(SparseMdpRegionModelCheckerTest, coin_Prob) {
std::string const& programFile = STORM_CPP_BASE_PATH "/examples/pmdp/consensus/coin2_2.nm";
@ -42,16 +90,16 @@ TEST(SparseMdpRegionModelCheckerTest, coin_Prob) {
modelchecker.specifyFormula(formulas[0]);
//start testing
auto allSatRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.3<=p<=0.4,0.2<=q<=0.4");
auto allSatRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.3<=p<=0.45,0.2<=q<=0.54");
auto exBothRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.4<=p<=0.65,0.5<=q<=0.7");
auto allVioRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.6<=p<=0.75,0.7<=q<=0.72");
auto allVioRegion=storm::modelchecker::region::ParameterRegion<storm::RationalFunction>::parseRegion("0.4<=p<=0.7,0.55<=q<=0.6");
EXPECT_NEAR(0.9512773402, modelchecker.getReachabilityValue(allSatRegion.getLowerBounds()), storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(0.7455987332, modelchecker.getReachabilityValue(allSatRegion.getUpperBounds()), storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(0.41880345311, modelchecker.getReachabilityValue(exBothRegion.getLowerBounds()), storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(0.26787251126, modelchecker.getReachabilityValue(allSatRegion.getUpperBounds()), storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(0.41879628383, modelchecker.getReachabilityValue(exBothRegion.getLowerBounds()), storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(0.01535089684, modelchecker.getReachabilityValue(exBothRegion.getUpperBounds()), storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(0.01711494956, modelchecker.getReachabilityValue(allVioRegion.getLowerBounds()), storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(0.004422535374, modelchecker.getReachabilityValue(allVioRegion.getUpperBounds()), storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(0.24952612245, modelchecker.getReachabilityValue(allVioRegion.getLowerBounds()), storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(0.01711494956, modelchecker.getReachabilityValue(allVioRegion.getUpperBounds()), storm::settings::generalSettings().getPrecision());
//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);

Loading…
Cancel
Save