1#include "storm-config.h"
29enum class MaEngine { PrismSparse, JaniSparse, JaniHybrid };
31class SparseDoubleValueIterationEnvironment {
34 static const MaEngine engine = MaEngine::PrismSparse;
35 static const bool isExact =
false;
45class JaniSparseDoubleValueIterationEnvironment {
48 static const MaEngine engine = MaEngine::JaniSparse;
49 static const bool isExact =
false;
59class JaniHybridDoubleValueIterationEnvironment {
62 static const MaEngine engine = MaEngine::JaniHybrid;
63 static const bool isExact =
false;
67 static void checkLibraryAvailable() {
68#ifndef STORM_HAVE_SYLVAN
69 GTEST_SKIP() <<
"Library Sylvan not available.";
80class SparseDoubleIntervalIterationEnvironment {
83 static const MaEngine engine = MaEngine::PrismSparse;
84 static const bool isExact =
false;
96class SparseRationalPolicyIterationEnvironment {
99 static const MaEngine engine = MaEngine::PrismSparse;
100 static const bool isExact =
true;
109class SparseRationalRationalSearchEnvironment {
112 static const MaEngine engine = MaEngine::PrismSparse;
113 static const bool isExact =
true;
123template<
typename TestType>
124class MarkovAutomatonCslModelCheckerTest :
public ::testing::Test {
126 typedef typename TestType::ValueType
ValueType;
130 MarkovAutomatonCslModelCheckerTest() : _environment(TestType::createEnvironment()) {}
132 void SetUp()
override {
134 GTEST_SKIP() <<
"Z3 not available.";
136 if constexpr (TestType::engine == MaEngine::JaniHybrid) {
137 TestType::checkLibraryAvailable();
145 return storm::utility::convertNumber<ValueType>(input);
150 bool isSparseModel()
const {
151 return std::is_same<typename TestType::ModelType, SparseModelType>::value;
153 bool isSymbolicModel()
const {
154 return std::is_same<typename TestType::ModelType, SymbolicModelType>::value;
157 template<
typename MT =
typename TestType::ModelType>
158 typename std::enable_if<std::is_same<MT, SparseModelType>::value,
159 std::pair<std::shared_ptr<MT>, std::vector<std::shared_ptr<storm::logic::Formula const>>>>::type
160 buildModelFormulas(std::string
const& pathToPrismFile, std::string
const& formulasAsString, std::string
const& constantDefinitionString =
"")
const {
161 std::pair<std::shared_ptr<MT>, std::vector<std::shared_ptr<storm::logic::Formula const>>> result;
164 if (TestType::engine == MaEngine::PrismSparse) {
166 result.first = storm::api::buildSparseModel<ValueType>(program, result.second)->template as<MT>();
167 }
else if (TestType::engine == MaEngine::JaniSparse) {
170 result.first = storm::api::buildSparseModel<ValueType>(janiData.first, result.second)->template as<MT>();
175 template<
typename MT =
typename TestType::ModelType>
176 typename std::enable_if<std::is_same<MT, SymbolicModelType>::value,
177 std::pair<std::shared_ptr<MT>, std::vector<std::shared_ptr<storm::logic::Formula const>>>>::type
178 buildModelFormulas(std::string
const& pathToPrismFile, std::string
const& formulasAsString, std::string
const& constantDefinitionString =
"")
const {
179 std::pair<std::shared_ptr<MT>, std::vector<std::shared_ptr<storm::logic::Formula const>>> result;
184 result.first = storm::api::buildSymbolicModel<TestType::ddType, ValueType>(janiData.first, result.second)->template as<MT>();
188 std::vector<storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>> getTasks(
189 std::vector<std::shared_ptr<storm::logic::Formula const>>
const& formulas)
const {
190 std::vector<storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>> result;
191 for (
auto const& f : formulas) {
192 result.emplace_back(*f);
197 template<
typename MT =
typename TestType::ModelType>
198 typename std::enable_if<std::is_same<MT, SparseModelType>::value, std::shared_ptr<storm::modelchecker::AbstractModelChecker<MT>>>::type createModelChecker(
199 std::shared_ptr<MT>
const& model)
const {
200 if (TestType::engine == MaEngine::PrismSparse || TestType::engine == MaEngine::JaniSparse) {
201 return std::make_shared<storm::modelchecker::SparseMarkovAutomatonCslModelChecker<SparseModelType>>(*model);
206 template<
typename MT =
typename TestType::ModelType>
207 typename std::enable_if<std::is_same<MT, SymbolicModelType>::value, std::shared_ptr<storm::modelchecker::AbstractModelChecker<MT>>>::type
208 createModelChecker(std::shared_ptr<MT>
const& model)
const {
209 if (TestType::engine == MaEngine::JaniHybrid) {
210 return std::make_shared<storm::modelchecker::HybridMarkovAutomatonCslModelChecker<SymbolicModelType>>(*model);
217 template<
typename MT =
typename TestType::ModelType>
218 typename std::enable_if<std::is_same<MT, SparseModelType>::value,
void>::type execute(std::shared_ptr<MT>
const& model,
219 std::function<
void()>
const& f)
const {
223 template<
typename MT =
typename TestType::ModelType>
224 typename std::enable_if<std::is_same<MT, SymbolicModelType>::value,
void>::type execute(std::shared_ptr<MT>
const& model,
225 std::function<
void()>
const& f)
const {
226 model->getManager().execute(f);
230 std::unique_ptr<storm::modelchecker::CheckResult>& result) {
232 result->filter(*filter);
233 return result->asQualitativeCheckResult().forallTrue();
237 std::unique_ptr<storm::modelchecker::CheckResult>& result) {
239 result->filter(*filter);
240 return result->asQuantitativeCheckResult<
ValueType>().getMin();
247 if (isSparseModel()) {
248 return std::make_unique<storm::modelchecker::ExplicitQualitativeCheckResult>(model->template as<SparseModelType>()->getInitialStates());
250 return std::make_unique<storm::modelchecker::SymbolicQualitativeCheckResult<TestType::ddType>>(
251 model->template as<SymbolicModelType>()->getReachableStates(), model->template as<SymbolicModelType>()->getInitialStates());
256typedef ::testing::Types<SparseDoubleValueIterationEnvironment, JaniSparseDoubleValueIterationEnvironment, JaniHybridDoubleValueIterationEnvironment,
257 SparseDoubleIntervalIterationEnvironment, SparseRationalPolicyIterationEnvironment, SparseRationalRationalSearchEnvironment>
262TYPED_TEST(MarkovAutomatonCslModelCheckerTest, server) {
263 std::string formulasString =
"Tmax=? [F \"error\"]";
264 formulasString +=
"; Pmax=? [F \"processB\"]";
265 formulasString +=
"; Pmax=? [F<1 \"error\"]";
267 auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR
"/ma/server.ma", formulasString);
268 auto model = std::move(modelFormulas.first);
269 auto tasks = this->getTasks(modelFormulas.second);
270 this->execute(model, [&]() {
271 EXPECT_EQ(6ul, model->getNumberOfStates());
272 EXPECT_EQ(10ul, model->getNumberOfTransitions());
274 auto checker = this->createModelChecker(model);
275 std::unique_ptr<storm::modelchecker::CheckResult> result;
277 result = checker->check(this->env(), tasks[0]);
280 result = checker->check(this->env(), tasks[1]);
284 result = checker->check(this->env(), tasks[2]);
290TYPED_TEST(MarkovAutomatonCslModelCheckerTest, simple) {
291 std::string formulasString =
"Pmin=? [F<1 s>2]";
292 formulasString +=
"; Pmax=? [F<1.3 s=3]";
294 auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR
"/ma/simple.ma", formulasString);
295 auto model = std::move(modelFormulas.first);
296 auto tasks = this->getTasks(modelFormulas.second);
297 this->execute(model, [&]() {
298 EXPECT_EQ(5ul, model->getNumberOfStates());
299 EXPECT_EQ(8ul, model->getNumberOfTransitions());
301 auto checker = this->createModelChecker(model);
302 std::unique_ptr<storm::modelchecker::CheckResult> result;
305 result = checker->check(this->env(), tasks[0]);
308 result = checker->check(this->env(), tasks[1]);
314TYPED_TEST(MarkovAutomatonCslModelCheckerTest, simple2) {
315 std::string formulasString =
"R{\"rew0\"}max=? [C]";
316 formulasString +=
"; R{\"rew0\"}min=? [C]";
317 formulasString +=
"; R{\"rew1\"}max=? [C]";
318 formulasString +=
"; R{\"rew1\"}min=? [C]";
319 formulasString +=
"; R{\"rew2\"}max=? [C]";
320 formulasString +=
"; R{\"rew2\"}min=? [C]";
321 formulasString +=
"; R{\"rew3\"}min=? [C]";
322 formulasString +=
"; LRAmin=? [s=0 | s=3]";
323 formulasString +=
"; R{\"rew3\"}max=?[ LRA ]";
324 formulasString +=
"; R{\"rew3\"}min=?[ LRA ]";
326 auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR
"/ma/simple2.ma", formulasString);
327 auto model = std::move(modelFormulas.first);
328 auto tasks = this->getTasks(modelFormulas.second);
329 EXPECT_EQ(6ul, model->getNumberOfStates());
330 EXPECT_EQ(11ul, model->getNumberOfTransitions());
332 auto checker = this->createModelChecker(model);
333 std::unique_ptr<storm::modelchecker::CheckResult> result;
335 if (TypeParam::engine != MaEngine::JaniHybrid) {
338 result = checker->check(this->env(), tasks[0]);
341 result = checker->check(this->env(), tasks[1]);
344 result = checker->check(this->env(), tasks[2]);
347 result = checker->check(this->env(), tasks[3]);
350 result = checker->check(this->env(), tasks[4]);
353 result = checker->check(this->env(), tasks[5]);
356 result = checker->check(this->env(), tasks[6]);
360#ifndef STORM_HAVE_Z3_OPTIMIZE
364 result = checker->check(this->env(), tasks[7]);
367 result = checker->check(this->env(), tasks[8]);
371 result = checker->check(this->env(), tasks[9]);
373#ifndef STORM_HAVE_Z3_OPTIMIZE
378TYPED_TEST(MarkovAutomatonCslModelCheckerTest, LtlSimple) {
379#ifdef STORM_HAVE_LTL_MODELCHECKING_SUPPORT
380 std::string formulasString =
"Pmax=? [X X s=3]";
381 formulasString +=
"; Pmax=? [X X G s>2]";
382 formulasString +=
"; Pmin=? [X X G s>2]";
383 formulasString +=
"; Pmax=? [F ((s=0) U X(s=0) & X(s=2))]";
385 auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR
"/ma/simple.ma", formulasString);
386 auto model = std::move(modelFormulas.first);
387 auto tasks = this->getTasks(modelFormulas.second);
388 EXPECT_EQ(5ul, model->getNumberOfStates());
389 EXPECT_EQ(8ul, model->getNumberOfTransitions());
391 auto checker = this->createModelChecker(model);
392 std::unique_ptr<storm::modelchecker::CheckResult> result;
395 if (TypeParam::engine == MaEngine::PrismSparse || TypeParam::engine == MaEngine::JaniSparse) {
396 result = checker->check(this->env(), tasks[0]);
399 result = checker->check(this->env(), tasks[1]);
402 result = checker->check(this->env(), tasks[2]);
405 result = checker->check(this->env(), tasks[3]);
409 EXPECT_FALSE(checker->canHandle(tasks[0]));
416TYPED_TEST(MarkovAutomatonCslModelCheckerTest, HOASimple) {
418 std::string formulasString =
"; P=?[HOA: {\"" STORM_TEST_RESOURCES_DIR
"/hoa/automaton_Fandp0Xp1.hoa\", \"p0\" -> (s>1), \"p1\" -> !(s=1) }]";
420 formulasString +=
"; P=?[HOA: {\"" STORM_TEST_RESOURCES_DIR
"/hoa/automaton_UXp0p1.hoa\", \"p0\" -> (s=2), \"p1\" -> (s=1) }]";
422 auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR
"/ma/simple.ma", formulasString);
423 auto model = std::move(modelFormulas.first);
424 auto tasks = this->getTasks(modelFormulas.second);
425 EXPECT_EQ(5ul, model->getNumberOfStates());
426 EXPECT_EQ(8ul, model->getNumberOfTransitions());
428 auto checker = this->createModelChecker(model);
429 std::unique_ptr<storm::modelchecker::CheckResult> result;
432 if (TypeParam::engine == MaEngine::PrismSparse || TypeParam::engine == MaEngine::JaniSparse) {
433 result = checker->check(tasks[0]);
436 result = checker->check(tasks[1]);
439 EXPECT_FALSE(checker->canHandle(tasks[0]));
std::unique_ptr< storm::modelchecker::QualitativeCheckResult > getInitialStateFilter(std::shared_ptr< storm::models::sparse::Model< storm::Interval > > const &model)
double getQuantitativeResultAtInitialState(std::shared_ptr< storm::models::sparse::Model< storm::Interval > > const &model, std::unique_ptr< storm::modelchecker::CheckResult > &result)
SolverEnvironment & solver()
void setPrecision(storm::RationalNumber value)
void setMethod(storm::solver::MinMaxMethod value, bool isSetFromDefault=false)
void setRelativeTerminationCriterion(bool value)
MinMaxSolverEnvironment & minMax()
void setForceSoundness(bool value)
This class represents a Markov automaton.
This class represents a discrete-time Markov decision process.
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)
std::pair< storm::jani::Model, std::vector< storm::jani::Property > > convertPrismToJani(storm::prism::Program const &program, storm::converter::PrismToJaniConverterOptions options)
SFTBDDChecker::ValueType ValueType
NumberType parseNumber(std::string const &value)
Parse number from string.
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 isZero(ValueType const &a)
bool isInfinity(ValueType const &a)
TYPED_TEST(GraphTestAR, SymbolicProb01StochasticGameDieSmall)
TYPED_TEST_SUITE(GraphTestAR, TestingTypes,)
::testing::Types< Cudd, Sylvan > TestingTypes