1#include "storm-config.h"
32enum class CtmcEngine { PrismSparse, JaniSparse, JaniHybrid };
35class GBSparseGmmxxGmresIluEnvironment {
38 static const CtmcEngine engine = CtmcEngine::PrismSparse;
39 static const bool isExact =
false;
48 storm::utility::convertNumber<storm::RationalNumber>(1e-8));
51 storm::utility::convertNumber<storm::RationalNumber>(1e-8));
56class GBJaniSparseGmmxxGmresIluEnvironment {
59 static const CtmcEngine engine = CtmcEngine::JaniSparse;
60 static const bool isExact =
false;
69 storm::utility::convertNumber<storm::RationalNumber>(1e-8));
72 storm::utility::convertNumber<storm::RationalNumber>(1e-8));
77class GBJaniHybridCuddGmmxxGmresEnvironment {
80 static const CtmcEngine engine = CtmcEngine::JaniHybrid;
81 static const bool isExact =
false;
85 static void checkLibraryAvailable() {
86#ifndef STORM_HAVE_CUDD
87 GTEST_SKIP() <<
"Library CUDD not available.";
97 storm::utility::convertNumber<storm::RationalNumber>(1e-8));
100 storm::utility::convertNumber<storm::RationalNumber>(1e-8));
105class GBJaniHybridSylvanGmmxxGmresEnvironment {
108 static const CtmcEngine engine = CtmcEngine::JaniHybrid;
109 static const bool isExact =
false;
113 static void checkLibraryAvailable() {
114#ifndef STORM_HAVE_SYLVAN
115 GTEST_SKIP() <<
"Library Sylvan not available.";
125 storm::utility::convertNumber<storm::RationalNumber>(1e-8));
128 storm::utility::convertNumber<storm::RationalNumber>(1e-8));
134class GBSparseEigenDGmresEnvironment {
137 static const CtmcEngine engine = CtmcEngine::PrismSparse;
138 static const bool isExact =
false;
151class GBSparseEigenDoubleLUEnvironment {
154 static const CtmcEngine engine = CtmcEngine::PrismSparse;
155 static const bool isExact =
false;
167class GBSparseNativeSorEnvironment {
170 static const CtmcEngine engine = CtmcEngine::PrismSparse;
171 static const bool isExact =
false;
186class DistrSparseGmmxxGmresIluEnvironment {
189 static const CtmcEngine engine = CtmcEngine::PrismSparse;
190 static const bool isExact =
false;
199 storm::utility::convertNumber<storm::RationalNumber>(1e-8));
202 storm::utility::convertNumber<storm::RationalNumber>(1e-8));
208class DistrSparseEigenDoubleLUEnvironment {
211 static const CtmcEngine engine = CtmcEngine::PrismSparse;
212 static const bool isExact =
false;
226class ValueIterationSparseEnvironment {
229 static const CtmcEngine engine = CtmcEngine::PrismSparse;
230 static const bool isExact =
false;
240class SoundEnvironment {
243 static const CtmcEngine engine = CtmcEngine::PrismSparse;
244 static const bool isExact =
false;
254template<
typename TestType>
255class LraCtmcCslModelCheckerTest :
public ::testing::Test {
257 typedef typename TestType::ValueType
ValueType;
261 LraCtmcCslModelCheckerTest() : _environment(TestType::createEnvironment()) {}
263 void SetUp()
override {
265 GTEST_SKIP() <<
"Z3 not available.";
267 if constexpr (TestType::engine == CtmcEngine::JaniHybrid) {
268 TestType::checkLibraryAvailable();
276 return storm::utility::convertNumber<ValueType>(input);
281 bool isSparseModel()
const {
282 return std::is_same<typename TestType::ModelType, SparseModelType>::value;
284 bool isSymbolicModel()
const {
285 return std::is_same<typename TestType::ModelType, SymbolicModelType>::value;
287 CtmcEngine getEngine()
const {
288 return TestType::engine;
291 template<
typename MT =
typename TestType::ModelType>
292 typename std::enable_if<std::is_same<MT, SparseModelType>::value,
293 std::pair<std::shared_ptr<MT>, std::vector<std::shared_ptr<storm::logic::Formula const>>>>::type
294 buildModelFormulas(std::string
const& pathToPrismFile, std::string
const& formulasAsString, std::string
const& constantDefinitionString =
"")
const {
295 std::pair<std::shared_ptr<MT>, std::vector<std::shared_ptr<storm::logic::Formula const>>> result;
298 if (TestType::engine == CtmcEngine::PrismSparse) {
300 result.first = storm::api::buildSparseModel<ValueType>(program, result.second)->template as<MT>();
301 }
else if (TestType::engine == CtmcEngine::JaniSparse) {
303 janiData.first.substituteFunctions();
305 result.first = storm::api::buildSparseModel<ValueType>(janiData.first, result.second)->template as<MT>();
310 template<
typename MT =
typename TestType::ModelType>
311 typename std::enable_if<std::is_same<MT, SymbolicModelType>::value,
312 std::pair<std::shared_ptr<MT>, std::vector<std::shared_ptr<storm::logic::Formula const>>>>::type
313 buildModelFormulas(std::string
const& pathToPrismFile, std::string
const& formulasAsString, std::string
const& constantDefinitionString =
"")
const {
314 std::pair<std::shared_ptr<MT>, std::vector<std::shared_ptr<storm::logic::Formula const>>> result;
317 if (TestType::engine == CtmcEngine::JaniHybrid) {
319 janiData.first.substituteFunctions();
321 result.first = storm::api::buildSymbolicModel<TestType::ddType, ValueType>(janiData.first, result.second)->template as<MT>();
326 std::vector<storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>> getTasks(
327 std::vector<std::shared_ptr<storm::logic::Formula const>>
const& formulas)
const {
328 std::vector<storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>> result;
329 for (
auto const& f : formulas) {
330 result.emplace_back(*f);
335 template<
typename MT =
typename TestType::ModelType>
336 typename std::enable_if<std::is_same<MT, SparseModelType>::value, std::shared_ptr<storm::modelchecker::AbstractModelChecker<MT>>>::type createModelChecker(
337 std::shared_ptr<MT>
const& model)
const {
338 if (TestType::engine == CtmcEngine::PrismSparse || TestType::engine == CtmcEngine::JaniSparse) {
339 return std::make_shared<storm::modelchecker::SparseCtmcCslModelChecker<SparseModelType>>(*model);
344 template<
typename MT =
typename TestType::ModelType>
345 typename std::enable_if<std::is_same<MT, SymbolicModelType>::value, std::shared_ptr<storm::modelchecker::AbstractModelChecker<MT>>>::type
346 createModelChecker(std::shared_ptr<MT>
const& model)
const {
347 if (TestType::engine == CtmcEngine::JaniHybrid) {
348 return std::make_shared<storm::modelchecker::HybridCtmcCslModelChecker<SymbolicModelType>>(*model);
353 template<
typename MT =
typename TestType::ModelType>
354 typename std::enable_if<std::is_same<MT, SparseModelType>::value,
void>::type execute(std::shared_ptr<MT>
const& model,
355 std::function<
void()>
const& f)
const {
359 template<
typename MT =
typename TestType::ModelType>
360 typename std::enable_if<std::is_same<MT, SymbolicModelType>::value,
void>::type execute(std::shared_ptr<MT>
const& model,
361 std::function<
void()>
const& f)
const {
362 model->getManager().execute(f);
366 std::unique_ptr<storm::modelchecker::CheckResult>& result) {
368 result->filter(*filter);
369 return result->asQualitativeCheckResult().forallTrue();
373 std::unique_ptr<storm::modelchecker::CheckResult>& result) {
375 result->filter(*filter);
376 return result->asQuantitativeCheckResult<
ValueType>().getMin();
383 if (isSparseModel()) {
384 return std::make_unique<storm::modelchecker::ExplicitQualitativeCheckResult>(model->template as<SparseModelType>()->getInitialStates());
386 return std::make_unique<storm::modelchecker::SymbolicQualitativeCheckResult<TestType::ddType>>(
387 model->template as<SymbolicModelType>()->getReachableStates(), model->template as<SymbolicModelType>()->getInitialStates());
392typedef ::testing::Types<
394 GBSparseGmmxxGmresIluEnvironment, GBJaniSparseGmmxxGmresIluEnvironment, GBJaniHybridCuddGmmxxGmresEnvironment, GBJaniHybridSylvanGmmxxGmresEnvironment,
395 DistrSparseGmmxxGmresIluEnvironment,
397 GBSparseEigenDGmresEnvironment, GBSparseEigenDoubleLUEnvironment, GBSparseNativeSorEnvironment, DistrSparseEigenDoubleLUEnvironment,
398 ValueIterationSparseEnvironment, SoundEnvironment>
403TYPED_TEST(LraCtmcCslModelCheckerTest, Cluster) {
404 std::string formulasString =
"LRA=? [\"minimum\"]";
406 auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR
"/ctmc/cluster2.sm", formulasString);
407 auto model = std::move(modelFormulas.first);
408 auto tasks = this->getTasks(modelFormulas.second);
409 this->execute(model, [&]() {
410 EXPECT_EQ(276ul, model->getNumberOfStates());
411 EXPECT_EQ(1120ul, model->getNumberOfTransitions());
413 auto checker = this->createModelChecker(model);
414 std::unique_ptr<storm::modelchecker::CheckResult> result;
416 result = checker->check(this->env(), tasks[0]);
421TYPED_TEST(LraCtmcCslModelCheckerTest, Embedded) {
422 std::string formulasString =
"LRA=? [\"fail_sensors\"]";
424 auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR
"/ctmc/embedded2.sm", formulasString);
425 auto model = std::move(modelFormulas.first);
426 auto tasks = this->getTasks(modelFormulas.second);
427 this->execute(model, [&]() {
428 EXPECT_EQ(3478ul, model->getNumberOfStates());
429 EXPECT_EQ(14639ul, model->getNumberOfTransitions());
431 auto checker = this->createModelChecker(model);
432 std::unique_ptr<storm::modelchecker::CheckResult> result;
434 result = checker->check(this->env(), tasks[0]);
439TYPED_TEST(LraCtmcCslModelCheckerTest, Polling) {
440 std::string formulasString =
"LRA=?[\"target\"]";
442 auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR
"/ctmc/polling2.sm", formulasString);
443 auto model = std::move(modelFormulas.first);
444 auto tasks = this->getTasks(modelFormulas.second);
445 this->execute(model, [&]() {
446 EXPECT_EQ(12ul, model->getNumberOfStates());
447 EXPECT_EQ(22ul, model->getNumberOfTransitions());
449 auto checker = this->createModelChecker(model);
450 std::unique_ptr<storm::modelchecker::CheckResult> result;
452 result = checker->check(this->env(), tasks[0]);
457TYPED_TEST(LraCtmcCslModelCheckerTest, Tandem) {
458 std::string formulasString =
"LRA=? [\"first_queue_full\"]";
460 auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR
"/ctmc/tandem5.sm", formulasString);
461 auto model = std::move(modelFormulas.first);
462 auto tasks = this->getTasks(modelFormulas.second);
463 this->execute(model, [&]() {
464 EXPECT_EQ(66ul, model->getNumberOfStates());
465 EXPECT_EQ(189ul, model->getNumberOfTransitions());
467 auto checker = this->createModelChecker(model);
468 std::unique_ptr<storm::modelchecker::CheckResult> result;
470 result = checker->check(this->env(), tasks[0]);
475TYPED_TEST(LraCtmcCslModelCheckerTest, Rewards) {
476 std::string formulasString =
"R=? [ LRA ]";
478 auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR
"/ctmc/lrarewards.sm", formulasString);
479 auto model = std::move(modelFormulas.first);
480 auto tasks = this->getTasks(modelFormulas.second);
481 this->execute(model, [&]() {
482 EXPECT_EQ(4ul, model->getNumberOfStates());
483 EXPECT_EQ(6ul, model->getNumberOfTransitions());
485 auto checker = this->createModelChecker(model);
486 std::unique_ptr<storm::modelchecker::CheckResult> result;
488 result = checker->check(this->env(), tasks[0]);
493TYPED_TEST(LraCtmcCslModelCheckerTest, kanban) {
494 std::string formulasString =
"R{\"throughput\"}=? [ LRA ]";
496 auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR
"/ctmc/kanban.prism", formulasString);
497 auto model = std::move(modelFormulas.first);
498 auto tasks = this->getTasks(modelFormulas.second);
499 this->execute(model, [&]() {
500 EXPECT_EQ(160ul, model->getNumberOfStates());
501 EXPECT_EQ(616ul, model->getNumberOfTransitions());
503 auto checker = this->createModelChecker(model);
504 std::unique_ptr<storm::modelchecker::CheckResult> result;
506 result = checker->check(this->env(), tasks[0]);
508 this->
parseNumber(
"1132372552133951639536770152429724263999896896549676426094918302160613340902023133969841067385167041200690481843915870926707"
509 "11590526535239899047608853509681914074220789038015289373871985431257486278/"
510 "1223067474012215838745994023624181143448435715858923491568712969277184634645504346456117443333632535902774869182827010789201"
511 "972713368729205674432492059242349591780604188152950845769793378621446766887"),
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)
void setPrecision(storm::RationalNumber value)
void setPreconditioner(storm::solver::EigenLinearEquationSolverPreconditioner value)
void setMethod(storm::solver::EigenLinearEquationSolverMethod value)
SolverEnvironment & solver()
void setMethod(storm::solver::GmmxxLinearEquationSolverMethod value)
void setPrecision(storm::RationalNumber value)
void setPreconditioner(storm::solver::GmmxxLinearEquationSolverPreconditioner value)
void setDetLraMethod(storm::solver::LraMethod value, bool isSetFromDefault=false)
void setPrecision(storm::RationalNumber value)
void setSorOmega(storm::RationalNumber const &value)
void setMethod(storm::solver::NativeLinearEquationSolverMethod value)
void setLinearEquationSolverType(storm::solver::EquationSolverType const &value, bool isSetFromDefault=false)
EigenSolverEnvironment & eigen()
void setForceSoundness(bool value)
NativeSolverEnvironment & native()
GmmxxSolverEnvironment & gmmxx()
LongRunAverageSolverEnvironment & lra()
This class represents a continuous-time Markov chain.
This class represents a continuous-time Markov chain.
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...
TYPED_TEST(GraphTestAR, SymbolicProb01StochasticGameDieSmall)
TYPED_TEST_SUITE(GraphTestAR, TestingTypes,)
::testing::Types< Cudd, Sylvan > TestingTypes