9 changed files with 0 additions and 3015 deletions
-
170src/test/storm/modelchecker/prctl/ConditionalDtmcPrctlModelCheckerTest.cpp
-
701src/test/storm/modelchecker/prctl/DtmcPrctlModelCheckerTest.cpp
-
158src/test/storm/modelchecker/prctl/ExplicitDtmcPrctlModelCheckerTest.cpp
-
199src/test/storm/modelchecker/prctl/ExplicitMdpPrctlModelCheckerTest.cpp
-
268src/test/storm/modelchecker/prctl/LraDtmcPrctlModelCheckerTest.cpp
-
468src/test/storm/modelchecker/prctl/LraMdpPrctlModelCheckerTest.cpp
-
607src/test/storm/modelchecker/prctl/MdpPrctlModelCheckerTest.cpp
-
302src/test/storm/modelchecker/prctl/QuantileQueryTest.cpp
-
142src/test/storm/modelchecker/prctl/SchedulerGenerationMdpPrctlModelCheckerTest.cpp
@ -1,170 +0,0 @@ |
|||||
#include "test/storm_gtest.h"
|
|
||||
#include "test/storm_gtest.h"
|
|
||||
#include "storm-config.h"
|
|
||||
|
|
||||
#include "storm-parsers/parser/FormulaParser.h"
|
|
||||
#include "storm/logic/Formulas.h"
|
|
||||
#include "storm/models/sparse/StandardRewardModel.h"
|
|
||||
#include "storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.h"
|
|
||||
#include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h"
|
|
||||
#include "storm-parsers/parser/PrismParser.h"
|
|
||||
#include "storm/api/builder.h"
|
|
||||
#include "storm/storage/expressions/ExpressionManager.h"
|
|
||||
|
|
||||
#include "storm/environment/solver/GmmxxSolverEnvironment.h"
|
|
||||
#include "storm/environment/solver/EigenSolverEnvironment.h"
|
|
||||
#include "storm/environment/solver/NativeSolverEnvironment.h"
|
|
||||
|
|
||||
namespace { |
|
||||
|
|
||||
class GmmxxDoubleGmresEnvironment { |
|
||||
public: |
|
||||
typedef double ValueType; |
|
||||
static const bool isExact = false; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Gmmxx); |
|
||||
env.solver().gmmxx().setMethod(storm::solver::GmmxxLinearEquationSolverMethod::Gmres); |
|
||||
env.solver().gmmxx().setPreconditioner(storm::solver::GmmxxLinearEquationSolverPreconditioner::Ilu); |
|
||||
env.solver().gmmxx().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class EigenDoubleDGmresEnvironment { |
|
||||
public: |
|
||||
typedef double ValueType; |
|
||||
static const bool isExact = false; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Eigen); |
|
||||
env.solver().eigen().setMethod(storm::solver::EigenLinearEquationSolverMethod::DGmres); |
|
||||
env.solver().eigen().setPreconditioner(storm::solver::EigenLinearEquationSolverPreconditioner::Ilu); |
|
||||
env.solver().eigen().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class EigenRationalLUEnvironment { |
|
||||
public: |
|
||||
typedef storm::RationalNumber ValueType; |
|
||||
static const bool isExact = true; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Eigen); |
|
||||
env.solver().eigen().setMethod(storm::solver::EigenLinearEquationSolverMethod::SparseLU); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class NativeSorEnvironment { |
|
||||
public: |
|
||||
typedef double ValueType; |
|
||||
static const bool isExact = false; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native); |
|
||||
env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::SOR); |
|
||||
env.solver().native().setSorOmega(storm::utility::convertNumber<storm::RationalNumber>(0.9)); |
|
||||
env.solver().native().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class NativePowerEnvironment { |
|
||||
public: |
|
||||
typedef double ValueType; |
|
||||
static const bool isExact = false; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native); |
|
||||
env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::Power); |
|
||||
env.solver().native().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class NativeWalkerChaeEnvironment { |
|
||||
public: |
|
||||
typedef double ValueType; |
|
||||
static const bool isExact = false; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native); |
|
||||
env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::WalkerChae); |
|
||||
env.solver().native().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
env.solver().native().setMaximalNumberOfIterations(50000); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
template<typename TestType> |
|
||||
class ConditionalDtmcPrctlModelCheckerTest : public ::testing::Test { |
|
||||
public: |
|
||||
typedef typename TestType::ValueType ValueType; |
|
||||
ConditionalDtmcPrctlModelCheckerTest() : _environment(TestType::createEnvironment()) {} |
|
||||
storm::Environment const& env() const { return _environment; } |
|
||||
ValueType parseNumber(std::string const& input) const { return storm::utility::convertNumber<ValueType>(input);} |
|
||||
ValueType precision() const { return TestType::isExact ? parseNumber("0") : parseNumber("1e-6");} |
|
||||
|
|
||||
private: |
|
||||
storm::Environment _environment; |
|
||||
}; |
|
||||
|
|
||||
typedef ::testing::Types< |
|
||||
GmmxxDoubleGmresEnvironment, |
|
||||
EigenDoubleDGmresEnvironment, |
|
||||
EigenRationalLUEnvironment, |
|
||||
NativeSorEnvironment, |
|
||||
NativePowerEnvironment, |
|
||||
NativeWalkerChaeEnvironment |
|
||||
> TestingTypes; |
|
||||
|
|
||||
TYPED_TEST_SUITE(ConditionalDtmcPrctlModelCheckerTest, TestingTypes); |
|
||||
|
|
||||
|
|
||||
TYPED_TEST(ConditionalDtmcPrctlModelCheckerTest, Conditional) { |
|
||||
typedef typename TestFixture::ValueType ValueType; |
|
||||
|
|
||||
storm::prism::Program program = storm::parser::PrismParser::parse(STORM_TEST_RESOURCES_DIR "/dtmc/test_conditional.pm"); |
|
||||
|
|
||||
storm::generator::NextStateGeneratorOptions options; |
|
||||
options.setBuildAllLabels().setBuildAllRewardModels(); |
|
||||
std::shared_ptr<storm::models::sparse::Model<ValueType>> model = storm::builder::ExplicitModelBuilder<ValueType>(program, options).build(); |
|
||||
ASSERT_TRUE(model->getType() == storm::models::ModelType::Dtmc); |
|
||||
ASSERT_EQ(4ul, model->getNumberOfStates()); |
|
||||
ASSERT_EQ(5ul, model->getNumberOfTransitions()); |
|
||||
|
|
||||
std::shared_ptr<storm::models::sparse::Dtmc<ValueType>> dtmc = model->template as<storm::models::sparse::Dtmc<ValueType>>(); |
|
||||
|
|
||||
storm::modelchecker::SparseDtmcPrctlModelChecker<storm::models::sparse::Dtmc<ValueType>> checker(*dtmc); |
|
||||
|
|
||||
// A parser that we use for conveniently constructing the formulas.
|
|
||||
|
|
||||
auto expManager = std::make_shared<storm::expressions::ExpressionManager>(); |
|
||||
storm::parser::FormulaParser formulaParser(expManager); |
|
||||
std::shared_ptr<storm::logic::Formula const> formula = formulaParser.parseSingleFormulaFromString("P=? [F \"target\"]"); |
|
||||
|
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
EXPECT_NEAR(this->parseNumber("0.5"), quantitativeResult1[0], this->precision()); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("P=? [F \"target\" || F \"condition\"]"); |
|
||||
|
|
||||
result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
EXPECT_NEAR(storm::utility::one<ValueType>(), quantitativeResult2[0], this->precision()); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("R=? [F \"target\"]"); |
|
||||
|
|
||||
result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
EXPECT_EQ(storm::utility::infinity<ValueType>(), quantitativeResult3[0]); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("R=? [F \"target\" || F \"condition\"]"); |
|
||||
|
|
||||
result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult4 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
EXPECT_NEAR(storm::utility::one<ValueType>(), quantitativeResult4[0], this->precision()); |
|
||||
} |
|
||||
} |
|
@ -1,701 +0,0 @@ |
|||||
#include "test/storm_gtest.h"
|
|
||||
#include "test/storm_gtest.h"
|
|
||||
#include "storm-config.h"
|
|
||||
|
|
||||
#include "storm/api/builder.h"
|
|
||||
#include "storm-conv/api/storm-conv.h"
|
|
||||
#include "storm-parsers/api/model_descriptions.h"
|
|
||||
#include "storm/api/properties.h"
|
|
||||
#include "storm-parsers/api/properties.h"
|
|
||||
#include "storm-parsers/parser/FormulaParser.h"
|
|
||||
#include "storm/logic/Formulas.h"
|
|
||||
#include "storm/solver/EigenLinearEquationSolver.h"
|
|
||||
#include "storm/models/sparse/StandardRewardModel.h"
|
|
||||
#include "storm/models/symbolic/StandardRewardModel.h"
|
|
||||
#include "storm/models/sparse/Dtmc.h"
|
|
||||
#include "storm/models/symbolic/Dtmc.h"
|
|
||||
#include "storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.h"
|
|
||||
#include "storm/modelchecker/prctl/HybridDtmcPrctlModelChecker.h"
|
|
||||
#include "storm/modelchecker/prctl/SymbolicDtmcPrctlModelChecker.h"
|
|
||||
#include "storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.h"
|
|
||||
#include "storm/modelchecker/results/QuantitativeCheckResult.h"
|
|
||||
#include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h"
|
|
||||
#include "storm/modelchecker/results/SymbolicQualitativeCheckResult.h"
|
|
||||
#include "storm/modelchecker/results/QualitativeCheckResult.h"
|
|
||||
#include "storm-parsers/parser/PrismParser.h"
|
|
||||
#include "storm/storage/expressions/ExpressionManager.h"
|
|
||||
#include "storm/settings/modules/CoreSettings.h"
|
|
||||
#include "storm/environment/solver/NativeSolverEnvironment.h"
|
|
||||
#include "storm/environment/solver/GmmxxSolverEnvironment.h"
|
|
||||
#include "storm/environment/solver/EigenSolverEnvironment.h"
|
|
||||
#include "storm/environment/solver/TopologicalSolverEnvironment.h"
|
|
||||
|
|
||||
namespace { |
|
||||
|
|
||||
enum class DtmcEngine {PrismSparse, JaniSparse, JitSparse, Hybrid, PrismDd, JaniDd}; |
|
||||
|
|
||||
class SparseGmmxxGmresIluEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // unused for sparse models
|
|
||||
static const DtmcEngine engine = DtmcEngine::PrismSparse; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Dtmc<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Gmmxx); |
|
||||
env.solver().gmmxx().setMethod(storm::solver::GmmxxLinearEquationSolverMethod::Gmres); |
|
||||
env.solver().gmmxx().setPreconditioner(storm::solver::GmmxxLinearEquationSolverPreconditioner::Ilu); |
|
||||
env.solver().gmmxx().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class JaniSparseGmmxxGmresIluEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // unused for sparse models
|
|
||||
static const DtmcEngine engine = DtmcEngine::JaniSparse; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Dtmc<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Gmmxx); |
|
||||
env.solver().gmmxx().setMethod(storm::solver::GmmxxLinearEquationSolverMethod::Gmres); |
|
||||
env.solver().gmmxx().setPreconditioner(storm::solver::GmmxxLinearEquationSolverPreconditioner::Ilu); |
|
||||
env.solver().gmmxx().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class JitSparseGmmxxGmresIluEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // unused for sparse models
|
|
||||
static const DtmcEngine engine = DtmcEngine::JitSparse; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Dtmc<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Gmmxx); |
|
||||
env.solver().gmmxx().setMethod(storm::solver::GmmxxLinearEquationSolverMethod::Gmres); |
|
||||
env.solver().gmmxx().setPreconditioner(storm::solver::GmmxxLinearEquationSolverPreconditioner::Ilu); |
|
||||
env.solver().gmmxx().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseGmmxxGmresDiagEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // unused for sparse models
|
|
||||
static const DtmcEngine engine = DtmcEngine::PrismSparse; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Dtmc<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Gmmxx); |
|
||||
env.solver().gmmxx().setMethod(storm::solver::GmmxxLinearEquationSolverMethod::Gmres); |
|
||||
env.solver().gmmxx().setPreconditioner(storm::solver::GmmxxLinearEquationSolverPreconditioner::Diagonal); |
|
||||
env.solver().gmmxx().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseGmmxxBicgstabIluEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // unused for sparse models
|
|
||||
static const DtmcEngine engine = DtmcEngine::PrismSparse; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Dtmc<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Gmmxx); |
|
||||
env.solver().gmmxx().setMethod(storm::solver::GmmxxLinearEquationSolverMethod::Bicgstab); |
|
||||
env.solver().gmmxx().setPreconditioner(storm::solver::GmmxxLinearEquationSolverPreconditioner::Ilu); |
|
||||
env.solver().gmmxx().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseEigenDGmresEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // unused for sparse models
|
|
||||
static const DtmcEngine engine = DtmcEngine::PrismSparse; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Dtmc<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Eigen); |
|
||||
env.solver().eigen().setMethod(storm::solver::EigenLinearEquationSolverMethod::DGmres); |
|
||||
env.solver().eigen().setPreconditioner(storm::solver::EigenLinearEquationSolverPreconditioner::Ilu); |
|
||||
env.solver().eigen().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseEigenDoubleLUEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // unused for sparse models
|
|
||||
static const DtmcEngine engine = DtmcEngine::PrismSparse; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Dtmc<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Eigen); |
|
||||
env.solver().eigen().setMethod(storm::solver::EigenLinearEquationSolverMethod::SparseLU); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseEigenRationalLUEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // unused for sparse models
|
|
||||
static const DtmcEngine engine = DtmcEngine::PrismSparse; |
|
||||
static const bool isExact = true; |
|
||||
typedef storm::RationalNumber ValueType; |
|
||||
typedef storm::models::sparse::Dtmc<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Eigen); |
|
||||
env.solver().eigen().setMethod(storm::solver::EigenLinearEquationSolverMethod::SparseLU); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseRationalEliminationEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // unused for sparse models
|
|
||||
static const DtmcEngine engine = DtmcEngine::PrismSparse; |
|
||||
static const bool isExact = true; |
|
||||
typedef storm::RationalNumber ValueType; |
|
||||
typedef storm::models::sparse::Dtmc<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Elimination); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseNativeJacobiEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // unused for sparse models
|
|
||||
static const DtmcEngine engine = DtmcEngine::PrismSparse; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Dtmc<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native); |
|
||||
env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::Jacobi); |
|
||||
env.solver().native().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseNativeWalkerChaeEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // unused for sparse models
|
|
||||
static const DtmcEngine engine = DtmcEngine::PrismSparse; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Dtmc<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native); |
|
||||
env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::WalkerChae); |
|
||||
env.solver().native().setMaximalNumberOfIterations(1000000); |
|
||||
env.solver().native().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-7)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseNativeSorEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // unused for sparse models
|
|
||||
static const DtmcEngine engine = DtmcEngine::PrismSparse; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Dtmc<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native); |
|
||||
env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::SOR); |
|
||||
env.solver().native().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseNativePowerEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // unused for sparse models
|
|
||||
static const DtmcEngine engine = DtmcEngine::PrismSparse; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Dtmc<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native); |
|
||||
env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::Power); |
|
||||
env.solver().native().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseNativeSoundValueIterationEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // unused for sparse models
|
|
||||
static const DtmcEngine engine = DtmcEngine::PrismSparse; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Dtmc<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setForceSoundness(true); |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native); |
|
||||
env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::SoundValueIteration); |
|
||||
env.solver().native().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-6)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseNativeIntervalIterationEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // unused for sparse models
|
|
||||
static const DtmcEngine engine = DtmcEngine::PrismSparse; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Dtmc<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setForceSoundness(true); |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native); |
|
||||
env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::IntervalIteration); |
|
||||
env.solver().native().setRelativeTerminationCriterion(false); |
|
||||
env.solver().native().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-6)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseNativeRationalSearchEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // unused for sparse models
|
|
||||
static const DtmcEngine engine = DtmcEngine::PrismSparse; |
|
||||
static const bool isExact = true; |
|
||||
typedef storm::RationalNumber ValueType; |
|
||||
typedef storm::models::sparse::Dtmc<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native); |
|
||||
env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::RationalSearch); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseTopologicalEigenLUEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // unused for sparse models
|
|
||||
static const DtmcEngine engine = DtmcEngine::PrismSparse; |
|
||||
static const bool isExact = true; |
|
||||
typedef storm::RationalNumber ValueType; |
|
||||
typedef storm::models::sparse::Dtmc<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Topological); |
|
||||
env.solver().topological().setUnderlyingEquationSolverType(storm::solver::EquationSolverType::Eigen); |
|
||||
env.solver().eigen().setMethod(storm::solver::EigenLinearEquationSolverMethod::SparseLU); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class HybridSylvanGmmxxGmresEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; |
|
||||
static const DtmcEngine engine = DtmcEngine::Hybrid; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::symbolic::Dtmc<ddType, ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Gmmxx); |
|
||||
env.solver().gmmxx().setMethod(storm::solver::GmmxxLinearEquationSolverMethod::Gmres); |
|
||||
env.solver().gmmxx().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class HybridCuddNativeJacobiEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::CUDD; |
|
||||
static const DtmcEngine engine = DtmcEngine::Hybrid; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::symbolic::Dtmc<ddType, ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native); |
|
||||
env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::Jacobi); |
|
||||
env.solver().native().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class HybridCuddNativeSoundValueIterationEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::CUDD; |
|
||||
static const DtmcEngine engine = DtmcEngine::Hybrid; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::symbolic::Dtmc<ddType, ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setForceSoundness(true); |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native); |
|
||||
env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::Power); |
|
||||
env.solver().native().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-6)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class HybridSylvanNativeRationalSearchEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; |
|
||||
static const DtmcEngine engine = DtmcEngine::Hybrid; |
|
||||
static const bool isExact = true; |
|
||||
typedef storm::RationalNumber ValueType; |
|
||||
typedef storm::models::symbolic::Dtmc<ddType, ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native); |
|
||||
env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::RationalSearch); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class DdSylvanNativePowerEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; |
|
||||
static const DtmcEngine engine = DtmcEngine::PrismDd; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::symbolic::Dtmc<ddType, ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native); |
|
||||
env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::Power); |
|
||||
env.solver().native().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class JaniDdSylvanNativePowerEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; |
|
||||
static const DtmcEngine engine = DtmcEngine::JaniDd; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::symbolic::Dtmc<ddType, ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native); |
|
||||
env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::Power); |
|
||||
env.solver().native().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class DdCuddNativeJacobiEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::CUDD; |
|
||||
static const DtmcEngine engine = DtmcEngine::PrismDd; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::symbolic::Dtmc<ddType, ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native); |
|
||||
env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::Power); |
|
||||
env.solver().native().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class DdSylvanRationalSearchEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; |
|
||||
static const DtmcEngine engine = DtmcEngine::PrismDd; |
|
||||
static const bool isExact = true; |
|
||||
typedef storm::RationalNumber ValueType; |
|
||||
typedef storm::models::symbolic::Dtmc<ddType, ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native); |
|
||||
env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::RationalSearch); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
template<typename TestType> |
|
||||
class DtmcPrctlModelCheckerTest : public ::testing::Test { |
|
||||
public: |
|
||||
typedef typename TestType::ValueType ValueType; |
|
||||
typedef typename storm::models::sparse::Dtmc<ValueType> SparseModelType; |
|
||||
typedef typename storm::models::symbolic::Dtmc<TestType::ddType, ValueType> SymbolicModelType; |
|
||||
|
|
||||
DtmcPrctlModelCheckerTest() : _environment(TestType::createEnvironment()) {} |
|
||||
storm::Environment const& env() const { return _environment; } |
|
||||
ValueType parseNumber(std::string const& input) const { return storm::utility::convertNumber<ValueType>(input);} |
|
||||
ValueType precision() const { return TestType::isExact ? parseNumber("0") : parseNumber("1e-6");} |
|
||||
bool isSparseModel() const { return std::is_same<typename TestType::ModelType, SparseModelType>::value; } |
|
||||
bool isSymbolicModel() const { return std::is_same<typename TestType::ModelType, SymbolicModelType>::value; } |
|
||||
|
|
||||
template <typename MT = typename TestType::ModelType> |
|
||||
typename std::enable_if<std::is_same<MT, SparseModelType>::value, std::pair<std::shared_ptr<MT>, std::vector<std::shared_ptr<storm::logic::Formula const>>>>::type |
|
||||
buildModelFormulas(std::string const& pathToPrismFile, std::string const& formulasAsString, std::string const& constantDefinitionString = "") const { |
|
||||
std::pair<std::shared_ptr<MT>, std::vector<std::shared_ptr<storm::logic::Formula const>>> result; |
|
||||
storm::prism::Program program = storm::api::parseProgram(pathToPrismFile); |
|
||||
program = storm::utility::prism::preprocess(program, constantDefinitionString); |
|
||||
if (TestType::engine == DtmcEngine::PrismSparse) { |
|
||||
result.second = storm::api::extractFormulasFromProperties(storm::api::parsePropertiesForPrismProgram(formulasAsString, program)); |
|
||||
result.first = storm::api::buildSparseModel<ValueType>(program, result.second)->template as<MT>(); |
|
||||
} else if (TestType::engine == DtmcEngine::JaniSparse || TestType::engine == DtmcEngine::JitSparse) { |
|
||||
auto janiData = storm::api::convertPrismToJani(program, storm::api::parsePropertiesForPrismProgram(formulasAsString, program)); |
|
||||
result.second = storm::api::extractFormulasFromProperties(janiData.second); |
|
||||
result.first = storm::api::buildSparseModel<ValueType>(janiData.first, result.second, TestType::engine == DtmcEngine::JitSparse)->template as<MT>(); |
|
||||
} |
|
||||
|
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
template <typename MT = typename TestType::ModelType> |
|
||||
typename std::enable_if<std::is_same<MT, SymbolicModelType>::value, std::pair<std::shared_ptr<MT>, std::vector<std::shared_ptr<storm::logic::Formula const>>>>::type |
|
||||
buildModelFormulas(std::string const& pathToPrismFile, std::string const& formulasAsString, std::string const& constantDefinitionString = "") const { |
|
||||
std::pair<std::shared_ptr<MT>, std::vector<std::shared_ptr<storm::logic::Formula const>>> result; |
|
||||
storm::prism::Program program = storm::api::parseProgram(pathToPrismFile); |
|
||||
program = storm::utility::prism::preprocess(program, constantDefinitionString); |
|
||||
if (TestType::engine == DtmcEngine::Hybrid || TestType::engine == DtmcEngine::PrismDd) { |
|
||||
result.second = storm::api::extractFormulasFromProperties(storm::api::parsePropertiesForPrismProgram(formulasAsString, program)); |
|
||||
result.first = storm::api::buildSymbolicModel<TestType::ddType, ValueType>(program, result.second)->template as<MT>(); |
|
||||
} else if (TestType::engine == DtmcEngine::JaniDd) { |
|
||||
auto janiData = storm::api::convertPrismToJani(program, storm::api::parsePropertiesForPrismProgram(formulasAsString, program)); |
|
||||
janiData.first.substituteFunctions(); |
|
||||
result.second = storm::api::extractFormulasFromProperties(janiData.second); |
|
||||
result.first = storm::api::buildSymbolicModel<TestType::ddType, ValueType>(janiData.first, result.second)->template as<MT>(); |
|
||||
} |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
std::vector<storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>> getTasks(std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas) const { |
|
||||
std::vector<storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>> result; |
|
||||
for (auto const& f : formulas) { |
|
||||
result.emplace_back(*f); |
|
||||
} |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
template <typename MT = typename TestType::ModelType> |
|
||||
typename std::enable_if<std::is_same<MT, SparseModelType>::value, std::shared_ptr<storm::modelchecker::AbstractModelChecker<MT>>>::type |
|
||||
createModelChecker(std::shared_ptr<MT> const& model) const { |
|
||||
if (TestType::engine == DtmcEngine::PrismSparse || TestType::engine == DtmcEngine::JaniSparse || TestType::engine == DtmcEngine::JitSparse) { |
|
||||
return std::make_shared<storm::modelchecker::SparseDtmcPrctlModelChecker<SparseModelType>>(*model); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
template <typename MT = typename TestType::ModelType> |
|
||||
typename std::enable_if<std::is_same<MT, SymbolicModelType>::value, std::shared_ptr<storm::modelchecker::AbstractModelChecker<MT>>>::type |
|
||||
createModelChecker(std::shared_ptr<MT> const& model) const { |
|
||||
if (TestType::engine == DtmcEngine::Hybrid) { |
|
||||
return std::make_shared<storm::modelchecker::HybridDtmcPrctlModelChecker<SymbolicModelType>>(*model); |
|
||||
} else if (TestType::engine == DtmcEngine::PrismDd || TestType::engine == DtmcEngine::JaniDd) { |
|
||||
return std::make_shared<storm::modelchecker::SymbolicDtmcPrctlModelChecker<SymbolicModelType>>(*model); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
bool getQualitativeResultAtInitialState(std::shared_ptr<storm::models::Model<ValueType>> const& model, std::unique_ptr<storm::modelchecker::CheckResult>& result) { |
|
||||
auto filter = getInitialStateFilter(model); |
|
||||
result->filter(*filter); |
|
||||
return result->asQualitativeCheckResult().forallTrue(); |
|
||||
} |
|
||||
|
|
||||
ValueType getQuantitativeResultAtInitialState(std::shared_ptr<storm::models::Model<ValueType>> const& model, std::unique_ptr<storm::modelchecker::CheckResult>& result) { |
|
||||
auto filter = getInitialStateFilter(model); |
|
||||
result->filter(*filter); |
|
||||
return result->asQuantitativeCheckResult<ValueType>().getMin(); |
|
||||
} |
|
||||
|
|
||||
private: |
|
||||
storm::Environment _environment; |
|
||||
|
|
||||
std::unique_ptr<storm::modelchecker::QualitativeCheckResult> getInitialStateFilter(std::shared_ptr<storm::models::Model<ValueType>> const& model) const { |
|
||||
if (isSparseModel()) { |
|
||||
return std::make_unique<storm::modelchecker::ExplicitQualitativeCheckResult>(model->template as<SparseModelType>()->getInitialStates()); |
|
||||
} else { |
|
||||
return std::make_unique<storm::modelchecker::SymbolicQualitativeCheckResult<TestType::ddType>>(model->template as<SymbolicModelType>()->getReachableStates(), model->template as<SymbolicModelType>()->getInitialStates()); |
|
||||
} |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
typedef ::testing::Types< |
|
||||
SparseGmmxxGmresIluEnvironment, |
|
||||
JaniSparseGmmxxGmresIluEnvironment, |
|
||||
JitSparseGmmxxGmresIluEnvironment, |
|
||||
SparseGmmxxGmresDiagEnvironment, |
|
||||
SparseGmmxxBicgstabIluEnvironment, |
|
||||
SparseEigenDGmresEnvironment, |
|
||||
SparseEigenDoubleLUEnvironment, |
|
||||
SparseEigenRationalLUEnvironment, |
|
||||
SparseRationalEliminationEnvironment, |
|
||||
SparseNativeJacobiEnvironment, |
|
||||
SparseNativeWalkerChaeEnvironment, |
|
||||
SparseNativeSorEnvironment, |
|
||||
SparseNativePowerEnvironment, |
|
||||
SparseNativeSoundValueIterationEnvironment, |
|
||||
SparseNativeIntervalIterationEnvironment, |
|
||||
SparseNativeRationalSearchEnvironment, |
|
||||
SparseTopologicalEigenLUEnvironment, |
|
||||
HybridSylvanGmmxxGmresEnvironment, |
|
||||
HybridCuddNativeJacobiEnvironment, |
|
||||
HybridCuddNativeSoundValueIterationEnvironment, |
|
||||
HybridSylvanNativeRationalSearchEnvironment, |
|
||||
DdSylvanNativePowerEnvironment, |
|
||||
JaniDdSylvanNativePowerEnvironment, |
|
||||
DdCuddNativeJacobiEnvironment, |
|
||||
DdSylvanRationalSearchEnvironment |
|
||||
> TestingTypes; |
|
||||
|
|
||||
TYPED_TEST_SUITE(DtmcPrctlModelCheckerTest, TestingTypes); |
|
||||
|
|
||||
TYPED_TEST(DtmcPrctlModelCheckerTest, Die) { |
|
||||
std::string formulasString = "P=? [F \"one\"]"; |
|
||||
formulasString += "; P=? [F \"two\"]"; |
|
||||
formulasString += "; P=? [F \"three\"]"; |
|
||||
formulasString += "; R=? [F \"done\"]"; |
|
||||
|
|
||||
auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR "/dtmc/die.pm", formulasString); |
|
||||
auto model = std::move(modelFormulas.first); |
|
||||
auto tasks = this->getTasks(modelFormulas.second); |
|
||||
EXPECT_EQ(13ul, model->getNumberOfStates()); |
|
||||
EXPECT_EQ(20ul, model->getNumberOfTransitions()); |
|
||||
ASSERT_EQ(model->getType(), storm::models::ModelType::Dtmc); |
|
||||
auto checker = this->createModelChecker(model); |
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result; |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[0]); |
|
||||
EXPECT_NEAR(this->parseNumber("1/6"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[1]); |
|
||||
EXPECT_NEAR(this->parseNumber("1/6"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[2]); |
|
||||
EXPECT_NEAR(this->parseNumber("1/6"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[3]); |
|
||||
EXPECT_NEAR(this->parseNumber("11/3"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
} |
|
||||
|
|
||||
TYPED_TEST(DtmcPrctlModelCheckerTest, Crowds) { |
|
||||
std::string formulasString = "P=? [F observe0>1]"; |
|
||||
formulasString += "; P=? [F \"observeIGreater1\"]"; |
|
||||
formulasString += "; P=? [F observe1>1]"; |
|
||||
|
|
||||
auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR "/dtmc/crowds-4-3.pm", formulasString); |
|
||||
auto model = std::move(modelFormulas.first); |
|
||||
auto tasks = this->getTasks(modelFormulas.second); |
|
||||
EXPECT_EQ(726ul, model->getNumberOfStates()); |
|
||||
EXPECT_EQ(1146ul, model->getNumberOfTransitions()); |
|
||||
ASSERT_EQ(model->getType(), storm::models::ModelType::Dtmc); |
|
||||
auto checker = this->createModelChecker(model); |
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result; |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[0]); |
|
||||
EXPECT_NEAR(this->parseNumber("78686542099694893/1268858272000000000"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[1]); |
|
||||
EXPECT_NEAR(this->parseNumber("40300855878315123/1268858272000000000"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[2]); |
|
||||
EXPECT_NEAR(this->parseNumber("13433618626105041/1268858272000000000"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
TYPED_TEST(DtmcPrctlModelCheckerTest, SynchronousLeader) { |
|
||||
std::string formulasString = "P=? [F \"elected\"]"; |
|
||||
formulasString += "; P=? [F<=5 \"elected\"]"; |
|
||||
formulasString += "; R=? [F \"elected\"]"; |
|
||||
|
|
||||
auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR "/dtmc/leader-3-5.pm", formulasString); |
|
||||
auto model = std::move(modelFormulas.first); |
|
||||
auto tasks = this->getTasks(modelFormulas.second); |
|
||||
EXPECT_EQ(273ul, model->getNumberOfStates()); |
|
||||
EXPECT_EQ(397ul, model->getNumberOfTransitions()); |
|
||||
ASSERT_EQ(model->getType(), storm::models::ModelType::Dtmc); |
|
||||
auto checker = this->createModelChecker(model); |
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result; |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[0]); |
|
||||
EXPECT_NEAR(this->parseNumber("1"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[1]); |
|
||||
EXPECT_NEAR(this->parseNumber("24/25"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[2]); |
|
||||
EXPECT_NEAR(this->parseNumber("25/24"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
} |
|
||||
|
|
||||
TEST(DtmcPrctlModelCheckerTest, AllUntilProbabilities) { |
|
||||
std::string formulasString = "P=? [F \"one\"]"; |
|
||||
formulasString += "; P=? [F \"two\"]"; |
|
||||
formulasString += "; P=? [F \"three\"]"; |
|
||||
|
|
||||
storm::prism::Program program = storm::api::parseProgram(STORM_TEST_RESOURCES_DIR "/dtmc/die.pm"); |
|
||||
auto formulas = storm::api::extractFormulasFromProperties(storm::api::parsePropertiesForPrismProgram(formulasString, program)); |
|
||||
std::vector<storm::modelchecker::CheckTask<storm::logic::Formula, double>> tasks; |
|
||||
for (auto const& f : formulas) { |
|
||||
tasks.emplace_back(*f); |
|
||||
} |
|
||||
auto model = storm::api::buildSparseModel<double>(program, formulas)->template as<storm::models::sparse::Dtmc<double>>(); |
|
||||
EXPECT_EQ(13ul, model->getNumberOfStates()); |
|
||||
EXPECT_EQ(20ul, model->getNumberOfTransitions()); |
|
||||
|
|
||||
storm::storage::SparseMatrix<double> matrix = model->getTransitionMatrix(); |
|
||||
storm::storage::BitVector initialStates(13); |
|
||||
initialStates.set(0); |
|
||||
storm::storage::BitVector phiStates(13); |
|
||||
storm::storage::BitVector psiStates(13); |
|
||||
psiStates.set(7); |
|
||||
psiStates.set(8); |
|
||||
psiStates.set(9); |
|
||||
psiStates.set(10); |
|
||||
psiStates.set(11); |
|
||||
psiStates.set(12); |
|
||||
storm::Environment env; |
|
||||
storm::solver::SolveGoal<double> goal(*model, tasks[0]); |
|
||||
std::vector<double> result = storm::modelchecker::helper::SparseDtmcPrctlHelper<double>::computeAllUntilProbabilities(env, std::move(goal), matrix, initialStates, phiStates, psiStates); |
|
||||
|
|
||||
EXPECT_NEAR(1.0/6, result[7], 1e-6); |
|
||||
EXPECT_NEAR(1.0/6, result[8], 1e-6); |
|
||||
EXPECT_NEAR(1.0/6, result[9], 1e-6); |
|
||||
EXPECT_NEAR(1.0/6, result[10], 1e-6); |
|
||||
EXPECT_NEAR(1.0/6, result[11], 1e-6); |
|
||||
EXPECT_NEAR(1.0/6, result[12], 1e-6); |
|
||||
|
|
||||
phiStates.set(6); |
|
||||
psiStates.set(1); |
|
||||
result = storm::modelchecker::helper::SparseDtmcPrctlHelper<double>::computeAllUntilProbabilities(env, std::move(goal), matrix, initialStates, phiStates, psiStates); |
|
||||
|
|
||||
EXPECT_NEAR(1, result[0], 1e-6); |
|
||||
EXPECT_NEAR(0.5, result[1], 1e-6); |
|
||||
EXPECT_NEAR(0.5, result[2], 1e-6); |
|
||||
EXPECT_NEAR(0.25, result[5], 1e-6); |
|
||||
EXPECT_NEAR(0, result[7], 1e-6); |
|
||||
EXPECT_NEAR(0, result[8], 1e-6); |
|
||||
EXPECT_NEAR(0, result[9], 1e-6); |
|
||||
EXPECT_NEAR(0.125, result[10], 1e-6); |
|
||||
EXPECT_NEAR(0.125, result[11], 1e-6); |
|
||||
EXPECT_NEAR(0, result[12], 1e-6); |
|
||||
} |
|
||||
|
|
||||
} |
|
@ -1,158 +0,0 @@ |
|||||
#include "test/storm_gtest.h"
|
|
||||
#include "storm-config.h"
|
|
||||
|
|
||||
#include "storm-parsers/parser/FormulaParser.h"
|
|
||||
#include "storm/logic/Formulas.h"
|
|
||||
#include "storm/models/sparse/StandardRewardModel.h"
|
|
||||
#include "storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.h"
|
|
||||
#include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h"
|
|
||||
#include "storm/settings/SettingsManager.h"
|
|
||||
#include "storm/settings/modules/GeneralSettings.h"
|
|
||||
#include "storm/settings/SettingMemento.h"
|
|
||||
#include "storm-parsers/parser/AutoParser.h"
|
|
||||
#include "storm-parsers/parser/PrismParser.h"
|
|
||||
#include "storm/builder/ExplicitModelBuilder.h"
|
|
||||
#include "storm/storage/expressions/ExpressionManager.h"
|
|
||||
|
|
||||
#include "storm/environment/solver/SolverEnvironment.h"
|
|
||||
|
|
||||
TEST(ExplicitDtmcPrctlModelCheckerTest, Die) { |
|
||||
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_TEST_RESOURCES_DIR "/tra/die.tra", STORM_TEST_RESOURCES_DIR "/lab/die.lab", "", STORM_TEST_RESOURCES_DIR "/rew/die.coin_flips.trans.rew"); |
|
||||
|
|
||||
storm::Environment env; |
|
||||
double const precision = 1e-6; |
|
||||
// Increase precision a little to get more accurate results
|
|
||||
env.solver().setLinearEquationSolverPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
|
|
||||
// A parser that we use for conveniently constructing the formulas.
|
|
||||
|
|
||||
auto expManager = std::make_shared<storm::expressions::ExpressionManager>(); |
|
||||
storm::parser::FormulaParser formulaParser(expManager); |
|
||||
|
|
||||
ASSERT_EQ(abstractModel->getType(), storm::models::ModelType::Dtmc); |
|
||||
|
|
||||
std::shared_ptr<storm::models::sparse::Dtmc<double>> dtmc = abstractModel->as<storm::models::sparse::Dtmc<double>>(); |
|
||||
|
|
||||
ASSERT_EQ(dtmc->getNumberOfStates(), 13ull); |
|
||||
ASSERT_EQ(dtmc->getNumberOfTransitions(), 20ull); |
|
||||
|
|
||||
storm::modelchecker::SparseDtmcPrctlModelChecker<storm::models::sparse::Dtmc<double>> checker(*dtmc); |
|
||||
|
|
||||
std::shared_ptr<storm::logic::Formula const> formula = formulaParser.parseSingleFormulaFromString("P=? [F \"one\"]"); |
|
||||
|
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(1.0 / 6.0, quantitativeResult1[0], precision); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("P=? [F \"two\"]"); |
|
||||
|
|
||||
result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(1.0 / 6.0, quantitativeResult2[0], precision); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("P=? [F \"three\"]"); |
|
||||
|
|
||||
result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(1.0 / 6.0, quantitativeResult3[0], precision); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("R=? [F \"done\"]"); |
|
||||
|
|
||||
result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult4 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(11.0 / 3.0, quantitativeResult4[0], precision); |
|
||||
} |
|
||||
|
|
||||
TEST(ExplicitDtmcPrctlModelCheckerTest, Crowds) { |
|
||||
|
|
||||
storm::Environment env; |
|
||||
double const precision = 1e-6; |
|
||||
// Increase precision a little to get more accurate results
|
|
||||
env.solver().setLinearEquationSolverPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
|
|
||||
|
|
||||
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_TEST_RESOURCES_DIR "/tra/crowds5_5.tra", STORM_TEST_RESOURCES_DIR "/lab/crowds5_5.lab", "", ""); |
|
||||
|
|
||||
ASSERT_EQ(abstractModel->getType(), storm::models::ModelType::Dtmc); |
|
||||
|
|
||||
// A parser that we use for conveniently constructing the formulas.
|
|
||||
|
|
||||
auto expManager = std::make_shared<storm::expressions::ExpressionManager>(); |
|
||||
storm::parser::FormulaParser formulaParser(expManager); |
|
||||
|
|
||||
std::shared_ptr<storm::models::sparse::Dtmc<double>> dtmc = abstractModel->as<storm::models::sparse::Dtmc<double>>(); |
|
||||
|
|
||||
ASSERT_EQ(8607ull, dtmc->getNumberOfStates()); |
|
||||
ASSERT_EQ(15113ull, dtmc->getNumberOfTransitions()); |
|
||||
|
|
||||
storm::modelchecker::SparseDtmcPrctlModelChecker<storm::models::sparse::Dtmc<double>> checker(*dtmc); |
|
||||
|
|
||||
std::shared_ptr<storm::logic::Formula const> formula = formulaParser.parseSingleFormulaFromString("P=? [F \"observe0Greater1\"]"); |
|
||||
|
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(0.3328800375801578281, quantitativeResult1[0], precision); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("P=? [F \"observeIGreater1\"]"); |
|
||||
|
|
||||
result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(0.1522194965, quantitativeResult2[0], precision); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("P=? [F \"observeOnlyTrueSender\"]"); |
|
||||
|
|
||||
result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(0.32153724292835045, quantitativeResult3[0], precision); |
|
||||
} |
|
||||
|
|
||||
TEST(ExplicitDtmcPrctlModelCheckerTest, SynchronousLeader) { |
|
||||
storm::Environment env; |
|
||||
double const precision = 1e-6; |
|
||||
// Increase precision a little to get more accurate results
|
|
||||
env.solver().setLinearEquationSolverPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
|
|
||||
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_TEST_RESOURCES_DIR "/tra/leader4_8.tra", STORM_TEST_RESOURCES_DIR "/lab/leader4_8.lab", "", STORM_TEST_RESOURCES_DIR "/rew/leader4_8.pick.trans.rew"); |
|
||||
|
|
||||
ASSERT_EQ(abstractModel->getType(), storm::models::ModelType::Dtmc); |
|
||||
|
|
||||
// A parser that we use for conveniently constructing the formulas.
|
|
||||
|
|
||||
auto expManager = std::make_shared<storm::expressions::ExpressionManager>(); |
|
||||
storm::parser::FormulaParser formulaParser(expManager); |
|
||||
|
|
||||
std::shared_ptr<storm::models::sparse::Dtmc<double>> dtmc = abstractModel->as<storm::models::sparse::Dtmc<double>>(); |
|
||||
|
|
||||
ASSERT_EQ(12400ull, dtmc->getNumberOfStates()); |
|
||||
ASSERT_EQ(16495ull, dtmc->getNumberOfTransitions()); |
|
||||
|
|
||||
storm::modelchecker::SparseDtmcPrctlModelChecker<storm::models::sparse::Dtmc<double>> checker(*dtmc); |
|
||||
|
|
||||
std::shared_ptr<storm::logic::Formula const> formula = formulaParser.parseSingleFormulaFromString("P=? [F \"elected\"]"); |
|
||||
|
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(1.0, quantitativeResult1[0], precision); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("P=? [F<=20 \"elected\"]"); |
|
||||
|
|
||||
result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(0.9999965911265462636, quantitativeResult2[0], precision); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("R=? [F \"elected\"]"); |
|
||||
|
|
||||
result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(1.0448979591836789, quantitativeResult3[0], precision); |
|
||||
} |
|
@ -1,199 +0,0 @@ |
|||||
#include "test/storm_gtest.h"
|
|
||||
#include "storm-config.h"
|
|
||||
|
|
||||
#include "storm-parsers/parser/FormulaParser.h"
|
|
||||
#include "storm/logic/Formulas.h"
|
|
||||
#include "storm/solver/StandardMinMaxLinearEquationSolver.h"
|
|
||||
#include "storm/models/sparse/StandardRewardModel.h"
|
|
||||
#include "storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h"
|
|
||||
#include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h"
|
|
||||
|
|
||||
#include "storm/environment/solver/MinMaxSolverEnvironment.h"
|
|
||||
|
|
||||
#include "storm-parsers/parser/AutoParser.h"
|
|
||||
#include "storm-parsers/parser/PrismParser.h"
|
|
||||
#include "storm/builder/ExplicitModelBuilder.h"
|
|
||||
|
|
||||
TEST(ExplicitMdpPrctlModelCheckerTest, Dice) { |
|
||||
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_TEST_RESOURCES_DIR "/tra/two_dice.tra", STORM_TEST_RESOURCES_DIR "/lab/two_dice.lab", "", STORM_TEST_RESOURCES_DIR "/rew/two_dice.flip.trans.rew"); |
|
||||
storm::Environment env; |
|
||||
double const precision = 1e-6; |
|
||||
// Increase precision a little to get more accurate results
|
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
|
|
||||
// A parser that we use for conveniently constructing the formulas.
|
|
||||
storm::parser::FormulaParser formulaParser; |
|
||||
|
|
||||
ASSERT_EQ(abstractModel->getType(), storm::models::ModelType::Mdp); |
|
||||
|
|
||||
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = abstractModel->as<storm::models::sparse::Mdp<double>>(); |
|
||||
|
|
||||
ASSERT_EQ(mdp->getNumberOfStates(), 169ull); |
|
||||
ASSERT_EQ(mdp->getNumberOfTransitions(), 436ull); |
|
||||
|
|
||||
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> checker(*mdp); |
|
||||
|
|
||||
std::shared_ptr<storm::logic::Formula const> formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"two\"]"); |
|
||||
|
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(1.0/36.0, quantitativeResult1[0], precision); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"two\"]"); |
|
||||
|
|
||||
result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(1.0/36.0, quantitativeResult2[0], precision); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"three\"]"); |
|
||||
|
|
||||
result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(2.0/36.0, quantitativeResult3[0], precision); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"three\"]"); |
|
||||
|
|
||||
result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult4 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(2.0/36.0, quantitativeResult4[0], precision); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"four\"]"); |
|
||||
|
|
||||
result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult5 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(3.0/36.0, quantitativeResult5[0], precision); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"four\"]"); |
|
||||
|
|
||||
result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult6 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(3.0/36.0, quantitativeResult6[0], precision); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"done\"]"); |
|
||||
|
|
||||
result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult7 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(22.0/3.0, quantitativeResult7[0], precision); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("Rmax=? [F \"done\"]"); |
|
||||
|
|
||||
result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult8 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(22.0/3.0, quantitativeResult8[0], precision); |
|
||||
|
|
||||
abstractModel = storm::parser::AutoParser<>::parseModel(STORM_TEST_RESOURCES_DIR "/tra/two_dice.tra", STORM_TEST_RESOURCES_DIR "/lab/two_dice.lab", STORM_TEST_RESOURCES_DIR "/rew/two_dice.flip.state.rew", ""); |
|
||||
|
|
||||
ASSERT_EQ(abstractModel->getType(), storm::models::ModelType::Mdp); |
|
||||
|
|
||||
std::shared_ptr<storm::models::sparse::Mdp<double>> stateRewardMdp = abstractModel->as<storm::models::sparse::Mdp<double>>(); |
|
||||
|
|
||||
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> stateRewardModelChecker(*mdp); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"done\"]"); |
|
||||
|
|
||||
result = stateRewardModelChecker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult9 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(22.0/3.0, quantitativeResult9[0], precision); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("Rmax=? [F \"done\"]"); |
|
||||
|
|
||||
result = stateRewardModelChecker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult10 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(22.0/3.0, quantitativeResult10[0], precision); |
|
||||
|
|
||||
abstractModel = storm::parser::AutoParser<>::parseModel(STORM_TEST_RESOURCES_DIR "/tra/two_dice.tra", STORM_TEST_RESOURCES_DIR "/lab/two_dice.lab", STORM_TEST_RESOURCES_DIR "/rew/two_dice.flip.state.rew", STORM_TEST_RESOURCES_DIR "/rew/two_dice.flip.trans.rew"); |
|
||||
|
|
||||
ASSERT_EQ(abstractModel->getType(), storm::models::ModelType::Mdp); |
|
||||
|
|
||||
std::shared_ptr<storm::models::sparse::Mdp<double>> stateAndTransitionRewardMdp = abstractModel->as<storm::models::sparse::Mdp<double>>(); |
|
||||
|
|
||||
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> stateAndTransitionRewardModelChecker(*stateAndTransitionRewardMdp); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"done\"]"); |
|
||||
|
|
||||
result = stateAndTransitionRewardModelChecker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult11 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(44.0/3.0, quantitativeResult11[0], precision); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("Rmax=? [F \"done\"]"); |
|
||||
|
|
||||
result = stateAndTransitionRewardModelChecker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult12 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(44.0/3.0, quantitativeResult12[0], precision); |
|
||||
} |
|
||||
|
|
||||
TEST(ExplicitMdpPrctlModelCheckerTest, AsynchronousLeader) { |
|
||||
storm::Environment env; |
|
||||
double const precision = 1e-6; |
|
||||
// Increase precision a little to get more accurate results
|
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
|
|
||||
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_TEST_RESOURCES_DIR "/tra/leader4.tra", STORM_TEST_RESOURCES_DIR "/lab/leader4.lab", "", STORM_TEST_RESOURCES_DIR "/rew/leader4.trans.rew"); |
|
||||
|
|
||||
// A parser that we use for conveniently constructing the formulas.
|
|
||||
storm::parser::FormulaParser formulaParser; |
|
||||
|
|
||||
ASSERT_EQ(storm::models::ModelType::Mdp, abstractModel->getType()); |
|
||||
|
|
||||
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = abstractModel->as<storm::models::sparse::Mdp<double>>(); |
|
||||
|
|
||||
ASSERT_EQ(3172ull, mdp->getNumberOfStates()); |
|
||||
ASSERT_EQ(7144ull, mdp->getNumberOfTransitions()); |
|
||||
|
|
||||
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> checker(*mdp); |
|
||||
|
|
||||
std::shared_ptr<storm::logic::Formula const> formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"elected\"]"); |
|
||||
|
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(1.0, quantitativeResult1[0], precision); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"elected\"]"); |
|
||||
|
|
||||
result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(1.0, quantitativeResult2[0], precision); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F<=25 \"elected\"]"); |
|
||||
|
|
||||
result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(1.0/16.0, quantitativeResult3[0], precision); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F<=25 \"elected\"]"); |
|
||||
|
|
||||
result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult4 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(1.0/16.0, quantitativeResult4[0], precision); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"elected\"]"); |
|
||||
|
|
||||
result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult5 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(30.0/7.0, quantitativeResult5[0], precision); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("Rmax=? [F \"elected\"]"); |
|
||||
|
|
||||
result = checker.check(env, *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult6 = result->asExplicitQuantitativeCheckResult<double>(); |
|
||||
|
|
||||
EXPECT_NEAR(30.0/7.0, quantitativeResult6[0], precision); |
|
||||
} |
|
||||
|
|
@ -1,268 +0,0 @@ |
|||||
#include "test/storm_gtest.h"
|
|
||||
#include "storm-config.h"
|
|
||||
#include "test/storm_gtest.h"
|
|
||||
|
|
||||
#include "storm-parsers/parser/FormulaParser.h"
|
|
||||
#include "storm/settings/SettingMemento.h"
|
|
||||
#include "storm/logic/Formulas.h"
|
|
||||
#include "storm/solver/NativeLinearEquationSolver.h"
|
|
||||
#include "storm/models/sparse/StandardRewardModel.h"
|
|
||||
#include "storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.h"
|
|
||||
#include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h"
|
|
||||
#include "storm/settings/SettingsManager.h"
|
|
||||
#include "storm/solver/NativeLinearEquationSolver.h"
|
|
||||
#include "storm/settings/modules/GeneralSettings.h"
|
|
||||
|
|
||||
#include "storm/environment/solver/NativeSolverEnvironment.h"
|
|
||||
#include "storm/environment/solver/EigenSolverEnvironment.h"
|
|
||||
#include "storm/environment/solver/GmmxxSolverEnvironment.h"
|
|
||||
|
|
||||
#include "storm-parsers/parser/AutoParser.h"
|
|
||||
#include "storm/builder/ExplicitModelBuilder.h"
|
|
||||
|
|
||||
namespace { |
|
||||
|
|
||||
class GmmxxDoubleGmresEnvironment { |
|
||||
public: |
|
||||
typedef double ValueType; |
|
||||
static const bool isExact = false; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Gmmxx); |
|
||||
env.solver().gmmxx().setMethod(storm::solver::GmmxxLinearEquationSolverMethod::Gmres); |
|
||||
env.solver().gmmxx().setPreconditioner(storm::solver::GmmxxLinearEquationSolverPreconditioner::Ilu); |
|
||||
env.solver().gmmxx().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class EigenDoubleDGmresEnvironment { |
|
||||
public: |
|
||||
typedef double ValueType; |
|
||||
static const bool isExact = false; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Eigen); |
|
||||
env.solver().eigen().setMethod(storm::solver::EigenLinearEquationSolverMethod::DGmres); |
|
||||
env.solver().eigen().setPreconditioner(storm::solver::EigenLinearEquationSolverPreconditioner::Ilu); |
|
||||
env.solver().eigen().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class EigenRationalLUEnvironment { |
|
||||
public: |
|
||||
typedef double ValueType; |
|
||||
static const bool isExact = true; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Eigen); |
|
||||
env.solver().eigen().setMethod(storm::solver::EigenLinearEquationSolverMethod::SparseLU); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class NativeSorEnvironment { |
|
||||
public: |
|
||||
typedef double ValueType; |
|
||||
static const bool isExact = false; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native); |
|
||||
env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::SOR); |
|
||||
env.solver().native().setSorOmega(storm::utility::convertNumber<storm::RationalNumber>(0.9)); |
|
||||
env.solver().native().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class NativeWalkerChaeEnvironment { |
|
||||
public: |
|
||||
typedef double ValueType; |
|
||||
static const bool isExact = false; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setLinearEquationSolverType(storm::solver::EquationSolverType::Native); |
|
||||
env.solver().native().setMethod(storm::solver::NativeLinearEquationSolverMethod::WalkerChae); |
|
||||
env.solver().native().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
env.solver().native().setMaximalNumberOfIterations(50000); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
template<typename TestType> |
|
||||
class LraDtmcPrctlModelCheckerTest : public ::testing::Test { |
|
||||
public: |
|
||||
typedef typename TestType::ValueType ValueType; |
|
||||
LraDtmcPrctlModelCheckerTest() : _environment(TestType::createEnvironment()) {} |
|
||||
storm::Environment const& env() const { return _environment; } |
|
||||
ValueType parseNumber(std::string const& input) const { return storm::utility::convertNumber<ValueType>(input);} |
|
||||
ValueType precision() const { return TestType::isExact ? parseNumber("0") : parseNumber("1e-6");} |
|
||||
|
|
||||
private: |
|
||||
storm::Environment _environment; |
|
||||
}; |
|
||||
|
|
||||
typedef ::testing::Types< |
|
||||
GmmxxDoubleGmresEnvironment, |
|
||||
EigenDoubleDGmresEnvironment, |
|
||||
EigenRationalLUEnvironment, |
|
||||
NativeSorEnvironment, |
|
||||
NativeWalkerChaeEnvironment |
|
||||
> TestingTypes; |
|
||||
|
|
||||
TYPED_TEST_SUITE(LraDtmcPrctlModelCheckerTest, TestingTypes); |
|
||||
|
|
||||
|
|
||||
|
|
||||
TYPED_TEST(LraDtmcPrctlModelCheckerTest, LRASingleBscc) { |
|
||||
typedef typename TestFixture::ValueType ValueType; |
|
||||
|
|
||||
storm::storage::SparseMatrixBuilder<ValueType> matrixBuilder; |
|
||||
std::shared_ptr<storm::models::sparse::Dtmc<ValueType>> dtmc; |
|
||||
|
|
||||
// A parser that we use for conveniently constructing the formulas.
|
|
||||
storm::parser::FormulaParser formulaParser; |
|
||||
|
|
||||
{ |
|
||||
matrixBuilder = storm::storage::SparseMatrixBuilder<ValueType>(2, 2, 2); |
|
||||
matrixBuilder.addNextValue(0, 1, this->parseNumber("1")); |
|
||||
matrixBuilder.addNextValue(1, 0, this->parseNumber("1")); |
|
||||
storm::storage::SparseMatrix<ValueType> transitionMatrix = matrixBuilder.build(); |
|
||||
|
|
||||
storm::models::sparse::StateLabeling ap(2); |
|
||||
ap.addLabel("a"); |
|
||||
ap.addLabelToState("a", 1); |
|
||||
|
|
||||
dtmc.reset(new storm::models::sparse::Dtmc<ValueType>(transitionMatrix, ap)); |
|
||||
|
|
||||
storm::modelchecker::SparseDtmcPrctlModelChecker<storm::models::sparse::Dtmc<ValueType>> checker(*dtmc); |
|
||||
|
|
||||
std::shared_ptr<storm::logic::Formula const> formula = formulaParser.parseSingleFormulaFromString("LRA=? [\"a\"]"); |
|
||||
|
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("0.5"), quantitativeResult1[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0.5"), quantitativeResult1[1], this->precision()); |
|
||||
} |
|
||||
{ |
|
||||
matrixBuilder = storm::storage::SparseMatrixBuilder<ValueType>(2, 2, 4); |
|
||||
matrixBuilder.addNextValue(0, 0, this->parseNumber("0.5")); |
|
||||
matrixBuilder.addNextValue(0, 1, this->parseNumber("0.5")); |
|
||||
matrixBuilder.addNextValue(1, 0, this->parseNumber("0.5")); |
|
||||
matrixBuilder.addNextValue(1, 1, this->parseNumber("0.5")); |
|
||||
storm::storage::SparseMatrix<ValueType> transitionMatrix = matrixBuilder.build(); |
|
||||
|
|
||||
storm::models::sparse::StateLabeling ap(2); |
|
||||
ap.addLabel("a"); |
|
||||
ap.addLabelToState("a", 1); |
|
||||
|
|
||||
dtmc.reset(new storm::models::sparse::Dtmc<ValueType>(transitionMatrix, ap)); |
|
||||
|
|
||||
storm::modelchecker::SparseDtmcPrctlModelChecker<storm::models::sparse::Dtmc<ValueType>> checker(*dtmc); |
|
||||
|
|
||||
std::shared_ptr<storm::logic::Formula const> formula = formulaParser.parseSingleFormulaFromString("LRA=? [\"a\"]"); |
|
||||
|
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("0.5"), quantitativeResult1[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0.5"), quantitativeResult1[1], this->precision()); |
|
||||
} |
|
||||
|
|
||||
{ |
|
||||
matrixBuilder = storm::storage::SparseMatrixBuilder<ValueType>(3, 3, 3); |
|
||||
matrixBuilder.addNextValue(0, 1, this->parseNumber("1")); |
|
||||
matrixBuilder.addNextValue(1, 2, this->parseNumber("1")); |
|
||||
matrixBuilder.addNextValue(2, 0, this->parseNumber("1")); |
|
||||
storm::storage::SparseMatrix<ValueType> transitionMatrix = matrixBuilder.build(); |
|
||||
|
|
||||
storm::models::sparse::StateLabeling ap(3); |
|
||||
ap.addLabel("a"); |
|
||||
ap.addLabelToState("a", 2); |
|
||||
|
|
||||
dtmc.reset(new storm::models::sparse::Dtmc<ValueType>(transitionMatrix, ap)); |
|
||||
|
|
||||
storm::modelchecker::SparseDtmcPrctlModelChecker<storm::models::sparse::Dtmc<ValueType>> checker(*dtmc); |
|
||||
|
|
||||
std::shared_ptr<storm::logic::Formula const> formula = formulaParser.parseSingleFormulaFromString("LRA=? [\"a\"]"); |
|
||||
|
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("1/3"), quantitativeResult1[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("1/3"), quantitativeResult1[1], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("1/3"), quantitativeResult1[2], this->precision()); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
TYPED_TEST(LraDtmcPrctlModelCheckerTest, LRA) { |
|
||||
typedef typename TestFixture::ValueType ValueType; |
|
||||
|
|
||||
storm::storage::SparseMatrixBuilder<ValueType> matrixBuilder; |
|
||||
std::shared_ptr<storm::models::sparse::Dtmc<ValueType>> dtmc; |
|
||||
|
|
||||
// A parser that we use for conveniently constructing the formulas.
|
|
||||
storm::parser::FormulaParser formulaParser; |
|
||||
|
|
||||
{ |
|
||||
matrixBuilder = storm::storage::SparseMatrixBuilder<ValueType>(15, 15, 20, true); |
|
||||
matrixBuilder.addNextValue(0, 1, this->parseNumber("1")); |
|
||||
matrixBuilder.addNextValue(1, 4, this->parseNumber("0.7")); |
|
||||
matrixBuilder.addNextValue(1, 6, this->parseNumber("0.3")); |
|
||||
matrixBuilder.addNextValue(2, 0, this->parseNumber("1")); |
|
||||
|
|
||||
matrixBuilder.addNextValue(3, 5, this->parseNumber("0.8")); |
|
||||
matrixBuilder.addNextValue(3, 9, this->parseNumber("0.2")); |
|
||||
matrixBuilder.addNextValue(4, 3, this->parseNumber("1")); |
|
||||
matrixBuilder.addNextValue(5, 3, this->parseNumber("1")); |
|
||||
|
|
||||
matrixBuilder.addNextValue(6, 7, this->parseNumber("1")); |
|
||||
matrixBuilder.addNextValue(7, 8, this->parseNumber("1")); |
|
||||
matrixBuilder.addNextValue(8, 6, this->parseNumber("1")); |
|
||||
|
|
||||
matrixBuilder.addNextValue(9, 10, this->parseNumber("1")); |
|
||||
matrixBuilder.addNextValue(10, 9, this->parseNumber("1")); |
|
||||
matrixBuilder.addNextValue(11, 9, this->parseNumber("1")); |
|
||||
|
|
||||
matrixBuilder.addNextValue(12, 5, this->parseNumber("0.4")); |
|
||||
matrixBuilder.addNextValue(12, 8, this->parseNumber("0.3")); |
|
||||
matrixBuilder.addNextValue(12, 11, this->parseNumber("0.3")); |
|
||||
|
|
||||
matrixBuilder.addNextValue(13, 7, this->parseNumber("0.7")); |
|
||||
matrixBuilder.addNextValue(13, 12, this->parseNumber("0.3")); |
|
||||
|
|
||||
matrixBuilder.addNextValue(14, 12, this->parseNumber("1")); |
|
||||
|
|
||||
storm::storage::SparseMatrix<ValueType> transitionMatrix = matrixBuilder.build(); |
|
||||
|
|
||||
storm::models::sparse::StateLabeling ap(15); |
|
||||
ap.addLabel("a"); |
|
||||
ap.addLabelToState("a", 1); |
|
||||
ap.addLabelToState("a", 4); |
|
||||
ap.addLabelToState("a", 5); |
|
||||
ap.addLabelToState("a", 7); |
|
||||
ap.addLabelToState("a", 11); |
|
||||
ap.addLabelToState("a", 13); |
|
||||
ap.addLabelToState("a", 14); |
|
||||
|
|
||||
dtmc.reset(new storm::models::sparse::Dtmc<ValueType>(transitionMatrix, ap)); |
|
||||
|
|
||||
storm::modelchecker::SparseDtmcPrctlModelChecker<storm::models::sparse::Dtmc<ValueType>> checker(*dtmc); |
|
||||
|
|
||||
std::shared_ptr<storm::logic::Formula const> formula = formulaParser.parseSingleFormulaFromString("LRA=? [\"a\"]"); |
|
||||
|
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("1/10"), quantitativeResult1[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0"), quantitativeResult1[3], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("1/3"), quantitativeResult1[6], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0"), quantitativeResult1[9], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("1/10"), quantitativeResult1[12], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("79/300"), quantitativeResult1[13], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("1/10"), quantitativeResult1[14], this->precision()); |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,468 +0,0 @@ |
|||||
#include "test/storm_gtest.h"
|
|
||||
|
|
||||
#include "test/storm_gtest.h"
|
|
||||
|
|
||||
#include "storm-config.h"
|
|
||||
|
|
||||
#include "storm/api/builder.h"
|
|
||||
#include "storm-conv/api/storm-conv.h"
|
|
||||
#include "storm-parsers/api/model_descriptions.h"
|
|
||||
#include "storm/api/properties.h"
|
|
||||
#include "storm-parsers/api/properties.h"
|
|
||||
|
|
||||
#include "storm-parsers/parser/FormulaParser.h"
|
|
||||
#include "storm/logic/Formulas.h"
|
|
||||
#include "storm/solver/StandardMinMaxLinearEquationSolver.h"
|
|
||||
#include "storm/models/sparse/StandardRewardModel.h"
|
|
||||
#include "storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h"
|
|
||||
#include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h"
|
|
||||
#include "storm/settings/SettingsManager.h"
|
|
||||
|
|
||||
#include "storm/settings/modules/GeneralSettings.h"
|
|
||||
|
|
||||
#include "storm/settings/modules/NativeEquationSolverSettings.h"
|
|
||||
#include "storm-parsers/parser/AutoParser.h"
|
|
||||
#include "storm/environment/solver/MinMaxSolverEnvironment.h"
|
|
||||
|
|
||||
namespace { |
|
||||
|
|
||||
|
|
||||
class SparseValueTypeValueIterationEnvironment { |
|
||||
public: |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Mdp<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setLraMethod(storm::solver::LraMethod::ValueIteration); |
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-10)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseValueTypeLinearProgrammingEnvironment { |
|
||||
public: |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Mdp<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setLraMethod(storm::solver::LraMethod::LinearProgramming); |
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-10)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseRationalLinearProgrammingEnvironment { |
|
||||
public: |
|
||||
static const bool isExact = true; |
|
||||
typedef storm::RationalNumber ValueType; |
|
||||
typedef storm::models::sparse::Mdp<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setLraMethod(storm::solver::LraMethod::LinearProgramming); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
template<typename TestType> |
|
||||
class LraMdpPrctlModelCheckerTest : public ::testing::Test { |
|
||||
public: |
|
||||
typedef typename TestType::ValueType ValueType; |
|
||||
typedef typename storm::models::sparse::Mdp<ValueType> SparseModelType; |
|
||||
|
|
||||
LraMdpPrctlModelCheckerTest() : _environment(TestType::createEnvironment()) {} |
|
||||
storm::Environment const& env() const { return _environment; } |
|
||||
ValueType parseNumber(std::string const& input) const { return storm::utility::convertNumber<ValueType>(input);} |
|
||||
ValueType precision() const { return TestType::isExact ? parseNumber("0") : parseNumber("1e-6");} |
|
||||
bool isSparseModel() const { return std::is_same<typename TestType::ModelType, SparseModelType>::value; } |
|
||||
|
|
||||
std::pair<std::shared_ptr<SparseModelType>, std::vector<std::shared_ptr<storm::logic::Formula const>>> buildModelFormulas(std::string const& pathToPrismFile, std::string const& formulasAsString, std::string const& constantDefinitionString = "") const { |
|
||||
std::pair<std::shared_ptr<SparseModelType>, std::vector<std::shared_ptr<storm::logic::Formula const>>> result; |
|
||||
storm::prism::Program program = storm::api::parseProgram(pathToPrismFile); |
|
||||
program = storm::utility::prism::preprocess(program, constantDefinitionString); |
|
||||
result.second = storm::api::extractFormulasFromProperties(storm::api::parsePropertiesForPrismProgram(formulasAsString, program)); |
|
||||
result.first = storm::api::buildSparseModel<ValueType>(program, result.second)->template as<SparseModelType>(); |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
std::vector<storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>> getTasks(std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas) const { |
|
||||
std::vector<storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>> result; |
|
||||
for (auto const& f : formulas) { |
|
||||
result.emplace_back(*f); |
|
||||
} |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
private: |
|
||||
storm::Environment _environment; |
|
||||
}; |
|
||||
|
|
||||
typedef ::testing::Types< |
|
||||
SparseValueTypeValueIterationEnvironment, |
|
||||
SparseValueTypeLinearProgrammingEnvironment |
|
||||
#ifdef STORM_HAVE_Z3_OPTIMIZE
|
|
||||
, SparseRationalLinearProgrammingEnvironment |
|
||||
#endif
|
|
||||
> TestingTypes; |
|
||||
|
|
||||
TYPED_TEST_SUITE(LraMdpPrctlModelCheckerTest, TestingTypes); |
|
||||
|
|
||||
|
|
||||
TYPED_TEST(LraMdpPrctlModelCheckerTest, LRA_SingleMec) { |
|
||||
typedef typename TestFixture::ValueType ValueType; |
|
||||
|
|
||||
storm::storage::SparseMatrixBuilder<ValueType> matrixBuilder; |
|
||||
std::shared_ptr<storm::models::sparse::Mdp<ValueType>> mdp; |
|
||||
|
|
||||
// A parser that we use for conveniently constructing the formulas.
|
|
||||
storm::parser::FormulaParser formulaParser; |
|
||||
|
|
||||
{ |
|
||||
matrixBuilder = storm::storage::SparseMatrixBuilder<ValueType>(2, 2, 2); |
|
||||
matrixBuilder.addNextValue(0, 1, this->parseNumber("1")); |
|
||||
matrixBuilder.addNextValue(1, 0, this->parseNumber("1")); |
|
||||
storm::storage::SparseMatrix<ValueType> transitionMatrix = matrixBuilder.build(); |
|
||||
|
|
||||
storm::models::sparse::StateLabeling ap(2); |
|
||||
ap.addLabel("a"); |
|
||||
ap.addLabelToState("a", 1); |
|
||||
|
|
||||
mdp.reset(new storm::models::sparse::Mdp<ValueType>(transitionMatrix, ap)); |
|
||||
|
|
||||
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<ValueType>> checker(*mdp); |
|
||||
|
|
||||
std::shared_ptr<storm::logic::Formula const> formula = formulaParser.parseSingleFormulaFromString("LRAmax=? [\"a\"]"); |
|
||||
|
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("0.5"), quantitativeResult1[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0.5"), quantitativeResult1[1], this->precision()); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("LRAmin=? [\"a\"]"); |
|
||||
|
|
||||
result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("0.5"), quantitativeResult2[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0.5"), quantitativeResult2[1], this->precision()); |
|
||||
} |
|
||||
{ |
|
||||
matrixBuilder = storm::storage::SparseMatrixBuilder<ValueType>(2, 2, 4); |
|
||||
matrixBuilder.addNextValue(0, 0, this->parseNumber("0.5")); |
|
||||
matrixBuilder.addNextValue(0, 1, this->parseNumber("0.5")); |
|
||||
matrixBuilder.addNextValue(1, 0, this->parseNumber("0.5")); |
|
||||
matrixBuilder.addNextValue(1, 1, this->parseNumber("0.5")); |
|
||||
storm::storage::SparseMatrix<ValueType> transitionMatrix = matrixBuilder.build(); |
|
||||
|
|
||||
storm::models::sparse::StateLabeling ap(2); |
|
||||
ap.addLabel("a"); |
|
||||
ap.addLabelToState("a", 1); |
|
||||
|
|
||||
mdp.reset(new storm::models::sparse::Mdp<ValueType>(transitionMatrix, ap)); |
|
||||
|
|
||||
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<ValueType>> checker(*mdp); |
|
||||
|
|
||||
std::shared_ptr<storm::logic::Formula const> formula = formulaParser.parseSingleFormulaFromString("LRAmax=? [\"a\"]"); |
|
||||
|
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("0.5"), quantitativeResult1[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0.5"), quantitativeResult1[1], this->precision()); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("LRAmin=? [\"a\"]"); |
|
||||
|
|
||||
result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("0.5"), quantitativeResult2[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0.5"), quantitativeResult2[1], this->precision()); |
|
||||
} |
|
||||
{ |
|
||||
matrixBuilder = storm::storage::SparseMatrixBuilder<ValueType>(4, 3, 4, true, true, 3); |
|
||||
matrixBuilder.newRowGroup(0); |
|
||||
matrixBuilder.addNextValue(0, 1, this->parseNumber("1")); |
|
||||
matrixBuilder.newRowGroup(1); |
|
||||
matrixBuilder.addNextValue(1, 0, this->parseNumber("1")); |
|
||||
matrixBuilder.addNextValue(2, 2, this->parseNumber("1")); |
|
||||
matrixBuilder.newRowGroup(3); |
|
||||
matrixBuilder.addNextValue(3, 0, this->parseNumber("1")); |
|
||||
storm::storage::SparseMatrix<ValueType> transitionMatrix = matrixBuilder.build(); |
|
||||
|
|
||||
storm::models::sparse::StateLabeling ap(3); |
|
||||
ap.addLabel("a"); |
|
||||
ap.addLabelToState("a", 2); |
|
||||
ap.addLabel("b"); |
|
||||
ap.addLabelToState("b", 0); |
|
||||
ap.addLabel("c"); |
|
||||
ap.addLabelToState("c", 0); |
|
||||
ap.addLabelToState("c", 2); |
|
||||
|
|
||||
mdp.reset(new storm::models::sparse::Mdp<ValueType>(transitionMatrix, ap)); |
|
||||
|
|
||||
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<ValueType>> checker(*mdp); |
|
||||
|
|
||||
std::shared_ptr<storm::logic::Formula const> formula = formulaParser.parseSingleFormulaFromString("LRAmax=? [\"a\"]"); |
|
||||
|
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("1/3"), quantitativeResult1[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("1/3"), quantitativeResult1[1], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("1/3"), quantitativeResult1[2], this->precision()); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("LRAmin=? [\"a\"]"); |
|
||||
|
|
||||
result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("0"), quantitativeResult2[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0"), quantitativeResult2[1], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0"), quantitativeResult2[2], this->precision()); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("LRAmax=? [\"b\"]"); |
|
||||
|
|
||||
result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("0.5"), quantitativeResult3[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0.5"), quantitativeResult3[1], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0.5"), quantitativeResult3[2], this->precision()); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("LRAmin=? [\"b\"]"); |
|
||||
|
|
||||
result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult4 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("1/3"), quantitativeResult4[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("1/3"), quantitativeResult4[1], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("1/3"), quantitativeResult4[2], this->precision()); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("LRAmax=? [\"c\"]"); |
|
||||
|
|
||||
result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult5 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("2/3"), quantitativeResult5[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("2/3"), quantitativeResult5[1], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("2/3"), quantitativeResult5[2], this->precision()); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("LRAmin=? [\"c\"]"); |
|
||||
|
|
||||
result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult6 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("0.5"), quantitativeResult6[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0.5"), quantitativeResult6[1], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0.5"), quantitativeResult6[2], this->precision()); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
TYPED_TEST(LraMdpPrctlModelCheckerTest, LRA) { |
|
||||
typedef typename TestFixture::ValueType ValueType; |
|
||||
|
|
||||
storm::storage::SparseMatrixBuilder<ValueType> matrixBuilder; |
|
||||
std::shared_ptr<storm::models::sparse::Mdp<ValueType>> mdp; |
|
||||
|
|
||||
// A parser that we use for conveniently constructing the formulas.
|
|
||||
storm::parser::FormulaParser formulaParser; |
|
||||
|
|
||||
{ |
|
||||
matrixBuilder = storm::storage::SparseMatrixBuilder<ValueType>(4, 3, 4, true, true, 3); |
|
||||
matrixBuilder.newRowGroup(0); |
|
||||
matrixBuilder.addNextValue(0, 1, this->parseNumber("1")); |
|
||||
matrixBuilder.newRowGroup(1); |
|
||||
matrixBuilder.addNextValue(1, 1, this->parseNumber("1")); |
|
||||
matrixBuilder.addNextValue(2, 2, this->parseNumber("1")); |
|
||||
matrixBuilder.newRowGroup(3); |
|
||||
matrixBuilder.addNextValue(3, 2, this->parseNumber("1")); |
|
||||
storm::storage::SparseMatrix<ValueType> transitionMatrix = matrixBuilder.build(); |
|
||||
|
|
||||
storm::models::sparse::StateLabeling ap(3); |
|
||||
ap.addLabel("a"); |
|
||||
ap.addLabelToState("a", 0); |
|
||||
ap.addLabel("b"); |
|
||||
ap.addLabelToState("b", 1); |
|
||||
ap.addLabel("c"); |
|
||||
ap.addLabelToState("c", 2); |
|
||||
|
|
||||
mdp.reset(new storm::models::sparse::Mdp<ValueType>(transitionMatrix, ap)); |
|
||||
|
|
||||
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<ValueType>> checker(*mdp); |
|
||||
|
|
||||
std::shared_ptr<storm::logic::Formula const> formula = formulaParser.parseSingleFormulaFromString("LRAmax=? [\"a\"]"); |
|
||||
|
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("0"), quantitativeResult1[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0"), quantitativeResult1[1], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0"), quantitativeResult1[2], this->precision()); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("LRAmin=? [\"a\"]"); |
|
||||
|
|
||||
result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("0"), quantitativeResult2[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0"), quantitativeResult2[1], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0"), quantitativeResult2[2], this->precision()); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("LRAmax=? [\"b\"]"); |
|
||||
|
|
||||
result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("1"), quantitativeResult3[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("1"), quantitativeResult3[1], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0"), quantitativeResult3[2], this->precision()); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("LRAmin=? [\"b\"]"); |
|
||||
|
|
||||
result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult4 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("0"), quantitativeResult4[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0"), quantitativeResult4[1], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0"), quantitativeResult4[2], this->precision()); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("LRAmax=? [\"c\"]"); |
|
||||
|
|
||||
result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult5 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("1"), quantitativeResult5[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("1"), quantitativeResult5[1], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("1"), quantitativeResult5[2], this->precision()); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("LRAmin=? [\"c\"]"); |
|
||||
|
|
||||
result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult6 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("0"), quantitativeResult6[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0"), quantitativeResult6[1], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("1"), quantitativeResult6[2], this->precision()); |
|
||||
} |
|
||||
{ |
|
||||
matrixBuilder = storm::storage::SparseMatrixBuilder<ValueType>(22, 15, 28, true, true, 15); |
|
||||
matrixBuilder.newRowGroup(0); |
|
||||
matrixBuilder.addNextValue(0, 1, this->parseNumber("1")); |
|
||||
matrixBuilder.newRowGroup(1); |
|
||||
matrixBuilder.addNextValue(1, 0, this->parseNumber("1")); |
|
||||
matrixBuilder.addNextValue(2, 2, this->parseNumber("1")); |
|
||||
matrixBuilder.addNextValue(3, 4, this->parseNumber("0.7")); |
|
||||
matrixBuilder.addNextValue(3, 6, this->parseNumber("0.3")); |
|
||||
matrixBuilder.newRowGroup(4); |
|
||||
matrixBuilder.addNextValue(4, 0, this->parseNumber("1")); |
|
||||
|
|
||||
matrixBuilder.newRowGroup(5); |
|
||||
matrixBuilder.addNextValue(5, 4, this->parseNumber("1")); |
|
||||
matrixBuilder.addNextValue(6, 5, this->parseNumber("0.8")); |
|
||||
matrixBuilder.addNextValue(6, 9, this->parseNumber("0.2")); |
|
||||
matrixBuilder.newRowGroup(7); |
|
||||
matrixBuilder.addNextValue(7, 3, this->parseNumber("1")); |
|
||||
matrixBuilder.addNextValue(8, 5, this->parseNumber("1")); |
|
||||
matrixBuilder.newRowGroup(9); |
|
||||
matrixBuilder.addNextValue(9, 3, this->parseNumber("1")); |
|
||||
|
|
||||
matrixBuilder.newRowGroup(10); |
|
||||
matrixBuilder.addNextValue(10, 7, this->parseNumber("1")); |
|
||||
matrixBuilder.newRowGroup(11); |
|
||||
matrixBuilder.addNextValue(11, 6, this->parseNumber("1")); |
|
||||
matrixBuilder.addNextValue(12, 8, this->parseNumber("1")); |
|
||||
matrixBuilder.newRowGroup(13); |
|
||||
matrixBuilder.addNextValue(13, 6, this->parseNumber("1")); |
|
||||
|
|
||||
matrixBuilder.newRowGroup(14); |
|
||||
matrixBuilder.addNextValue(14, 10, this->parseNumber("1")); |
|
||||
matrixBuilder.newRowGroup(15); |
|
||||
matrixBuilder.addNextValue(15, 9, this->parseNumber("1")); |
|
||||
matrixBuilder.addNextValue(16, 11, this->parseNumber("1")); |
|
||||
matrixBuilder.newRowGroup(17); |
|
||||
matrixBuilder.addNextValue(17, 9, this->parseNumber("1")); |
|
||||
|
|
||||
matrixBuilder.newRowGroup(18); |
|
||||
matrixBuilder.addNextValue(18, 5, this->parseNumber("0.4")); |
|
||||
matrixBuilder.addNextValue(18, 8, this->parseNumber("0.3")); |
|
||||
matrixBuilder.addNextValue(18, 11, this->parseNumber("0.3")); |
|
||||
|
|
||||
matrixBuilder.newRowGroup(19); |
|
||||
matrixBuilder.addNextValue(19, 7, this->parseNumber("0.7")); |
|
||||
matrixBuilder.addNextValue(19, 12, this->parseNumber("0.3")); |
|
||||
|
|
||||
matrixBuilder.newRowGroup(20); |
|
||||
matrixBuilder.addNextValue(20, 12, this->parseNumber("0.1")); |
|
||||
matrixBuilder.addNextValue(20, 13, this->parseNumber("0.9")); |
|
||||
matrixBuilder.addNextValue(21, 12, this->parseNumber("1")); |
|
||||
|
|
||||
storm::storage::SparseMatrix<ValueType> transitionMatrix = matrixBuilder.build(); |
|
||||
|
|
||||
storm::models::sparse::StateLabeling ap(15); |
|
||||
ap.addLabel("a"); |
|
||||
ap.addLabelToState("a", 1); |
|
||||
ap.addLabelToState("a", 4); |
|
||||
ap.addLabelToState("a", 5); |
|
||||
ap.addLabelToState("a", 7); |
|
||||
ap.addLabelToState("a", 11); |
|
||||
ap.addLabelToState("a", 13); |
|
||||
ap.addLabelToState("a", 14); |
|
||||
|
|
||||
mdp.reset(new storm::models::sparse::Mdp<ValueType>(transitionMatrix, ap)); |
|
||||
|
|
||||
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<ValueType>> checker(*mdp); |
|
||||
|
|
||||
std::shared_ptr<storm::logic::Formula const> formula = formulaParser.parseSingleFormulaFromString("LRAmax=? [\"a\"]"); |
|
||||
|
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("37 / 60"), quantitativeResult1[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("2/3"), quantitativeResult1[3], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0.5"), quantitativeResult1[6], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("1/3"), quantitativeResult1[9], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("31 / 60"), quantitativeResult1[12], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("101 / 200"), quantitativeResult1[13], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("31 / 60"), quantitativeResult1[14], this->precision()); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("LRAmin=? [\"a\"]"); |
|
||||
|
|
||||
result = checker.check(this->env(), *formula); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("0.1"), quantitativeResult2[0], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0"), quantitativeResult2[3], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("1/3"), quantitativeResult2[6], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0"), quantitativeResult2[9], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0.1"), quantitativeResult2[12], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("79 / 300"), quantitativeResult2[13], this->precision()); |
|
||||
EXPECT_NEAR(this->parseNumber("0.1"), quantitativeResult2[14], this->precision()); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
TYPED_TEST(LraMdpPrctlModelCheckerTest, cs_nfail) { |
|
||||
typedef typename TestFixture::ValueType ValueType; |
|
||||
|
|
||||
std::string formulasString = "R{\"grants\"}max=? [ MP ]"; |
|
||||
|
|
||||
auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR "/mdp/cs_nfail3.nm", formulasString); |
|
||||
auto model = std::move(modelFormulas.first); |
|
||||
auto tasks = this->getTasks(modelFormulas.second); |
|
||||
EXPECT_EQ(184ul, model->getNumberOfStates()); |
|
||||
EXPECT_EQ(541ul, model->getNumberOfTransitions()); |
|
||||
ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp); |
|
||||
auto mdp = model->template as<storm::models::sparse::Mdp<ValueType>>(); |
|
||||
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<ValueType>> checker(*mdp); |
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result; |
|
||||
|
|
||||
result = checker.check(this->env(), tasks[0]); |
|
||||
storm::modelchecker::ExplicitQuantitativeCheckResult<ValueType>& quantitativeResult = result->asExplicitQuantitativeCheckResult<ValueType>(); |
|
||||
|
|
||||
EXPECT_NEAR(this->parseNumber("333/1000"), quantitativeResult[*mdp->getInitialStates().begin()], this->precision()); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
} |
|
@ -1,607 +0,0 @@ |
|||||
#include "test/storm_gtest.h"
|
|
||||
#include "storm-config.h"
|
|
||||
|
|
||||
#include "test/storm_gtest.h"
|
|
||||
|
|
||||
#include "storm/api/builder.h"
|
|
||||
#include "storm-conv/api/storm-conv.h"
|
|
||||
#include "storm-parsers/api/model_descriptions.h"
|
|
||||
#include "storm/api/properties.h"
|
|
||||
#include "storm-parsers/api/properties.h"
|
|
||||
|
|
||||
#include "storm/models/sparse/Mdp.h"
|
|
||||
#include "storm/models/symbolic/Mdp.h"
|
|
||||
#include "storm/models/sparse/StandardRewardModel.h"
|
|
||||
#include "storm/models/symbolic/StandardRewardModel.h"
|
|
||||
#include "storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h"
|
|
||||
#include "storm/modelchecker/prctl/HybridMdpPrctlModelChecker.h"
|
|
||||
#include "storm/modelchecker/prctl/SymbolicMdpPrctlModelChecker.h"
|
|
||||
#include "storm/modelchecker/results/QuantitativeCheckResult.h"
|
|
||||
#include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h"
|
|
||||
#include "storm/modelchecker/results/SymbolicQualitativeCheckResult.h"
|
|
||||
#include "storm/modelchecker/results/QualitativeCheckResult.h"
|
|
||||
#include "storm/environment/solver/MinMaxSolverEnvironment.h"
|
|
||||
#include "storm/environment/solver/TopologicalSolverEnvironment.h"
|
|
||||
#include "storm/settings/modules/CoreSettings.h"
|
|
||||
#include "storm/logic/Formulas.h"
|
|
||||
#include "storm/storage/jani/Property.h"
|
|
||||
#include "storm/exceptions/UncheckedRequirementException.h"
|
|
||||
|
|
||||
namespace { |
|
||||
|
|
||||
enum class MdpEngine {PrismSparse, JaniSparse, JitSparse, Hybrid, PrismDd, JaniDd}; |
|
||||
|
|
||||
class SparseDoubleValueIterationEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // Unused for sparse models
|
|
||||
static const MdpEngine engine = MdpEngine::PrismSparse; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Mdp<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration); |
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-10)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class JaniSparseDoubleValueIterationEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // Unused for sparse models
|
|
||||
static const MdpEngine engine = MdpEngine::JaniSparse; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Mdp<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration); |
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-10)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class JitSparseDoubleValueIterationEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // Unused for sparse models
|
|
||||
static const MdpEngine engine = MdpEngine::JitSparse; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Mdp<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration); |
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-10)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseDoubleIntervalIterationEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // Unused for sparse models
|
|
||||
static const MdpEngine engine = MdpEngine::PrismSparse; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Mdp<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setForceSoundness(true); |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::IntervalIteration); |
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-6)); |
|
||||
env.solver().minMax().setRelativeTerminationCriterion(false); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
class SparseDoubleSoundValueIterationEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // Unused for sparse models
|
|
||||
static const MdpEngine engine = MdpEngine::PrismSparse; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Mdp<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setForceSoundness(true); |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::SoundValueIteration); |
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-6)); |
|
||||
env.solver().minMax().setRelativeTerminationCriterion(false); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseDoubleTopologicalValueIterationEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // Unused for sparse models
|
|
||||
static const MdpEngine engine = MdpEngine::PrismSparse; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Mdp<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::Topological); |
|
||||
env.solver().topological().setUnderlyingMinMaxMethod(storm::solver::MinMaxMethod::ValueIteration); |
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
env.solver().minMax().setRelativeTerminationCriterion(false); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseDoubleTopologicalSoundValueIterationEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // Unused for sparse models
|
|
||||
static const MdpEngine engine = MdpEngine::PrismSparse; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::sparse::Mdp<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setForceSoundness(true); |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::Topological); |
|
||||
env.solver().topological().setUnderlyingMinMaxMethod(storm::solver::MinMaxMethod::SoundValueIteration); |
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-6)); |
|
||||
env.solver().minMax().setRelativeTerminationCriterion(false); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseRationalPolicyIterationEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // Unused for sparse models
|
|
||||
static const MdpEngine engine = MdpEngine::PrismSparse; |
|
||||
static const bool isExact = true; |
|
||||
typedef storm::RationalNumber ValueType; |
|
||||
typedef storm::models::sparse::Mdp<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::PolicyIteration); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseRationalViToPiEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // Unused for sparse models
|
|
||||
static const MdpEngine engine = MdpEngine::PrismSparse; |
|
||||
static const bool isExact = true; |
|
||||
typedef storm::RationalNumber ValueType; |
|
||||
typedef storm::models::sparse::Mdp<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ViToPi); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SparseRationalRationalSearchEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; // Unused for sparse models
|
|
||||
static const MdpEngine engine = MdpEngine::PrismSparse; |
|
||||
static const bool isExact = true; |
|
||||
typedef storm::RationalNumber ValueType; |
|
||||
typedef storm::models::sparse::Mdp<ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::RationalSearch); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
class HybridCuddDoubleValueIterationEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::CUDD; |
|
||||
static const MdpEngine engine = MdpEngine::Hybrid; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::symbolic::Mdp<ddType, ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration); |
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-10)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
class HybridSylvanDoubleValueIterationEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; |
|
||||
static const MdpEngine engine = MdpEngine::Hybrid; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::symbolic::Mdp<ddType, ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration); |
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-10)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
class HybridCuddDoubleSoundValueIterationEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::CUDD; |
|
||||
static const MdpEngine engine = MdpEngine::Hybrid; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::symbolic::Mdp<ddType, ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setForceSoundness(true); |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::SoundValueIteration); |
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-6)); |
|
||||
env.solver().minMax().setRelativeTerminationCriterion(false); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
class HybridSylvanRationalPolicyIterationEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; |
|
||||
static const MdpEngine engine = MdpEngine::Hybrid; |
|
||||
static const bool isExact = true; |
|
||||
typedef storm::RationalNumber ValueType; |
|
||||
typedef storm::models::symbolic::Mdp<ddType, ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::PolicyIteration); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
class DdCuddDoubleValueIterationEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::CUDD; |
|
||||
static const MdpEngine engine = MdpEngine::PrismDd; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::symbolic::Mdp<ddType, ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration); |
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-10)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
class JaniDdCuddDoubleValueIterationEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::CUDD; |
|
||||
static const MdpEngine engine = MdpEngine::JaniDd; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::symbolic::Mdp<ddType, ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration); |
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-10)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
class DdSylvanDoubleValueIterationEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; |
|
||||
static const MdpEngine engine = MdpEngine::PrismDd; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::symbolic::Mdp<ddType, ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration); |
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-10)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
class DdCuddDoublePolicyIterationEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::CUDD; |
|
||||
static const MdpEngine engine = MdpEngine::PrismDd; |
|
||||
static const bool isExact = false; |
|
||||
typedef double ValueType; |
|
||||
typedef storm::models::symbolic::Mdp<ddType, ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::PolicyIteration); |
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-10)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
class DdSylvanRationalRationalSearchEnvironment { |
|
||||
public: |
|
||||
static const storm::dd::DdType ddType = storm::dd::DdType::Sylvan; |
|
||||
static const MdpEngine engine = MdpEngine::PrismDd; |
|
||||
static const bool isExact = true; |
|
||||
typedef storm::RationalNumber ValueType; |
|
||||
typedef storm::models::symbolic::Mdp<ddType, ValueType> ModelType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::RationalSearch); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
template<typename TestType> |
|
||||
class MdpPrctlModelCheckerTest : public ::testing::Test { |
|
||||
public: |
|
||||
typedef typename TestType::ValueType ValueType; |
|
||||
typedef typename storm::models::sparse::Mdp<ValueType> SparseModelType; |
|
||||
typedef typename storm::models::symbolic::Mdp<TestType::ddType, ValueType> SymbolicModelType; |
|
||||
|
|
||||
MdpPrctlModelCheckerTest() : _environment(TestType::createEnvironment()) {} |
|
||||
storm::Environment const& env() const { return _environment; } |
|
||||
ValueType parseNumber(std::string const& input) const { return storm::utility::convertNumber<ValueType>(input);} |
|
||||
ValueType precision() const { return TestType::isExact ? parseNumber("0") : parseNumber("1e-6");} |
|
||||
bool isSparseModel() const { return std::is_same<typename TestType::ModelType, SparseModelType>::value; } |
|
||||
bool isSymbolicModel() const { return std::is_same<typename TestType::ModelType, SymbolicModelType>::value; } |
|
||||
|
|
||||
template <typename MT = typename TestType::ModelType> |
|
||||
typename std::enable_if<std::is_same<MT, SparseModelType>::value, std::pair<std::shared_ptr<MT>, std::vector<std::shared_ptr<storm::logic::Formula const>>>>::type |
|
||||
buildModelFormulas(std::string const& pathToPrismFile, std::string const& formulasAsString, std::string const& constantDefinitionString = "") const { |
|
||||
std::pair<std::shared_ptr<MT>, std::vector<std::shared_ptr<storm::logic::Formula const>>> result; |
|
||||
storm::prism::Program program = storm::api::parseProgram(pathToPrismFile); |
|
||||
program = storm::utility::prism::preprocess(program, constantDefinitionString); |
|
||||
if (TestType::engine == MdpEngine::PrismSparse) { |
|
||||
result.second = storm::api::extractFormulasFromProperties(storm::api::parsePropertiesForPrismProgram(formulasAsString, program)); |
|
||||
result.first = storm::api::buildSparseModel<ValueType>(program, result.second)->template as<MT>(); |
|
||||
} else if (TestType::engine == MdpEngine::JaniSparse || TestType::engine == MdpEngine::JitSparse) { |
|
||||
auto janiData = storm::api::convertPrismToJani(program, storm::api::parsePropertiesForPrismProgram(formulasAsString, program)); |
|
||||
janiData.first.substituteFunctions(); |
|
||||
result.second = storm::api::extractFormulasFromProperties(janiData.second); |
|
||||
result.first = storm::api::buildSparseModel<ValueType>(janiData.first, result.second, TestType::engine == MdpEngine::JitSparse)->template as<MT>(); |
|
||||
} |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
template <typename MT = typename TestType::ModelType> |
|
||||
typename std::enable_if<std::is_same<MT, SymbolicModelType>::value, std::pair<std::shared_ptr<MT>, std::vector<std::shared_ptr<storm::logic::Formula const>>>>::type |
|
||||
buildModelFormulas(std::string const& pathToPrismFile, std::string const& formulasAsString, std::string const& constantDefinitionString = "") const { |
|
||||
std::pair<std::shared_ptr<MT>, std::vector<std::shared_ptr<storm::logic::Formula const>>> result; |
|
||||
storm::prism::Program program = storm::api::parseProgram(pathToPrismFile); |
|
||||
program = storm::utility::prism::preprocess(program, constantDefinitionString); |
|
||||
if (TestType::engine == MdpEngine::Hybrid || TestType::engine == MdpEngine::PrismDd) { |
|
||||
result.second = storm::api::extractFormulasFromProperties(storm::api::parsePropertiesForPrismProgram(formulasAsString, program)); |
|
||||
result.first = storm::api::buildSymbolicModel<TestType::ddType, ValueType>(program, result.second)->template as<MT>(); |
|
||||
} else if (TestType::engine == MdpEngine::JaniDd) { |
|
||||
auto janiData = storm::api::convertPrismToJani(program, storm::api::parsePropertiesForPrismProgram(formulasAsString, program)); |
|
||||
janiData.first.substituteFunctions(); |
|
||||
result.second = storm::api::extractFormulasFromProperties(janiData.second); |
|
||||
result.first = storm::api::buildSymbolicModel<TestType::ddType, ValueType>(janiData.first, result.second)->template as<MT>(); |
|
||||
} |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
std::vector<storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>> getTasks(std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas) const { |
|
||||
std::vector<storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>> result; |
|
||||
for (auto const& f : formulas) { |
|
||||
result.emplace_back(*f); |
|
||||
} |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
template <typename MT = typename TestType::ModelType> |
|
||||
typename std::enable_if<std::is_same<MT, SparseModelType>::value, std::shared_ptr<storm::modelchecker::AbstractModelChecker<MT>>>::type |
|
||||
createModelChecker(std::shared_ptr<MT> const& model) const { |
|
||||
if (TestType::engine == MdpEngine::PrismSparse || TestType::engine == MdpEngine::JaniSparse || TestType::engine == MdpEngine::JitSparse) { |
|
||||
return std::make_shared<storm::modelchecker::SparseMdpPrctlModelChecker<SparseModelType>>(*model); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
template <typename MT = typename TestType::ModelType> |
|
||||
typename std::enable_if<std::is_same<MT, SymbolicModelType>::value, std::shared_ptr<storm::modelchecker::AbstractModelChecker<MT>>>::type |
|
||||
createModelChecker(std::shared_ptr<MT> const& model) const { |
|
||||
if (TestType::engine == MdpEngine::Hybrid) { |
|
||||
return std::make_shared<storm::modelchecker::HybridMdpPrctlModelChecker<SymbolicModelType>>(*model); |
|
||||
} else if (TestType::engine == MdpEngine::PrismDd || TestType::engine == MdpEngine::JaniDd) { |
|
||||
return std::make_shared<storm::modelchecker::SymbolicMdpPrctlModelChecker<SymbolicModelType>>(*model); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
bool getQualitativeResultAtInitialState(std::shared_ptr<storm::models::Model<ValueType>> const& model, std::unique_ptr<storm::modelchecker::CheckResult>& result) { |
|
||||
auto filter = getInitialStateFilter(model); |
|
||||
result->filter(*filter); |
|
||||
return result->asQualitativeCheckResult().forallTrue(); |
|
||||
} |
|
||||
|
|
||||
ValueType getQuantitativeResultAtInitialState(std::shared_ptr<storm::models::Model<ValueType>> const& model, std::unique_ptr<storm::modelchecker::CheckResult>& result) { |
|
||||
auto filter = getInitialStateFilter(model); |
|
||||
result->filter(*filter); |
|
||||
return result->asQuantitativeCheckResult<ValueType>().getMin(); |
|
||||
} |
|
||||
|
|
||||
private: |
|
||||
storm::Environment _environment; |
|
||||
|
|
||||
std::unique_ptr<storm::modelchecker::QualitativeCheckResult> getInitialStateFilter(std::shared_ptr<storm::models::Model<ValueType>> const& model) const { |
|
||||
if (isSparseModel()) { |
|
||||
return std::make_unique<storm::modelchecker::ExplicitQualitativeCheckResult>(model->template as<SparseModelType>()->getInitialStates()); |
|
||||
} else { |
|
||||
return std::make_unique<storm::modelchecker::SymbolicQualitativeCheckResult<TestType::ddType>>(model->template as<SymbolicModelType>()->getReachableStates(), model->template as<SymbolicModelType>()->getInitialStates()); |
|
||||
} |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
typedef ::testing::Types< |
|
||||
SparseDoubleValueIterationEnvironment, |
|
||||
JaniSparseDoubleValueIterationEnvironment, |
|
||||
JitSparseDoubleValueIterationEnvironment, |
|
||||
SparseDoubleIntervalIterationEnvironment, |
|
||||
SparseDoubleSoundValueIterationEnvironment, |
|
||||
SparseDoubleTopologicalValueIterationEnvironment, |
|
||||
SparseDoubleTopologicalSoundValueIterationEnvironment, |
|
||||
SparseRationalPolicyIterationEnvironment, |
|
||||
SparseRationalViToPiEnvironment, |
|
||||
SparseRationalRationalSearchEnvironment, |
|
||||
HybridCuddDoubleValueIterationEnvironment, |
|
||||
HybridSylvanDoubleValueIterationEnvironment, |
|
||||
HybridCuddDoubleSoundValueIterationEnvironment, |
|
||||
HybridSylvanRationalPolicyIterationEnvironment, |
|
||||
DdCuddDoubleValueIterationEnvironment, |
|
||||
JaniDdCuddDoubleValueIterationEnvironment, |
|
||||
DdSylvanDoubleValueIterationEnvironment, |
|
||||
DdCuddDoublePolicyIterationEnvironment, |
|
||||
DdSylvanRationalRationalSearchEnvironment |
|
||||
> TestingTypes; |
|
||||
|
|
||||
TYPED_TEST_SUITE(MdpPrctlModelCheckerTest, TestingTypes); |
|
||||
|
|
||||
|
|
||||
TYPED_TEST(MdpPrctlModelCheckerTest, Dice) { |
|
||||
std::string formulasString = "Pmin=? [F \"two\"]"; |
|
||||
formulasString += "; Pmax=? [F \"two\"]"; |
|
||||
formulasString += "; Pmin=? [F \"three\"]"; |
|
||||
formulasString += "; Pmax=? [F \"three\"]"; |
|
||||
formulasString += "; Pmin=? [F \"four\"]"; |
|
||||
formulasString += "; Pmax=? [F \"four\"]"; |
|
||||
formulasString += "; Rmin=? [F \"done\"]"; |
|
||||
formulasString += "; Rmax=? [F \"done\"]"; |
|
||||
|
|
||||
auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR "/mdp/two_dice.nm", formulasString); |
|
||||
auto model = std::move(modelFormulas.first); |
|
||||
auto tasks = this->getTasks(modelFormulas.second); |
|
||||
EXPECT_EQ(169ul, model->getNumberOfStates()); |
|
||||
EXPECT_EQ(436ul, model->getNumberOfTransitions()); |
|
||||
ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp); |
|
||||
auto checker = this->createModelChecker(model); |
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result; |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[0]); |
|
||||
EXPECT_NEAR(this->parseNumber("1/36"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[1]); |
|
||||
EXPECT_NEAR(this->parseNumber("1/36"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[2]); |
|
||||
EXPECT_NEAR(this->parseNumber("2/36"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[3]); |
|
||||
EXPECT_NEAR(this->parseNumber("2/36"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[4]); |
|
||||
EXPECT_NEAR(this->parseNumber("3/36"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[5]); |
|
||||
EXPECT_NEAR(this->parseNumber("3/36"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[6]); |
|
||||
EXPECT_NEAR(this->parseNumber("22/3"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[7]); |
|
||||
EXPECT_NEAR(this->parseNumber("22/3"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
} |
|
||||
|
|
||||
TYPED_TEST(MdpPrctlModelCheckerTest, AsynchronousLeader) { |
|
||||
std::string formulasString = "Pmin=? [F \"elected\"]"; |
|
||||
formulasString += "; Pmax=? [F \"elected\"]"; |
|
||||
formulasString += "; Pmin=? [F<=25 \"elected\"]"; |
|
||||
formulasString += "; Pmax=? [F<=25 \"elected\"]"; |
|
||||
formulasString += "; Rmin=? [F \"elected\"]"; |
|
||||
formulasString += "; Rmax=? [F \"elected\"]"; |
|
||||
|
|
||||
auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR "/mdp/leader4.nm", formulasString); |
|
||||
auto model = std::move(modelFormulas.first); |
|
||||
auto tasks = this->getTasks(modelFormulas.second); |
|
||||
EXPECT_EQ(3172ul, model->getNumberOfStates()); |
|
||||
EXPECT_EQ(7144ul, model->getNumberOfTransitions()); |
|
||||
ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp); |
|
||||
auto checker = this->createModelChecker(model); |
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result; |
|
||||
|
|
||||
|
|
||||
result = checker->check(this->env(), tasks[0]); |
|
||||
EXPECT_NEAR(this->parseNumber("1"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[1]); |
|
||||
EXPECT_NEAR(this->parseNumber("1"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[2]); |
|
||||
EXPECT_NEAR(this->parseNumber("1/16"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[3]); |
|
||||
EXPECT_NEAR(this->parseNumber("1/16"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[4]); |
|
||||
EXPECT_NEAR(this->parseNumber("30/7"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[5]); |
|
||||
EXPECT_NEAR(this->parseNumber("30/7"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
} |
|
||||
|
|
||||
TYPED_TEST(MdpPrctlModelCheckerTest, consensus) { |
|
||||
std::string formulasString = "Pmax=? [F \"finished\"]"; |
|
||||
formulasString += "; Pmax=? [F \"all_coins_equal_1\"]"; |
|
||||
formulasString += "; P<0.8 [F \"all_coins_equal_1\"]"; |
|
||||
formulasString += "; P<0.9 [F \"all_coins_equal_1\"]"; |
|
||||
formulasString += "; Rmax=? [F \"all_coins_equal_1\"]"; |
|
||||
formulasString += "; Rmin=? [F \"all_coins_equal_1\"]"; |
|
||||
formulasString += "; Rmax=? [F \"finished\"]"; |
|
||||
formulasString += "; Rmin=? [F \"finished\"]"; |
|
||||
|
|
||||
auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR "/mdp/coin2-2.nm", formulasString); |
|
||||
auto model = std::move(modelFormulas.first); |
|
||||
auto tasks = this->getTasks(modelFormulas.second); |
|
||||
EXPECT_EQ(272ul, model->getNumberOfStates()); |
|
||||
EXPECT_EQ(492ul, model->getNumberOfTransitions()); |
|
||||
ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp); |
|
||||
auto checker = this->createModelChecker(model); |
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result; |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[0]); |
|
||||
EXPECT_NEAR(this->parseNumber("1"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[1]); |
|
||||
EXPECT_NEAR(this->parseNumber("57/64"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[2]); |
|
||||
EXPECT_FALSE(this->getQualitativeResultAtInitialState(model, result)); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[3]); |
|
||||
EXPECT_TRUE(this->getQualitativeResultAtInitialState(model, result)); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[4]); |
|
||||
EXPECT_TRUE(storm::utility::isInfinity(this->getQuantitativeResultAtInitialState(model, result))); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[5]); |
|
||||
EXPECT_TRUE(storm::utility::isInfinity(this->getQuantitativeResultAtInitialState(model, result))); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[6]); |
|
||||
EXPECT_NEAR(this->parseNumber("75"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
|
|
||||
result = checker->check(this->env(), tasks[7]); |
|
||||
EXPECT_NEAR(this->parseNumber("48"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
} |
|
||||
|
|
||||
TYPED_TEST(MdpPrctlModelCheckerTest, TinyRewards) { |
|
||||
std::string formulasString = "Rmin=? [F \"target\"]"; |
|
||||
auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR "/mdp/tiny_rewards.nm", formulasString); |
|
||||
auto model = std::move(modelFormulas.first); |
|
||||
auto tasks = this->getTasks(modelFormulas.second); |
|
||||
EXPECT_EQ(3ul, model->getNumberOfStates()); |
|
||||
EXPECT_EQ(4ul, model->getNumberOfTransitions()); |
|
||||
ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp); |
|
||||
auto checker = this->createModelChecker(model); |
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result; |
|
||||
|
|
||||
// This example considers a zero-reward end component that does not reach the target
|
|
||||
// For some methods this requires end-component elimination which is (currently) not supported in the Dd engine
|
|
||||
|
|
||||
if (TypeParam::engine == MdpEngine::PrismDd && this->env().solver().minMax().getMethod() == storm::solver::MinMaxMethod::RationalSearch) { |
|
||||
STORM_SILENT_EXPECT_THROW(checker->check(this->env(), tasks[0]), storm::exceptions::UncheckedRequirementException); |
|
||||
} else { |
|
||||
result = checker->check(this->env(), tasks[0]); |
|
||||
EXPECT_NEAR(this->parseNumber("1"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
TYPED_TEST(MdpPrctlModelCheckerTest, Team) { |
|
||||
std::string formulasString = "R{\"w_1_total\"}max=? [ C ]"; |
|
||||
auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR "/mdp/multiobj_team3.nm", formulasString); |
|
||||
auto model = std::move(modelFormulas.first); |
|
||||
auto tasks = this->getTasks(modelFormulas.second); |
|
||||
EXPECT_EQ(12475ul, model->getNumberOfStates()); |
|
||||
EXPECT_EQ(15228ul, model->getNumberOfTransitions()); |
|
||||
ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp); |
|
||||
auto checker = this->createModelChecker(model); |
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result; |
|
||||
|
|
||||
// This example considers an expected total reward formula, which is not supported in all engines
|
|
||||
|
|
||||
if (TypeParam::engine == MdpEngine::PrismSparse || TypeParam::engine == MdpEngine::JaniSparse || TypeParam::engine == MdpEngine::JitSparse) { |
|
||||
result = checker->check(this->env(), tasks[0]); |
|
||||
EXPECT_NEAR(this->parseNumber("114/49"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); |
|
||||
} else { |
|
||||
EXPECT_FALSE(checker->canHandle(tasks[0])); |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,302 +0,0 @@ |
|||||
#include "test/storm_gtest.h"
|
|
||||
#include "storm-config.h"
|
|
||||
|
|
||||
#include "test/storm_gtest.h"
|
|
||||
|
|
||||
#include "storm/api/builder.h"
|
|
||||
#include "storm-parsers/api/model_descriptions.h"
|
|
||||
#include "storm/api/properties.h"
|
|
||||
#include "storm-parsers/api/properties.h"
|
|
||||
#include "storm/parser/CSVParser.h"
|
|
||||
|
|
||||
#include "storm/models/sparse/Mdp.h"
|
|
||||
#include "storm/models/sparse/StandardRewardModel.h"
|
|
||||
#include "storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h"
|
|
||||
#include "storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.h"
|
|
||||
#include "storm/modelchecker/results/ExplicitParetoCurveCheckResult.h"
|
|
||||
#include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h"
|
|
||||
#include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h"
|
|
||||
#include "storm/environment/solver/MinMaxSolverEnvironment.h"
|
|
||||
#include "storm/logic/Formulas.h"
|
|
||||
#include "storm/storage/jani/Property.h"
|
|
||||
|
|
||||
namespace { |
|
||||
|
|
||||
enum class MdpEngine {PrismSparse, JaniSparse, JitSparse, Hybrid, PrismDd, JaniDd}; |
|
||||
|
|
||||
class UnsoundEnvironment { |
|
||||
public: |
|
||||
typedef double ValueType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-10)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class SoundEnvironment { |
|
||||
public: |
|
||||
typedef double ValueType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().setForceSoundness(true); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class ExactEnvironment { |
|
||||
public: |
|
||||
typedef storm::RationalNumber ValueType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
template<typename TestType> |
|
||||
class QuantileQueryTest : public ::testing::Test { |
|
||||
public: |
|
||||
typedef typename TestType::ValueType ValueType; |
|
||||
QuantileQueryTest() : _environment(TestType::createEnvironment()) {} |
|
||||
storm::Environment const& env() const { return _environment; } |
|
||||
ValueType parseNumber(std::string const& input) const { |
|
||||
if (input.find("inf") != std::string::npos) { |
|
||||
return storm::utility::infinity<ValueType>(); |
|
||||
} |
|
||||
return storm::utility::convertNumber<ValueType>(input); |
|
||||
} |
|
||||
|
|
||||
template <typename MT> |
|
||||
std::pair<std::shared_ptr<MT>, std::vector<std::shared_ptr<storm::logic::Formula const>>> buildModelFormulas(std::string const& pathToPrismFile, std::string const& formulasAsString, std::string const& constantDefinitionString = "") const { |
|
||||
std::pair<std::shared_ptr<MT>, std::vector<std::shared_ptr<storm::logic::Formula const>>> result; |
|
||||
storm::prism::Program program = storm::api::parseProgram(pathToPrismFile); |
|
||||
program = storm::utility::prism::preprocess(program, constantDefinitionString); |
|
||||
result.second = storm::api::extractFormulasFromProperties(storm::api::parsePropertiesForPrismProgram(formulasAsString, program)); |
|
||||
result.first = storm::api::buildSparseModel<ValueType>(program, result.second)->template as<MT>(); |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
std::vector<storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>> getTasks(std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas) const { |
|
||||
std::vector<storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>> result; |
|
||||
for (auto const& f : formulas) { |
|
||||
result.emplace_back(*f, true); // only initial states are relevant
|
|
||||
} |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
template <typename MT> |
|
||||
typename std::enable_if<std::is_same<MT, storm::models::sparse::Mdp<ValueType>>::value, std::shared_ptr<storm::modelchecker::AbstractModelChecker<MT>>>::type |
|
||||
createModelChecker(std::shared_ptr<MT> const& model) const { |
|
||||
return std::make_shared<storm::modelchecker::SparseMdpPrctlModelChecker<MT>>(*model); |
|
||||
} |
|
||||
template <typename MT> |
|
||||
typename std::enable_if<std::is_same<MT, storm::models::sparse::Dtmc<ValueType>>::value, std::shared_ptr<storm::modelchecker::AbstractModelChecker<MT>>>::type |
|
||||
createModelChecker(std::shared_ptr<MT> const& model) const { |
|
||||
return std::make_shared<storm::modelchecker::SparseDtmcPrctlModelChecker<MT>>(*model); |
|
||||
} |
|
||||
|
|
||||
std::pair<bool, std::string> compareResult(std::shared_ptr<storm::models::sparse::Model<ValueType>> const& model, std::unique_ptr<storm::modelchecker::CheckResult>& result, std::vector<std::string> const& expected) { |
|
||||
bool equal = true; |
|
||||
std::string errorMessage = ""; |
|
||||
auto filter = getInitialStateFilter(model); |
|
||||
result->filter(*filter); |
|
||||
std::vector<std::vector<ValueType>> resultPoints; |
|
||||
if (result->isExplicitParetoCurveCheckResult()) { |
|
||||
resultPoints = result->asExplicitParetoCurveCheckResult<ValueType>().getPoints(); |
|
||||
} else { |
|
||||
if (!result->isExplicitQuantitativeCheckResult()) { |
|
||||
return { false, "The CheckResult has unexpected type."}; |
|
||||
} |
|
||||
resultPoints = {{ result->asExplicitQuantitativeCheckResult<ValueType>().getMax() }}; |
|
||||
} |
|
||||
std::vector<std::vector<ValueType>> expectedPoints; |
|
||||
for (auto const& pointAsString : expected) { |
|
||||
std::vector<ValueType> point; |
|
||||
for (auto const& entry : storm::parser::parseCommaSeperatedValues(pointAsString)) { |
|
||||
point.push_back(parseNumber(entry)); |
|
||||
} |
|
||||
expectedPoints.push_back(std::move(point)); |
|
||||
} |
|
||||
for (auto const& resPoint : resultPoints) { |
|
||||
bool contained = false; |
|
||||
for (auto const& expPoint : expectedPoints) { |
|
||||
if (resPoint == expPoint) { |
|
||||
contained = true; |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
if (!contained) { |
|
||||
equal = false; |
|
||||
errorMessage += "The result " + storm::utility::vector::toString(resPoint) + " is not contained in the expected solution. "; |
|
||||
} |
|
||||
} |
|
||||
for (auto const& expPoint : expectedPoints) { |
|
||||
bool contained = false; |
|
||||
for (auto const& resPoint : resultPoints) { |
|
||||
if (resPoint == expPoint) { |
|
||||
contained = true; |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
if (!contained) { |
|
||||
equal = false; |
|
||||
errorMessage += "The expected " + storm::utility::vector::toString(expPoint) + " is not contained in the obtained solution. "; |
|
||||
} |
|
||||
} |
|
||||
return {equal, errorMessage}; |
|
||||
} |
|
||||
|
|
||||
private: |
|
||||
storm::Environment _environment; |
|
||||
|
|
||||
std::unique_ptr<storm::modelchecker::QualitativeCheckResult> getInitialStateFilter(std::shared_ptr<storm::models::sparse::Model<ValueType>> const& model) const { |
|
||||
return std::make_unique<storm::modelchecker::ExplicitQualitativeCheckResult>(model->getInitialStates()); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
typedef ::testing::Types< |
|
||||
UnsoundEnvironment, |
|
||||
SoundEnvironment, |
|
||||
ExactEnvironment |
|
||||
> TestingTypes; |
|
||||
|
|
||||
TYPED_TEST_SUITE(QuantileQueryTest, TestingTypes); |
|
||||
|
|
||||
|
|
||||
TYPED_TEST(QuantileQueryTest, simple_Dtmc) { |
|
||||
typedef storm::models::sparse::Dtmc<typename TestFixture::ValueType> ModelType; |
|
||||
|
|
||||
std::string formulasString = "quantile(max A, max B, P>0.95 [F{\"first\"}<=A,{\"second\"}<=B s=3]);\n"; |
|
||||
|
|
||||
auto modelFormulas = this->template buildModelFormulas<ModelType>(STORM_TEST_RESOURCES_DIR "/dtmc/quantiles_simple_dtmc.pm", formulasString); |
|
||||
auto model = std::move(modelFormulas.first); |
|
||||
auto tasks = this->getTasks(modelFormulas.second); |
|
||||
EXPECT_EQ(4ul, model->getNumberOfStates()); |
|
||||
EXPECT_EQ(6ul, model->getNumberOfTransitions()); |
|
||||
auto checker = this->template createModelChecker<ModelType>(model); |
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result; |
|
||||
std::vector<std::string> expectedResult; |
|
||||
std::pair<bool, std::string> compare; |
|
||||
uint64_t taskId = 0; |
|
||||
|
|
||||
expectedResult.clear(); |
|
||||
expectedResult.push_back("7, 18"); |
|
||||
expectedResult.push_back("8, 16"); |
|
||||
expectedResult.push_back("9, 14"); |
|
||||
result = checker->check(this->env(), tasks[taskId++]); |
|
||||
compare = this->compareResult(model, result, expectedResult); |
|
||||
EXPECT_TRUE(compare.first) << compare.second; |
|
||||
} |
|
||||
|
|
||||
TYPED_TEST(QuantileQueryTest, simple_Mdp) { |
|
||||
typedef storm::models::sparse::Mdp<typename TestFixture::ValueType> ModelType; |
|
||||
|
|
||||
std::string formulasString = "quantile(B1, B2, Pmax>0.5 [F{\"first\"}>=B1,{\"second\"}>=B2 s=1]);\n"; |
|
||||
formulasString += "quantile(B1, B2, Pmax>0.5 [F{\"first\"}<=B1,{\"second\"}<=B2 s=1]);\n"; |
|
||||
formulasString += "quantile(B1, B2, Pmin>0.5 [F{\"first\"}<=B1,{\"second\"}<=B2 s=1]);\n"; |
|
||||
formulasString += "quantile(B1, Pmax>0.5 [F{\"second\"}>=B1 s=1]);\n"; |
|
||||
formulasString += "quantile(B1, B2, B3, Pmax>0.5 [F{\"first\"}<=B1,{\"second\"}<=B2,{\"third\"}<=B3 s=1]);\n"; |
|
||||
|
|
||||
auto modelFormulas = this->template buildModelFormulas<ModelType>(STORM_TEST_RESOURCES_DIR "/mdp/quantiles_simple_mdp.nm", formulasString); |
|
||||
auto model = std::move(modelFormulas.first); |
|
||||
auto tasks = this->getTasks(modelFormulas.second); |
|
||||
EXPECT_EQ(7ul, model->getNumberOfStates()); |
|
||||
EXPECT_EQ(13ul, model->getNumberOfTransitions()); |
|
||||
auto checker = this->template createModelChecker<ModelType>(model); |
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result; |
|
||||
std::vector<std::string> expectedResult; |
|
||||
std::pair<bool, std::string> compare; |
|
||||
uint64_t taskId = 0; |
|
||||
|
|
||||
expectedResult.clear(); |
|
||||
expectedResult.push_back(" 0, 6"); |
|
||||
expectedResult.push_back(" 1, 5"); |
|
||||
expectedResult.push_back(" 2, 4"); |
|
||||
expectedResult.push_back(" 3, 3"); |
|
||||
expectedResult.push_back("inf, 2"); |
|
||||
result = checker->check(this->env(), tasks[taskId++]); |
|
||||
compare = this->compareResult(model, result, expectedResult); |
|
||||
EXPECT_TRUE(compare.first) << compare.second; |
|
||||
|
|
||||
expectedResult.clear(); |
|
||||
expectedResult.push_back(" 0, 2"); |
|
||||
expectedResult.push_back(" 5, 1"); |
|
||||
expectedResult.push_back(" 6, 0"); |
|
||||
result = checker->check(this->env(), tasks[taskId++]); |
|
||||
compare = this->compareResult(model, result, expectedResult); |
|
||||
EXPECT_TRUE(compare.first) << compare.second; |
|
||||
|
|
||||
expectedResult.clear(); |
|
||||
result = checker->check(this->env(), tasks[taskId++]); |
|
||||
compare = this->compareResult(model, result, expectedResult); |
|
||||
EXPECT_TRUE(compare.first) << compare.second; |
|
||||
|
|
||||
expectedResult.clear(); |
|
||||
expectedResult.push_back(" 6"); |
|
||||
result = checker->check(this->env(), tasks[taskId++]); |
|
||||
compare = this->compareResult(model, result, expectedResult); |
|
||||
EXPECT_TRUE(compare.first) << compare.second; |
|
||||
|
|
||||
expectedResult.clear(); |
|
||||
expectedResult.push_back(" 0, 2, 1.4"); |
|
||||
expectedResult.push_back(" 5, 1, 9.8"); |
|
||||
expectedResult.push_back(" 6, 0, 9.8"); |
|
||||
result = checker->check(this->env(), tasks[taskId++]); |
|
||||
compare = this->compareResult(model, result, expectedResult); |
|
||||
EXPECT_TRUE(compare.first) << compare.second; |
|
||||
} |
|
||||
|
|
||||
TYPED_TEST(QuantileQueryTest, firewire) { |
|
||||
typedef storm::models::sparse::Mdp<typename TestFixture::ValueType> ModelType; |
|
||||
|
|
||||
std::string formulasString = "quantile(min TIME, min ROUNDS, Pmax>0.95 [F{\"time\"}<=TIME,{\"rounds\"}<=ROUNDS \"done\"]);\n"; |
|
||||
|
|
||||
auto modelFormulas = this->template buildModelFormulas<ModelType>(STORM_TEST_RESOURCES_DIR "/mdp/quantiles_firewire.nm", formulasString, "delay=36"); |
|
||||
auto model = std::move(modelFormulas.first); |
|
||||
auto tasks = this->getTasks(modelFormulas.second); |
|
||||
EXPECT_EQ(776ul, model->getNumberOfStates()); |
|
||||
EXPECT_EQ(1411ul, model->getNumberOfTransitions()); |
|
||||
auto checker = this->template createModelChecker<ModelType>(model); |
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result; |
|
||||
std::vector<std::string> expectedResult; |
|
||||
std::pair<bool, std::string> compare; |
|
||||
uint64_t taskId = 0; |
|
||||
|
|
||||
expectedResult.clear(); |
|
||||
expectedResult.push_back("123, 1"); |
|
||||
result = checker->check(this->env(), tasks[taskId++]); |
|
||||
compare = this->compareResult(model, result, expectedResult); |
|
||||
EXPECT_TRUE(compare.first) << compare.second; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
TYPED_TEST(QuantileQueryTest, resources) { |
|
||||
typedef storm::models::sparse::Mdp<typename TestFixture::ValueType> ModelType; |
|
||||
|
|
||||
std::string formulasString = "quantile(max GOLD, max GEM, Pmax>0.95 [F{\"gold\"}>=GOLD,{\"gem\"}>=GEM,{\"steps\"}<=100 true]);\n"; |
|
||||
|
|
||||
auto modelFormulas = this->template buildModelFormulas<ModelType>(STORM_TEST_RESOURCES_DIR "/mdp/quantiles_resources.nm", formulasString); |
|
||||
auto model = std::move(modelFormulas.first); |
|
||||
auto tasks = this->getTasks(modelFormulas.second); |
|
||||
EXPECT_EQ(94ul, model->getNumberOfStates()); |
|
||||
EXPECT_EQ(326ul, model->getNumberOfTransitions()); |
|
||||
auto checker = this->template createModelChecker<ModelType>(model); |
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result; |
|
||||
std::vector<std::string> expectedResult; |
|
||||
std::pair<bool, std::string> compare; |
|
||||
uint64_t taskId = 0; |
|
||||
|
|
||||
expectedResult.clear(); |
|
||||
expectedResult.push_back("0, 10"); |
|
||||
expectedResult.push_back("1, 9"); |
|
||||
expectedResult.push_back("4, 8"); |
|
||||
expectedResult.push_back("7, 7"); |
|
||||
expectedResult.push_back("8, 4"); |
|
||||
expectedResult.push_back("9, 2"); |
|
||||
expectedResult.push_back("10, 0"); |
|
||||
result = checker->check(this->env(), tasks[taskId++]); |
|
||||
compare = this->compareResult(model, result, expectedResult); |
|
||||
EXPECT_TRUE(compare.first) << compare.second; |
|
||||
|
|
||||
} |
|
||||
} |
|
@ -1,142 +0,0 @@ |
|||||
#include "test/storm_gtest.h"
|
|
||||
#include "storm-config.h"
|
|
||||
|
|
||||
#include "storm-parsers/parser/FormulaParser.h"
|
|
||||
#include "storm/logic/Formulas.h"
|
|
||||
#include "storm/solver/StandardMinMaxLinearEquationSolver.h"
|
|
||||
#include "storm/models/sparse/StandardRewardModel.h"
|
|
||||
#include "storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h"
|
|
||||
#include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h"
|
|
||||
#include "storm/settings/SettingsManager.h"
|
|
||||
#include "storm/settings/modules/GeneralSettings.h"
|
|
||||
|
|
||||
#include "storm/environment/solver/MinMaxSolverEnvironment.h"
|
|
||||
|
|
||||
#include "storm-parsers/parser/AutoParser.h"
|
|
||||
#include "storm-parsers/parser/PrismParser.h"
|
|
||||
#include "storm/builder/ExplicitModelBuilder.h"
|
|
||||
|
|
||||
namespace { |
|
||||
class DoubleViEnvironment { |
|
||||
public: |
|
||||
typedef double ValueType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration); |
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
class DoubleSoundViEnvironment { |
|
||||
public: |
|
||||
typedef double ValueType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration); |
|
||||
env.solver().setForceSoundness(true); |
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-6)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
class DoublePIEnvironment { |
|
||||
public: |
|
||||
typedef double ValueType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::PolicyIteration); |
|
||||
env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-8)); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
class RationalPIEnvironment { |
|
||||
public: |
|
||||
typedef storm::RationalNumber ValueType; |
|
||||
static storm::Environment createEnvironment() { |
|
||||
storm::Environment env; |
|
||||
env.solver().minMax().setMethod(storm::solver::MinMaxMethod::PolicyIteration); |
|
||||
return env; |
|
||||
} |
|
||||
}; |
|
||||
// class RationalRationalSearchEnvironment {
|
|
||||
// public:
|
|
||||
// typedef storm::RationalNumber ValueType;
|
|
||||
// static storm::Environment createEnvironment() {
|
|
||||
// storm::Environment env;
|
|
||||
// env.solver().minMax().setMethod(storm::solver::MinMaxMethod::RationalSearch);
|
|
||||
// return env;
|
|
||||
// }
|
|
||||
// };
|
|
||||
|
|
||||
template<typename TestType> |
|
||||
class SchedulerGenerationMdpPrctlModelCheckerTest : public ::testing::Test { |
|
||||
public: |
|
||||
typedef typename TestType::ValueType ValueType; |
|
||||
SchedulerGenerationMdpPrctlModelCheckerTest() : _environment(TestType::createEnvironment()) {} |
|
||||
storm::Environment const& env() const { return _environment; } |
|
||||
private: |
|
||||
storm::Environment _environment; |
|
||||
}; |
|
||||
|
|
||||
typedef ::testing::Types< |
|
||||
DoubleViEnvironment, |
|
||||
DoubleSoundViEnvironment, |
|
||||
DoublePIEnvironment, |
|
||||
RationalPIEnvironment |
|
||||
//RationalRationalSearchEnvironment
|
|
||||
> TestingTypes; |
|
||||
|
|
||||
TYPED_TEST_SUITE(SchedulerGenerationMdpPrctlModelCheckerTest, TestingTypes); |
|
||||
|
|
||||
|
|
||||
TYPED_TEST(SchedulerGenerationMdpPrctlModelCheckerTest, reachability) { |
|
||||
typedef typename TestFixture::ValueType ValueType; |
|
||||
|
|
||||
storm::prism::Program program = storm::parser::PrismParser::parse(STORM_TEST_RESOURCES_DIR "/mdp/scheduler_generation.nm"); |
|
||||
|
|
||||
// A parser that we use for conveniently constructing the formulas.
|
|
||||
storm::parser::FormulaParser formulaParser; |
|
||||
|
|
||||
storm::generator::NextStateGeneratorOptions options; |
|
||||
options.setBuildAllLabels(); |
|
||||
std::shared_ptr<storm::models::sparse::Model<ValueType>> model = storm::builder::ExplicitModelBuilder<ValueType>(program, options).build(); |
|
||||
EXPECT_EQ(4ull, model->getNumberOfStates()); |
|
||||
EXPECT_EQ(11ull, model->getNumberOfTransitions()); |
|
||||
|
|
||||
ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp); |
|
||||
|
|
||||
std::shared_ptr<storm::models::sparse::Mdp<ValueType>> mdp = model->template as<storm::models::sparse::Mdp<ValueType>>(); |
|
||||
|
|
||||
EXPECT_EQ(7ull, mdp->getNumberOfChoices()); |
|
||||
|
|
||||
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<ValueType>> checker(*mdp); |
|
||||
|
|
||||
std::shared_ptr<storm::logic::Formula const> formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"target\"]"); |
|
||||
|
|
||||
storm::modelchecker::CheckTask<storm::logic::Formula, ValueType> checkTask(*formula); |
|
||||
checkTask.setProduceSchedulers(true); |
|
||||
|
|
||||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(this->env(), checkTask); |
|
||||
|
|
||||
ASSERT_TRUE(result->isExplicitQuantitativeCheckResult()); |
|
||||
ASSERT_TRUE(result->asExplicitQuantitativeCheckResult<ValueType>().hasScheduler()); |
|
||||
storm::storage::Scheduler<ValueType> const& scheduler = result->asExplicitQuantitativeCheckResult<ValueType>().getScheduler(); |
|
||||
EXPECT_EQ(0ull, scheduler.getChoice(0).getDeterministicChoice()); |
|
||||
EXPECT_EQ(1ull, scheduler.getChoice(1).getDeterministicChoice()); |
|
||||
EXPECT_EQ(0ull, scheduler.getChoice(2).getDeterministicChoice()); |
|
||||
EXPECT_EQ(0ull, scheduler.getChoice(3).getDeterministicChoice()); |
|
||||
|
|
||||
formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"target\"]"); |
|
||||
|
|
||||
checkTask = storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>(*formula); |
|
||||
checkTask.setProduceSchedulers(true); |
|
||||
result = checker.check(checkTask); |
|
||||
|
|
||||
ASSERT_TRUE(result->isExplicitQuantitativeCheckResult()); |
|
||||
ASSERT_TRUE(result->asExplicitQuantitativeCheckResult<ValueType>().hasScheduler()); |
|
||||
storm::storage::Scheduler<ValueType> const& scheduler2 = result->asExplicitQuantitativeCheckResult<ValueType>().getScheduler(); |
|
||||
EXPECT_EQ(1ull, scheduler2.getChoice(0).getDeterministicChoice()); |
|
||||
EXPECT_EQ(2ull, scheduler2.getChoice(1).getDeterministicChoice()); |
|
||||
EXPECT_EQ(0ull, scheduler2.getChoice(2).getDeterministicChoice()); |
|
||||
EXPECT_EQ(0ull, scheduler2.getChoice(3).getDeterministicChoice()); |
|
||||
} |
|
||||
} |
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue