|
|
@ -11,6 +11,7 @@ |
|
|
|
#include "storm/storage/geometry/Polytope.h"
|
|
|
|
#include "storm/storage/geometry/Hyperrectangle.h"
|
|
|
|
#include "storm/settings/modules/GeneralSettings.h"
|
|
|
|
#include "storm/settings/modules/MultiObjectiveSettings.h"
|
|
|
|
#include "storm/settings/SettingsManager.h"
|
|
|
|
#include "storm/utility/storm.h"
|
|
|
|
|
|
|
@ -42,7 +43,7 @@ TEST(SparseMaPcaaModelCheckerTest, serverRationalNumbers) { |
|
|
|
std::vector<storm::RationalNumber> q = {q1, q2}; |
|
|
|
auto expectedAchievableValues = storm::storage::geometry::Polytope<storm::RationalNumber>::createDownwardClosure(std::vector<std::vector<storm::RationalNumber>>({p,q})); |
|
|
|
EXPECT_TRUE(expectedAchievableValues->contains(result->asParetoCurveCheckResult<storm::RationalNumber>().getUnderApproximation())); |
|
|
|
EXPECT_TRUE(result->asParetoCurveCheckResult<storm::RationalNumber>().getUnderApproximation()->contains(expectedAchievableValues)); |
|
|
|
EXPECT_TRUE(result->asParetoCurveCheckResult<storm::RationalNumber>().getOverApproximation()->contains(expectedAchievableValues)); |
|
|
|
|
|
|
|
}*/ |
|
|
|
|
|
|
@ -51,32 +52,137 @@ TEST(SparseMaPcaaModelCheckerTest, server) { |
|
|
|
|
|
|
|
std::string programFile = STORM_TEST_RESOURCES_DIR "/ma/server.ma"; |
|
|
|
std::string formulasAsString = "multi(Tmax=? [ F \"error\" ], Pmax=? [ F \"processB\" ]) "; // pareto
|
|
|
|
// formulasAsString += "; \n multi(..)";
|
|
|
|
|
|
|
|
// programm, model, formula
|
|
|
|
|
|
|
|
storm::prism::Program program = storm::parseProgram(programFile); |
|
|
|
program = storm::utility::prism::preprocess(program, ""); |
|
|
|
std::vector<std::shared_ptr<storm::logic::Formula const>> formulas = storm::parseFormulasForPrismProgram(formulasAsString, program); |
|
|
|
std::shared_ptr<storm::models::sparse::MarkovAutomaton<double>> ma = storm::buildSparseModel<double>(program, formulas)->as<storm::models::sparse::MarkovAutomaton<double>>(); |
|
|
|
storm::modelchecker::SparseMarkovAutomatonCslModelChecker<storm::models::sparse::MarkovAutomaton<double>> checker(*ma); |
|
|
|
|
|
|
|
std::unique_ptr<storm::modelchecker::CheckResult> result = storm::modelchecker::multiobjective::performPcaa(*ma, formulas[0]->asMultiObjectiveFormula()); |
|
|
|
ASSERT_TRUE(result->isParetoCurveCheckResult()); |
|
|
|
|
|
|
|
// we do our checks with rationals to avoid numerical issues when doing polytope computations...
|
|
|
|
std::vector<double> p = {11.0/6.0, 1.0/2.0}; |
|
|
|
std::vector<double> q = {29.0/18.0, 2.0/3.0}; |
|
|
|
auto expectedAchievableValues = storm::storage::geometry::Polytope<double>::createDownwardClosure(std::vector<std::vector<double>>({p,q})); |
|
|
|
auto expectedAchievableValues = storm::storage::geometry::Polytope<storm::RationalNumber>::createDownwardClosure( |
|
|
|
std::vector<std::vector<storm::RationalNumber>>({storm::utility::vector::convertNumericVector<storm::RationalNumber>(p), |
|
|
|
storm::utility::vector::convertNumericVector<storm::RationalNumber>(q)})); |
|
|
|
// due to precision issues, we enlarge one of the polytopes before checking containement
|
|
|
|
std::vector<double> lb = {-storm::settings::getModule<storm::settings::modules::GeneralSettings>().getPrecision(), -storm::settings::getModule<storm::settings::modules::GeneralSettings>().getPrecision()}; |
|
|
|
std::vector<double> ub = {storm::settings::getModule<storm::settings::modules::GeneralSettings>().getPrecision(), storm::settings::getModule<storm::settings::modules::GeneralSettings>().getPrecision()}; |
|
|
|
auto bloatingBox = storm::storage::geometry::Hyperrectangle<double>(lb,ub).asPolytope(); |
|
|
|
storm::RationalNumber eps = storm::utility::convertNumber<storm::RationalNumber>(storm::settings::getModule<storm::settings::modules::GeneralSettings>().getPrecision()); |
|
|
|
std::vector<storm::RationalNumber> lb(2,-eps), ub(2,eps); |
|
|
|
auto bloatingBox = storm::storage::geometry::Hyperrectangle<storm::RationalNumber>(lb,ub).asPolytope(); |
|
|
|
|
|
|
|
EXPECT_TRUE(expectedAchievableValues->minkowskiSum(bloatingBox)->contains(result->asParetoCurveCheckResult<double>().getUnderApproximation())); |
|
|
|
EXPECT_TRUE(result->asParetoCurveCheckResult<double>().getUnderApproximation()->minkowskiSum(bloatingBox)->contains(expectedAchievableValues)); |
|
|
|
EXPECT_TRUE(expectedAchievableValues->minkowskiSum(bloatingBox)->contains(result->asParetoCurveCheckResult<double>().getUnderApproximation()->convertNumberRepresentation<storm::RationalNumber>())); |
|
|
|
EXPECT_TRUE(result->asParetoCurveCheckResult<double>().getOverApproximation()->convertNumberRepresentation<storm::RationalNumber>()->minkowskiSum(bloatingBox)->contains(expectedAchievableValues)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
TEST(SparseMaPcaaModelCheckerTest, jobscheduler_pareto_3Obj) { |
|
|
|
|
|
|
|
std::string programFile = STORM_TEST_RESOURCES_DIR "/ma/jobscheduler.ma"; |
|
|
|
std::string formulasAsString = "multi(Tmin=? [ F num_finished=3 ], Pmax=? [ F<=0.2 num_finished=2 ], Pmin=? [ F f_j1=1 & f_j3=0 ]) "; |
|
|
|
|
|
|
|
storm::prism::Program program = storm::parseProgram(programFile); |
|
|
|
program = storm::utility::prism::preprocess(program, ""); |
|
|
|
std::vector<std::shared_ptr<storm::logic::Formula const>> formulas = storm::parseFormulasForPrismProgram(formulasAsString, program); |
|
|
|
std::shared_ptr<storm::models::sparse::MarkovAutomaton<double>> ma = storm::buildSparseModel<double>(program, formulas)->as<storm::models::sparse::MarkovAutomaton<double>>(); |
|
|
|
|
|
|
|
std::unique_ptr<storm::modelchecker::CheckResult> result = storm::modelchecker::multiobjective::performPcaa(*ma, formulas[0]->asMultiObjectiveFormula()); |
|
|
|
ASSERT_TRUE(result->isParetoCurveCheckResult()); |
|
|
|
|
|
|
|
std::vector<double> j12 = {1.266666667,0.1617571721,0.5}; |
|
|
|
std::vector<double> j13 = {1.283333333,0.1707737575,0.25}; |
|
|
|
std::vector<double> j23 = {1.333333333,0.1978235137,0.1}; |
|
|
|
|
|
|
|
// we do our checks with rationals to avoid numerical issues when doing polytope computations...
|
|
|
|
auto expectedAchievableValues = storm::storage::geometry::Polytope<storm::RationalNumber>::createDownwardClosure( |
|
|
|
std::vector<std::vector<storm::RationalNumber>>({storm::utility::vector::convertNumericVector<storm::RationalNumber>(j12), |
|
|
|
storm::utility::vector::convertNumericVector<storm::RationalNumber>(j13), |
|
|
|
storm::utility::vector::convertNumericVector<storm::RationalNumber>(j23)})); |
|
|
|
// due to precision issues, we enlarge one of the polytopes before checking containement
|
|
|
|
storm::RationalNumber eps = storm::utility::convertNumber<storm::RationalNumber>(storm::settings::getModule<storm::settings::modules::GeneralSettings>().getPrecision()); |
|
|
|
std::vector<storm::RationalNumber> lb(3,-eps), ub(3,eps); |
|
|
|
auto bloatingBox = storm::storage::geometry::Hyperrectangle<storm::RationalNumber>(lb,ub).asPolytope(); |
|
|
|
|
|
|
|
EXPECT_TRUE(expectedAchievableValues->minkowskiSum(bloatingBox)->contains(result->asParetoCurveCheckResult<double>().getUnderApproximation()->convertNumberRepresentation<storm::RationalNumber>())); |
|
|
|
EXPECT_TRUE(result->asParetoCurveCheckResult<double>().getOverApproximation()->convertNumberRepresentation<storm::RationalNumber>()->minkowskiSum(bloatingBox)->contains(expectedAchievableValues)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
TEST(SparseMaPcaaModelCheckerTest, jobscheduler_achievability_3Obj) { |
|
|
|
|
|
|
|
std::string programFile = STORM_TEST_RESOURCES_DIR "/ma/jobscheduler.ma"; |
|
|
|
std::string formulasAsString = "multi(T<=1.31 [ F num_finished=3 ], P>=0.17 [ F<=0.2 num_finished=2 ], P<=0.31 [ F f_j1=1 & f_j3=0 ]) "; //true
|
|
|
|
formulasAsString += "; multi(T<=1.29 [ F num_finished=3 ], P>=0.18 [ F<=0.2 num_finished=2 ], P<=0.29 [ F f_j1=1 & f_j3=0 ])"; //false
|
|
|
|
|
|
|
|
storm::prism::Program program = storm::parseProgram(programFile); |
|
|
|
program = storm::utility::prism::preprocess(program, ""); |
|
|
|
std::vector<std::shared_ptr<storm::logic::Formula const>> formulas = storm::parseFormulasForPrismProgram(formulasAsString, program); |
|
|
|
std::shared_ptr<storm::models::sparse::MarkovAutomaton<double>> ma = storm::buildSparseModel<double>(program, formulas)->as<storm::models::sparse::MarkovAutomaton<double>>(); |
|
|
|
uint_fast64_t const initState = *ma->getInitialStates().begin(); |
|
|
|
|
|
|
|
std::unique_ptr<storm::modelchecker::CheckResult> result = storm::modelchecker::multiobjective::performPcaa(*ma, formulas[0]->asMultiObjectiveFormula()); |
|
|
|
ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); |
|
|
|
EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); |
|
|
|
|
|
|
|
std::unique_ptr<storm::modelchecker::CheckResult> result2 = storm::modelchecker::multiobjective::performPcaa(*ma, formulas[1]->asMultiObjectiveFormula()); |
|
|
|
ASSERT_TRUE(result2->isExplicitQualitativeCheckResult()); |
|
|
|
EXPECT_FALSE(result2->asExplicitQualitativeCheckResult()[initState]); |
|
|
|
} |
|
|
|
|
|
|
|
TEST(SparseMaPcaaModelCheckerTest, jobscheduler_quantitative_3Obj) { |
|
|
|
|
|
|
|
std::string programFile = STORM_TEST_RESOURCES_DIR "/ma/jobscheduler.ma"; |
|
|
|
std::string formulasAsString = "multi(Tmin=? [ F num_finished=3 ], P>=0.1797900683 [ F<=0.2 num_finished=2 ], P<=0.3 [ F f_j1=1 & f_j3=0 ]) "; //quantitative
|
|
|
|
formulasAsString += "; multi(T<=1.26 [ F num_finished=3 ], P>=0.2 [ F<=0.2 num_finished=2 ], Pmin=? [ F f_j1=1 & f_j3=0 ])"; //false
|
|
|
|
|
|
|
|
storm::prism::Program program = storm::parseProgram(programFile); |
|
|
|
program = storm::utility::prism::preprocess(program, ""); |
|
|
|
std::vector<std::shared_ptr<storm::logic::Formula const>> formulas = storm::parseFormulasForPrismProgram(formulasAsString, program); |
|
|
|
std::shared_ptr<storm::models::sparse::MarkovAutomaton<double>> ma = storm::buildSparseModel<double>(program, formulas)->as<storm::models::sparse::MarkovAutomaton<double>>(); |
|
|
|
uint_fast64_t const initState = *ma->getInitialStates().begin(); |
|
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<storm::modelchecker::CheckResult> result = storm::modelchecker::multiobjective::performPcaa(*ma, formulas[0]->asMultiObjectiveFormula()); |
|
|
|
ASSERT_TRUE(result->isExplicitQuantitativeCheckResult()); |
|
|
|
EXPECT_NEAR(1.3, result->asExplicitQuantitativeCheckResult<double>()[initState], storm::settings::getModule<storm::settings::modules::MultiObjectiveSettings>().getPrecision()); |
|
|
|
|
|
|
|
std::unique_ptr<storm::modelchecker::CheckResult> result2 = storm::modelchecker::multiobjective::performPcaa(*ma, formulas[1]->asMultiObjectiveFormula()); |
|
|
|
ASSERT_TRUE(result2->isExplicitQualitativeCheckResult()); |
|
|
|
EXPECT_FALSE(result2->asExplicitQualitativeCheckResult()[initState]); |
|
|
|
} |
|
|
|
|
|
|
|
TEST(SparseMaPcaaModelCheckerTest, jobscheduler_pareto_2Obj) { |
|
|
|
|
|
|
|
std::string programFile = STORM_TEST_RESOURCES_DIR "/ma/jobscheduler.ma"; |
|
|
|
std::string formulasAsString = "multi( Pmax=? [ F<=0.1 num_finished=1], Pmin=? [F<=0.2 num_finished=3]) "; |
|
|
|
|
|
|
|
storm::prism::Program program = storm::parseProgram(programFile); |
|
|
|
program = storm::utility::prism::preprocess(program, ""); |
|
|
|
std::vector<std::shared_ptr<storm::logic::Formula const>> formulas = storm::parseFormulasForPrismProgram(formulasAsString, program); |
|
|
|
std::shared_ptr<storm::models::sparse::MarkovAutomaton<double>> ma = storm::buildSparseModel<double>(program, formulas)->as<storm::models::sparse::MarkovAutomaton<double>>(); |
|
|
|
|
|
|
|
std::unique_ptr<storm::modelchecker::CheckResult> result = storm::modelchecker::multiobjective::performPcaa(*ma, formulas[0]->asMultiObjectiveFormula()); |
|
|
|
ASSERT_TRUE(result->isParetoCurveCheckResult()); |
|
|
|
|
|
|
|
std::vector<double> j12 = {0.2591835573, 0.01990529674}; |
|
|
|
std::vector<double> j13 = {0.329682099, 0.01970194998}; |
|
|
|
std::vector<double> j23 = {0.3934717664, 0.01948095743}; |
|
|
|
|
|
|
|
// we do our checks with rationals to avoid numerical issues when doing polytope computations...
|
|
|
|
auto expectedAchievableValues = storm::storage::geometry::Polytope<storm::RationalNumber>::createDownwardClosure( |
|
|
|
std::vector<std::vector<storm::RationalNumber>>({storm::utility::vector::convertNumericVector<storm::RationalNumber>(j12), |
|
|
|
storm::utility::vector::convertNumericVector<storm::RationalNumber>(j13), |
|
|
|
storm::utility::vector::convertNumericVector<storm::RationalNumber>(j23)})); |
|
|
|
// due to precision issues, we enlarge one of the polytopes before checking containement
|
|
|
|
storm::RationalNumber eps = storm::utility::convertNumber<storm::RationalNumber>(storm::settings::getModule<storm::settings::modules::GeneralSettings>().getPrecision()); |
|
|
|
std::vector<storm::RationalNumber> lb(2,-eps), ub(2,eps); |
|
|
|
auto bloatingBox = storm::storage::geometry::Hyperrectangle<storm::RationalNumber>(lb,ub).asPolytope(); |
|
|
|
|
|
|
|
EXPECT_TRUE(expectedAchievableValues->minkowskiSum(bloatingBox)->contains(result->asParetoCurveCheckResult<double>().getUnderApproximation()->convertNumberRepresentation<storm::RationalNumber>())); |
|
|
|
EXPECT_TRUE(result->asParetoCurveCheckResult<double>().getOverApproximation()->convertNumberRepresentation<storm::RationalNumber>()->minkowskiSum(bloatingBox)->contains(expectedAchievableValues)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#endif /* STORM_HAVE_HYPRO */
|