Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
SparseDerivativeInstantiationModelCheckerTest.cpp
Go to the documentation of this file.
1#include "carl/core/RationalFunction.h"
2#include "storm-config.h"
3#include "test/storm_gtest.h"
4
6#include "storm/api/builder.h"
7#include "storm/api/storm.h"
19
21
26
27namespace {
28class RationalGmmxxEnvironment {
29 public:
31 typedef storm::RationalNumber ConstantType;
32 static storm::Environment createEnvironment() {
34 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Gmmxx);
35 return env;
36 }
37};
38class DoubleGmmxxEnvironment {
39 public:
41 typedef double ConstantType;
42 static storm::Environment createEnvironment() {
44 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Gmmxx);
45 return env;
46 }
47};
48class RationalEigenEnvironment {
49 public:
51 typedef storm::RationalNumber ConstantType;
52 static storm::Environment createEnvironment() {
54 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Eigen);
55 return env;
56 }
57};
58class DoubleEigenEnvironment {
59 public:
61 typedef double ConstantType;
62 static storm::Environment createEnvironment() {
64 env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Eigen);
65 return env;
66 }
67};
68template<typename TestType>
69class SparseDerivativeInstantiationModelCheckerTest : public ::testing::Test {
70 public:
71 typedef typename TestType::ValueType ValueType;
72 typedef typename TestType::ConstantType ConstantType;
73 template<typename ValueType>
75 template<typename ValueType>
77 template<typename ValueType>
78 using Instantiation = std::map<VariableType<storm::RationalFunction>, CoefficientType<storm::RationalFunction>>;
79 template<typename ValueType>
80 using ResultMap = std::map<VariableType<storm::RationalFunction>, ConstantType>;
81 SparseDerivativeInstantiationModelCheckerTest() : _environment(TestType::createEnvironment()) {}
82 storm::Environment const& env() const {
83 return _environment;
84 }
85 virtual void SetUp() {
86#ifndef STORM_HAVE_Z3
87 GTEST_SKIP() << "Z3 not available.";
88#endif
89 carl::VariablePool::getInstance().clear();
90 }
91 virtual void TearDown() {
92 carl::VariablePool::getInstance().clear();
93 }
95 std::vector<std::shared_ptr<const storm::logic::Formula>> formulas, storm::RationalFunction reachabilityFunction);
96
97 private:
98 storm::Environment _environment;
99};
100
101typedef ::testing::Types<RationalGmmxxEnvironment, DoubleGmmxxEnvironment, RationalEigenEnvironment, DoubleEigenEnvironment> TestingTypes;
102} // namespace
103
104TYPED_TEST_SUITE(SparseDerivativeInstantiationModelCheckerTest, TestingTypes, );
105
106template<typename TestType>
107void SparseDerivativeInstantiationModelCheckerTest<TestType>::testModel(std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> dtmc,
108 std::vector<std::shared_ptr<const storm::logic::Formula>> formulas,
109 storm::RationalFunction reachabilityFunction) {
110 auto formulaWithoutBound = std::make_shared<storm::logic::ProbabilityOperatorFormula>(
111 formulas[0]->asProbabilityOperatorFormula().getSubformula().asSharedPointer(), storm::logic::OperatorInformation(boost::none, boost::none));
112
115
116 std::map<VariableType<storm::RationalFunction>, storm::RationalFunction> derivatives;
117 for (auto const& parameter : parameters) {
118 derivatives[parameter] = reachabilityFunction.derivative(parameter);
119 }
120
121 // Generate test cases.
122 std::vector<Instantiation<storm::RationalFunction>> testInstantiations;
123 Instantiation<storm::RationalFunction> emptyInstantiation;
124 testInstantiations.push_back(emptyInstantiation);
125 for (auto const& param : parameters) {
126 std::vector<Instantiation<storm::RationalFunction>> newInstantiations;
127 for (auto point : testInstantiations) {
128 for (typename TestType::ConstantType x = storm::utility::convertNumber<ConstantType>(1e-6); x <= 1;
129 x += (1 - storm::utility::convertNumber<ConstantType>(1e-6)) / 10) {
130 std::map<VariableType<storm::RationalFunction>, CoefficientType<storm::RationalFunction>> newMap(point);
131 newMap[param] = storm::utility::convertNumber<CoefficientType<storm::RationalFunction>>(x);
132 newInstantiations.push_back(newMap);
133 }
134 }
135 testInstantiations = newInstantiations;
136 }
137
138 // The test cases we are going to study. Left are the actual instantiations, right are the maps
139 // for the results (which happen to share the same type).
140 std::map<Instantiation<storm::RationalFunction>, ResultMap<storm::RationalFunction>> testCases;
141 for (auto const& instantiation : testInstantiations) {
142 ResultMap<storm::RationalFunction> resultMap;
143 for (auto const& entry : instantiation) {
144 auto parameter = entry.first;
145 auto derivativeWrtParameter = derivatives[parameter];
146 typename TestType::ConstantType evaluatedDerivative =
147 storm::utility::convertNumber<typename TestType::ConstantType>(derivativeWrtParameter.evaluate(instantiation));
148 resultMap[parameter] = evaluatedDerivative;
149 }
150 testCases[instantiation] = resultMap;
151 }
152
153 auto checkTask = storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>(*formulaWithoutBound);
154 derivativeModelChecker.specifyFormula(env(), checkTask);
155
156 for (auto const& testCase : testCases) {
157 Instantiation<ValueType> instantiation = testCase.first;
158 for (auto const& position : instantiation) {
159 auto parameter = position.first;
160 auto parameterValue = position.second;
161 auto expectedResult = testCase.second.at(parameter);
162
163 auto derivative = derivativeModelChecker.check(env(), instantiation, parameter);
164 ASSERT_NEAR(storm::utility::convertNumber<double>(derivative->getValueVector()[0]), storm::utility::convertNumber<double>(expectedResult), 1e-6)
165 << instantiation;
166 }
167 }
168}
169
170// A very simple DTMC
171TYPED_TEST(SparseDerivativeInstantiationModelCheckerTest, Simple) {
172 std::string programFile = STORM_TEST_RESOURCES_DIR "/pdtmc/gradient1.pm";
173 std::string formulaAsString = "Pmax=? [F s=2]";
174 std::string constantsAsString = ""; // e.g. pL=0.9,TOACK=0.5
175
176 // We have to create the dtmc and formulas here, because we need its parameters to create the polynomial
177 storm::prism::Program program = storm::api::parseProgram(programFile);
178 program = storm::utility::prism::preprocess(program, constantsAsString);
179 std::vector<std::shared_ptr<const storm::logic::Formula>> formulas =
181 std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> model =
182 storm::api::buildSparseModel<storm::RationalFunction>(program, formulas)->as<storm::models::sparse::Dtmc<storm::RationalFunction>>();
183 std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> dtmc = model->as<storm::models::sparse::Dtmc<storm::RationalFunction>>();
185 ASSERT_TRUE(simplifier.simplify(*(formulas[0])));
186 model = simplifier.getSimplifiedModel();
188
189 // The associated polynomial. In this case, it's p * (1 - p).
190 carl::Variable varP = carl::VariablePool::getInstance().findVariableWithName("p");
191 std::shared_ptr<storm::RawPolynomialCache> cache = std::make_shared<storm::RawPolynomialCache>();
193 storm::RationalFunction reachabilityFunction = p * (storm::RationalFunction(1) - p);
194
195 this->testModel(dtmc, formulas, reachabilityFunction);
196}
197
198// A very simple DTMC with two parameters
199TYPED_TEST(SparseDerivativeInstantiationModelCheckerTest, Simple2) {
200 std::string programFile = STORM_TEST_RESOURCES_DIR "/pdtmc/gradient2.pm";
201 std::string formulaAsString = "Pmax=? [F s=2]";
202 std::string constantsAsString = ""; // e.g. pL=0.9,TOACK=0.5
203
204 // We have to create the dtmc and formulas here, because we need its parameters to create the polynomial
205 storm::prism::Program program = storm::api::parseProgram(programFile);
206 program = storm::utility::prism::preprocess(program, constantsAsString);
207 std::vector<std::shared_ptr<const storm::logic::Formula>> formulas =
209 std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> model =
210 storm::api::buildSparseModel<storm::RationalFunction>(program, formulas)->as<storm::models::sparse::Dtmc<storm::RationalFunction>>();
211 std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> dtmc = model->as<storm::models::sparse::Dtmc<storm::RationalFunction>>();
213 ASSERT_TRUE(simplifier.simplify(*(formulas[0])));
214 model = simplifier.getSimplifiedModel();
216
217 // The associated polynomial. In this case, it's p * (1 - q).
218 carl::Variable varP = carl::VariablePool::getInstance().findVariableWithName("p");
219 carl::Variable varQ = carl::VariablePool::getInstance().findVariableWithName("q");
220 std::shared_ptr<storm::RawPolynomialCache> cache = std::make_shared<storm::RawPolynomialCache>();
223 storm::RationalFunction reachabilityFunction = p * (storm::RationalFunction(1) - q);
224
225 this->testModel(dtmc, formulas, reachabilityFunction);
226}
227
228// The bounded retransmission protocol
229TYPED_TEST(SparseDerivativeInstantiationModelCheckerTest, Brp162) {
230 std::string programFile = STORM_TEST_RESOURCES_DIR "/pdtmc/brp16_2.pm";
231 std::string formulaAsString = "Pmax=? [F s=4 & i=N ]";
232 std::string constantsAsString = ""; // e.g. pL=0.9,TOACK=0.5
233
234 // We have to create the dtmc and formulas here, because we need its parameters to create the polynomial
235 storm::prism::Program program = storm::api::parseProgram(programFile);
236 program = storm::utility::prism::preprocess(program, constantsAsString);
237 std::vector<std::shared_ptr<const storm::logic::Formula>> formulas =
239 std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> model =
240 storm::api::buildSparseModel<storm::RationalFunction>(program, formulas)->as<storm::models::sparse::Dtmc<storm::RationalFunction>>();
241 std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> dtmc = model->as<storm::models::sparse::Dtmc<storm::RationalFunction>>();
243 ASSERT_TRUE(simplifier.simplify(*(formulas[0])));
244 model = simplifier.getSimplifiedModel();
246
247 carl::Variable pLVar = carl::VariablePool::getInstance().findVariableWithName("pL");
248 carl::Variable pKVar = carl::VariablePool::getInstance().findVariableWithName("pK");
249 std::shared_ptr<storm::RawPolynomialCache> cache = std::make_shared<storm::RawPolynomialCache>();
252
253 // The term is ((pK)^16 * (pL)^16 * (pK^2*pL^2+(-3)*pK*pL+3)^16)/(1), so we're just going to create this here.
254 auto firstTerm = pK * pK * pK * pK * pK * pK * pK * pK * pK * pK * pK * pK * pK * pK * pK * pK;
255 auto secondTerm = pL * pL * pL * pL * pL * pL * pL * pL * pL * pL * pL * pL * pL * pL * pL * pL;
256 auto thirdTermUnpowed = pK * pK * pL * pL + (-3) * pK * pL + 3;
257 auto thirdTerm = thirdTermUnpowed * thirdTermUnpowed * thirdTermUnpowed * thirdTermUnpowed * thirdTermUnpowed * thirdTermUnpowed * thirdTermUnpowed *
258 thirdTermUnpowed * thirdTermUnpowed * thirdTermUnpowed * thirdTermUnpowed * thirdTermUnpowed * thirdTermUnpowed * thirdTermUnpowed *
259 thirdTermUnpowed * thirdTermUnpowed;
260 storm::RationalFunction reachabilityFunction = firstTerm * secondTerm * thirdTerm;
261
262 this->testModel(dtmc, formulas, reachabilityFunction);
263}
TYPED_TEST(SparseDerivativeInstantiationModelCheckerTest, Simple)
TYPED_TEST_SUITE(SparseDerivativeInstantiationModelCheckerTest, TestingTypes,)
void testModel(std::string programFile, std::string formulaAsString, std::string constantsAsString)
SolverEnvironment & solver()
void setLinearEquationSolverType(storm::solver::EquationSolverType const &value, bool isSetFromDefault=false)
std::shared_ptr< ModelType > as()
Casts the model into the model type given by the template parameter.
Definition ModelBase.h:36
This class represents a discrete-time Markov chain.
Definition Dtmc.h:14
This class performs different steps to simplify the given (parametric) model.
std::vector< storm::jani::Property > parsePropertiesForPrismProgram(std::string const &inputString, storm::prism::Program const &program, boost::optional< std::set< std::string > > const &propertyFilter)
storm::prism::Program parseProgram(std::string const &filename, bool prismCompatibility, bool simplify)
std::vector< std::shared_ptr< storm::logic::Formula const > > extractFormulasFromProperties(std::vector< storm::jani::Property > const &properties)
typename utility::parametric::VariableType< FunctionType >::type VariableType
typename utility::parametric::CoefficientType< FunctionType >::type CoefficientType
SFTBDDChecker::ValueType ValueType
std::set< storm::RationalFunctionVariable > getProbabilityParameters(Model< storm::RationalFunction > const &model)
Get all probability parameters occurring on transitions.
Definition Model.cpp:703
storm::prism::Program preprocess(storm::prism::Program const &program, std::map< storm::expressions::Variable, storm::expressions::Expression > const &constantDefinitions)
Definition prism.cpp:19
carl::RationalFunction< Polynomial, true > RationalFunction
carl::MultivariatePolynomial< RationalFunctionCoefficient > RawPolynomial
::testing::Types< Cudd, Sylvan > TestingTypes
Definition GraphTest.cpp:46