1#include "storm-config.h"
22enum class MdpEngine { PrismSparse, JaniSparse,
Hybrid, PrismDd, JaniDd };
24class UnsoundEnvironment {
34class SoundEnvironment {
44class ExactEnvironment {
53template<
typename TestType>
54class QuantileQueryTest :
public ::testing::Test {
56 typedef typename TestType::ValueType
ValueType;
57 QuantileQueryTest() : _environment(TestType::createEnvironment()) {}
59 void SetUp()
override {
61 GTEST_SKIP() <<
"Z3 not available.";
69 if (input.find(
"inf") != std::string::npos) {
70 return storm::utility::infinity<ValueType>();
72 return storm::utility::convertNumber<ValueType>(input);
76 std::pair<std::shared_ptr<MT>, std::vector<std::shared_ptr<storm::logic::Formula const>>> buildModelFormulas(
77 std::string
const& pathToPrismFile, std::string
const& formulasAsString, std::string
const& constantDefinitionString =
"")
const {
78 std::pair<std::shared_ptr<MT>, std::vector<std::shared_ptr<storm::logic::Formula const>>> result;
82 result.first = storm::api::buildSparseModel<ValueType>(program, result.second)->template as<MT>();
86 std::vector<storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>> getTasks(
87 std::vector<std::shared_ptr<storm::logic::Formula const>>
const& formulas)
const {
88 std::vector<storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>> result;
89 for (
auto const& f : formulas) {
90 result.emplace_back(*f,
true);
96 typename std::enable_if<std::is_same<MT, storm::models::sparse::Mdp<ValueType>>::value,
97 std::shared_ptr<storm::modelchecker::AbstractModelChecker<MT>>>::type
98 createModelChecker(std::shared_ptr<MT>
const& model)
const {
99 return std::make_shared<storm::modelchecker::SparseMdpPrctlModelChecker<MT>>(*model);
101 template<
typename MT>
102 typename std::enable_if<std::is_same<MT, storm::models::sparse::Dtmc<ValueType>>::value,
103 std::shared_ptr<storm::modelchecker::AbstractModelChecker<MT>>>::type
104 createModelChecker(std::shared_ptr<MT>
const& model)
const {
105 return std::make_shared<storm::modelchecker::SparseDtmcPrctlModelChecker<MT>>(*model);
109 std::unique_ptr<storm::modelchecker::CheckResult>& result, std::vector<std::string>
const& expected) {
111 std::string errorMessage =
"";
113 std::is_same<ValueType, double>::value ? storm::utility::convertNumber<ValueType>(1e-10) :
storm::utility::
zero<
ValueType>();
115 result->filter(*filter);
116 std::vector<std::vector<ValueType>> resultPoints;
117 if (result->isExplicitParetoCurveCheckResult()) {
118 resultPoints = result->asExplicitParetoCurveCheckResult<
ValueType>().getPoints();
120 if (!result->isExplicitQuantitativeCheckResult()) {
121 return {
false,
"The CheckResult has unexpected type."};
123 resultPoints = {{result->asExplicitQuantitativeCheckResult<
ValueType>().getMax()}};
125 std::vector<std::vector<ValueType>> expectedPoints;
126 for (
auto const& pointAsString : expected) {
127 std::vector<ValueType> point;
131 expectedPoints.push_back(std::move(point));
133 for (
auto const& resPoint : resultPoints) {
134 bool contained =
false;
135 for (
auto const& expPoint : expectedPoints) {
146 for (
auto const& expPoint : expectedPoints) {
147 bool contained =
false;
148 for (
auto const& resPoint : resultPoints) {
159 return {equal, errorMessage};
167 return std::make_unique<storm::modelchecker::ExplicitQualitativeCheckResult>(model->getInitialStates());
171typedef ::testing::Types<UnsoundEnvironment, SoundEnvironment, ExactEnvironment>
TestingTypes;
178 std::string formulasString =
"quantile(max A, max B, P>0.95 [F{\"first\"}<=A,{\"second\"}<=B s=3]);\n";
180 auto modelFormulas = this->
template buildModelFormulas<ModelType>(STORM_TEST_RESOURCES_DIR
"/dtmc/quantiles_simple_dtmc.pm", formulasString);
181 auto model = std::move(modelFormulas.first);
182 auto tasks = this->getTasks(modelFormulas.second);
183 EXPECT_EQ(4ul, model->getNumberOfStates());
184 EXPECT_EQ(6ul, model->getNumberOfTransitions());
185 auto checker = this->
template createModelChecker<ModelType>(model);
186 std::unique_ptr<storm::modelchecker::CheckResult> result;
187 std::vector<std::string> expectedResult;
188 std::pair<bool, std::string> compare;
191 expectedResult.clear();
192 expectedResult.push_back(
"7, 18");
193 expectedResult.push_back(
"8, 16");
194 expectedResult.push_back(
"9, 14");
195 result = checker->check(this->env(), tasks[taskId++]);
196 compare = this->compareResult(model, result, expectedResult);
197 EXPECT_TRUE(compare.first) << compare.second;
203 std::string formulasString =
"quantile(B1, B2, Pmax>0.5 [F{\"first\"}>=B1,{\"second\"}>=B2 s=1]);\n";
204 formulasString +=
"quantile(B1, B2, Pmax>0.5 [F{\"first\"}<=B1,{\"second\"}<=B2 s=1]);\n";
205 formulasString +=
"quantile(B1, B2, Pmin>0.5 [F{\"first\"}<=B1,{\"second\"}<=B2 s=1]);\n";
206 formulasString +=
"quantile(B1, Pmax>0.5 [F{\"second\"}>=B1 s=1]);\n";
207 formulasString +=
"quantile(B1, B2, B3, Pmax>0.5 [F{\"first\"}<=B1,{\"second\"}<=B2,{\"third\"}<=B3 s=1]);\n";
209 auto modelFormulas = this->
template buildModelFormulas<ModelType>(STORM_TEST_RESOURCES_DIR
"/mdp/quantiles_simple_mdp.nm", formulasString);
210 auto model = std::move(modelFormulas.first);
211 auto tasks = this->getTasks(modelFormulas.second);
212 EXPECT_EQ(7ul, model->getNumberOfStates());
213 EXPECT_EQ(13ul, model->getNumberOfTransitions());
214 auto checker = this->
template createModelChecker<ModelType>(model);
215 std::unique_ptr<storm::modelchecker::CheckResult> result;
216 std::vector<std::string> expectedResult;
217 std::pair<bool, std::string> compare;
220 expectedResult.clear();
221 expectedResult.push_back(
" 0, 6");
222 expectedResult.push_back(
" 1, 5");
223 expectedResult.push_back(
" 2, 4");
224 expectedResult.push_back(
" 3, 3");
225 expectedResult.push_back(
"inf, 2");
226 result = checker->check(this->env(), tasks[taskId++]);
227 compare = this->compareResult(model, result, expectedResult);
228 EXPECT_TRUE(compare.first) << compare.second;
230 expectedResult.clear();
231 expectedResult.push_back(
" 0, 2");
232 expectedResult.push_back(
" 5, 1");
233 expectedResult.push_back(
" 6, 0");
234 result = checker->check(this->env(), tasks[taskId++]);
235 compare = this->compareResult(model, result, expectedResult);
236 EXPECT_TRUE(compare.first) << compare.second;
238 expectedResult.clear();
239 result = checker->check(this->env(), tasks[taskId++]);
240 compare = this->compareResult(model, result, expectedResult);
241 EXPECT_TRUE(compare.first) << compare.second;
243 expectedResult.clear();
244 expectedResult.push_back(
" 6");
245 result = checker->check(this->env(), tasks[taskId++]);
246 compare = this->compareResult(model, result, expectedResult);
247 EXPECT_TRUE(compare.first) << compare.second;
249 expectedResult.clear();
250 expectedResult.push_back(
" 0, 2, 1.4");
251 expectedResult.push_back(
" 5, 1, 9.8");
252 expectedResult.push_back(
" 6, 0, 9.8");
253 result = checker->check(this->env(), tasks[taskId++]);
254 compare = this->compareResult(model, result, expectedResult);
255 EXPECT_TRUE(compare.first) << compare.second;
261 std::string formulasString =
"quantile(min TIME, min ROUNDS, Pmax>0.95 [F{\"time\"}<=TIME,{\"rounds\"}<=ROUNDS \"done\"]);\n";
263 auto modelFormulas = this->
template buildModelFormulas<ModelType>(STORM_TEST_RESOURCES_DIR
"/mdp/quantiles_firewire.nm", formulasString,
"delay=36");
264 auto model = std::move(modelFormulas.first);
265 auto tasks = this->getTasks(modelFormulas.second);
266 EXPECT_EQ(776ul, model->getNumberOfStates());
267 EXPECT_EQ(1411ul, model->getNumberOfTransitions());
268 auto checker = this->
template createModelChecker<ModelType>(model);
269 std::unique_ptr<storm::modelchecker::CheckResult> result;
270 std::vector<std::string> expectedResult;
271 std::pair<bool, std::string> compare;
274 expectedResult.clear();
275 expectedResult.push_back(
"123, 1");
276 result = checker->check(this->env(), tasks[taskId++]);
277 compare = this->compareResult(model, result, expectedResult);
278 EXPECT_TRUE(compare.first) << compare.second;
284 std::string formulasString =
"quantile(max GOLD, max GEM, Pmax>0.95 [F{\"gold\"}>=GOLD,{\"gem\"}>=GEM,{\"steps\"}<=100 true]);\n";
286 auto modelFormulas = this->
template buildModelFormulas<ModelType>(STORM_TEST_RESOURCES_DIR
"/mdp/quantiles_resources.nm", formulasString);
287 auto model = std::move(modelFormulas.first);
288 auto tasks = this->getTasks(modelFormulas.second);
289 EXPECT_EQ(94ul, model->getNumberOfStates());
290 EXPECT_EQ(326ul, model->getNumberOfTransitions());
291 auto checker = this->
template createModelChecker<ModelType>(model);
292 std::unique_ptr<storm::modelchecker::CheckResult> result;
293 std::vector<std::string> expectedResult;
294 std::pair<bool, std::string> compare;
297 expectedResult.clear();
298 expectedResult.push_back(
"0, 10");
299 expectedResult.push_back(
"1, 9");
300 expectedResult.push_back(
"4, 8");
301 expectedResult.push_back(
"7, 7");
302 expectedResult.push_back(
"8, 4");
303 expectedResult.push_back(
"9, 2");
304 expectedResult.push_back(
"10, 0");
305 result = checker->check(this->env(), tasks[taskId++]);
306 compare = this->compareResult(model, result, expectedResult);
307 EXPECT_TRUE(compare.first) << compare.second;
std::unique_ptr< storm::modelchecker::QualitativeCheckResult > getInitialStateFilter(std::shared_ptr< storm::models::sparse::Model< storm::Interval > > const &model)
SolverEnvironment & solver()
void setPrecision(storm::RationalNumber value)
MinMaxSolverEnvironment & minMax()
void setForceSoundness(bool value)
This class represents a discrete-time Markov chain.
This class represents a (discrete-time) Markov decision process.
Base class for all sparse models.
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)
SFTBDDChecker::ValueType ValueType
NumberType parseNumber(std::string const &value)
Parse number from string.
std::vector< std::string > parseCommaSeperatedValues(std::string const &input)
Given a string seperated by commas, returns the values.
storm::prism::Program preprocess(storm::prism::Program const &program, std::map< storm::expressions::Variable, storm::expressions::Expression > const &constantDefinitions)
storm::storage::BitVector filter(std::vector< T > const &values, std::function< bool(T const &value)> const &function)
Retrieves a bit vector containing all the indices for which the value at this position makes the give...
bool equalModuloPrecision(T const &val1, T const &val2, T const &precision, bool relativeError=true)
Compares the given elements and determines whether they are equal modulo the given precision.
std::string toString(std::vector< ValueType > const &vector)
Output vector as string.
TYPED_TEST(GraphTestAR, SymbolicProb01StochasticGameDieSmall)
TYPED_TEST_SUITE(GraphTestAR, TestingTypes,)
::testing::Types< Cudd, Sylvan > TestingTypes