From 9e9767ceeb8e982e77ad1b16adbd822412caf816 Mon Sep 17 00:00:00 2001 From: Thomas Knoll Date: Fri, 4 Aug 2023 10:24:44 +0200 Subject: [PATCH 01/40] changed shield export handling --- resources/3rdparty/cudd-3.0.0/config.h.in | 10 ++++++---- src/storm-cli-utilities/model-handling.h | 9 +++++++++ src/storm/api/export.h | 9 +++++++++ .../prctl/SparseMdpPrctlModelChecker.cpp | 2 ++ .../prctl/SparseMdpPrctlModelChecker.h | 2 +- .../modelchecker/results/CheckResult.cpp | 4 ++++ src/storm/modelchecker/results/CheckResult.h | 1 + .../ExplicitQuantitativeCheckResult.cpp | 16 +++++++++++++++ src/storm/shields/AbstractShield.cpp | 10 ++++++++++ src/storm/shields/AbstractShield.h | 3 +++ src/storm/shields/OptimalShield.cpp | 1 + src/storm/shields/PostShield.cpp | 1 + src/storm/shields/PreShield.cpp | 1 + src/storm/shields/ShieldHandling.cpp | 20 ++++++++++++++++++- src/storm/shields/ShieldHandling.h | 3 +++ 15 files changed, 86 insertions(+), 6 deletions(-) diff --git a/resources/3rdparty/cudd-3.0.0/config.h.in b/resources/3rdparty/cudd-3.0.0/config.h.in index 1bea1dd11..8d78585dd 100644 --- a/resources/3rdparty/cudd-3.0.0/config.h.in +++ b/resources/3rdparty/cudd-3.0.0/config.h.in @@ -33,9 +33,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_MATH_H -/* Define to 1 if you have the header file. */ -#undef HAVE_MEMORY_H - /* Define to 1 if your compiler supports enough C++11 */ #undef HAVE_MODERN_CXX @@ -57,6 +54,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_H + /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H @@ -139,7 +139,9 @@ /* The size of `void *', as computed by sizeof. */ #undef SIZEOF_VOID_P -/* Define to 1 if you have the ANSI C header files. */ +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ #undef STDC_HEADERS /* Define to 1 to use system qsort */ diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h index e41bdf47f..efcad6579 100644 --- a/src/storm-cli-utilities/model-handling.h +++ b/src/storm-cli-utilities/model-handling.h @@ -1043,6 +1043,15 @@ namespace storm { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Scheduler export not supported for this property."); } } + if (result->isExplicitQuantitativeCheckResult()) { + if (result-> template asExplicitQuantitativeCheckResult().hasShield()) { + auto shield = result->template asExplicitQuantitativeCheckResult().getShield(); + STORM_PRINT_AND_LOG("Exporting shield ..."); + + storm::api::exportShield(sparseModel, shield); + } + } + if (ioSettings.isExportCheckResultSet()) { STORM_LOG_WARN_COND(sparseModel->hasStateValuations(), "No information of state valuations available. The result output will use internal state ids. You might be interested in building the model with state valuations using --buildstateval."); STORM_LOG_WARN_COND(exportCount == 0, "Prepending " << exportCount << " to file name for this property because there are multiple properties."); diff --git a/src/storm/api/export.h b/src/storm/api/export.h index 6f4b82f77..078c2fc46 100644 --- a/src/storm/api/export.h +++ b/src/storm/api/export.h @@ -11,6 +11,7 @@ #include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h" #include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h" #include "storm/exceptions/NotSupportedException.h" +#include "storm/shields/AbstractShield.h" namespace storm { @@ -62,6 +63,14 @@ namespace storm { } storm::utility::closeFile(stream); } + + template + void exportShield(std::shared_ptr> const& model, std::shared_ptr> const& shield) { + std::ofstream stream; + storm::utility::openFile(shield->getShieldFileName(), stream); + shield->printToStream(stream, model); + storm::utility::closeFile(stream); + } template inline void exportCheckResultToJson(std::shared_ptr> const& model, std::unique_ptr const& checkResult, std::string const& filename) { diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index 5a96c23ef..d45e592fe 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -135,6 +135,8 @@ namespace storm { std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.maybeStates), storm::storage::BitVector(ret.maybeStates.size(), true)); + auto shield = tempest::shields::createShieldTest(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.maybeStates), storm::storage::BitVector(ret.maybeStates.size(), true)); + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); } else if (checkTask.isProduceSchedulersSet() && ret.scheduler) { result->asExplicitQuantitativeCheckResult().setScheduler(std::move(ret.scheduler)); } diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h index 3feb0802d..cdb87ec75 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h @@ -4,7 +4,7 @@ #include "storm/modelchecker/propositional/SparsePropositionalModelChecker.h" #include "storm/models/sparse/Mdp.h" #include "storm/solver/MinMaxLinearEquationSolver.h" - +#include "storm/shields/AbstractShield.h" namespace storm { diff --git a/src/storm/modelchecker/results/CheckResult.cpp b/src/storm/modelchecker/results/CheckResult.cpp index 26eb24946..28be6339f 100644 --- a/src/storm/modelchecker/results/CheckResult.cpp +++ b/src/storm/modelchecker/results/CheckResult.cpp @@ -166,6 +166,10 @@ namespace storm { bool CheckResult::hasScheduler() const { return false; } + + bool CheckResult::hasShield() const { + return false; + } // Explicitly instantiate the template functions. template QuantitativeCheckResult& CheckResult::asQuantitativeCheckResult(); diff --git a/src/storm/modelchecker/results/CheckResult.h b/src/storm/modelchecker/results/CheckResult.h index 740a8269d..bfb462949 100644 --- a/src/storm/modelchecker/results/CheckResult.h +++ b/src/storm/modelchecker/results/CheckResult.h @@ -113,6 +113,7 @@ namespace storm { SymbolicParetoCurveCheckResult const& asSymbolicParetoCurveCheckResult() const; virtual bool hasScheduler() const; + virtual bool hasShield() const; virtual std::ostream& writeToStream(std::ostream& out) const = 0; }; diff --git a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp index ee7c2d91d..af654b505 100644 --- a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp @@ -204,6 +204,11 @@ namespace storm { bool ExplicitQuantitativeCheckResult::hasScheduler() const { return static_cast(scheduler); } + + template + bool ExplicitQuantitativeCheckResult::hasShield() const { + return static_cast(shield); + } template void ExplicitQuantitativeCheckResult::setScheduler(std::unique_ptr>&& scheduler) { @@ -222,6 +227,17 @@ namespace storm { return *scheduler.get(); } + template + void ExplicitQuantitativeCheckResult::setShield(std::unique_ptr> shield) { + this->shield = std::move(shield); + } + + template + std::shared_ptr::IndexType>> const& ExplicitQuantitativeCheckResult::getShield() const { + STORM_LOG_THROW(this->hasScheduler(), storm::exceptions::InvalidOperationException, "Unable to retrieve non-existing scheduler."); + return shield.get(); + } + template void print(std::ostream& out, ValueType const& value) { if (value == storm::utility::infinity()) { diff --git a/src/storm/shields/AbstractShield.cpp b/src/storm/shields/AbstractShield.cpp index 779f3b894..c81ac2ecc 100644 --- a/src/storm/shields/AbstractShield.cpp +++ b/src/storm/shields/AbstractShield.cpp @@ -34,10 +34,20 @@ namespace tempest { return std::string(boost::core::demangled_name(BOOST_CORE_TYPEID(*this))); } + template + std::string AbstractShield::getShieldFileName() const { + return shieldingExpression->getFilename() + ".shield"; + } + + template + void AbstractShield::printToStream(std::ostream& out, std::shared_ptr> const& model) const { + // construct().printToStream(out, shieldingExpression, model) + } // Explicitly instantiate appropriate template class AbstractShield::index_type>; #ifdef STORM_HAVE_CARL template class AbstractShield::index_type>; + template class AbstractShield::index_type>; #endif } } diff --git a/src/storm/shields/AbstractShield.h b/src/storm/shields/AbstractShield.h index b479efe71..3a0ee4dd4 100644 --- a/src/storm/shields/AbstractShield.h +++ b/src/storm/shields/AbstractShield.h @@ -49,6 +49,9 @@ namespace tempest { storm::OptimizationDirection getOptimizationDirection(); std::string getClassName() const; + std::string getShieldFileName() const; + + void printToStream(std::ostream& out, std::shared_ptr> const& model) const; protected: AbstractShield(std::vector const& rowGroupIndices, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); diff --git a/src/storm/shields/OptimalShield.cpp b/src/storm/shields/OptimalShield.cpp index 8be4b1fef..b1e35a5c1 100644 --- a/src/storm/shields/OptimalShield.cpp +++ b/src/storm/shields/OptimalShield.cpp @@ -68,6 +68,7 @@ namespace tempest { template class OptimalShield::index_type>; #ifdef STORM_HAVE_CARL template class OptimalShield::index_type>; + #endif } } diff --git a/src/storm/shields/PostShield.cpp b/src/storm/shields/PostShield.cpp index 5ef487ad0..63eb452d8 100644 --- a/src/storm/shields/PostShield.cpp +++ b/src/storm/shields/PostShield.cpp @@ -71,6 +71,7 @@ namespace tempest { template class PostShield::index_type>; #ifdef STORM_HAVE_CARL template class PostShield::index_type>; + #endif } } diff --git a/src/storm/shields/PreShield.cpp b/src/storm/shields/PreShield.cpp index a16b777c7..3fad08b82 100644 --- a/src/storm/shields/PreShield.cpp +++ b/src/storm/shields/PreShield.cpp @@ -71,6 +71,7 @@ namespace tempest { template class PreShield::index_type>; #ifdef STORM_HAVE_CARL template class PreShield::index_type>; + #endif } } diff --git a/src/storm/shields/ShieldHandling.cpp b/src/storm/shields/ShieldHandling.cpp index 007959d5d..b3e0bcdcf 100644 --- a/src/storm/shields/ShieldHandling.cpp +++ b/src/storm/shields/ShieldHandling.cpp @@ -22,7 +22,22 @@ namespace tempest { storm::utility::closeFile(stream); } storm::utility::closeFile(stream); - } + } + + template + std::unique_ptr> createShieldTest(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates) { + if(coalitionStates.is_initialized()) coalitionStates.get().complement(); + if(shieldingExpression->isPreSafetyShield()) { + PreShield shield(model->getTransitionMatrix().getRowGroupIndices(), choiceValues, shieldingExpression, optimizationDirection, relevantStates, coalitionStates); + return std::make_unique>(shield); + } else if(shieldingExpression->isPostSafetyShield()) { + PostShield shield(model->getTransitionMatrix().getRowGroupIndices(), choiceValues, shieldingExpression, optimizationDirection, relevantStates, coalitionStates); + return std::make_unique>(shield); + } else { + STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Unknown Shielding Type: " + shieldingExpression->typeToString()); + } + } + template void createQuantitativeShield(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates) { @@ -43,9 +58,12 @@ namespace tempest { } // Explicitly instantiate appropriate template void createShield::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); + template std::unique_ptr::index_type>> createShieldTest::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); template void createQuantitativeShield::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); #ifdef STORM_HAVE_CARL template void createShield::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); + template std::unique_ptr::index_type>> createShieldTest::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); + template void createQuantitativeShield::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); #endif } diff --git a/src/storm/shields/ShieldHandling.h b/src/storm/shields/ShieldHandling.h index 768888a7d..c36d38258 100644 --- a/src/storm/shields/ShieldHandling.h +++ b/src/storm/shields/ShieldHandling.h @@ -26,6 +26,9 @@ namespace tempest { template void createShield(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); + template + std::unique_ptr> createShieldTest(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); + template void createQuantitativeShield(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); } From 021b2036e6fcf45ddb833b6025089873b2a53ccc Mon Sep 17 00:00:00 2001 From: Thomas Knoll Date: Fri, 4 Aug 2023 10:44:13 +0200 Subject: [PATCH 02/40] changed print to stream to be pure virtual --- .../results/ExplicitQuantitativeCheckResult.h | 12 +++++++++++- src/storm/shields/AbstractShield.cpp | 5 +---- src/storm/shields/AbstractShield.h | 2 +- src/storm/shields/OptimalShield.cpp | 8 +++++++- src/storm/shields/OptimalShield.h | 2 ++ src/storm/shields/PostShield.cpp | 10 +++++++++- src/storm/shields/PostShield.h | 3 +++ src/storm/shields/PreShield.cpp | 11 ++++++++++- src/storm/shields/PreShield.h | 3 +++ 9 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h index 4fe38b0f0..5375a7902 100644 --- a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h +++ b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h @@ -14,6 +14,8 @@ #include "storm/utility/OsDetection.h" #include "storm/adapters/JsonAdapter.h" +#include "storm/shields/AbstractShield.h" + namespace storm { namespace modelchecker { // fwd @@ -24,7 +26,8 @@ namespace storm { public: typedef std::vector vector_type; typedef std::map map_type; - + typedef typename storm::storage::SparseMatrix::index_type IndexType; + ExplicitQuantitativeCheckResult(); ExplicitQuantitativeCheckResult(map_type const& values); ExplicitQuantitativeCheckResult(map_type&& values); @@ -74,10 +77,15 @@ namespace storm { virtual ValueType sum() const override; virtual bool hasScheduler() const override; + virtual bool hasShield() const override; + void setScheduler(std::unique_ptr>&& scheduler); storm::storage::Scheduler const& getScheduler() const; storm::storage::Scheduler& getScheduler(); + void setShield(std::unique_ptr> shield); + std::shared_ptr> const& getShield() const; + storm::json toJson(boost::optional const& stateValuations = boost::none) const; private: @@ -86,6 +94,8 @@ namespace storm { // An optional scheduler that accompanies the values. boost::optional>> scheduler; + boost::optional>> shield; + }; } } diff --git a/src/storm/shields/AbstractShield.cpp b/src/storm/shields/AbstractShield.cpp index c81ac2ecc..abb57f57e 100644 --- a/src/storm/shields/AbstractShield.cpp +++ b/src/storm/shields/AbstractShield.cpp @@ -39,10 +39,7 @@ namespace tempest { return shieldingExpression->getFilename() + ".shield"; } - template - void AbstractShield::printToStream(std::ostream& out, std::shared_ptr> const& model) const { - // construct().printToStream(out, shieldingExpression, model) - } + // Explicitly instantiate appropriate template class AbstractShield::index_type>; #ifdef STORM_HAVE_CARL diff --git a/src/storm/shields/AbstractShield.h b/src/storm/shields/AbstractShield.h index 3a0ee4dd4..26c2e1c63 100644 --- a/src/storm/shields/AbstractShield.h +++ b/src/storm/shields/AbstractShield.h @@ -51,7 +51,7 @@ namespace tempest { std::string getClassName() const; std::string getShieldFileName() const; - void printToStream(std::ostream& out, std::shared_ptr> const& model) const; + virtual void printToStream(std::ostream& out, std::shared_ptr> const& model) = 0; protected: AbstractShield(std::vector const& rowGroupIndices, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); diff --git a/src/storm/shields/OptimalShield.cpp b/src/storm/shields/OptimalShield.cpp index b1e35a5c1..d1b5daadb 100644 --- a/src/storm/shields/OptimalShield.cpp +++ b/src/storm/shields/OptimalShield.cpp @@ -64,11 +64,17 @@ namespace tempest { return shield; } + template + void OptimalShield::printToStream(std::ostream& out, std::shared_ptr> const& model) { + this->construct().printToStream(out, this->shieldingExpression, model); + } + // Explicitly instantiate appropriate classes template class OptimalShield::index_type>; #ifdef STORM_HAVE_CARL template class OptimalShield::index_type>; - + // template class OptimalShield::index_type>; + #endif } } diff --git a/src/storm/shields/OptimalShield.h b/src/storm/shields/OptimalShield.h index b7c55712e..bae16d8af 100644 --- a/src/storm/shields/OptimalShield.h +++ b/src/storm/shields/OptimalShield.h @@ -14,6 +14,8 @@ namespace tempest { storm::storage::PostScheduler construct(); template storm::storage::PostScheduler constructWithCompareType(); + virtual void printToStream(std::ostream& out, std::shared_ptr> const& model) override; + private: std::vector choiceValues; }; diff --git a/src/storm/shields/PostShield.cpp b/src/storm/shields/PostShield.cpp index 63eb452d8..150ea94f6 100644 --- a/src/storm/shields/PostShield.cpp +++ b/src/storm/shields/PostShield.cpp @@ -67,11 +67,19 @@ namespace tempest { return shield; } + + template + void PostShield::printToStream(std::ostream& out, std::shared_ptr> const& model) { + this->construct().printToStream(out, this->shieldingExpression, model); + } + + // Explicitly instantiate appropriate classes template class PostShield::index_type>; #ifdef STORM_HAVE_CARL template class PostShield::index_type>; - + // template class PostShield::index_type>; + #endif } } diff --git a/src/storm/shields/PostShield.h b/src/storm/shields/PostShield.h index f2a43905f..85a325f93 100644 --- a/src/storm/shields/PostShield.h +++ b/src/storm/shields/PostShield.h @@ -14,6 +14,9 @@ namespace tempest { storm::storage::PostScheduler construct(); template storm::storage::PostScheduler constructWithCompareType(); + + virtual void printToStream(std::ostream& out, std::shared_ptr> const& model) override; + private: std::vector choiceValues; }; diff --git a/src/storm/shields/PreShield.cpp b/src/storm/shields/PreShield.cpp index 3fad08b82..a4437f3f3 100644 --- a/src/storm/shields/PreShield.cpp +++ b/src/storm/shields/PreShield.cpp @@ -67,11 +67,20 @@ namespace tempest { } return shield; } + + + template + void PreShield::printToStream(std::ostream& out, std::shared_ptr> const& model) { + this->construct().printToStream(out, this->shieldingExpression, model); + } + + // Explicitly instantiate appropriate classes template class PreShield::index_type>; #ifdef STORM_HAVE_CARL template class PreShield::index_type>; - + //template class PreShield::index_type>; + #endif } } diff --git a/src/storm/shields/PreShield.h b/src/storm/shields/PreShield.h index 6e98dd7e8..cdaee54f3 100644 --- a/src/storm/shields/PreShield.h +++ b/src/storm/shields/PreShield.h @@ -14,6 +14,9 @@ namespace tempest { storm::storage::PreScheduler construct(); template storm::storage::PreScheduler constructWithCompareType(); + + virtual void printToStream(std::ostream& out, std::shared_ptr> const& model) override; + private: std::vector choiceValues; }; From 83c3a75ecf14ba658239611139c068f85e52647a Mon Sep 17 00:00:00 2001 From: Thomas Knoll Date: Fri, 4 Aug 2023 10:58:08 +0200 Subject: [PATCH 03/40] added create shield for quantitative shield --- src/storm/shields/ShieldHandling.cpp | 18 ++++++++++++++++++ src/storm/shields/ShieldHandling.h | 4 ++++ 2 files changed, 22 insertions(+) diff --git a/src/storm/shields/ShieldHandling.cpp b/src/storm/shields/ShieldHandling.cpp index b3e0bcdcf..fffe74fe6 100644 --- a/src/storm/shields/ShieldHandling.cpp +++ b/src/storm/shields/ShieldHandling.cpp @@ -56,15 +56,33 @@ namespace tempest { } storm::utility::closeFile(stream); } + + template + std::unique_ptr> createQuantitativeShieldTest(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates) { + if(coalitionStates.is_initialized()) coalitionStates.get().complement(); // TODO CHECK THIS!!! + if(shieldingExpression->isOptimalPreShield()) { + PreShield shield(model->getTransitionMatrix().getRowGroupIndices(), choiceValues, shieldingExpression, optimizationDirection, relevantStates, coalitionStates); + return std::make_unique>(shield); + } else if(shieldingExpression->isOptimalPostShield()) { + PostShield shield(model->getTransitionMatrix().getRowGroupIndices(), choiceValues, shieldingExpression, optimizationDirection, relevantStates, coalitionStates); + return std::make_unique>(shield); + + } else { + STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Unknown Shielding Type: " + shieldingExpression->typeToString()); + } + } + // Explicitly instantiate appropriate template void createShield::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); template std::unique_ptr::index_type>> createShieldTest::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); template void createQuantitativeShield::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); + template std::unique_ptr::index_type>> createQuantitativeShieldTest::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); #ifdef STORM_HAVE_CARL template void createShield::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); template std::unique_ptr::index_type>> createShieldTest::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); template void createQuantitativeShield::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); + template std::unique_ptr::index_type>> createQuantitativeShieldTest::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); #endif } } diff --git a/src/storm/shields/ShieldHandling.h b/src/storm/shields/ShieldHandling.h index c36d38258..86aea2eba 100644 --- a/src/storm/shields/ShieldHandling.h +++ b/src/storm/shields/ShieldHandling.h @@ -31,5 +31,9 @@ namespace tempest { template void createQuantitativeShield(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); + + template + std::unique_ptr> createQuantitativeShieldTest(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); + } } From a38728d683eab1cffe63956cc0592db159effc37 Mon Sep 17 00:00:00 2001 From: Thomas Knoll Date: Fri, 4 Aug 2023 11:14:09 +0200 Subject: [PATCH 04/40] changed rest of create shield function calls --- .../prctl/SparseMdpPrctlModelChecker.cpp | 24 +++++++++++++------ .../rpatl/SparseSmgRpatlModelChecker.cpp | 20 ++++++++++++---- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index d45e592fe..03710502e 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -100,10 +100,13 @@ namespace storm { std::vector choiceValues; numericResult = helper.compute(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), pathFormula.getNonStrictLowerBound(), pathFormula.getNonStrictUpperBound(), resultMaybeStates, choiceValues, checkTask.getHint()); + std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(numericResult))); if(checkTask.isShieldingTask()) { - tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(resultMaybeStates), storm::storage::BitVector(resultMaybeStates.size(), true)); + //tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(resultMaybeStates), storm::storage::BitVector(resultMaybeStates.size(), true)); + auto shield = tempest::shields::createShieldTest(std::make_shared>(this->getModel()), std::move(choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(resultMaybeStates), storm::storage::BitVector(resultMaybeStates.size(), true)); + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); } - return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); + return result; } } @@ -116,7 +119,9 @@ namespace storm { auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeNextProbabilities(env, storm::solver::SolveGoal(this->getModel(), checkTask), checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { - tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.maybeStates), storm::storage::BitVector(ret.maybeStates.size(), true)); + //tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.maybeStates), storm::storage::BitVector(ret.maybeStates.size(), true)); + auto shield = tempest::shields::createShieldTest(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.maybeStates), storm::storage::BitVector(ret.maybeStates.size(), true)); + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); } else if (checkTask.isProduceSchedulersSet() && ret.scheduler) { result->asExplicitQuantitativeCheckResult().setScheduler(std::move(ret.scheduler)); } @@ -134,8 +139,8 @@ namespace storm { auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeUntilProbabilities(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet(), checkTask.getHint()); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { - tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.maybeStates), storm::storage::BitVector(ret.maybeStates.size(), true)); - auto shield = tempest::shields::createShieldTest(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.maybeStates), storm::storage::BitVector(ret.maybeStates.size(), true)); + //tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.maybeStates), storm::storage::BitVector(ret.maybeStates.size(), true)); + auto shield = tempest::shields::createShieldTest(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.maybeStates), storm::storage::BitVector(ret.maybeStates.size(), true)); result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); } else if (checkTask.isProduceSchedulersSet() && ret.scheduler) { result->asExplicitQuantitativeCheckResult().setScheduler(std::move(ret.scheduler)); @@ -152,7 +157,10 @@ namespace storm { auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeGloballyProbabilities(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet()); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { - tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(),subResult.getTruthValuesVector(), storm::storage::BitVector(ret.maybeStates.size(), true)); + //tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(),subResult.getTruthValuesVector(), storm::storage::BitVector(ret.maybeStates.size(), true)); + auto shield = tempest::shields::createShieldTest(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(),subResult.getTruthValuesVector(), storm::storage::BitVector(ret.maybeStates.size(), true)); + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); + } else if (checkTask.isProduceSchedulersSet() && ret.scheduler) { result->asExplicitQuantitativeCheckResult().setScheduler(std::move(ret.scheduler)); } @@ -302,7 +310,9 @@ namespace storm { std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(values))); if(checkTask.isShieldingTask()) { storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); - tempest::shields::createQuantitativeShield(std::make_shared>(this->getModel()), helper.getChoiceValues(), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, allStatesBv); + // tempest::shields::createQuantitativeShield(std::make_shared>(this->getModel()), helper.getChoiceValues(), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, allStatesBv); + auto shield = tempest::shields::createQuantitativeShieldTest(std::make_shared>(this->getModel()), helper.getChoiceValues(), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, allStatesBv); + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); } else if (checkTask.isProduceSchedulersSet()) { result->asExplicitQuantitativeCheckResult().setScheduler(std::make_unique>(helper.extractScheduler())); } diff --git a/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp b/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp index ca7271aa9..0b859ecc1 100644 --- a/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp +++ b/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp @@ -145,7 +145,9 @@ namespace storm { std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); - tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); + // tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); + auto shield = tempest::shields::createShieldTest(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); } else if (checkTask.isProduceSchedulersSet() && ret.scheduler) { result->asExplicitQuantitativeCheckResult().setScheduler(std::move(ret.scheduler)); } @@ -162,7 +164,9 @@ namespace storm { std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); - tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); + // tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); + auto shield = tempest::shields::createShieldTest(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); } else if (checkTask.isProduceSchedulersSet() && ret.scheduler) { result->asExplicitQuantitativeCheckResult().setScheduler(std::move(ret.scheduler)); } @@ -197,7 +201,9 @@ namespace storm { std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); - tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); + // tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); + auto shield = tempest::shields::createShieldTest(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); } return result; } @@ -219,7 +225,9 @@ namespace storm { auto ret = storm::modelchecker::helper::SparseSmgRpatlHelper::computeBoundedUntilProbabilities(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), statesOfCoalition, checkTask.isProduceSchedulersSet(), checkTask.getHint(), pathFormula.getNonStrictLowerBound(), pathFormula.getNonStrictUpperBound()); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { - tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.relevantStates), ~statesOfCoalition); + // tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.relevantStates), ~statesOfCoalition); + auto shield = tempest::shields::createShieldTest(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.relevantStates), ~statesOfCoalition); + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); } return result; } @@ -239,7 +247,9 @@ namespace storm { std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(values))); if(checkTask.isShieldingTask()) { storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); - tempest::shields::createQuantitativeShield(std::make_shared>(this->getModel()), helper.getChoiceValues(), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, statesOfCoalition); + // tempest::shields::createQuantitativeShield(std::make_shared>(this->getModel()), helper.getChoiceValues(), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, statesOfCoalition); + auto shield = tempest::shields::createQuantitativeShieldTest(std::make_shared>(this->getModel()), helper.getChoiceValues(), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, statesOfCoalition); + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); } else if (checkTask.isProduceSchedulersSet()) { result->asExplicitQuantitativeCheckResult().setScheduler(std::make_unique>(helper.extractScheduler())); } From e561545e1a8996fbc63a676a67fe25d6bf32c964 Mon Sep 17 00:00:00 2001 From: Thomas Knoll Date: Mon, 7 Aug 2023 09:46:07 +0200 Subject: [PATCH 05/40] added second get shield --- .../results/ExplicitQuantitativeCheckResult.cpp | 8 +++++++- .../results/ExplicitQuantitativeCheckResult.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp index af654b505..b3c83efb6 100644 --- a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp @@ -234,7 +234,13 @@ namespace storm { template std::shared_ptr::IndexType>> const& ExplicitQuantitativeCheckResult::getShield() const { - STORM_LOG_THROW(this->hasScheduler(), storm::exceptions::InvalidOperationException, "Unable to retrieve non-existing scheduler."); + STORM_LOG_THROW(this->hasShield(), storm::exceptions::InvalidOperationException, "Unable to retrieve non-existing shield."); + return shield.get(); + } + + template + std::shared_ptr::IndexType>>& ExplicitQuantitativeCheckResult::getShield() { + STORM_LOG_THROW(this->hasShield(), storm::exceptions::InvalidOperationException, "Unable to retrieve non-existing shield."); return shield.get(); } diff --git a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h index 5375a7902..d434e10b1 100644 --- a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h +++ b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h @@ -85,6 +85,7 @@ namespace storm { void setShield(std::unique_ptr> shield); std::shared_ptr> const& getShield() const; + std::shared_ptr>& getShield(); storm::json toJson(boost::optional const& stateValuations = boost::none) const; From 256cb82157692196488cf892f101d60c6787a8f4 Mon Sep 17 00:00:00 2001 From: Thomas Knoll Date: Mon, 7 Aug 2023 16:04:02 +0200 Subject: [PATCH 06/40] added functions for querying choice map in shields --- src/storm/storage/PostScheduler.cpp | 6 ++++++ src/storm/storage/PostScheduler.h | 10 ++++++++++ src/storm/storage/PreScheduler.cpp | 8 ++++++++ src/storm/storage/PreScheduler.h | 8 ++++++++ 4 files changed, 32 insertions(+) diff --git a/src/storm/storage/PostScheduler.cpp b/src/storm/storage/PostScheduler.cpp index 11d0a7aed..3131e21c9 100644 --- a/src/storm/storage/PostScheduler.cpp +++ b/src/storm/storage/PostScheduler.cpp @@ -40,6 +40,12 @@ namespace storm { schedulerChoiceMapping[memoryState][modelState] = choice; } + template + PostSchedulerChoice const& PostScheduler::getChoice(uint_fast64_t modelState, uint_fast64_t memoryState) const { + STORM_LOG_ASSERT(modelState < schedulerChoiceMapping[memoryState].size(), "Illegal model state index"); + return schedulerChoiceMapping[memoryState][modelState]; + } + template bool PostScheduler::isDeterministicScheduler() const { return true; diff --git a/src/storm/storage/PostScheduler.h b/src/storm/storage/PostScheduler.h index 99fc3c1b8..44fcb6abd 100644 --- a/src/storm/storage/PostScheduler.h +++ b/src/storm/storage/PostScheduler.h @@ -37,6 +37,15 @@ namespace storm { */ void setChoice(PostSchedulerChoice const& newChoice, uint_fast64_t modelState, uint_fast64_t memoryState = 0); + /*! + * Gets the choice defined by the scheduler for the given model and memory state. + * + * @param state The state for which to get the choice. + * @param memoryState the memory state which we consider. + */ + PostSchedulerChoice const& getChoice(uint_fast64_t modelState, uint_fast64_t memoryState = 0) const; + + /*! * Is the scheduler defined on the states indicated by the selected-states bitvector? */ @@ -97,3 +106,4 @@ namespace storm { }; } } + \ No newline at end of file diff --git a/src/storm/storage/PreScheduler.cpp b/src/storm/storage/PreScheduler.cpp index bb09a81f1..d78400731 100644 --- a/src/storm/storage/PreScheduler.cpp +++ b/src/storm/storage/PreScheduler.cpp @@ -40,6 +40,14 @@ namespace storm { schedulerChoice = choice; } + template + PreSchedulerChoice const& PreScheduler::getChoice(uint_fast64_t modelState, uint_fast64_t memoryState) const { + STORM_LOG_ASSERT(memoryState < getNumberOfMemoryStates(), "Illegal memory state index"); + STORM_LOG_ASSERT(modelState < schedulerChoices[memoryState].size(), "Illegal model state index"); + return schedulerChoices[memoryState][modelState]; + } + + template void PreScheduler::printToStream(std::ostream& out, std::shared_ptr shieldingExpression, std::shared_ptr> model, bool skipUniqueChoices) const { STORM_LOG_THROW(model == nullptr || model->getNumberOfStates() == this->schedulerChoices.front().size(), storm::exceptions::InvalidOperationException, "The given model is not compatible with this scheduler."); diff --git a/src/storm/storage/PreScheduler.h b/src/storm/storage/PreScheduler.h index 5cfa2e8cb..6277c5051 100644 --- a/src/storm/storage/PreScheduler.h +++ b/src/storm/storage/PreScheduler.h @@ -31,6 +31,14 @@ namespace storm { void setChoice(PreSchedulerChoice const& choice, uint_fast64_t modelState, uint_fast64_t memoryState); + /*! + * Gets the choice defined by the scheduler for the given model and memory state. + * + * @param state The state for which to get the choice. + * @param memoryState the memory state which we consider. + */ + PreSchedulerChoice const& getChoice(uint_fast64_t modelState, uint_fast64_t memoryState = 0) const; + /*! * Prints the scheduler to the given output stream. */ From 80eaf7c05ac5a4c42bf22021357a5293f5acb05c Mon Sep 17 00:00:00 2001 From: Thomas Knoll Date: Tue, 8 Aug 2023 09:48:15 +0200 Subject: [PATCH 07/40] refactored shield handling method names --- .../prctl/SparseMdpPrctlModelChecker.cpp | 27 +++++----- .../rpatl/SparseSmgRpatlModelChecker.cpp | 24 ++++----- src/storm/shields/ShieldHandling.cpp | 54 +++---------------- src/storm/shields/ShieldHandling.h | 10 +--- 4 files changed, 33 insertions(+), 82 deletions(-) diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index 03710502e..931b0ef54 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -102,10 +102,10 @@ namespace storm { numericResult = helper.compute(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), pathFormula.getNonStrictLowerBound(), pathFormula.getNonStrictUpperBound(), resultMaybeStates, choiceValues, checkTask.getHint()); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(numericResult))); if(checkTask.isShieldingTask()) { - //tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(resultMaybeStates), storm::storage::BitVector(resultMaybeStates.size(), true)); - auto shield = tempest::shields::createShieldTest(std::make_shared>(this->getModel()), std::move(choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(resultMaybeStates), storm::storage::BitVector(resultMaybeStates.size(), true)); + auto shield = tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(resultMaybeStates), storm::storage::BitVector(resultMaybeStates.size(), true)); result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); } + return result; } } @@ -119,10 +119,10 @@ namespace storm { auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeNextProbabilities(env, storm::solver::SolveGoal(this->getModel(), checkTask), checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { - //tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.maybeStates), storm::storage::BitVector(ret.maybeStates.size(), true)); - auto shield = tempest::shields::createShieldTest(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.maybeStates), storm::storage::BitVector(ret.maybeStates.size(), true)); + auto shield = tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.maybeStates), storm::storage::BitVector(ret.maybeStates.size(), true)); result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); - } else if (checkTask.isProduceSchedulersSet() && ret.scheduler) { + } + if (checkTask.isProduceSchedulersSet() && ret.scheduler) { result->asExplicitQuantitativeCheckResult().setScheduler(std::move(ret.scheduler)); } return result; @@ -137,12 +137,13 @@ namespace storm { ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeUntilProbabilities(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet(), checkTask.getHint()); + STORM_LOG_DEBUG(ret.values); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { - //tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.maybeStates), storm::storage::BitVector(ret.maybeStates.size(), true)); - auto shield = tempest::shields::createShieldTest(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.maybeStates), storm::storage::BitVector(ret.maybeStates.size(), true)); + auto shield = tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.maybeStates), storm::storage::BitVector(ret.maybeStates.size(), true)); result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); - } else if (checkTask.isProduceSchedulersSet() && ret.scheduler) { + } + if (checkTask.isProduceSchedulersSet() && ret.scheduler) { result->asExplicitQuantitativeCheckResult().setScheduler(std::move(ret.scheduler)); } return result; @@ -155,13 +156,14 @@ namespace storm { std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeGloballyProbabilities(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet()); + STORM_LOG_DEBUG(ret.values); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { - //tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(),subResult.getTruthValuesVector(), storm::storage::BitVector(ret.maybeStates.size(), true)); - auto shield = tempest::shields::createShieldTest(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(),subResult.getTruthValuesVector(), storm::storage::BitVector(ret.maybeStates.size(), true)); + auto shield = tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(),subResult.getTruthValuesVector(), storm::storage::BitVector(ret.maybeStates.size(), true)); result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); - } else if (checkTask.isProduceSchedulersSet() && ret.scheduler) { + } + if (checkTask.isProduceSchedulersSet() && ret.scheduler) { result->asExplicitQuantitativeCheckResult().setScheduler(std::move(ret.scheduler)); } return result; @@ -310,8 +312,7 @@ namespace storm { std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(values))); if(checkTask.isShieldingTask()) { storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); - // tempest::shields::createQuantitativeShield(std::make_shared>(this->getModel()), helper.getChoiceValues(), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, allStatesBv); - auto shield = tempest::shields::createQuantitativeShieldTest(std::make_shared>(this->getModel()), helper.getChoiceValues(), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, allStatesBv); + auto shield = tempest::shields::createQuantitativeShield(std::make_shared>(this->getModel()), helper.getChoiceValues(), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, allStatesBv); result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); } else if (checkTask.isProduceSchedulersSet()) { result->asExplicitQuantitativeCheckResult().setScheduler(std::make_unique>(helper.extractScheduler())); diff --git a/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp b/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp index 0b859ecc1..53562ef04 100644 --- a/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp +++ b/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp @@ -145,10 +145,10 @@ namespace storm { std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); - // tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); - auto shield = tempest::shields::createShieldTest(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); + auto shield = tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); - } else if (checkTask.isProduceSchedulersSet() && ret.scheduler) { + } + if (checkTask.isProduceSchedulersSet() && ret.scheduler) { result->asExplicitQuantitativeCheckResult().setScheduler(std::move(ret.scheduler)); } return result; @@ -164,10 +164,10 @@ namespace storm { std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); - // tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); - auto shield = tempest::shields::createShieldTest(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); + auto shield = tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); - } else if (checkTask.isProduceSchedulersSet() && ret.scheduler) { + } + if (checkTask.isProduceSchedulersSet() && ret.scheduler) { result->asExplicitQuantitativeCheckResult().setScheduler(std::move(ret.scheduler)); } return result; @@ -201,8 +201,7 @@ namespace storm { std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); - // tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); - auto shield = tempest::shields::createShieldTest(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); + auto shield = tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); } return result; @@ -225,8 +224,7 @@ namespace storm { auto ret = storm::modelchecker::helper::SparseSmgRpatlHelper::computeBoundedUntilProbabilities(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), statesOfCoalition, checkTask.isProduceSchedulersSet(), checkTask.getHint(), pathFormula.getNonStrictLowerBound(), pathFormula.getNonStrictUpperBound()); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { - // tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.relevantStates), ~statesOfCoalition); - auto shield = tempest::shields::createShieldTest(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.relevantStates), ~statesOfCoalition); + auto shield = tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.relevantStates), ~statesOfCoalition); result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); } return result; @@ -247,10 +245,10 @@ namespace storm { std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(values))); if(checkTask.isShieldingTask()) { storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); - // tempest::shields::createQuantitativeShield(std::make_shared>(this->getModel()), helper.getChoiceValues(), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, statesOfCoalition); - auto shield = tempest::shields::createQuantitativeShieldTest(std::make_shared>(this->getModel()), helper.getChoiceValues(), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, statesOfCoalition); + auto shield = tempest::shields::createQuantitativeShield(std::make_shared>(this->getModel()), helper.getChoiceValues(), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, statesOfCoalition); result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); - } else if (checkTask.isProduceSchedulersSet()) { + } + if (checkTask.isProduceSchedulersSet()) { result->asExplicitQuantitativeCheckResult().setScheduler(std::make_unique>(helper.extractScheduler())); } return result; diff --git a/src/storm/shields/ShieldHandling.cpp b/src/storm/shields/ShieldHandling.cpp index fffe74fe6..fc5d48bfc 100644 --- a/src/storm/shields/ShieldHandling.cpp +++ b/src/storm/shields/ShieldHandling.cpp @@ -7,25 +7,7 @@ namespace tempest { } template - void createShield(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates) { - std::ofstream stream; - storm::utility::openFile(shieldFilename(shieldingExpression), stream); - if(coalitionStates.is_initialized()) coalitionStates.get().complement(); - if(shieldingExpression->isPreSafetyShield()) { - PreShield shield(model->getTransitionMatrix().getRowGroupIndices(), choiceValues, shieldingExpression, optimizationDirection, relevantStates, coalitionStates); - shield.construct().printToStream(stream, shieldingExpression, model); - } else if(shieldingExpression->isPostSafetyShield()) { - PostShield shield(model->getTransitionMatrix().getRowGroupIndices(), choiceValues, shieldingExpression, optimizationDirection, relevantStates, coalitionStates); - shield.construct().printToStream(stream, shieldingExpression, model); - } else { - STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Unknown Shielding Type: " + shieldingExpression->typeToString()); - storm::utility::closeFile(stream); - } - storm::utility::closeFile(stream); - } - - template - std::unique_ptr> createShieldTest(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates) { + std::unique_ptr> createShield(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates) { if(coalitionStates.is_initialized()) coalitionStates.get().complement(); if(shieldingExpression->isPreSafetyShield()) { PreShield shield(model->getTransitionMatrix().getRowGroupIndices(), choiceValues, shieldingExpression, optimizationDirection, relevantStates, coalitionStates); @@ -38,27 +20,8 @@ namespace tempest { } } - - template - void createQuantitativeShield(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates) { - std::ofstream stream; - storm::utility::openFile(shieldFilename(shieldingExpression), stream); - if(coalitionStates.is_initialized()) coalitionStates.get().complement(); // TODO CHECK THIS!!! - if(shieldingExpression->isOptimalPreShield()) { - PreShield shield(model->getTransitionMatrix().getRowGroupIndices(), choiceValues, shieldingExpression, optimizationDirection, relevantStates, coalitionStates); - shield.construct().printToStream(stream, shieldingExpression, model); - } else if(shieldingExpression->isOptimalPostShield()) { - PostShield shield(model->getTransitionMatrix().getRowGroupIndices(), choiceValues, shieldingExpression, optimizationDirection, relevantStates, coalitionStates); - shield.construct().printToStream(stream, shieldingExpression, model); - } else { - STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Unknown Shielding Type: " + shieldingExpression->typeToString()); - storm::utility::closeFile(stream); - } - storm::utility::closeFile(stream); - } - template - std::unique_ptr> createQuantitativeShieldTest(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates) { + std::unique_ptr> createQuantitativeShield(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates) { if(coalitionStates.is_initialized()) coalitionStates.get().complement(); // TODO CHECK THIS!!! if(shieldingExpression->isOptimalPreShield()) { PreShield shield(model->getTransitionMatrix().getRowGroupIndices(), choiceValues, shieldingExpression, optimizationDirection, relevantStates, coalitionStates); @@ -73,16 +36,11 @@ namespace tempest { } // Explicitly instantiate appropriate - template void createShield::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); - template std::unique_ptr::index_type>> createShieldTest::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); - template void createQuantitativeShield::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); - template std::unique_ptr::index_type>> createQuantitativeShieldTest::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); + template std::unique_ptr::index_type>> createShield::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); + template std::unique_ptr::index_type>> createQuantitativeShield::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); #ifdef STORM_HAVE_CARL - template void createShield::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); - template std::unique_ptr::index_type>> createShieldTest::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); - - template void createQuantitativeShield::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); - template std::unique_ptr::index_type>> createQuantitativeShieldTest::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); + template std::unique_ptr::index_type>> createShield::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); + template std::unique_ptr::index_type>> createQuantitativeShield::index_type>(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); #endif } } diff --git a/src/storm/shields/ShieldHandling.h b/src/storm/shields/ShieldHandling.h index 86aea2eba..e50d3e860 100644 --- a/src/storm/shields/ShieldHandling.h +++ b/src/storm/shields/ShieldHandling.h @@ -24,16 +24,10 @@ namespace tempest { std::string shieldFilename(std::shared_ptr const& shieldingExpression); template - void createShield(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); + std::unique_ptr> createShield(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); template - std::unique_ptr> createShieldTest(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); - - template - void createQuantitativeShield(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); - - template - std::unique_ptr> createQuantitativeShieldTest(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); + std::unique_ptr> createQuantitativeShield(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); } } From 110b6a3308a116f34fe1ea90275caf1bbc6f116c Mon Sep 17 00:00:00 2001 From: Thomas Knoll Date: Thu, 10 Aug 2023 08:55:03 +0200 Subject: [PATCH 08/40] added print to json for shields added filename to export shield --- src/storm-cli-utilities/model-handling.h | 2 +- src/storm/shields/AbstractShield.h | 2 + src/storm/shields/OptimalShield.cpp | 5 ++ src/storm/shields/OptimalShield.h | 1 + src/storm/shields/PostShield.cpp | 5 ++ src/storm/shields/PostShield.h | 1 + src/storm/shields/PreShield.cpp | 5 ++ src/storm/shields/PreShield.h | 1 + src/storm/storage/PreScheduler.cpp | 78 ++++++++++++++++++++++++ src/storm/storage/PreScheduler.h | 8 ++- 10 files changed, 106 insertions(+), 2 deletions(-) diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h index efcad6579..b932df8f0 100644 --- a/src/storm-cli-utilities/model-handling.h +++ b/src/storm-cli-utilities/model-handling.h @@ -1048,7 +1048,7 @@ namespace storm { auto shield = result->template asExplicitQuantitativeCheckResult().getShield(); STORM_PRINT_AND_LOG("Exporting shield ..."); - storm::api::exportShield(sparseModel, shield); + storm::api::exportShield(sparseModel, shield, shield->getShieldFileName()); } } diff --git a/src/storm/shields/AbstractShield.h b/src/storm/shields/AbstractShield.h index 26c2e1c63..8ca8d9117 100644 --- a/src/storm/shields/AbstractShield.h +++ b/src/storm/shields/AbstractShield.h @@ -52,6 +52,8 @@ namespace tempest { std::string getShieldFileName() const; virtual void printToStream(std::ostream& out, std::shared_ptr> const& model) = 0; + virtual void printJsonToStream(std::ostream& out, std::shared_ptr> const& model) = 0; + protected: AbstractShield(std::vector const& rowGroupIndices, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); diff --git a/src/storm/shields/OptimalShield.cpp b/src/storm/shields/OptimalShield.cpp index d1b5daadb..ff12e1c12 100644 --- a/src/storm/shields/OptimalShield.cpp +++ b/src/storm/shields/OptimalShield.cpp @@ -69,6 +69,11 @@ namespace tempest { this->construct().printToStream(out, this->shieldingExpression, model); } + template + void OptimalShield::printJsonToStream(std::ostream& out, std::shared_ptr> const& model) { + STORM_LOG_THROW(false, storm::exceptions::InvalidOperationException, "not supported yet"); + } + // Explicitly instantiate appropriate classes template class OptimalShield::index_type>; #ifdef STORM_HAVE_CARL diff --git a/src/storm/shields/OptimalShield.h b/src/storm/shields/OptimalShield.h index bae16d8af..0dac50587 100644 --- a/src/storm/shields/OptimalShield.h +++ b/src/storm/shields/OptimalShield.h @@ -15,6 +15,7 @@ namespace tempest { template storm::storage::PostScheduler constructWithCompareType(); virtual void printToStream(std::ostream& out, std::shared_ptr> const& model) override; + virtual void printJsonToStream(std::ostream& out, std::shared_ptr> const& model) override; private: std::vector choiceValues; diff --git a/src/storm/shields/PostShield.cpp b/src/storm/shields/PostShield.cpp index 150ea94f6..b9165b45e 100644 --- a/src/storm/shields/PostShield.cpp +++ b/src/storm/shields/PostShield.cpp @@ -73,6 +73,11 @@ namespace tempest { this->construct().printToStream(out, this->shieldingExpression, model); } + template + void PostShield::printJsonToStream(std::ostream& out, std::shared_ptr> const& model) { + STORM_LOG_THROW(false, storm::exceptions::InvalidOperationException, "not supported yet"); + } + // Explicitly instantiate appropriate classes template class PostShield::index_type>; diff --git a/src/storm/shields/PostShield.h b/src/storm/shields/PostShield.h index 85a325f93..b857a9216 100644 --- a/src/storm/shields/PostShield.h +++ b/src/storm/shields/PostShield.h @@ -16,6 +16,7 @@ namespace tempest { storm::storage::PostScheduler constructWithCompareType(); virtual void printToStream(std::ostream& out, std::shared_ptr> const& model) override; + virtual void printJsonToStream(std::ostream& out, std::shared_ptr> const& model) override; private: std::vector choiceValues; diff --git a/src/storm/shields/PreShield.cpp b/src/storm/shields/PreShield.cpp index a4437f3f3..716d4f8d1 100644 --- a/src/storm/shields/PreShield.cpp +++ b/src/storm/shields/PreShield.cpp @@ -74,6 +74,11 @@ namespace tempest { this->construct().printToStream(out, this->shieldingExpression, model); } + template + void PreShield::printJsonToStream(std::ostream& out, std::shared_ptr> const& model) { + this->construct().printJsonToStream(out, model); + } + // Explicitly instantiate appropriate classes template class PreShield::index_type>; diff --git a/src/storm/shields/PreShield.h b/src/storm/shields/PreShield.h index cdaee54f3..1b5f099b8 100644 --- a/src/storm/shields/PreShield.h +++ b/src/storm/shields/PreShield.h @@ -16,6 +16,7 @@ namespace tempest { storm::storage::PreScheduler constructWithCompareType(); virtual void printToStream(std::ostream& out, std::shared_ptr> const& model) override; + virtual void printJsonToStream(std::ostream& out, std::shared_ptr> const& model) override; private: std::vector choiceValues; diff --git a/src/storm/storage/PreScheduler.cpp b/src/storm/storage/PreScheduler.cpp index d78400731..92069070b 100644 --- a/src/storm/storage/PreScheduler.cpp +++ b/src/storm/storage/PreScheduler.cpp @@ -137,6 +137,84 @@ namespace storm { out << "___________________________________________________________________" << std::endl; } + + + + template + void PreScheduler::printJsonToStream(std::ostream& out, std::shared_ptr> model, bool skipUniqueChoices) const { + STORM_LOG_THROW(model == nullptr || model->getNumberOfStates() == schedulerChoices.front().size(), storm::exceptions::InvalidOperationException, "The given model is not compatible with this scheduler."); + STORM_LOG_WARN_COND(!(skipUniqueChoices && model == nullptr), "Can not skip unique choices if the model is not given."); + storm::json output; + for (uint64_t state = 0; state < schedulerChoices.front().size(); ++state) { + // Check whether the state is skipped + if (skipUniqueChoices && model != nullptr && model->getTransitionMatrix().getRowGroupSize(state) == 1) { + continue; + } + + for (uint_fast64_t memoryState = 0; memoryState < getNumberOfMemoryStates(); ++memoryState) { + storm::json stateChoicesJson; + if (model && model->hasStateValuations()) { + stateChoicesJson["s"] = model->getStateValuations().template toJson(state); + } else { + stateChoicesJson["s"] = state; + } + + if (!isMemorylessScheduler()) { + stateChoicesJson["m"] = memoryState; + } + + auto const &choice = schedulerChoices[memoryState][state]; + storm::json choicesJson; + + for (auto const &choiceProbPair : choice.getChoiceMap()) { + uint64_t globalChoiceIndex = model->getTransitionMatrix().getRowGroupIndices()[state] ;//+ choiceProbPair.first; + storm::json choiceJson; + if (model && model->hasChoiceOrigins() && + model->getChoiceOrigins()->getIdentifier(globalChoiceIndex) != + model->getChoiceOrigins()->getIdentifierForChoicesWithNoOrigin()) { + choiceJson["origin"] = model->getChoiceOrigins()->getChoiceAsJson(globalChoiceIndex); + } + if (model && model->hasChoiceLabeling()) { + auto choiceLabels = model->getChoiceLabeling().getLabelsOfChoice(globalChoiceIndex); + choiceJson["labels"] = std::vector(choiceLabels.begin(), + choiceLabels.end()); + } + choiceJson["index"] = globalChoiceIndex; + choiceJson["prob"] = storm::utility::convertNumber( + std::get<1>(choiceProbPair)); + + // Memory updates + if(!isMemorylessScheduler()) { + choiceJson["memory-updates"] = std::vector>(); + uint64_t row = model->getTransitionMatrix().getRowGroupIndices()[state]; //+ std::get<0>(choiceProbPair); + for (auto entryIt = model->getTransitionMatrix().getRow(row).begin(); entryIt < model->getTransitionMatrix().getRow(row).end(); ++entryIt) { + storm::json updateJson; + // next model state + if (model && model->hasStateValuations()) { + updateJson["s'"] = model->getStateValuations().template toJson(entryIt->getColumn()); + } else { + updateJson["s'"] = entryIt->getColumn(); + } + // next memory state + updateJson["m'"] = this->memoryStructure->getSuccessorMemoryState(memoryState, entryIt - model->getTransitionMatrix().begin()); + choiceJson["memory-updates"].push_back(std::move(updateJson)); + } + } + + choicesJson.push_back(std::move(choiceJson)); + } + if (!choicesJson.is_null()) { + stateChoicesJson["c"] = std::move(choicesJson); + output.push_back(std::move(stateChoicesJson)); + } + } + } + out << output.dump(4); + } + + + + template class PreScheduler; #ifdef STORM_HAVE_CARL template class PreScheduler; diff --git a/src/storm/storage/PreScheduler.h b/src/storm/storage/PreScheduler.h index 6277c5051..e695e0732 100644 --- a/src/storm/storage/PreScheduler.h +++ b/src/storm/storage/PreScheduler.h @@ -40,10 +40,16 @@ namespace storm { PreSchedulerChoice const& getChoice(uint_fast64_t modelState, uint_fast64_t memoryState = 0) const; /*! - * Prints the scheduler to the given output stream. + * Prints the pre scheduler to the given output stream. */ void printToStream(std::ostream& out, std::shared_ptr shieldingExpression, std::shared_ptr> model = nullptr, bool skipUniqueChoices = false) const; + /*! + * Prints the pre scheduler in json format to the given output stream. + */ + void printJsonToStream(std::ostream& out, std::shared_ptr> model = nullptr, bool skipUniqueChoices = false) const; + + private: boost::optional memoryStructure; std::vector>> schedulerChoices; From e001d8dbcb281609c66f4760b32cf83da1d0b89d Mon Sep 17 00:00:00 2001 From: Thomas Knoll Date: Thu, 10 Aug 2023 12:51:02 +0200 Subject: [PATCH 09/40] changed json export in pre scheduler --- src/storm/api/export.h | 11 +++-- src/storm/shields/OptimalShield.cpp | 2 +- src/storm/shields/PostShield.cpp | 2 +- src/storm/storage/PostScheduler.cpp | 73 +++++++++++++++++++++++++++++ src/storm/storage/PostScheduler.h | 8 ++++ src/storm/storage/PreScheduler.cpp | 8 ++-- 6 files changed, 95 insertions(+), 9 deletions(-) diff --git a/src/storm/api/export.h b/src/storm/api/export.h index 078c2fc46..452e957d2 100644 --- a/src/storm/api/export.h +++ b/src/storm/api/export.h @@ -65,10 +65,15 @@ namespace storm { } template - void exportShield(std::shared_ptr> const& model, std::shared_ptr> const& shield) { + void exportShield(std::shared_ptr> const& model, std::shared_ptr> const& shield, std::string const& filename) { std::ofstream stream; - storm::utility::openFile(shield->getShieldFileName(), stream); - shield->printToStream(stream, model); + storm::utility::openFile(filename, stream); + std::string jsonFileExtension = ".json"; + if (filename.size() > 4 && std::equal(jsonFileExtension.rbegin(), jsonFileExtension.rend(), filename.rbegin())) { + shield->printJsonToStream(stream, model); + } else { + shield->printToStream(stream, model); + } storm::utility::closeFile(stream); } diff --git a/src/storm/shields/OptimalShield.cpp b/src/storm/shields/OptimalShield.cpp index ff12e1c12..6d03e77da 100644 --- a/src/storm/shields/OptimalShield.cpp +++ b/src/storm/shields/OptimalShield.cpp @@ -71,7 +71,7 @@ namespace tempest { template void OptimalShield::printJsonToStream(std::ostream& out, std::shared_ptr> const& model) { - STORM_LOG_THROW(false, storm::exceptions::InvalidOperationException, "not supported yet"); + this->construct().printJsonToStream(out, model); } // Explicitly instantiate appropriate classes diff --git a/src/storm/shields/PostShield.cpp b/src/storm/shields/PostShield.cpp index b9165b45e..6dffd5344 100644 --- a/src/storm/shields/PostShield.cpp +++ b/src/storm/shields/PostShield.cpp @@ -75,7 +75,7 @@ namespace tempest { template void PostShield::printJsonToStream(std::ostream& out, std::shared_ptr> const& model) { - STORM_LOG_THROW(false, storm::exceptions::InvalidOperationException, "not supported yet"); + this->construct().printJsonToStream(out, model); } diff --git a/src/storm/storage/PostScheduler.cpp b/src/storm/storage/PostScheduler.cpp index 3131e21c9..35873ea31 100644 --- a/src/storm/storage/PostScheduler.cpp +++ b/src/storm/storage/PostScheduler.cpp @@ -128,6 +128,79 @@ namespace storm { out << "___________________________________________________________________" << std::endl; } + template + void PostScheduler::printJsonToStream(std::ostream& out, std::shared_ptr> model, bool skipUniqueChoices) const { + // STORM_LOG_THROW(model == nullptr || model->getNumberOfStates() == schedulerChoices.front().size(), storm::exceptions::InvalidOperationException, "The given model is not compatible with this scheduler."); + // STORM_LOG_WARN_COND(!(skipUniqueChoices && model == nullptr), "Can not skip unique choices if the model is not given."); + // storm::json output; + // for (uint64_t state = 0; state < schedulerChoices.front().size(); ++state) { + // // Check whether the state is skipped + // if (skipUniqueChoices && model != nullptr && model->getTransitionMatrix().getRowGroupSize(state) == 1) { + // continue; + // } + + // for (uint_fast64_t memoryState = 0; memoryState < getNumberOfMemoryStates(); ++memoryState) { + // storm::json stateChoicesJson; + // if (model && model->hasStateValuations()) { + // stateChoicesJson["s"] = model->getStateValuations().template toJson(state); + // } else { + // stateChoicesJson["s"] = state; + // } + + // if (!isMemorylessScheduler()) { + // stateChoicesJson["m"] = memoryState; + // } + + // auto const &choice = schedulerChoices[memoryState][state]; + // storm::json choicesJson; + + // for (auto const &choiceProbPair : choice.getChoiceMap()) { + // uint64_t globalChoiceIndex = model->getTransitionMatrix().getRowGroupIndices()[state] ;//+ choiceProbPair.first; + // storm::json choiceJson; + // if (model && model->hasChoiceOrigins() && + // model->getChoiceOrigins()->getIdentifier(globalChoiceIndex) != + // model->getChoiceOrigins()->getIdentifierForChoicesWithNoOrigin()) { + // choiceJson["origin"] = model->getChoiceOrigins()->getChoiceAsJson(globalChoiceIndex); + // } + // if (model && model->hasChoiceLabeling()) { + // auto choiceLabels = model->getChoiceLabeling().getLabelsOfChoice(globalChoiceIndex); + // choiceJson["labels"] = std::vector(choiceLabels.begin(), + // choiceLabels.end()); + // } + // choiceJson["index"] = globalChoiceIndex; + // choiceJson["prob"] = storm::utility::convertNumber( + // std::get<1>(choiceProbPair)); + + // // Memory updates + // if(!isMemorylessScheduler()) { + // choiceJson["memory-updates"] = std::vector>(); + // uint64_t row = model->getTransitionMatrix().getRowGroupIndices()[state]; //+ std::get<0>(choiceProbPair); + // for (auto entryIt = model->getTransitionMatrix().getRow(row).begin(); entryIt < model->getTransitionMatrix().getRow(row).end(); ++entryIt) { + // storm::json updateJson; + // // next model state + // if (model && model->hasStateValuations()) { + // updateJson["s'"] = model->getStateValuations().template toJson(entryIt->getColumn()); + // } else { + // updateJson["s'"] = entryIt->getColumn(); + // } + // // next memory state + // updateJson["m'"] = this->memoryStructure->getSuccessorMemoryState(memoryState, entryIt - model->getTransitionMatrix().begin()); + // choiceJson["memory-updates"].push_back(std::move(updateJson)); + // } + // } + + // choicesJson.push_back(std::move(choiceJson)); + // } + // if (!choicesJson.is_null()) { + // stateChoicesJson["c"] = std::move(choicesJson); + // output.push_back(std::move(stateChoicesJson)); + // } + // } + // } + // out << output.dump(4); + } + + template class PostScheduler; #ifdef STORM_HAVE_CARL template class PostScheduler; diff --git a/src/storm/storage/PostScheduler.h b/src/storm/storage/PostScheduler.h index 44fcb6abd..c2eaebde2 100644 --- a/src/storm/storage/PostScheduler.h +++ b/src/storm/storage/PostScheduler.h @@ -92,6 +92,14 @@ namespace storm { * Requires a model to be given. */ void printToStream(std::ostream& out, std::shared_ptr shieldingExpression, std::shared_ptr> model = nullptr, bool skipUniqueChoices = false) const; + + /*! + * Prints the pre scheduler in json format to the given output stream. + */ + void printJsonToStream(std::ostream& out, std::shared_ptr> model = nullptr, bool skipUniqueChoices = false) const; + + + private: boost::optional memoryStructure; std::vector>> schedulerChoiceMapping; diff --git a/src/storm/storage/PreScheduler.cpp b/src/storm/storage/PreScheduler.cpp index 92069070b..373b8986e 100644 --- a/src/storm/storage/PreScheduler.cpp +++ b/src/storm/storage/PreScheduler.cpp @@ -167,7 +167,7 @@ namespace storm { storm::json choicesJson; for (auto const &choiceProbPair : choice.getChoiceMap()) { - uint64_t globalChoiceIndex = model->getTransitionMatrix().getRowGroupIndices()[state] ;//+ choiceProbPair.first; + uint64_t globalChoiceIndex = model->getTransitionMatrix().getRowGroupIndices()[state] + std::get(choiceProbPair); storm::json choiceJson; if (model && model->hasChoiceOrigins() && model->getChoiceOrigins()->getIdentifier(globalChoiceIndex) != @@ -181,17 +181,17 @@ namespace storm { } choiceJson["index"] = globalChoiceIndex; choiceJson["prob"] = storm::utility::convertNumber( - std::get<1>(choiceProbPair)); + std::get(choiceProbPair)); // Memory updates if(!isMemorylessScheduler()) { choiceJson["memory-updates"] = std::vector>(); - uint64_t row = model->getTransitionMatrix().getRowGroupIndices()[state]; //+ std::get<0>(choiceProbPair); + uint64_t row = model->getTransitionMatrix().getRowGroupIndices()[state] + std::get(choiceProbPair); for (auto entryIt = model->getTransitionMatrix().getRow(row).begin(); entryIt < model->getTransitionMatrix().getRow(row).end(); ++entryIt) { storm::json updateJson; // next model state if (model && model->hasStateValuations()) { - updateJson["s'"] = model->getStateValuations().template toJson(entryIt->getColumn()); + updateJson["s'"] = model->getStateValuations().template toJson(entryIt->getColumn()); } else { updateJson["s'"] = entryIt->getColumn(); } From de2243b09543efc01bb7f5dff1c390ef986c5b25 Mon Sep 17 00:00:00 2001 From: Thomas Knoll Date: Fri, 11 Aug 2023 09:00:47 +0200 Subject: [PATCH 10/40] addded post scheduler json export removed workaround in pre scheduler json --- src/storm/storage/PostScheduler.cpp | 124 +++++++++++++--------------- src/storm/storage/PreScheduler.cpp | 78 ++++++++--------- 2 files changed, 96 insertions(+), 106 deletions(-) diff --git a/src/storm/storage/PostScheduler.cpp b/src/storm/storage/PostScheduler.cpp index 35873ea31..420b4b4e7 100644 --- a/src/storm/storage/PostScheduler.cpp +++ b/src/storm/storage/PostScheduler.cpp @@ -130,74 +130,62 @@ namespace storm { template void PostScheduler::printJsonToStream(std::ostream& out, std::shared_ptr> model, bool skipUniqueChoices) const { - // STORM_LOG_THROW(model == nullptr || model->getNumberOfStates() == schedulerChoices.front().size(), storm::exceptions::InvalidOperationException, "The given model is not compatible with this scheduler."); - // STORM_LOG_WARN_COND(!(skipUniqueChoices && model == nullptr), "Can not skip unique choices if the model is not given."); - // storm::json output; - // for (uint64_t state = 0; state < schedulerChoices.front().size(); ++state) { - // // Check whether the state is skipped - // if (skipUniqueChoices && model != nullptr && model->getTransitionMatrix().getRowGroupSize(state) == 1) { - // continue; - // } - - // for (uint_fast64_t memoryState = 0; memoryState < getNumberOfMemoryStates(); ++memoryState) { - // storm::json stateChoicesJson; - // if (model && model->hasStateValuations()) { - // stateChoicesJson["s"] = model->getStateValuations().template toJson(state); - // } else { - // stateChoicesJson["s"] = state; - // } - - // if (!isMemorylessScheduler()) { - // stateChoicesJson["m"] = memoryState; - // } - - // auto const &choice = schedulerChoices[memoryState][state]; - // storm::json choicesJson; - - // for (auto const &choiceProbPair : choice.getChoiceMap()) { - // uint64_t globalChoiceIndex = model->getTransitionMatrix().getRowGroupIndices()[state] ;//+ choiceProbPair.first; - // storm::json choiceJson; - // if (model && model->hasChoiceOrigins() && - // model->getChoiceOrigins()->getIdentifier(globalChoiceIndex) != - // model->getChoiceOrigins()->getIdentifierForChoicesWithNoOrigin()) { - // choiceJson["origin"] = model->getChoiceOrigins()->getChoiceAsJson(globalChoiceIndex); - // } - // if (model && model->hasChoiceLabeling()) { - // auto choiceLabels = model->getChoiceLabeling().getLabelsOfChoice(globalChoiceIndex); - // choiceJson["labels"] = std::vector(choiceLabels.begin(), - // choiceLabels.end()); - // } - // choiceJson["index"] = globalChoiceIndex; - // choiceJson["prob"] = storm::utility::convertNumber( - // std::get<1>(choiceProbPair)); - - // // Memory updates - // if(!isMemorylessScheduler()) { - // choiceJson["memory-updates"] = std::vector>(); - // uint64_t row = model->getTransitionMatrix().getRowGroupIndices()[state]; //+ std::get<0>(choiceProbPair); - // for (auto entryIt = model->getTransitionMatrix().getRow(row).begin(); entryIt < model->getTransitionMatrix().getRow(row).end(); ++entryIt) { - // storm::json updateJson; - // // next model state - // if (model && model->hasStateValuations()) { - // updateJson["s'"] = model->getStateValuations().template toJson(entryIt->getColumn()); - // } else { - // updateJson["s'"] = entryIt->getColumn(); - // } - // // next memory state - // updateJson["m'"] = this->memoryStructure->getSuccessorMemoryState(memoryState, entryIt - model->getTransitionMatrix().begin()); - // choiceJson["memory-updates"].push_back(std::move(updateJson)); - // } - // } - - // choicesJson.push_back(std::move(choiceJson)); - // } - // if (!choicesJson.is_null()) { - // stateChoicesJson["c"] = std::move(choicesJson); - // output.push_back(std::move(stateChoicesJson)); - // } - // } - // } - // out << output.dump(4); + STORM_LOG_THROW(model == nullptr || model->getNumberOfStates() == schedulerChoiceMapping.front().size(), storm::exceptions::InvalidOperationException, "The given model is not compatible with this scheduler."); + STORM_LOG_WARN_COND(!(skipUniqueChoices && model == nullptr), "Can not skip unique choices if the model is not given."); + storm::json output; + for (uint64_t state = 0; state < schedulerChoiceMapping.front().size(); ++state) { + // Check whether the state is skipped + if (skipUniqueChoices && model != nullptr && model->getTransitionMatrix().getRowGroupSize(state) == 1) { + continue; + } + + storm::json stateChoicesJson; + if (model && model->hasStateValuations()) { + stateChoicesJson["s"] = model->getStateValuations().template toJson(state); + } else { + stateChoicesJson["s"] = state; + } + + auto const &choice = schedulerChoiceMapping[0][state]; + storm::json choicesJson; + if (!choice.getChoiceMap().empty()) { + for (auto const &choiceProbPair : choice.getChoiceMap()) { + uint64_t globalChoiceIndex = model->getTransitionMatrix().getRowGroupIndices()[state] + std::get<0>(choiceProbPair); + uint64_t globalChoiceCorrectionIndex = model->getTransitionMatrix().getRowGroupIndices()[state] + std::get<1>(choiceProbPair); + storm::json choiceJson; + if (model && model->hasChoiceOrigins() && + model->getChoiceOrigins()->getIdentifier(globalChoiceIndex) != + model->getChoiceOrigins()->getIdentifierForChoicesWithNoOrigin()) { + auto choiceOriginJson = model->getChoiceOrigins()->getChoiceAsJson(globalChoiceIndex); + auto choiceOriginCorrectionJson = model->getChoiceOrigins()->getChoiceAsJson(globalChoiceCorrectionIndex); + std::string choiceActionLabel = choiceOriginJson["action-label"]; + std::string choiceCorrectionActionLabel = choiceOriginCorrectionJson["action-label"]; + choiceOriginJson["action-label"] = choiceActionLabel.append(": ").append(choiceCorrectionActionLabel); + choiceJson["origin"] = choiceOriginJson; + } + if (model && model->hasChoiceLabeling()) { + auto choiceLabels = model->getChoiceLabeling().getLabelsOfChoice(globalChoiceIndex); + + choiceJson["labels"] = std::vector(choiceLabels.begin(), + choiceLabels.end()); + } + choiceJson["index"] = globalChoiceIndex; + choiceJson["prob"] = storm::utility::convertNumber( + std::get<1>(choiceProbPair)); + + + choicesJson.push_back(std::move(choiceJson)); + } + } else { + choicesJson = "undefined"; + } + + stateChoicesJson["c"] = std::move(choicesJson); + output.push_back(std::move(stateChoicesJson)); + + } + + out << output.dump(4); } diff --git a/src/storm/storage/PreScheduler.cpp b/src/storm/storage/PreScheduler.cpp index 373b8986e..bc3e6e833 100644 --- a/src/storm/storage/PreScheduler.cpp +++ b/src/storm/storage/PreScheduler.cpp @@ -165,48 +165,50 @@ namespace storm { auto const &choice = schedulerChoices[memoryState][state]; storm::json choicesJson; - - for (auto const &choiceProbPair : choice.getChoiceMap()) { - uint64_t globalChoiceIndex = model->getTransitionMatrix().getRowGroupIndices()[state] + std::get(choiceProbPair); - storm::json choiceJson; - if (model && model->hasChoiceOrigins() && - model->getChoiceOrigins()->getIdentifier(globalChoiceIndex) != - model->getChoiceOrigins()->getIdentifierForChoicesWithNoOrigin()) { - choiceJson["origin"] = model->getChoiceOrigins()->getChoiceAsJson(globalChoiceIndex); - } - if (model && model->hasChoiceLabeling()) { - auto choiceLabels = model->getChoiceLabeling().getLabelsOfChoice(globalChoiceIndex); - choiceJson["labels"] = std::vector(choiceLabels.begin(), - choiceLabels.end()); - } - choiceJson["index"] = globalChoiceIndex; - choiceJson["prob"] = storm::utility::convertNumber( - std::get(choiceProbPair)); - - // Memory updates - if(!isMemorylessScheduler()) { - choiceJson["memory-updates"] = std::vector>(); - uint64_t row = model->getTransitionMatrix().getRowGroupIndices()[state] + std::get(choiceProbPair); - for (auto entryIt = model->getTransitionMatrix().getRow(row).begin(); entryIt < model->getTransitionMatrix().getRow(row).end(); ++entryIt) { - storm::json updateJson; - // next model state - if (model && model->hasStateValuations()) { - updateJson["s'"] = model->getStateValuations().template toJson(entryIt->getColumn()); - } else { - updateJson["s'"] = entryIt->getColumn(); + if (!choice.getChoiceMap().empty()) { + for (auto const &choiceProbPair : choice.getChoiceMap()) { + uint64_t globalChoiceIndex = model->getTransitionMatrix().getRowGroupIndices()[state] + std::get(choiceProbPair); + storm::json choiceJson; + if (model && model->hasChoiceOrigins() && + model->getChoiceOrigins()->getIdentifier(globalChoiceIndex) != + model->getChoiceOrigins()->getIdentifierForChoicesWithNoOrigin()) { + choiceJson["origin"] = model->getChoiceOrigins()->getChoiceAsJson(globalChoiceIndex); + } + if (model && model->hasChoiceLabeling()) { + auto choiceLabels = model->getChoiceLabeling().getLabelsOfChoice(globalChoiceIndex); + choiceJson["labels"] = std::vector(choiceLabels.begin(), + choiceLabels.end()); + } + choiceJson["index"] = globalChoiceIndex; + choiceJson["prob"] = storm::utility::convertNumber( + std::get(choiceProbPair)); + + // Memory updates + if(!isMemorylessScheduler()) { + choiceJson["memory-updates"] = std::vector>(); + uint64_t row = model->getTransitionMatrix().getRowGroupIndices()[state] + std::get(choiceProbPair); + for (auto entryIt = model->getTransitionMatrix().getRow(row).begin(); entryIt < model->getTransitionMatrix().getRow(row).end(); ++entryIt) { + storm::json updateJson; + // next model state + if (model && model->hasStateValuations()) { + updateJson["s'"] = model->getStateValuations().template toJson(entryIt->getColumn()); + } else { + updateJson["s'"] = entryIt->getColumn(); + } + // next memory state + updateJson["m'"] = this->memoryStructure->getSuccessorMemoryState(memoryState, entryIt - model->getTransitionMatrix().begin()); + choiceJson["memory-updates"].push_back(std::move(updateJson)); } - // next memory state - updateJson["m'"] = this->memoryStructure->getSuccessorMemoryState(memoryState, entryIt - model->getTransitionMatrix().begin()); - choiceJson["memory-updates"].push_back(std::move(updateJson)); } - } - choicesJson.push_back(std::move(choiceJson)); - } - if (!choicesJson.is_null()) { - stateChoicesJson["c"] = std::move(choicesJson); - output.push_back(std::move(stateChoicesJson)); + choicesJson.push_back(std::move(choiceJson)); + } + } else { + choicesJson = "undefined"; } + + stateChoicesJson["c"] = std::move(choicesJson); + output.push_back(std::move(stateChoicesJson)); } } out << output.dump(4); From f4ad399b327fb3d458b72be1bab32448ced26d88 Mon Sep 17 00:00:00 2001 From: Thomas Knoll Date: Fri, 11 Aug 2023 13:08:13 +0200 Subject: [PATCH 11/40] added export shield iosetting --- src/storm-cli-utilities/model-handling.h | 15 +++++++++------ src/storm/settings/modules/IOSettings.cpp | 10 ++++++++++ src/storm/settings/modules/IOSettings.h | 11 +++++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h index b932df8f0..c90852df5 100644 --- a/src/storm-cli-utilities/model-handling.h +++ b/src/storm-cli-utilities/model-handling.h @@ -1043,14 +1043,17 @@ namespace storm { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Scheduler export not supported for this property."); } } - if (result->isExplicitQuantitativeCheckResult()) { - if (result-> template asExplicitQuantitativeCheckResult().hasShield()) { - auto shield = result->template asExplicitQuantitativeCheckResult().getShield(); - STORM_PRINT_AND_LOG("Exporting shield ..."); - - storm::api::exportShield(sparseModel, shield, shield->getShieldFileName()); + if (ioSettings.isExportShieldSet()) { + if (result->isExplicitQuantitativeCheckResult()) { + if (result-> template asExplicitQuantitativeCheckResult().hasShield()) { + auto shield = result->template asExplicitQuantitativeCheckResult().getShield(); + STORM_PRINT_AND_LOG("Exporting shield ... "); + + storm::api::exportShield(sparseModel, shield, ioSettings.getExportShieldFilename()); + } } } + if (ioSettings.isExportCheckResultSet()) { STORM_LOG_WARN_COND(sparseModel->hasStateValuations(), "No information of state valuations available. The result output will use internal state ids. You might be interested in building the model with state valuations using --buildstateval."); diff --git a/src/storm/settings/modules/IOSettings.cpp b/src/storm/settings/modules/IOSettings.cpp index f0af3f4ad..d94c67a8e 100644 --- a/src/storm/settings/modules/IOSettings.cpp +++ b/src/storm/settings/modules/IOSettings.cpp @@ -25,6 +25,7 @@ namespace storm { const std::string IOSettings::exportCdfOptionName = "exportcdf"; const std::string IOSettings::exportCdfOptionShortName = "cdf"; const std::string IOSettings::exportSchedulerOptionName = "exportscheduler"; + const std::string IOSettings::exportShieldOptionName = "exportshield"; const std::string IOSettings::exportCheckResultOptionName = "exportresult"; const std::string IOSettings::explicitOptionName = "explicit"; const std::string IOSettings::explicitOptionShortName = "exp"; @@ -64,6 +65,7 @@ namespace storm { .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The name of the file to which the model is to be written.").build()).build()); this->addOption(storm::settings::OptionBuilder(moduleName, exportCdfOptionName, false, "Exports the cumulative density function for reward bounded properties into a .csv file.").setIsAdvanced().setShortName(exportCdfOptionShortName).addArgument(storm::settings::ArgumentBuilder::createStringArgument("directory", "A path to an existing directory where the cdf files will be stored.").build()).build()); this->addOption(storm::settings::OptionBuilder(moduleName, exportSchedulerOptionName, false, "Exports the choices of an optimal scheduler to the given file (if supported by engine).").setIsAdvanced().addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The output file. Use file extension '.json' to export in json.").build()).build()); + this->addOption(storm::settings::OptionBuilder(moduleName, exportShieldOptionName, false, "Exports the the generated shield to the given file (if supported by engine).").setIsAdvanced().addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The output file. Use file extension '.json' to export in json.").build()).build()); this->addOption(storm::settings::OptionBuilder(moduleName, exportCheckResultOptionName, false, "Exports the result to a given file (if supported by engine). The export will be in json.").setIsAdvanced().addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The output file.").build()).build()); this->addOption(storm::settings::OptionBuilder(moduleName, exportExplicitOptionName, "", "If given, the loaded model will be written to the specified file in the drn format.") .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "the name of the file to which the model is to be writen.").build()).build()); @@ -178,6 +180,14 @@ namespace storm { return this->getOption(exportSchedulerOptionName).getArgumentByName("filename").getValueAsString(); } + bool IOSettings::isExportShieldSet() const { + return this->getOption(exportShieldOptionName).getHasOptionBeenSet(); + } + + std::string IOSettings::getExportShieldFilename() const { + return this->getOption(exportShieldOptionName).getArgumentByName("filename").getValueAsString(); + } + bool IOSettings::isExportCheckResultSet() const { return this->getOption(exportCheckResultOptionName).getHasOptionBeenSet(); } diff --git a/src/storm/settings/modules/IOSettings.h b/src/storm/settings/modules/IOSettings.h index 3be8c646d..a03ea372e 100644 --- a/src/storm/settings/modules/IOSettings.h +++ b/src/storm/settings/modules/IOSettings.h @@ -106,6 +106,16 @@ namespace storm { */ std::string getExportSchedulerFilename() const; + /*! + * Retrieves whether a shield is to be exported. + */ + bool isExportShieldSet() const; + + /*! + * Retrieves a filename to which a shield will be exported. + */ + std::string getExportShieldFilename() const; + /*! * Retrieves whether the check result should be exported. */ @@ -365,6 +375,7 @@ namespace storm { static const std::string exportCdfOptionName; static const std::string exportCdfOptionShortName; static const std::string exportSchedulerOptionName; + static const std::string exportShieldOptionName; static const std::string exportCheckResultOptionName; static const std::string explicitOptionName; static const std::string explicitOptionShortName; From 3a3dd67232fafc683df561e87000ae0d4754ba46 Mon Sep 17 00:00:00 2001 From: Thomas Knoll Date: Fri, 11 Aug 2023 13:57:37 +0200 Subject: [PATCH 12/40] removed filename form shield classes --- src/storm-parsers/parser/FormulaParserGrammar.cpp | 8 ++++---- src/storm-parsers/parser/FormulaParserGrammar.h | 2 +- src/storm/logic/ShieldExpression.cpp | 10 +++------- src/storm/logic/ShieldExpression.h | 7 ++----- .../modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp | 1 + src/storm/shields/AbstractShield.cpp | 6 ------ src/storm/shields/AbstractShield.h | 3 +-- src/storm/shields/ShieldHandling.cpp | 4 ---- src/storm/shields/ShieldHandling.h | 4 +--- 9 files changed, 13 insertions(+), 32 deletions(-) diff --git a/src/storm-parsers/parser/FormulaParserGrammar.cpp b/src/storm-parsers/parser/FormulaParserGrammar.cpp index 53f3ba6c8..afb21561b 100644 --- a/src/storm-parsers/parser/FormulaParserGrammar.cpp +++ b/src/storm-parsers/parser/FormulaParserGrammar.cpp @@ -180,7 +180,7 @@ namespace storm { constantDefinition.name("constant definition"); // Shielding properties - shieldExpression = (qi::lit("<") > label > qi::lit(",") > shieldingType > -(qi::lit(",") > shieldComparison) > qi::lit(">"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createShieldExpression, phoenix::ref(*this), qi::_2, qi::_1, qi::_3)]; + shieldExpression = (qi::lit("<") > shieldingType > -(qi::lit(",") > shieldComparison) > qi::lit(">"))[qi::_val = phoenix::bind(&FormulaParserGrammar::createShieldExpression, phoenix::ref(*this), qi::_1, qi::_2)]; shieldExpression.name("shield expression"); @@ -645,12 +645,12 @@ namespace storm { return std::make_pair(comparisonType, value); } - std::shared_ptr FormulaParserGrammar::createShieldExpression(storm::logic::ShieldingType type, std::string name, boost::optional> comparisonStruct) { + std::shared_ptr FormulaParserGrammar::createShieldExpression(storm::logic::ShieldingType type, boost::optional> comparisonStruct) { if(comparisonStruct.is_initialized()) { - return std::shared_ptr(new storm::logic::ShieldExpression(type, name, comparisonStruct.get().first, comparisonStruct.get().second)); + return std::shared_ptr(new storm::logic::ShieldExpression(type, comparisonStruct.get().first, comparisonStruct.get().second)); } else { STORM_LOG_INFO("Construction of shield without a comparison parameter (lambda or gamma) will default to 'lambda=0'"); - return std::shared_ptr(new storm::logic::ShieldExpression(type, name)); + return std::shared_ptr(new storm::logic::ShieldExpression(type)); } } diff --git a/src/storm-parsers/parser/FormulaParserGrammar.h b/src/storm-parsers/parser/FormulaParserGrammar.h index 97089658e..c4916ffbb 100644 --- a/src/storm-parsers/parser/FormulaParserGrammar.h +++ b/src/storm-parsers/parser/FormulaParserGrammar.h @@ -249,7 +249,7 @@ namespace storm { std::shared_ptr createGameFormula(storm::logic::PlayerCoalition const& coalition, std::shared_ptr const& subformula) const; std::pair createShieldComparisonStruct(storm::logic::ShieldComparison comparisonType, double value); - std::shared_ptr createShieldExpression(storm::logic::ShieldingType type, std::string name, boost::optional> comparisonStruct); + std::shared_ptr createShieldExpression(storm::logic::ShieldingType type, boost::optional> comparisonStruct); bool areConstantDefinitionsAllowed() const; void addConstant(std::string const& name, ConstantDataType type, boost::optional const& expression); diff --git a/src/storm/logic/ShieldExpression.cpp b/src/storm/logic/ShieldExpression.cpp index 841d1a400..9902f625a 100644 --- a/src/storm/logic/ShieldExpression.cpp +++ b/src/storm/logic/ShieldExpression.cpp @@ -6,11 +6,11 @@ namespace storm { namespace logic { ShieldExpression::ShieldExpression() {} - ShieldExpression::ShieldExpression(ShieldingType type, std::string filename) : type(type), filename(filename) { + ShieldExpression::ShieldExpression(ShieldingType type) : type(type) { //Intentionally left empty } - ShieldExpression::ShieldExpression(ShieldingType type, std::string filename, ShieldComparison comparison, double value) : type(type), filename(filename), comparison(comparison), value(value) { + ShieldExpression::ShieldExpression(ShieldingType type, ShieldComparison comparison, double value) : type(type), comparison(comparison), value(value) { //Intentionally left empty } @@ -74,11 +74,7 @@ namespace storm { prettyString += "-Shield "; prettyString += "with " + comparisonType + " comparison (" + comparisonToString() + " = " + std::to_string(value) + "):"; return prettyString; - } - - std::string ShieldExpression::getFilename() const { - return filename; - } + } std::ostream& operator<<(std::ostream& out, ShieldExpression const& shieldExpression) { out << shieldExpression.toString(); diff --git a/src/storm/logic/ShieldExpression.h b/src/storm/logic/ShieldExpression.h index 808ebddf9..eddf0becb 100644 --- a/src/storm/logic/ShieldExpression.h +++ b/src/storm/logic/ShieldExpression.h @@ -18,8 +18,8 @@ namespace storm { class ShieldExpression { public: ShieldExpression(); - ShieldExpression(ShieldingType type, std::string filename); - ShieldExpression(ShieldingType type, std::string filename, ShieldComparison comparison, double value); + ShieldExpression(ShieldingType type); + ShieldExpression(ShieldingType type, ShieldComparison comparison, double value); bool isRelative() const; bool isPreSafetyShield() const; @@ -34,15 +34,12 @@ namespace storm { std::string comparisonToString() const; std::string toString() const; std::string prettify() const; - std::string getFilename() const; friend std::ostream& operator<<(std::ostream& stream, ShieldExpression const& shieldExpression); private: ShieldingType type; ShieldComparison comparison = ShieldComparison::Relative; double value = 0; - - std::string filename; }; } } diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp index 68951bf1b..c1d0071e2 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp +++ b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp @@ -695,6 +695,7 @@ namespace storm { std::vector choiceValues = std::vector(transitionMatrix.getRowGroupIndices().at(transitionMatrix.getRowGroupIndices().size() - 1), storm::utility::zero()); auto choice_it = maybeStateChoiceValues.begin(); + // TODO THIS IS BUGGY!! for(uint state = 0; state < transitionMatrix.getRowGroupIndices().size() - 1; state++) { uint rowGroupSize = transitionMatrix.getRowGroupIndices().at(state + 1) - transitionMatrix.getRowGroupIndices().at(state); if (qualitativeStateSets.maybeStates.get(state)) { diff --git a/src/storm/shields/AbstractShield.cpp b/src/storm/shields/AbstractShield.cpp index abb57f57e..82f27bdc9 100644 --- a/src/storm/shields/AbstractShield.cpp +++ b/src/storm/shields/AbstractShield.cpp @@ -33,12 +33,6 @@ namespace tempest { std::string AbstractShield::getClassName() const { return std::string(boost::core::demangled_name(BOOST_CORE_TYPEID(*this))); } - - template - std::string AbstractShield::getShieldFileName() const { - return shieldingExpression->getFilename() + ".shield"; - } - // Explicitly instantiate appropriate template class AbstractShield::index_type>; diff --git a/src/storm/shields/AbstractShield.h b/src/storm/shields/AbstractShield.h index 8ca8d9117..9ef54775e 100644 --- a/src/storm/shields/AbstractShield.h +++ b/src/storm/shields/AbstractShield.h @@ -49,8 +49,7 @@ namespace tempest { storm::OptimizationDirection getOptimizationDirection(); std::string getClassName() const; - std::string getShieldFileName() const; - + virtual void printToStream(std::ostream& out, std::shared_ptr> const& model) = 0; virtual void printJsonToStream(std::ostream& out, std::shared_ptr> const& model) = 0; diff --git a/src/storm/shields/ShieldHandling.cpp b/src/storm/shields/ShieldHandling.cpp index fc5d48bfc..bcef9332c 100644 --- a/src/storm/shields/ShieldHandling.cpp +++ b/src/storm/shields/ShieldHandling.cpp @@ -2,10 +2,6 @@ namespace tempest { namespace shields { - std::string shieldFilename(std::shared_ptr const& shieldingExpression) { - return shieldingExpression->getFilename() + ".shield"; - } - template std::unique_ptr> createShield(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates) { if(coalitionStates.is_initialized()) coalitionStates.get().complement(); diff --git a/src/storm/shields/ShieldHandling.h b/src/storm/shields/ShieldHandling.h index e50d3e860..1fff9a6a0 100644 --- a/src/storm/shields/ShieldHandling.h +++ b/src/storm/shields/ShieldHandling.h @@ -20,9 +20,7 @@ #include "storm/exceptions/InvalidArgumentException.h" namespace tempest { - namespace shields { - std::string shieldFilename(std::shared_ptr const& shieldingExpression); - + namespace shields { template std::unique_ptr> createShield(std::shared_ptr> model, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); From 43f851167861c0c43ec8b33e4375626e27664125 Mon Sep 17 00:00:00 2001 From: Thomas Knoll Date: Wed, 16 Aug 2023 15:58:07 +0200 Subject: [PATCH 13/40] prettified post/pre scheduler json export --- src/storm/storage/PostScheduler.cpp | 2 +- src/storm/storage/PreScheduler.cpp | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/storm/storage/PostScheduler.cpp b/src/storm/storage/PostScheduler.cpp index 420b4b4e7..dd8fb3d1f 100644 --- a/src/storm/storage/PostScheduler.cpp +++ b/src/storm/storage/PostScheduler.cpp @@ -160,7 +160,7 @@ namespace storm { auto choiceOriginCorrectionJson = model->getChoiceOrigins()->getChoiceAsJson(globalChoiceCorrectionIndex); std::string choiceActionLabel = choiceOriginJson["action-label"]; std::string choiceCorrectionActionLabel = choiceOriginCorrectionJson["action-label"]; - choiceOriginJson["action-label"] = choiceActionLabel.append(": ").append(choiceCorrectionActionLabel); + choiceOriginJson["action-label"] = choiceActionLabel.append(": ").append(choiceCorrectionActionLabel).append("\n"); choiceJson["origin"] = choiceOriginJson; } if (model && model->hasChoiceLabeling()) { diff --git a/src/storm/storage/PreScheduler.cpp b/src/storm/storage/PreScheduler.cpp index bc3e6e833..41508064b 100644 --- a/src/storm/storage/PreScheduler.cpp +++ b/src/storm/storage/PreScheduler.cpp @@ -172,7 +172,10 @@ namespace storm { if (model && model->hasChoiceOrigins() && model->getChoiceOrigins()->getIdentifier(globalChoiceIndex) != model->getChoiceOrigins()->getIdentifierForChoicesWithNoOrigin()) { - choiceJson["origin"] = model->getChoiceOrigins()->getChoiceAsJson(globalChoiceIndex); + auto choiceOriginJson = model->getChoiceOrigins()->getChoiceAsJson(globalChoiceIndex); + std::string choiceActionLabel = choiceOriginJson["action-label"]; + choiceOriginJson["action-label"] = choiceActionLabel.append("\n"); + choiceJson["origin"] = choiceOriginJson; } if (model && model->hasChoiceLabeling()) { auto choiceLabels = model->getChoiceLabeling().getLabelsOfChoice(globalChoiceIndex); From 1a1d46ceda13beddad4eb95399df996037b36654 Mon Sep 17 00:00:00 2001 From: Thomas Knoll Date: Wed, 16 Aug 2023 15:59:55 +0200 Subject: [PATCH 14/40] fixed tests because of shield export change --- src/test/storm/logic/FragmentCheckerTest.cpp | 12 +- ...ieldGenerationMdpPrctlModelCheckerTest.cpp | 57 ++++++--- ...ieldGenerationSmgRpatlModelCheckerTest.cpp | 117 +++++++++++++----- .../storm/parser/GameShieldingParserTest.cpp | 12 +- .../storm/parser/MdpShieldingParserTest.cpp | 10 +- 5 files changed, 136 insertions(+), 72 deletions(-) diff --git a/src/test/storm/logic/FragmentCheckerTest.cpp b/src/test/storm/logic/FragmentCheckerTest.cpp index 3583ac019..f4c039f27 100644 --- a/src/test/storm/logic/FragmentCheckerTest.cpp +++ b/src/test/storm/logic/FragmentCheckerTest.cpp @@ -85,13 +85,13 @@ TEST(FragmentCheckerTest, Prctl) { ASSERT_NO_THROW(formula = formulaParser.parseSingleFormulaFromString("P=? [F[0,1] \"label\"]")); EXPECT_TRUE(checker.conformsToSpecification(*formula, prctl)); - ASSERT_NO_THROW(formula = formulaParser.parseSingleFormulaFromString(" Pmax=? [\"label1\" U [5,7] \"label2\"]")); + ASSERT_NO_THROW(formula = formulaParser.parseSingleFormulaFromString(" Pmax=? [\"label1\" U [5,7] \"label2\"]")); EXPECT_TRUE(checker.conformsToSpecification(*formula, prctl)); - ASSERT_NO_THROW(formula = formulaParser.parseSingleFormulaFromString(" Pmax=? [G \"label\"]")); + ASSERT_NO_THROW(formula = formulaParser.parseSingleFormulaFromString(" Pmax=? [G \"label\"]")); EXPECT_TRUE(checker.conformsToSpecification(*formula, prctl)); - ASSERT_NO_THROW(formula = formulaParser.parseSingleFormulaFromString(" Pmin=? [F <5 \"label\"]")); + ASSERT_NO_THROW(formula = formulaParser.parseSingleFormulaFromString(" Pmin=? [F <5 \"label\"]")); EXPECT_TRUE(checker.conformsToSpecification(*formula, prctl)); } @@ -202,13 +202,13 @@ TEST(FragmentCheckerTest, Rpatl) { ASSERT_NO_THROW(formula = formulaParser.parseSingleFormulaFromString("<<1,2,3>> Pmin=? [F [2,5] \"label\"]")); EXPECT_TRUE(checker.conformsToSpecification(*formula, rpatl)); - ASSERT_NO_THROW(formula = formulaParser.parseSingleFormulaFromString(" <<1,2,3,4,5>> Pmax=? [\"label1\" U [0,7] \"label2\"]")); + ASSERT_NO_THROW(formula = formulaParser.parseSingleFormulaFromString(" <<1,2,3,4,5>> Pmax=? [\"label1\" U [0,7] \"label2\"]")); EXPECT_TRUE(checker.conformsToSpecification(*formula, rpatl)); - ASSERT_NO_THROW(formula = formulaParser.parseSingleFormulaFromString(" <> Pmax=? [G \"label\"]")); + ASSERT_NO_THROW(formula = formulaParser.parseSingleFormulaFromString(" <> Pmax=? [G \"label\"]")); EXPECT_TRUE(checker.conformsToSpecification(*formula, rpatl)); - ASSERT_NO_THROW(formula = formulaParser.parseSingleFormulaFromString(" <> Pmin=? [G \"label\"]")); + ASSERT_NO_THROW(formula = formulaParser.parseSingleFormulaFromString(" <> Pmin=? [G \"label\"]")); EXPECT_TRUE(checker.conformsToSpecification(*formula, rpatl)); } diff --git a/src/test/storm/modelchecker/prctl/mdp/ShieldGenerationMdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/ShieldGenerationMdpPrctlModelCheckerTest.cpp index 7fda8f70c..91f677fc7 100644 --- a/src/test/storm/modelchecker/prctl/mdp/ShieldGenerationMdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/ShieldGenerationMdpPrctlModelCheckerTest.cpp @@ -6,6 +6,7 @@ #include "storm-parsers/api/model_descriptions.h" #include "storm/api/properties.h" #include "storm-parsers/api/properties.h" +#include "storm/api/export.h" #include "storm/models/sparse/Smg.h" #include "storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h" @@ -99,15 +100,15 @@ namespace { fileNames.push_back("dieSelectionPostSafetygamma07Pmin"); // testing create shielding expressions - std::string formulasString = "<" + fileNames[0] + ", PreSafety, lambda=0.8> Pmax=? [ F <5 \"done\" ]"; - formulasString += "; <" + fileNames[1] + ", PreSafety, gamma=0.8> Pmax=? [ F <5 \"done\" ]"; - formulasString += "; <" + fileNames[2] + ", PreSafety, lambda=0.8> Pmin=? [ F <5 \"done\" ]"; - formulasString += "; <" + fileNames[3] + ", PreSafety, gamma=0.8> Pmin=? [ F <5 \"done\" ]"; + std::string formulasString = " Pmax=? [ F <5 \"done\" ]"; + formulasString += "; Pmax=? [ F <5 \"done\" ]"; + formulasString += "; Pmin=? [ F <5 \"done\" ]"; + formulasString += "; Pmin=? [ F <5 \"done\" ]"; - formulasString += "; <" + fileNames[4] + ", PostSafety, lambda=0.7> Pmax=? [ F <6 \"two\" ]"; - formulasString += "; <" + fileNames[5] + ", PostSafety, gamma=0.7> Pmax=? [ F <6 \"two\" ]"; - formulasString += "; <" + fileNames[6] + ", PostSafety, lambda=0.7> Pmin=? [ F <6 \"two\" ]"; - formulasString += "; <" + fileNames[7] + ", PostSafety, gamma=0.7> Pmin=? [ F <6 \"two\" ]"; + formulasString += "; Pmax=? [ F <6 \"two\" ]"; + formulasString += "; Pmax=? [ F <6 \"two\" ]"; + formulasString += "; Pmin=? [ F <6 \"two\" ]"; + formulasString += "; Pmin=? [ F <6 \"two\" ]"; auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR "/mdp/die_selection.nm", formulasString); auto mdp = std::move(modelFormulas.first); @@ -130,66 +131,90 @@ namespace { // shielding results filename = fileNames[0]; - auto preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, filename, comparisonRelative, value08)); + auto preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, comparisonRelative, value08)); tasks[0].setShieldingExpression(preSafetyShieldingExpression); EXPECT_TRUE(tasks[0].isShieldingTask()); auto result = checker.check(this->env(), tasks[0]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(mdp, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[1]; - preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, filename, comparisonAbsolute, value08)); + preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, comparisonAbsolute, value08)); tasks[1].setShieldingExpression(preSafetyShieldingExpression); EXPECT_TRUE(tasks[1].isShieldingTask()); result = checker.check(this->env(), tasks[1]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(mdp, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[2]; - preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, filename, comparisonRelative, value08)); + preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, comparisonRelative, value08)); tasks[2].setShieldingExpression(preSafetyShieldingExpression); EXPECT_TRUE(tasks[2].isShieldingTask()); result = checker.check(this->env(), tasks[2]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(mdp, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[3]; - preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, filename, comparisonAbsolute, value08)); + preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, comparisonAbsolute, value08)); tasks[3].setShieldingExpression(preSafetyShieldingExpression); EXPECT_TRUE(tasks[3].isShieldingTask()); result = checker.check(this->env(), tasks[3]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(mdp, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[4]; - auto postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, filename, comparisonRelative, value07)); + auto postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, comparisonRelative, value07)); tasks[4].setShieldingExpression(postSafetyShieldingExpression); EXPECT_TRUE(tasks[4].isShieldingTask()); result = checker.check(this->env(), tasks[4]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(mdp, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[5]; - postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, filename, comparisonAbsolute, value07)); + postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, comparisonAbsolute, value07)); tasks[5].setShieldingExpression(postSafetyShieldingExpression); EXPECT_TRUE(tasks[5].isShieldingTask()); result = checker.check(this->env(), tasks[5]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(mdp, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[6]; - postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, filename, comparisonRelative, value07)); + postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, comparisonRelative, value07)); tasks[6].setShieldingExpression(postSafetyShieldingExpression); EXPECT_TRUE(tasks[6].isShieldingTask()); result = checker.check(this->env(), tasks[6]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(mdp, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[7]; - postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, filename, comparisonAbsolute, value07)); + postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, comparisonAbsolute, value07)); tasks[7].setShieldingExpression(postSafetyShieldingExpression); EXPECT_TRUE(tasks[7].isShieldingTask()); result = checker.check(this->env(), tasks[7]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(mdp, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); } diff --git a/src/test/storm/modelchecker/rpatl/smg/ShieldGenerationSmgRpatlModelCheckerTest.cpp b/src/test/storm/modelchecker/rpatl/smg/ShieldGenerationSmgRpatlModelCheckerTest.cpp index 096766c29..9009df76f 100644 --- a/src/test/storm/modelchecker/rpatl/smg/ShieldGenerationSmgRpatlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/rpatl/smg/ShieldGenerationSmgRpatlModelCheckerTest.cpp @@ -5,6 +5,7 @@ #include "storm/api/builder.h" #include "storm-parsers/api/model_descriptions.h" #include "storm/api/properties.h" +#include "storm/api/export.h" #include "storm-parsers/api/properties.h" #include "storm/models/sparse/Smg.h" @@ -107,23 +108,23 @@ namespace { fileNames.push_back("rightDecisionPostSafetyGamma05PminF5"); // testing create shielding expressions - std::string formulasString = "<" + fileNames[0] + ", PreSafety, lambda=0.9> <> Pmax=? [ F <=3 \"target\" ]"; - formulasString += "; <" + fileNames[1] + ", PreSafety, lambda=0.9> <> Pmin=? [ F <=3 \"target\" ]"; - formulasString += "; <" + fileNames[2] + ", PreSafety, gamma=0.9> <> Pmax=? [ F <=3 \"target\" ]"; - formulasString += "; <" + fileNames[3] + ", PreSafety, gamma=0.9> <> Pmin=? [ F <=3 \"target\" ]"; - formulasString += "; <" + fileNames[4] + ", PostSafety, lambda=0.9> <> Pmax=? [ F <=3 \"target\" ]"; - formulasString += "; <" + fileNames[5] + ", PostSafety, lambda=0.9> <> Pmin=? [ F <=3 \"target\" ]"; - formulasString += "; <" + fileNames[6] + ", PostSafety, gamma=0.9> <> Pmax=? [ F <=3 \"target\" ]"; - formulasString += "; <" + fileNames[7] + ", PostSafety, gamma=0.9> <> Pmin=? [ F <=3 \"target\" ]"; - - formulasString += "; <" + fileNames[8] + ", PreSafety, lambda=0.5> <> Pmax=? [ F <=5 \"target\" ]"; - formulasString += "; <" + fileNames[9] + ", PreSafety, lambda=0.5> <> Pmin=? [ F <=5 \"target\" ]"; - formulasString += "; <" + fileNames[10] + ", PreSafety, gamma=0.5> <> Pmax=? [ F <=5 \"target\" ]"; - formulasString += "; <" + fileNames[11] + ", PreSafety, gamma=0.5> <> Pmin=? [ F <=5 \"target\" ]"; - formulasString += "; <" + fileNames[12] + ", PostSafety, lambda=0.5> <> Pmax=? [ F <=5 \"target\" ]"; - formulasString += "; <" + fileNames[13] + ", PostSafety, lambda=0.5> <> Pmin=? [ F <=5 \"target\" ]"; - formulasString += "; <" + fileNames[14] + ", PostSafety, gamma=0.5> <> Pmax=? [ F <=5 \"target\" ]"; - formulasString += "; <" + fileNames[15] + ", PostSafety, gamma=0.5> <> Pmin=? [ F <=5 \"target\" ]"; + std::string formulasString = " <> Pmax=? [ F <=3 \"target\" ]"; + formulasString += "; <> Pmin=? [ F <=3 \"target\" ]"; + formulasString += "; <> Pmax=? [ F <=3 \"target\" ]"; + formulasString += "; <> Pmin=? [ F <=3 \"target\" ]"; + formulasString += "; <> Pmax=? [ F <=3 \"target\" ]"; + formulasString += "; <> Pmin=? [ F <=3 \"target\" ]"; + formulasString += "; <> Pmax=? [ F <=3 \"target\" ]"; + formulasString += "; <> Pmin=? [ F <=3 \"target\" ]"; + + formulasString += "; <> Pmax=? [ F <=5 \"target\" ]"; + formulasString += "; <> Pmin=? [ F <=5 \"target\" ]"; + formulasString += "; <> Pmax=? [ F <=5 \"target\" ]"; + formulasString += "; <> Pmin=? [ F <=5 \"target\" ]"; + formulasString += "; <> Pmax=? [ F <=5 \"target\" ]"; + formulasString += "; <> Pmin=? [ F <=5 \"target\" ]"; + formulasString += "; <> Pmax=? [ F <=5 \"target\" ]"; + formulasString += "; <> Pmin=? [ F <=5 \"target\" ]"; auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR "/smg/rightDecision.nm", formulasString); auto smg = std::move(modelFormulas.first); @@ -147,131 +148,179 @@ namespace { // shielding results filename = fileNames[0]; - auto preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, filename, comparisonRelative, value09)); + auto preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, comparisonRelative, value09)); tasks[0].setShieldingExpression(preSafetyShieldingExpression); - EXPECT_TRUE(tasks[0].isShieldingTask()); + EXPECT_TRUE(tasks[0].isShieldingTask()); auto result = checker.check(this->env(), tasks[0]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(smg, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[1]; - preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, filename, comparisonRelative, value09)); + preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, comparisonRelative, value09)); tasks[1].setShieldingExpression(preSafetyShieldingExpression); EXPECT_TRUE(tasks[1].isShieldingTask()); result = checker.check(this->env(), tasks[1]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(smg, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[2]; - preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, filename, comparisonAbsolute, value09)); + preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, comparisonAbsolute, value09)); tasks[2].setShieldingExpression(preSafetyShieldingExpression); EXPECT_TRUE(tasks[2].isShieldingTask()); result = checker.check(this->env(), tasks[2]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(smg, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[3]; - preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, filename, comparisonAbsolute, value09)); + preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, comparisonAbsolute, value09)); tasks[3].setShieldingExpression(preSafetyShieldingExpression); EXPECT_TRUE(tasks[3].isShieldingTask()); result = checker.check(this->env(), tasks[3]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(smg, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[4]; - auto postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, filename, comparisonRelative, value09)); + auto postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, comparisonRelative, value09)); tasks[4].setShieldingExpression(postSafetyShieldingExpression); EXPECT_TRUE(tasks[4].isShieldingTask()); result = checker.check(this->env(), tasks[4]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(smg, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[5]; - postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, filename, comparisonRelative, value09)); + postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, comparisonRelative, value09)); tasks[5].setShieldingExpression(postSafetyShieldingExpression); EXPECT_TRUE(tasks[5].isShieldingTask()); result = checker.check(this->env(), tasks[5]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(smg, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[6]; - postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, filename, comparisonAbsolute, value09)); + postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, comparisonAbsolute, value09)); tasks[6].setShieldingExpression(postSafetyShieldingExpression); EXPECT_TRUE(tasks[6].isShieldingTask()); result = checker.check(this->env(), tasks[6]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(smg, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[7]; - postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, filename, comparisonAbsolute, value09)); + postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, comparisonAbsolute, value09)); tasks[7].setShieldingExpression(postSafetyShieldingExpression); EXPECT_TRUE(tasks[7].isShieldingTask()); result = checker.check(this->env(), tasks[7]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(smg, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[8]; - preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, filename, comparisonRelative, value05)); + preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, comparisonRelative, value05)); tasks[8].setShieldingExpression(preSafetyShieldingExpression); EXPECT_TRUE(tasks[8].isShieldingTask()); result = checker.check(this->env(), tasks[8]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(smg, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[9]; - preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, filename, comparisonRelative, value05)); + preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, comparisonRelative, value05)); tasks[9].setShieldingExpression(preSafetyShieldingExpression); EXPECT_TRUE(tasks[9].isShieldingTask()); result = checker.check(this->env(), tasks[9]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(smg, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[10]; - preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, filename, comparisonAbsolute, value05)); + preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, comparisonAbsolute, value05)); tasks[10].setShieldingExpression(preSafetyShieldingExpression); EXPECT_TRUE(tasks[10].isShieldingTask()); result = checker.check(this->env(), tasks[10]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(smg, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[11]; - preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, filename, comparisonAbsolute, value05)); + preSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePreSafety, comparisonAbsolute, value05)); tasks[11].setShieldingExpression(preSafetyShieldingExpression); EXPECT_TRUE(tasks[11].isShieldingTask()); result = checker.check(this->env(), tasks[11]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(smg, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[12]; - postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, filename, comparisonRelative, value05)); + postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, comparisonRelative, value05)); tasks[12].setShieldingExpression(postSafetyShieldingExpression); EXPECT_TRUE(tasks[12].isShieldingTask()); result = checker.check(this->env(), tasks[12]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(smg, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[13]; - postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, filename, comparisonRelative, value05)); + postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, comparisonRelative, value05)); tasks[13].setShieldingExpression(postSafetyShieldingExpression); EXPECT_TRUE(tasks[13].isShieldingTask()); result = checker.check(this->env(), tasks[13]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(smg, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[14]; - postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, filename, comparisonAbsolute, value05)); + postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, comparisonAbsolute, value05)); tasks[14].setShieldingExpression(postSafetyShieldingExpression); EXPECT_TRUE(tasks[14].isShieldingTask()); result = checker.check(this->env(), tasks[14]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(smg, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); filename = fileNames[15]; - postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, filename, comparisonAbsolute, value05)); + postSafetyShieldingExpression = std::shared_ptr(new storm::logic::ShieldExpression(typePostSafety, comparisonAbsolute, value05)); tasks[15].setShieldingExpression(postSafetyShieldingExpression); EXPECT_TRUE(tasks[15].isShieldingTask()); result = checker.check(this->env(), tasks[15]); + EXPECT_TRUE(result->isExplicitQuantitativeCheckResult()); + EXPECT_TRUE(result->hasShield()); + storm::api::exportShield(smg, result->template asExplicitQuantitativeCheckResult().getShield() , filename + ".shield"); this->getStringsToCompare(filename, shieldingString, compareFileString); EXPECT_EQ(shieldingString, compareFileString); } diff --git a/src/test/storm/parser/GameShieldingParserTest.cpp b/src/test/storm/parser/GameShieldingParserTest.cpp index a6ed3cb88..f19cb757b 100644 --- a/src/test/storm/parser/GameShieldingParserTest.cpp +++ b/src/test/storm/parser/GameShieldingParserTest.cpp @@ -6,9 +6,8 @@ TEST(GameShieldingParserTest, PreSafetyShieldTest) { storm::parser::FormulaParser formulaParser; - std::string filename = "preSafetyShieldFileName"; std::string value = "0.9"; - std::string input = "<" + filename + ", PreSafety, lambda=" + value + "> <> Pmax=? [F \"label\"]"; + std::string input = " <> Pmax=? [F \"label\"]"; std::shared_ptr formula(nullptr); ASSERT_NO_THROW(formula = formulaParser.parseSingleFormulaFromString(input)); @@ -25,15 +24,13 @@ TEST(GameShieldingParserTest, PreSafetyShieldTest) { EXPECT_FALSE(shieldExpression->isOptimalShield()); EXPECT_TRUE(shieldExpression->isRelative()); EXPECT_EQ(std::stod(value), shieldExpression->getValue()); - EXPECT_EQ(filename, shieldExpression->getFilename()); } TEST(GameShieldingParserTest, PostShieldTest) { storm::parser::FormulaParser formulaParser; - std::string filename = "postSafetyShieldFileName"; std::string value = "0.7569"; - std::string input = "<" + filename + ", PostSafety, gamma=" + value + "> <> Pmin=? [X !\"label\"]"; + std::string input = " <> Pmin=? [X !\"label\"]"; std::shared_ptr formula(nullptr); ASSERT_NO_THROW(formula = formulaParser.parseSingleFormulaFromString(input)); @@ -50,7 +47,6 @@ TEST(GameShieldingParserTest, PostShieldTest) { EXPECT_FALSE(shieldExpression->isOptimalShield()); EXPECT_FALSE(shieldExpression->isRelative()); EXPECT_EQ(std::stod(value), shieldExpression->getValue()); - EXPECT_EQ(filename, shieldExpression->getFilename()); } TEST(GameShieldingParserTest, OptimalShieldTest) { @@ -60,8 +56,7 @@ TEST(GameShieldingParserTest, OptimalShieldTest) { storm::parser::FormulaParser formulaParser(manager); - std::string filename = "optimalShieldFileName"; - std::string input = "<" + filename + ", Optimal> <> Pmax=? [G x>y]"; + std::string input = " <> Pmax=? [G x>y]"; std::shared_ptr formula(nullptr); ASSERT_NO_THROW(formula = formulaParser.parseSingleFormulaFromString(input)); @@ -76,5 +71,4 @@ TEST(GameShieldingParserTest, OptimalShieldTest) { EXPECT_FALSE(shieldExpression->isPreSafetyShield()); EXPECT_FALSE(shieldExpression->isPostSafetyShield()); EXPECT_TRUE(shieldExpression->isOptimalShield()); - EXPECT_EQ(filename, shieldExpression->getFilename()); } diff --git a/src/test/storm/parser/MdpShieldingParserTest.cpp b/src/test/storm/parser/MdpShieldingParserTest.cpp index 84b69d6db..5efa3e40d 100644 --- a/src/test/storm/parser/MdpShieldingParserTest.cpp +++ b/src/test/storm/parser/MdpShieldingParserTest.cpp @@ -6,9 +6,8 @@ TEST(MdpShieldingParserTest, PreSafetyShieldTest) { storm::parser::FormulaParser formulaParser; - std::string filename = "preSafetyShieldFileName"; std::string value = "0.6667"; - std::string input = "<" + filename + ", PreSafety, gamma=" + value + "> Pmax=? [F \"label\"]"; + std::string input = " Pmax=? [F \"label\"]"; std::shared_ptr formula(nullptr); std::vector property; @@ -22,7 +21,6 @@ TEST(MdpShieldingParserTest, PreSafetyShieldTest) { EXPECT_FALSE(shieldExpression->isOptimalShield()); EXPECT_FALSE(shieldExpression->isRelative()); EXPECT_EQ(std::stod(value), shieldExpression->getValue()); - EXPECT_EQ(filename, shieldExpression->getFilename()); } TEST(MdpShieldingParserTest, PostShieldTest) { @@ -30,7 +28,7 @@ TEST(MdpShieldingParserTest, PostShieldTest) { std::string filename = "postSafetyShieldFileName"; std::string value = "0.95"; - std::string input = "<" + filename + ", PostSafety, lambda=" + value + "> Pmin=? [X !\"label\"]"; + std::string input = " Pmin=? [X !\"label\"]"; std::shared_ptr formula(nullptr); std::vector property; @@ -44,7 +42,6 @@ TEST(MdpShieldingParserTest, PostShieldTest) { EXPECT_FALSE(shieldExpression->isOptimalShield()); EXPECT_TRUE(shieldExpression->isRelative()); EXPECT_EQ(std::stod(value), shieldExpression->getValue()); - EXPECT_EQ(filename, shieldExpression->getFilename()); } TEST(MdpShieldingParserTest, OptimalShieldTest) { @@ -55,7 +52,7 @@ TEST(MdpShieldingParserTest, OptimalShieldTest) { storm::parser::FormulaParser formulaParser(manager); std::string filename = "optimalShieldFileName"; - std::string input = "<" + filename + ", Optimal> Pmax=? [G (a|x>3)]"; + std::string input = " Pmax=? [G (a|x>3)]"; std::shared_ptr formula(nullptr); std::vector property; @@ -67,5 +64,4 @@ TEST(MdpShieldingParserTest, OptimalShieldTest) { EXPECT_FALSE(shieldExpression->isPreSafetyShield()); EXPECT_FALSE(shieldExpression->isPostSafetyShield()); EXPECT_TRUE(shieldExpression->isOptimalShield()); - EXPECT_EQ(filename, shieldExpression->getFilename()); } From a9f03779483ee7d404ed616cda6a309385833410 Mon Sep 17 00:00:00 2001 From: sp Date: Thu, 7 Sep 2023 15:19:14 +0200 Subject: [PATCH 15/40] fixed incorrect handling of choiceValues in helper --- .../prctl/helper/SparseMdpPrctlHelper.cpp | 38 +++---------------- 1 file changed, 6 insertions(+), 32 deletions(-) diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp index c1d0071e2..760cdce42 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp +++ b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp @@ -676,41 +676,15 @@ namespace storm { extractSchedulerChoices(*scheduler, resultForMaybeStates.getScheduler(), qualitativeStateSets.maybeStates); } } - if (goal.isShieldingTask()) { - std::vector subResult; - uint sizeChoiceValues = 0; - for(uint counter = 0; counter < qualitativeStateSets.maybeStates.size(); counter++) { - if(qualitativeStateSets.maybeStates.get(counter)) { - subResult.push_back(result.at(counter)); - } - } - - submatrix = transitionMatrix.getSubmatrix(true, qualitativeStateSets.maybeStates, qualitativeStateSets.maybeStates, false); - auto sub_multiplier = storm::solver::MultiplierFactory().create(env, submatrix); - sub_multiplier->multiply(env, subResult, &b, maybeStateChoiceValues); - - } } } - std::vector choiceValues = std::vector(transitionMatrix.getRowGroupIndices().at(transitionMatrix.getRowGroupIndices().size() - 1), storm::utility::zero()); - auto choice_it = maybeStateChoiceValues.begin(); - // TODO THIS IS BUGGY!! - for(uint state = 0; state < transitionMatrix.getRowGroupIndices().size() - 1; state++) { - uint rowGroupSize = transitionMatrix.getRowGroupIndices().at(state + 1) - transitionMatrix.getRowGroupIndices().at(state); - if (qualitativeStateSets.maybeStates.get(state)) { - for(uint choice = 0; choice < rowGroupSize; choice++, choice_it++) { - choiceValues.at(transitionMatrix.getRowGroupIndices().at(state) + choice) = *choice_it; - } - } else if (qualitativeStateSets.statesWithProbability0.get(state)) { - for(uint choice = 0; choice < rowGroupSize; choice++) { - choiceValues.at(transitionMatrix.getRowGroupIndices().at(state) + choice) = 0; - } - } else if (qualitativeStateSets.statesWithProbability1.get(state)) { - for(uint choice = 0; choice < rowGroupSize; choice++) { - choiceValues.at(transitionMatrix.getRowGroupIndices().at(state) + choice) = 1; - } - } + std::vector choiceValues; + if(goal.isShieldingTask()) { + choiceValues = std::vector(transitionMatrix.getRowGroupIndices().at(transitionMatrix.getRowGroupIndices().size() - 1), storm::utility::zero()); + std::vector b = std::vector(transitionMatrix.getRowCount(), storm::utility::zero()); + auto multiplier = storm::solver::MultiplierFactory().create(env, transitionMatrix); + multiplier->multiply(env, result, &b, choiceValues); } // Extend scheduler with choices for the states in the qualitative state sets. From c9529e6a1e2101be8f2ad3e745b1315cb693d8a8 Mon Sep 17 00:00:00 2001 From: Thomas Knoll Date: Fri, 29 Sep 2023 15:52:25 +0200 Subject: [PATCH 16/40] changed maybe states argument --- src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index 931b0ef54..9b2629e56 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -137,10 +137,10 @@ namespace storm { ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeUntilProbabilities(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet(), checkTask.getHint()); - STORM_LOG_DEBUG(ret.values); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { - auto shield = tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.maybeStates), storm::storage::BitVector(ret.maybeStates.size(), true)); + + auto shield = tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true), storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true)); result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); } if (checkTask.isProduceSchedulersSet() && ret.scheduler) { From d93d184d5dae67de2593d4f23ce0f56ad998dac8 Mon Sep 17 00:00:00 2001 From: sp Date: Thu, 26 Sep 2024 16:23:59 +0200 Subject: [PATCH 17/40] updated readme --- README.md | 67 +------------------------------------------------------ 1 file changed, 1 insertion(+), 66 deletions(-) diff --git a/README.md b/README.md index aeb2fa0f5..9220d2dfd 100644 --- a/README.md +++ b/README.md @@ -1,68 +1,3 @@ -Storm - A Modern Probabilistic Model Checker +Tempest - A Shield Synthesis Tool ============================================ -[![Build Status](https://github.com/moves-rwth/storm/workflows/Build%20Test/badge.svg)](https://github.com/moves-rwth/storm/actions) -[![GitHub release](https://img.shields.io/github/release/moves-rwth/storm.svg)](https://github.com/moves-rwth/storm/releases/) -[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.1181896.svg)](https://doi.org/10.5281/zenodo.1181896) - - -For more instructions, check out the documentation found in [Getting Started](http://www.stormchecker.org/getting-started.html). - - -Benchmarks ----------------------------- - -Example input files for Storm can be obtained from -https://github.com/moves-rwth/storm-examples. - -Various Benchmarks together with example invocations of Storm can be found at the [Quantitative Verification Benchmark Set (QVBS)](http://qcomp.org/benchmarks). - -Further examples and benchmarks can be found in the following repositories: - -* **Prism files** (DTMC, MDP, CTMC): -http://www.prismmodelchecker.org/benchmarks -* **Jani files** (DTMC, MDP, CTMC, MA): -http://jani-spec.org -* **GSPN**s: -(private, contact: sebastian.junges@cs.rwth-aachen.de) -* **DFT**s: -https://github.com/moves-rwth/dft-examples -* **PGCL**: -(private, contact: sebastian.junges@cs.rwth-aachen.de) - - -Authors ------------------------------ -Storm has been developed at RWTH Aachen University. - -###### Principal developers -* Christian Hensel -* Sebastian Junges -* Joost-Pieter Katoen -* Tim Quatmann -* Matthias Volk - -###### Developers (lexicographical order) -* Jana Berger -* Alexander Bork -* David Korzeniewski -* Jip Spel - -###### Contributors (lexicographical order) -* Daniel Basgöze -* Dimitri Bohlender -* Harold Bruintjes -* Michael Deutschen -* Linus Heck -* Thomas Heinemann -* Thomas Henn -* Tom Janson -* Jan Karuc -* Joachim Klein -* Gereon Kremer -* Sascha Vincent Kurowski -* Hannah Mertens -* Stefan Pranger -* Svenja Stein -* Manuel Sascha Weiand -* Lukas Westhofen From 0d60b468e132621c20114b6bf156683afa8cf299 Mon Sep 17 00:00:00 2001 From: sp Date: Tue, 5 Nov 2024 11:24:30 +0100 Subject: [PATCH 18/40] refactored shield export --- src/storm-cli-utilities/model-handling.h | 20 ++++++- src/storm/api/verification.h | 2 +- .../rpatl/SparseSmgRpatlModelChecker.cpp | 17 +++--- src/storm/shields/AbstractShield.cpp | 56 ++++++++++++++++++- src/storm/shields/AbstractShield.h | 43 +++++++++++--- src/storm/shields/OptimalShield.cpp | 27 +++++++-- src/storm/shields/OptimalShield.h | 7 ++- src/storm/shields/PostShield.cpp | 26 +++++++-- src/storm/shields/PostShield.h | 6 +- src/storm/shields/PreShield.cpp | 29 +++++++--- src/storm/shields/PreShield.h | 9 ++- src/storm/storage/PostScheduler.cpp | 9 +-- src/storm/storage/PreScheduler.cpp | 7 ++- src/storm/storage/PreScheduler.h | 1 + 14 files changed, 213 insertions(+), 46 deletions(-) diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h index c90852df5..cb915a005 100644 --- a/src/storm-cli-utilities/model-handling.h +++ b/src/storm-cli-utilities/model-handling.h @@ -49,6 +49,11 @@ #include "storm/settings/modules/HintSettings.h" #include "storm/storage/Qvbs.h" +#include "storm/shields/AbstractShield.h" +#include "storm/shields/PreShield.h" +#include "storm/shields/PostShield.h" +#include "storm/shields/OptimalShield.h" + #include "storm/utility/Stopwatch.h" namespace storm { @@ -1047,13 +1052,22 @@ namespace storm { if (result->isExplicitQuantitativeCheckResult()) { if (result-> template asExplicitQuantitativeCheckResult().hasShield()) { auto shield = result->template asExplicitQuantitativeCheckResult().getShield(); + if(shield->isPreShield()) { + shield->asPreShield().construct(); + } else if(shield->isPostShield()) { + shield->asPostShield().construct(); + } else if(shield->isOptimalShield()) { + shield->asOptimalShield().construct(); + } + STORM_PRINT_AND_LOG("Exporting shield ... "); - - storm::api::exportShield(sparseModel, shield, ioSettings.getExportShieldFilename()); + + STORM_LOG_WARN_COND(exportCount == 0, "Prepending " << exportCount << " to file name for this property because there are multiple properties."); + storm::api::exportShield(sparseModel, shield, (exportCount == 0 ? std::string("") : std::to_string(exportCount)) + ioSettings.getExportShieldFilename()); } } } - + if (ioSettings.isExportCheckResultSet()) { STORM_LOG_WARN_COND(sparseModel->hasStateValuations(), "No information of state valuations available. The result output will use internal state ids. You might be interested in building the model with state valuations using --buildstateval."); diff --git a/src/storm/api/verification.h b/src/storm/api/verification.h index 868c00be3..3abb50803 100644 --- a/src/storm/api/verification.h +++ b/src/storm/api/verification.h @@ -458,7 +458,7 @@ namespace storm { template typename std::enable_if::value, std::unique_ptr>::type verifyWithDdEngine(storm::Environment const&, std::shared_ptr> const&, storm::modelchecker::CheckTask const&) { - STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Dd engine cannot verify MDPs with this data type."); + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, ""); } template diff --git a/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp b/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp index 53562ef04..79cc6fc87 100644 --- a/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp +++ b/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp @@ -141,13 +141,14 @@ namespace storm { ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + auto ret = storm::modelchecker::helper::SparseSmgRpatlHelper::computeUntilProbabilities(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), statesOfCoalition, checkTask.isProduceSchedulersSet(), checkTask.getHint()); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); auto shield = tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); - result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); - } + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); + } if (checkTask.isProduceSchedulersSet() && ret.scheduler) { result->asExplicitQuantitativeCheckResult().setScheduler(std::move(ret.scheduler)); } @@ -165,8 +166,8 @@ namespace storm { if(checkTask.isShieldingTask()) { storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); auto shield = tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); - result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); - } + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); + } if (checkTask.isProduceSchedulersSet() && ret.scheduler) { result->asExplicitQuantitativeCheckResult().setScheduler(std::move(ret.scheduler)); } @@ -202,7 +203,7 @@ namespace storm { if(checkTask.isShieldingTask()) { storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); auto shield = tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); - result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); } return result; } @@ -225,7 +226,7 @@ namespace storm { std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { auto shield = tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.relevantStates), ~statesOfCoalition); - result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); } return result; } @@ -246,8 +247,8 @@ namespace storm { if(checkTask.isShieldingTask()) { storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); auto shield = tempest::shields::createQuantitativeShield(std::make_shared>(this->getModel()), helper.getChoiceValues(), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, statesOfCoalition); - result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); - } + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); + } if (checkTask.isProduceSchedulersSet()) { result->asExplicitQuantitativeCheckResult().setScheduler(std::make_unique>(helper.extractScheduler())); } diff --git a/src/storm/shields/AbstractShield.cpp b/src/storm/shields/AbstractShield.cpp index 82f27bdc9..ca446726c 100644 --- a/src/storm/shields/AbstractShield.cpp +++ b/src/storm/shields/AbstractShield.cpp @@ -1,4 +1,7 @@ #include "storm/shields/AbstractShield.h" +#include "storm/shields/PreShield.h" +#include "storm/shields/PostShield.h" +#include "storm/shields/OptimalShield.h" #include @@ -29,11 +32,62 @@ namespace tempest { return optimizationDirection; } + template + void AbstractShield::setShieldingExpression(std::shared_ptr const& shieldingExpression) { + this->shieldingExpression = shieldingExpression; + } + + template + bool AbstractShield::isPreShield() const { + return false; + } + + template + bool AbstractShield::isPostShield() const { + return false; + } + + template + bool AbstractShield::isOptimalShield() const { + return false; + } + + template + PreShield& AbstractShield::asPreShield() { + return dynamic_cast&>(*this); + } + + template + PreShield const& AbstractShield::asPreShield() const { + return dynamic_cast const&>(*this); + } + + template + PostShield& AbstractShield::asPostShield() { + return dynamic_cast&>(*this); + } + + template + PostShield const& AbstractShield::asPostShield() const { + return dynamic_cast const&>(*this); + } + + template + OptimalShield& AbstractShield::asOptimalShield() { + return dynamic_cast&>(*this); + } + + template + OptimalShield const& AbstractShield::asOptimalShield() const { + return dynamic_cast const&>(*this); + } + + template std::string AbstractShield::getClassName() const { return std::string(boost::core::demangled_name(BOOST_CORE_TYPEID(*this))); } - + // Explicitly instantiate appropriate template class AbstractShield::index_type>; #ifdef STORM_HAVE_CARL diff --git a/src/storm/shields/AbstractShield.h b/src/storm/shields/AbstractShield.h index 9ef54775e..04401cd6b 100644 --- a/src/storm/shields/AbstractShield.h +++ b/src/storm/shields/AbstractShield.h @@ -16,19 +16,33 @@ #include "storm/logic/ShieldExpression.h" +#include "storm/exceptions/NotSupportedException.h" + + namespace tempest { namespace shields { + template + class PreShield; + template + class PostShield; + template + class OptimalShield; + namespace utility { template struct ChoiceFilter { bool operator()(ValueType v, ValueType opt, double shieldValue) { - Compare compare; - if(relative && std::is_same>::value) { - return compare(v, opt + opt * shieldValue); - } else if(relative && std::is_same>::value) { - return compare(v, opt * shieldValue); + if constexpr (std::is_same_v || std::is_same_v) { + Compare compare; + if(relative && std::is_same>::value) { + return compare(v, opt + opt * shieldValue); + } else if(relative && std::is_same>::value) { + return compare(v, opt * shieldValue); + } + else return compare(v, shieldValue); + } else { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Cannot create shields for parametric models"); } - else return compare(v, shieldValue); } }; } @@ -47,9 +61,24 @@ namespace tempest { std::vector computeRowGroupSizes(); storm::OptimizationDirection getOptimizationDirection(); + void setShieldingExpression(std::shared_ptr const& shieldingExpression); std::string getClassName() const; - + + virtual bool isPreShield() const; + virtual bool isPostShield() const; + virtual bool isOptimalShield() const; + + PreShield& asPreShield(); + PreShield const& asPreShield() const; + + PostShield& asPostShield(); + PostShield const& asPostShield() const; + + OptimalShield& asOptimalShield(); + OptimalShield const& asOptimalShield() const; + + virtual void printToStream(std::ostream& out, std::shared_ptr> const& model) = 0; virtual void printJsonToStream(std::ostream& out, std::shared_ptr> const& model) = 0; diff --git a/src/storm/shields/OptimalShield.cpp b/src/storm/shields/OptimalShield.cpp index 6d03e77da..0d8fc0c63 100644 --- a/src/storm/shields/OptimalShield.cpp +++ b/src/storm/shields/OptimalShield.cpp @@ -64,21 +64,40 @@ namespace tempest { return shield; } + template - void OptimalShield::printToStream(std::ostream& out, std::shared_ptr> const& model) { - this->construct().printToStream(out, this->shieldingExpression, model); + std::shared_ptr> OptimalShield::getScheduler() const { + return optimalScheduler; + } + + template + bool OptimalShield::isOptimalShield() const { + return true; } template void OptimalShield::printJsonToStream(std::ostream& out, std::shared_ptr> const& model) { - this->construct().printJsonToStream(out, model); + optimalScheduler->printJsonToStream(out, model); + } + + template + void OptimalShield::printToStream(std::ostream& out, std::shared_ptr> const& model) { + optimalScheduler->printToStream(out, this->shieldingExpression, model); } + //template + //template + //std::enable_if_t::value, storm::storage::PostScheduler> OptimalShield::construct() { + // STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "todo"); + //} + + + // Explicitly instantiate appropriate classes template class OptimalShield::index_type>; #ifdef STORM_HAVE_CARL template class OptimalShield::index_type>; - // template class OptimalShield::index_type>; + template class OptimalShield::index_type>; #endif } diff --git a/src/storm/shields/OptimalShield.h b/src/storm/shields/OptimalShield.h index 0dac50587..3c2d9a2ff 100644 --- a/src/storm/shields/OptimalShield.h +++ b/src/storm/shields/OptimalShield.h @@ -14,11 +14,16 @@ namespace tempest { storm::storage::PostScheduler construct(); template storm::storage::PostScheduler constructWithCompareType(); + std::shared_ptr> getScheduler() const; + + virtual bool isOptimalShield() const override; + virtual void printToStream(std::ostream& out, std::shared_ptr> const& model) override; virtual void printJsonToStream(std::ostream& out, std::shared_ptr> const& model) override; - private: std::vector choiceValues; + + std::shared_ptr> optimalScheduler; }; } } diff --git a/src/storm/shields/PostShield.cpp b/src/storm/shields/PostShield.cpp index 6dffd5344..a3e86b7f2 100644 --- a/src/storm/shields/PostShield.cpp +++ b/src/storm/shields/PostShield.cpp @@ -45,7 +45,7 @@ namespace tempest { } ValueType optProbability = *(choice_it + optProbabilityIndex); if(!relative && !choiceFilter(optProbability, optProbability, this->shieldingExpression->getValue())) { - STORM_LOG_WARN("No shielding action possible with absolute comparison for state with index " << state); + //STORM_LOG_WARN("No shielding action possible with absolute comparison for state with index " << state); shield.setChoice(storm::storage::PostSchedulerChoice(), state, 0); choice_it += rowGroupSize; continue; @@ -69,21 +69,37 @@ namespace tempest { template - void PostShield::printToStream(std::ostream& out, std::shared_ptr> const& model) { - this->construct().printToStream(out, this->shieldingExpression, model); + std::shared_ptr> PostShield::getScheduler() const { + return postScheduler; + } + + template + bool PostShield::isPostShield() const { + return true; } template void PostShield::printJsonToStream(std::ostream& out, std::shared_ptr> const& model) { - this->construct().printJsonToStream(out, model); + postScheduler->printJsonToStream(out, model); } + template + void PostShield::printToStream(std::ostream& out, std::shared_ptr> const& model) { + postScheduler->printToStream(out, this->shieldingExpression, model); + } + + //template + //template + //std::enable_if_t::value, storm::storage::PostScheduler> PostShield::construct() { + // STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "todo"); + //} + // Explicitly instantiate appropriate classes template class PostShield::index_type>; #ifdef STORM_HAVE_CARL template class PostShield::index_type>; - // template class PostShield::index_type>; + template class PostShield::index_type>; #endif } diff --git a/src/storm/shields/PostShield.h b/src/storm/shields/PostShield.h index b857a9216..2116cf7bb 100644 --- a/src/storm/shields/PostShield.h +++ b/src/storm/shields/PostShield.h @@ -14,12 +14,16 @@ namespace tempest { storm::storage::PostScheduler construct(); template storm::storage::PostScheduler constructWithCompareType(); + std::shared_ptr> getScheduler() const; + + virtual bool isPostShield() const override; virtual void printToStream(std::ostream& out, std::shared_ptr> const& model) override; virtual void printJsonToStream(std::ostream& out, std::shared_ptr> const& model) override; - private: std::vector choiceValues; + + std::shared_ptr> postScheduler; }; } } diff --git a/src/storm/shields/PreShield.cpp b/src/storm/shields/PreShield.cpp index 716d4f8d1..7c62d5788 100644 --- a/src/storm/shields/PreShield.cpp +++ b/src/storm/shields/PreShield.cpp @@ -10,8 +10,12 @@ namespace tempest { // Intentionally left empty. } + template storm::storage::PreScheduler PreShield::construct() { + if constexpr (std::is_same_v) { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "todo"); + } if (this->getOptimizationDirection() == storm::OptimizationDirection::Minimize) { if(this->shieldingExpression->isRelative()) { return constructWithCompareType, true>(); @@ -38,7 +42,7 @@ namespace tempest { } for(uint state = 0; state < this->rowGroupIndices.size() - 1; state++) { uint rowGroupSize = this->rowGroupIndices[state + 1] - this->rowGroupIndices[state]; - if(this->relevantStates.get(state)) { + if(true){ //if(this->relevantStates.get(state)) { storm::storage::PreSchedulerChoice enabledChoices; ValueType optProbability; if(std::is_same>::value) { @@ -47,7 +51,7 @@ namespace tempest { optProbability = *std::min_element(choice_it, choice_it + rowGroupSize); } if(!relative && !choiceFilter(optProbability, optProbability, this->shieldingExpression->getValue())) { - STORM_LOG_WARN("No shielding action possible with absolute comparison for state with index " << state); + //STORM_LOG_WARN("No shielding action possible with absolute comparison for state with index " << state); shield.setChoice(storm::storage::PreSchedulerChoice(), state, 0); choice_it += rowGroupSize; continue; @@ -65,27 +69,38 @@ namespace tempest { } } + preScheduler = std::make_shared>(shield); return shield; } template - void PreShield::printToStream(std::ostream& out, std::shared_ptr> const& model) { - this->construct().printToStream(out, this->shieldingExpression, model); + std::shared_ptr> PreShield::getScheduler() const { + return preScheduler; + } + + template + bool PreShield::isPreShield() const { + return true; } template void PreShield::printJsonToStream(std::ostream& out, std::shared_ptr> const& model) { - this->construct().printJsonToStream(out, model); + preScheduler->printJsonToStream(out, model); } + template + void PreShield::printToStream(std::ostream& out, std::shared_ptr> const& model) { + preScheduler->printToStream(out, this->shieldingExpression, model); + } + + // Explicitly instantiate appropriate classes template class PreShield::index_type>; #ifdef STORM_HAVE_CARL template class PreShield::index_type>; - //template class PreShield::index_type>; - + template class PreShield::index_type>; #endif } } diff --git a/src/storm/shields/PreShield.h b/src/storm/shields/PreShield.h index 1b5f099b8..3bf80017c 100644 --- a/src/storm/shields/PreShield.h +++ b/src/storm/shields/PreShield.h @@ -11,15 +11,22 @@ namespace tempest { public: PreShield(std::vector const& rowGroupIndices, std::vector const& choiceValues, std::shared_ptr const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional coalitionStates); + storm::storage::PreScheduler construct(); + template storm::storage::PreScheduler constructWithCompareType(); + void setShieldingExpression(std::shared_ptr const& shieldingExpression); + std::shared_ptr> getScheduler() const; + + virtual bool isPreShield() const override; virtual void printToStream(std::ostream& out, std::shared_ptr> const& model) override; virtual void printJsonToStream(std::ostream& out, std::shared_ptr> const& model) override; - private: std::vector choiceValues; + + std::shared_ptr> preScheduler; }; } } diff --git a/src/storm/storage/PostScheduler.cpp b/src/storm/storage/PostScheduler.cpp index dd8fb3d1f..d8f5a7993 100644 --- a/src/storm/storage/PostScheduler.cpp +++ b/src/storm/storage/PostScheduler.cpp @@ -161,11 +161,11 @@ namespace storm { std::string choiceActionLabel = choiceOriginJson["action-label"]; std::string choiceCorrectionActionLabel = choiceOriginCorrectionJson["action-label"]; choiceOriginJson["action-label"] = choiceActionLabel.append(": ").append(choiceCorrectionActionLabel).append("\n"); - choiceJson["origin"] = choiceOriginJson; + choiceJson["origin"] = choiceOriginJson; } if (model && model->hasChoiceLabeling()) { auto choiceLabels = model->getChoiceLabeling().getLabelsOfChoice(globalChoiceIndex); - + choiceJson["labels"] = std::vector(choiceLabels.begin(), choiceLabels.end()); } @@ -179,10 +179,10 @@ namespace storm { } else { choicesJson = "undefined"; } - + stateChoicesJson["c"] = std::move(choicesJson); output.push_back(std::move(stateChoicesJson)); - + } out << output.dump(4); @@ -192,6 +192,7 @@ namespace storm { template class PostScheduler; #ifdef STORM_HAVE_CARL template class PostScheduler; + template class PostScheduler; #endif } } diff --git a/src/storm/storage/PreScheduler.cpp b/src/storm/storage/PreScheduler.cpp index 41508064b..f6f78c41d 100644 --- a/src/storm/storage/PreScheduler.cpp +++ b/src/storm/storage/PreScheduler.cpp @@ -138,7 +138,7 @@ namespace storm { } - + template void PreScheduler::printJsonToStream(std::ostream& out, std::shared_ptr> model, bool skipUniqueChoices) const { @@ -194,7 +194,7 @@ namespace storm { storm::json updateJson; // next model state if (model && model->hasStateValuations()) { - updateJson["s'"] = model->getStateValuations().template toJson(entryIt->getColumn()); + updateJson["s'"] = model->getStateValuations().template toJson(entryIt->getColumn()); } else { updateJson["s'"] = entryIt->getColumn(); } @@ -209,7 +209,7 @@ namespace storm { } else { choicesJson = "undefined"; } - + stateChoicesJson["c"] = std::move(choicesJson); output.push_back(std::move(stateChoicesJson)); } @@ -223,6 +223,7 @@ namespace storm { template class PreScheduler; #ifdef STORM_HAVE_CARL template class PreScheduler; + template class PreScheduler; #endif } } diff --git a/src/storm/storage/PreScheduler.h b/src/storm/storage/PreScheduler.h index e695e0732..294e7ecc1 100644 --- a/src/storm/storage/PreScheduler.h +++ b/src/storm/storage/PreScheduler.h @@ -13,6 +13,7 @@ namespace storm { /* * TODO needs obvious changes in all comment blocks */ + // TODO inherit from Scheduler? template class PreScheduler { public: From 6a799869808afb443216925222a20d55c5dcfe65 Mon Sep 17 00:00:00 2001 From: sp Date: Tue, 5 Nov 2024 11:26:16 +0100 Subject: [PATCH 19/40] introduce bounded globally mc for MDPs --- .../prctl/SparseMdpPrctlModelChecker.cpp | 52 ++++++++++++++----- .../prctl/SparseMdpPrctlModelChecker.h | 13 ++--- 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index 9b2629e56..a4001036f 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -45,7 +45,7 @@ namespace storm { template bool SparseMdpPrctlModelChecker::canHandleStatic(CheckTask const& checkTask, bool* requiresSingleInitialState) { storm::logic::Formula const& formula = checkTask.getFormula(); - if (formula.isInFragment(storm::logic::prctlstar().setLongRunAverageRewardFormulasAllowed(true).setLongRunAverageProbabilitiesAllowed(true).setConditionalProbabilityFormulasAllowed(true).setOnlyEventuallyFormuluasInConditionalFormulasAllowed(true).setTotalRewardFormulasAllowed(true).setRewardBoundedUntilFormulasAllowed(true).setRewardBoundedCumulativeRewardFormulasAllowed(true).setMultiDimensionalBoundedUntilFormulasAllowed(true).setMultiDimensionalCumulativeRewardFormulasAllowed(true).setTimeOperatorsAllowed(true).setReachbilityTimeFormulasAllowed(true).setRewardAccumulationAllowed(true))) { + if (formula.isInFragment(storm::logic::prctlstar().setLongRunAverageRewardFormulasAllowed(true).setLongRunAverageProbabilitiesAllowed(true).setConditionalProbabilityFormulasAllowed(true).setOnlyEventuallyFormuluasInConditionalFormulasAllowed(true).setTotalRewardFormulasAllowed(true).setRewardBoundedUntilFormulasAllowed(true).setRewardBoundedCumulativeRewardFormulasAllowed(true).setMultiDimensionalBoundedUntilFormulasAllowed(true).setBoundedGloballyFormulasAllowed(true).setMultiDimensionalCumulativeRewardFormulasAllowed(true).setTimeOperatorsAllowed(true).setReachbilityTimeFormulasAllowed(true).setRewardAccumulationAllowed(true))) { return true; } else if (checkTask.isOnlyInitialStatesRelevantSet()) { auto multiObjectiveFragment = storm::logic::multiObjective().setCumulativeRewardFormulasAllowed(true).setTimeBoundedCumulativeRewardFormulasAllowed(true).setStepBoundedCumulativeRewardFormulasAllowed(true).setRewardBoundedCumulativeRewardFormulasAllowed(true).setTimeBoundedUntilFormulasAllowed(true).setStepBoundedUntilFormulasAllowed(true).setRewardBoundedUntilFormulasAllowed(true).setMultiDimensionalBoundedUntilFormulasAllowed(true).setMultiDimensionalCumulativeRewardFormulasAllowed(true).setRewardAccumulationAllowed(true); @@ -69,6 +69,34 @@ namespace storm { } } + template + std::unique_ptr SparseMdpPrctlModelChecker::computeBoundedGloballyProbabilities(Environment const& env, CheckTask const& checkTask) { + storm::logic::BoundedGloballyFormula const& pathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + STORM_LOG_THROW(pathFormula.hasUpperBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have (a single) upper step bound."); + STORM_LOG_THROW(pathFormula.hasIntegerLowerBound(), storm::exceptions::InvalidPropertyException, "Formula lower step bound must be discrete/integral."); + STORM_LOG_THROW(pathFormula.hasIntegerUpperBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have discrete upper time bound."); + std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + storm::modelchecker::helper::SparseNondeterministicStepBoundedHorizonHelper helper; + std::vector numericResult; + + //This works only with empty vectors, no nullptr + storm::storage::BitVector resultMaybeStates; + std::vector choiceValues; + + storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); + numericResult = helper.compute(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), allStatesBv, ~subResult.getTruthValuesVector(), pathFormula.getNonStrictLowerBound(), pathFormula.getNonStrictUpperBound(), resultMaybeStates, choiceValues, checkTask.getHint()); + // flip directions TODO + std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(numericResult))); + if(checkTask.isShieldingTask()) { + auto shield = tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(resultMaybeStates), storm::storage::BitVector(resultMaybeStates.size(), true)); + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); + } + + return result; + } + template std::unique_ptr SparseMdpPrctlModelChecker::computeBoundedUntilProbabilities(Environment const& env, CheckTask const& checkTask) { storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula(); @@ -103,9 +131,9 @@ namespace storm { std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(numericResult))); if(checkTask.isShieldingTask()) { auto shield = tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(resultMaybeStates), storm::storage::BitVector(resultMaybeStates.size(), true)); - result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); } - + return result; } } @@ -120,7 +148,7 @@ namespace storm { std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { auto shield = tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.maybeStates), storm::storage::BitVector(ret.maybeStates.size(), true)); - result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); } if (checkTask.isProduceSchedulersSet() && ret.scheduler) { result->asExplicitQuantitativeCheckResult().setScheduler(std::move(ret.scheduler)); @@ -139,10 +167,10 @@ namespace storm { auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeUntilProbabilities(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet(), checkTask.getHint()); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { - + auto shield = tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true), storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true)); - result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); - } + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); + } if (checkTask.isProduceSchedulersSet() && ret.scheduler) { result->asExplicitQuantitativeCheckResult().setScheduler(std::move(ret.scheduler)); } @@ -160,9 +188,9 @@ namespace storm { std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { auto shield = tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(),subResult.getTruthValuesVector(), storm::storage::BitVector(ret.maybeStates.size(), true)); - result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); - - } + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); + + } if (checkTask.isProduceSchedulersSet() && ret.scheduler) { result->asExplicitQuantitativeCheckResult().setScheduler(std::move(ret.scheduler)); } @@ -313,7 +341,7 @@ namespace storm { if(checkTask.isShieldingTask()) { storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); auto shield = tempest::shields::createQuantitativeShield(std::make_shared>(this->getModel()), helper.getChoiceValues(), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, allStatesBv); - result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); } else if (checkTask.isProduceSchedulersSet()) { result->asExplicitQuantitativeCheckResult().setScheduler(std::make_unique>(helper.extractScheduler())); } @@ -326,7 +354,7 @@ namespace storm { auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper helper(this->getModel().getTransitionMatrix()); storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); - auto values = helper.computeLongRunAverageRewards(env, rewardModel.get()); + auto values = helper.computeLongRunAverageRewards(env, rewardModel.get()); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(values))); if (checkTask.isProduceSchedulersSet()) { result->asExplicitQuantitativeCheckResult().setScheduler(std::make_unique>(helper.extractScheduler())); diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h index cdb87ec75..8e364d520 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h @@ -7,26 +7,27 @@ #include "storm/shields/AbstractShield.h" namespace storm { - + class Environment; - + namespace modelchecker { template class SparseMdpPrctlModelChecker : public SparsePropositionalModelChecker { public: typedef typename SparseMdpModelType::ValueType ValueType; typedef typename SparseMdpModelType::RewardModelType RewardModelType; - + explicit SparseMdpPrctlModelChecker(SparseMdpModelType const& model); - + /*! * Returns false, if this task can certainly not be handled by this model checker (independent of the concrete model). * @param requiresSingleInitialState if not nullptr, this flag is set to true iff checking this formula requires a model with a single initial state */ static bool canHandleStatic(CheckTask const& checkTask, bool* requiresSingleInitialState = nullptr); - + // The implemented methods of the AbstractModelChecker interface. virtual bool canHandle(CheckTask const& checkTask) const override; + std::unique_ptr computeBoundedGloballyProbabilities(Environment const& env, CheckTask const& checkTask); virtual std::unique_ptr computeBoundedUntilProbabilities(Environment const& env, CheckTask const& checkTask) override; virtual std::unique_ptr computeNextProbabilities(Environment const& env, CheckTask const& checkTask) override; virtual std::unique_ptr computeUntilProbabilities(Environment const& env, CheckTask const& checkTask) override; @@ -43,7 +44,7 @@ namespace storm { virtual std::unique_ptr computeHOAPathProbabilities(Environment const& env, CheckTask const& checkTask) override; virtual std::unique_ptr checkMultiObjectiveFormula(Environment const& env, CheckTask const& checkTask) override; virtual std::unique_ptr checkQuantileFormula(Environment const& env, CheckTask const& checkTask) override; - + }; } // namespace modelchecker } // namespace storm From 4c514cecdd143f0888c47c991e0eeeaa9d659fe9 Mon Sep 17 00:00:00 2001 From: sp Date: Tue, 5 Nov 2024 14:19:36 +0100 Subject: [PATCH 20/40] L(S) and G(S) (from paper) --- .../rpatl/SparseSmgRpatlModelChecker.cpp | 3 +- .../rpatl/helper/SparseSmgRpatlHelper.cpp | 38 +++ .../rpatl/helper/SparseSmgRpatlHelper.h | 1 + .../helper/internal/SoundGameViHelper.cpp | 255 ++++++++++++++++++ .../rpatl/helper/internal/SoundGameViHelper.h | 119 ++++++++ 5 files changed, 414 insertions(+), 2 deletions(-) create mode 100644 src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp create mode 100644 src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h diff --git a/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp b/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp index 79cc6fc87..cb110be26 100644 --- a/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp +++ b/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp @@ -141,8 +141,7 @@ namespace storm { ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - - auto ret = storm::modelchecker::helper::SparseSmgRpatlHelper::computeUntilProbabilities(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), statesOfCoalition, checkTask.isProduceSchedulersSet(), checkTask.getHint()); + auto ret = storm::modelchecker::helper::SparseSmgRpatlHelper::computeUntilProbabilitiesSound(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), statesOfCoalition, checkTask.isProduceSchedulersSet(), checkTask.getHint()); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); diff --git a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp index 31ddac9da..784fc27d5 100644 --- a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp @@ -9,6 +9,7 @@ #include "storm/utility/vector.h" #include "storm/utility/graph.h" #include "storm/modelchecker/rpatl/helper/internal/GameViHelper.h" +#include "storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h" namespace storm { namespace modelchecker { @@ -59,6 +60,43 @@ namespace storm { return SMGSparseModelCheckingHelperReturnType(std::move(result), std::move(relevantStates), std::move(scheduler), std::move(constrainedChoiceValues)); } + template + SMGSparseModelCheckingHelperReturnType SparseSmgRpatlHelper::computeUntilProbabilitiesSound(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, storm::storage::BitVector statesOfCoalition, bool produceScheduler, ModelCheckerHint const& hint) { + + storm::modelchecker::helper::internal::SoundGameViHelper viHelper(transitionMatrix, statesOfCoalition); + + // Initialize the x vector and solution vector result. + // TODO Fabian: maybe relevant states (later) + std::vector xL = std::vector(transitionMatrix.getRowGroupCount(), storm::utility::zero()); + // std::transform(xL.begin(), xL.end(), psiStates.begin(), xL, [](double& a) { a *= 3; }) // TODO Fabian + // assigning 1s to the xL vector for all Goal states + assert(xL.size() == psiStates.size()); + for (size_t i = 0; i < xL.size(); i++) + { + if (psiStates[xL.size() - i]) + xL[i] = 1; + } + STORM_LOG_DEBUG("xL " << xL); + std::vector xU = std::vector(transitionMatrix.getRowGroupCount(), storm::utility::zero()); + storm::storage::BitVector probGreater0 = storm::utility::graph::performProbGreater0(backwardTransitions, phiStates, psiStates); + // assigning 1s to the xU vector for all states except the states s where Prob(sEf) = 0 for all goal states f + assert(xU.size() == probGreater0.size()); + for (size_t i = 0; i < xL.size(); i++) + { + if (probGreater0[i]) + xU[i] = 1; + } + STORM_LOG_DEBUG("xU " << xU); + + std::vector result = std::vector(transitionMatrix.getRowGroupCount(), storm::utility::zero()); + // std::vector constrainedChoiceValues = std::vector(b.size(), storm::utility::zero()); // TODO Fabian: do I need this? + std::vector constrainedChoiceValues; + + viHelper.performValueIteration(env, xL, xU, goal.direction(), constrainedChoiceValues); + + assert(false); + } + template storm::storage::Scheduler SparseSmgRpatlHelper::expandScheduler(storm::storage::Scheduler scheduler, storm::storage::BitVector psiStates, storm::storage::BitVector notPhiStates) { storm::storage::Scheduler completeScheduler(psiStates.size()); diff --git a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.h b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.h index 0592c929b..741d5961d 100644 --- a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.h +++ b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.h @@ -35,6 +35,7 @@ namespace storm { class SparseSmgRpatlHelper { public: static SMGSparseModelCheckingHelperReturnType computeUntilProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, storm::storage::BitVector statesOfCoalition, bool produceScheduler, ModelCheckerHint const& hint = ModelCheckerHint()); + static SMGSparseModelCheckingHelperReturnType computeUntilProbabilitiesSound(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, storm::storage::BitVector statesOfCoalition, bool produceScheduler, ModelCheckerHint const& hint); static SMGSparseModelCheckingHelperReturnType computeGloballyProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& psiStates, bool qualitative, storm::storage::BitVector statesOfCoalition, bool produceScheduler, ModelCheckerHint const& hint = ModelCheckerHint()); static SMGSparseModelCheckingHelperReturnType computeNextProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& psiStates, bool qualitative, storm::storage::BitVector statesOfCoalition, bool produceScheduler, ModelCheckerHint const& hint); static SMGSparseModelCheckingHelperReturnType computeBoundedGloballyProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& psiStates, bool qualitative, storm::storage::BitVector statesOfCoalition, bool produceScheduler, ModelCheckerHint const& hint, uint64_t lowerBound, uint64_t upperBound); diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp new file mode 100644 index 000000000..239a89d31 --- /dev/null +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp @@ -0,0 +1,255 @@ +#include "SoundGameViHelper.h" + +#include "storm/environment/Environment.h" +#include "storm/environment/solver/SolverEnvironment.h" +#include "storm/environment/solver/GameSolverEnvironment.h" + + +#include "storm/utility/SignalHandler.h" +#include "storm/utility/vector.h" + +namespace storm { + namespace modelchecker { + namespace helper { + namespace internal { + + template + SoundGameViHelper::SoundGameViHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector statesOfCoalition) : _transitionMatrix(transitionMatrix), _statesOfCoalition(statesOfCoalition) { + // Intentionally left empty. + } + + template + void SoundGameViHelper::prepareSolversAndMultipliers(const Environment& env) { + STORM_LOG_DEBUG("\n" << _transitionMatrix); + _multiplier = storm::solver::MultiplierFactory().create(env, _transitionMatrix); + _x1IsCurrent = false; + } + + template + void SoundGameViHelper::performValueIteration(Environment const& env, std::vector& xL, std::vector& xU, storm::solver::OptimizationDirection const dir, std::vector& constrainedChoiceValues) { + // new pair (x_old, x_new) for over_approximation() + + prepareSolversAndMultipliers(env); + // Get precision for convergence check. + ValueType precision = storm::utility::convertNumber(env.solver().game().getPrecision()); + + STORM_LOG_DEBUG("hello" << "world"); + uint64_t maxIter = env.solver().game().getMaximalNumberOfIterations(); + //_x1.assign(_transitionMatrix.getRowGroupCount(), storm::utility::zero()); + _x1L = xL; + _x2L = _x1L; + + _x1U = xU; + _x2U = _x1U; + + if (this->isProduceSchedulerSet()) { + if (!this->_producedOptimalChoices.is_initialized()) { + this->_producedOptimalChoices.emplace(); + } + this->_producedOptimalChoices->resize(this->_transitionMatrix.getRowGroupCount()); + } + + uint64_t iter = 0; + constrainedChoiceValues = std::vector(xL.size(), storm::utility::zero()); // ?? + + while (iter < maxIter) { + performIterationStep(env, dir); + if (checkConvergence(precision)) { + //_multiplier->multiply(env, xNewL(), nullptr, constrainedChoiceValues); // TODO Fabian: ??? + break; + } + if (storm::utility::resources::isTerminate()) { + break; + } + ++iter; + } + xL = xNewL(); + xU = xNewU(); + + STORM_LOG_DEBUG("result xL: " << xL); + STORM_LOG_DEBUG("result xU: " << xU); + + if (isProduceSchedulerSet()) { + // We will be doing one more iteration step and track scheduler choices this time. + performIterationStep(env, dir, &_producedOptimalChoices.get()); + } + } + + template + void SoundGameViHelper::performIterationStep(Environment const& env, storm::solver::OptimizationDirection const dir, std::vector* choices) { + // under approximation + if (!_multiplier) { + prepareSolversAndMultipliers(env); + } + _x1IsCurrent = !_x1IsCurrent; + + if (choices == nullptr) { + _multiplier->multiplyAndReduce(env, dir, xOldL(), nullptr, xNewL(), nullptr, &_statesOfCoalition); + } else { + _multiplier->multiplyAndReduce(env, dir, xOldL(), nullptr, xNewL(), choices, &_statesOfCoalition); + } + + // over_approximation + + if (choices == nullptr) { + _multiplier->multiplyAndReduce(env, dir, xOldU(), nullptr, xNewU(), nullptr, &_statesOfCoalition); + } else { + _multiplier->multiplyAndReduce(env, dir, xOldU(), nullptr, xNewU(), choices, &_statesOfCoalition); + } + + // TODO Fabian: find_MSECs() & deflate() + + } + + template + bool SoundGameViHelper::checkConvergence(ValueType threshold) const { + STORM_LOG_ASSERT(_multiplier, "tried to check for convergence without doing an iteration first."); + // Now check whether the currently produced results are precise enough + STORM_LOG_ASSERT(threshold > storm::utility::zero(), "Did not expect a non-positive threshold."); + auto x1It = xOldL().begin(); + auto x1Ite = xOldL().end(); + auto x2It = xNewL().begin(); + ValueType maxDiff = (*x2It - *x1It); + ValueType minDiff = maxDiff; + // The difference between maxDiff and minDiff is zero at this point. Thus, it doesn't make sense to check the threshold now. + for (++x1It, ++x2It; x1It != x1Ite; ++x1It, ++x2It) { + ValueType diff = (*x2It - *x1It); + // Potentially update maxDiff or minDiff + bool skipCheck = false; + if (maxDiff < diff) { + maxDiff = diff; + } else if (minDiff > diff) { + minDiff = diff; + } else { + skipCheck = true; + } + // Check convergence + if (!skipCheck && (maxDiff - minDiff) > threshold) { + return false; + } + } + return true; + } + + template + void SoundGameViHelper::setProduceScheduler(bool value) { + _produceScheduler = value; + } + + template + bool SoundGameViHelper::isProduceSchedulerSet() const { + return _produceScheduler; + } + + template + void SoundGameViHelper::setShieldingTask(bool value) { + _shieldingTask = value; + } + + template + bool SoundGameViHelper::isShieldingTask() const { + return _shieldingTask; + } + + template + void SoundGameViHelper::updateTransitionMatrix(storm::storage::SparseMatrix newTransitionMatrix) { + _transitionMatrix = newTransitionMatrix; + } + + template + void SoundGameViHelper::updateStatesOfCoalition(storm::storage::BitVector newStatesOfCoalition) { + _statesOfCoalition = newStatesOfCoalition; + } + + template + std::vector const& SoundGameViHelper::getProducedOptimalChoices() const { + STORM_LOG_ASSERT(this->isProduceSchedulerSet(), "Trying to get the produced optimal choices although no scheduler was requested."); + STORM_LOG_ASSERT(this->_producedOptimalChoices.is_initialized(), "Trying to get the produced optimal choices but none were available. Was there a computation call before?"); + return this->_producedOptimalChoices.get(); + } + + template + std::vector& SoundGameViHelper::getProducedOptimalChoices() { + STORM_LOG_ASSERT(this->isProduceSchedulerSet(), "Trying to get the produced optimal choices although no scheduler was requested."); + STORM_LOG_ASSERT(this->_producedOptimalChoices.is_initialized(), "Trying to get the produced optimal choices but none were available. Was there a computation call before?"); + return this->_producedOptimalChoices.get(); + } + + template + storm::storage::Scheduler SoundGameViHelper::extractScheduler() const{ + auto const& optimalChoices = getProducedOptimalChoices(); + storm::storage::Scheduler scheduler(optimalChoices.size()); + for (uint64_t state = 0; state < optimalChoices.size(); ++state) { + scheduler.setChoice(optimalChoices[state], state); + } + return scheduler; + } + + template + void SoundGameViHelper::getChoiceValues(Environment const& env, std::vector const& x, std::vector& choiceValues) { + _multiplier->multiply(env, x, nullptr, choiceValues); + } + + template + void SoundGameViHelper::fillChoiceValuesVector(std::vector& choiceValues, storm::storage::BitVector psiStates, std::vector::index_type> rowGroupIndices) { + std::vector allChoices = std::vector(rowGroupIndices.at(rowGroupIndices.size() - 1), storm::utility::zero()); + auto choice_it = choiceValues.begin(); + for(uint state = 0; state < rowGroupIndices.size() - 1; state++) { + uint rowGroupSize = rowGroupIndices[state + 1] - rowGroupIndices[state]; + if (psiStates.get(state)) { + for(uint choice = 0; choice < rowGroupSize; choice++, choice_it++) { + allChoices.at(rowGroupIndices.at(state) + choice) = *choice_it; + } + } + } + choiceValues = allChoices; + } + + template + std::vector& SoundGameViHelper::xNewL() { + return _x1IsCurrent ? _x1L : _x2L; + } + + template + std::vector const& SoundGameViHelper::xNewL() const { + return _x1IsCurrent ? _x1L : _x2L; + } + + template + std::vector& SoundGameViHelper::xOldL() { + return _x1IsCurrent ? _x2L : _x1L; + } + + template + std::vector const& SoundGameViHelper::xOldL() const { + return _x1IsCurrent ? _x2L : _x1L; + } + + template + std::vector& SoundGameViHelper::xNewU() { + return _x1IsCurrent ? _x1U : _x2U; + } + + template + std::vector const& SoundGameViHelper::xNewU() const { + return _x1IsCurrent ? _x1U : _x2U; + } + + template + std::vector& SoundGameViHelper::xOldU() { + return _x1IsCurrent ? _x2U : _x1U; + } + + template + std::vector const& SoundGameViHelper::xOldU() const { + return _x1IsCurrent ? _x2U : _x1U; + } + + template class SoundGameViHelper; +#ifdef STORM_HAVE_CARL + template class SoundGameViHelper; +#endif + } + } + } +} diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h new file mode 100644 index 000000000..f4e3d5b35 --- /dev/null +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h @@ -0,0 +1,119 @@ +#pragma once + +#include "storm/storage/SparseMatrix.h" +#include "storm/solver/LinearEquationSolver.h" +#include "storm/solver/MinMaxLinearEquationSolver.h" +#include "storm/solver/Multiplier.h" + +namespace storm { + class Environment; + + namespace storage { + template class Scheduler; + } + + namespace modelchecker { + namespace helper { + namespace internal { + + template + class SoundGameViHelper { + public: + SoundGameViHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector statesOfCoalition); + + void prepareSolversAndMultipliers(const Environment& env); + + /*! + * Perform value iteration until convergence + */ + void performValueIteration(Environment const& env, std::vector& xL, std::vector& xU, storm::solver::OptimizationDirection const dir, std::vector& constrainedChoiceValues); + + /*! + * Sets whether an optimal scheduler shall be constructed during the computation + */ + void setProduceScheduler(bool value); + + /*! + * @return whether an optimal scheduler shall be constructed during the computation + */ + bool isProduceSchedulerSet() const; + + /*! + * Sets whether an optimal scheduler shall be constructed during the computation + */ + void setShieldingTask(bool value); + + /*! + * @return whether an optimal scheduler shall be constructed during the computation + */ + bool isShieldingTask() const; + + /*! + * Changes the transitionMatrix to the given one. + */ + void updateTransitionMatrix(storm::storage::SparseMatrix newTransitionMatrix); + + /*! + * Changes the statesOfCoalition to the given one. + */ + void updateStatesOfCoalition(storm::storage::BitVector newStatesOfCoalition); + + storm::storage::Scheduler extractScheduler() const; + + void getChoiceValues(Environment const& env, std::vector const& x, std::vector& choiceValues); + + /*! + * Fills the choice values vector to the original size with zeros for ~psiState choices. + */ + void fillChoiceValuesVector(std::vector& choiceValues, storm::storage::BitVector psiStates, std::vector::index_type> rowGroupIndices); + + private: + /*! + * Performs one iteration step for value iteration + */ + void performIterationStep(Environment const& env, storm::solver::OptimizationDirection const dir, std::vector* choices = nullptr); + + /*! + * Checks whether the curently computed value achieves the desired precision + */ + bool checkConvergence(ValueType precision) const; + + std::vector& xNewL(); + std::vector const& xNewL() const; + + std::vector& xOldL(); + std::vector const& xOldL() const; + + std::vector& xNewU(); + std::vector const& xNewU() const; + + std::vector& xOldU(); + std::vector const& xOldU() const; + + bool _x1IsCurrent; + + /*! + * @pre before calling this, a computation call should have been performed during which scheduler production was enabled. + * @return the produced scheduler of the most recent call. + */ + std::vector const& getProducedOptimalChoices() const; + + /*! + * @pre before calling this, a computation call should have been performed during which scheduler production was enabled. + * @return the produced scheduler of the most recent call. + */ + std::vector& getProducedOptimalChoices(); + + storm::storage::SparseMatrix _transitionMatrix; + storm::storage::BitVector _statesOfCoalition; + std::vector _x, _x1L, _x2L, _x1U, _x2U; + std::unique_ptr> _multiplier; + + bool _produceScheduler = false; + bool _shieldingTask = false; + boost::optional> _producedOptimalChoices; + }; + } + } + } +} From 61b59e64fc03b8dec1311ced45760720495db59c Mon Sep 17 00:00:00 2001 From: Fabian Russold Date: Fri, 19 Jul 2024 11:27:26 +0200 Subject: [PATCH 21/40] reducedMinimizerActions BitVec --- .../rpatl/helper/SparseSmgRpatlHelper.cpp | 6 +- .../helper/internal/SoundGameViHelper.cpp | 63 +++++++++++++++---- .../rpatl/helper/internal/SoundGameViHelper.h | 9 ++- 3 files changed, 63 insertions(+), 15 deletions(-) diff --git a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp index 784fc27d5..1a346333b 100644 --- a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp @@ -63,7 +63,7 @@ namespace storm { template SMGSparseModelCheckingHelperReturnType SparseSmgRpatlHelper::computeUntilProbabilitiesSound(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, storm::storage::BitVector statesOfCoalition, bool produceScheduler, ModelCheckerHint const& hint) { - storm::modelchecker::helper::internal::SoundGameViHelper viHelper(transitionMatrix, statesOfCoalition); + storm::modelchecker::helper::internal::SoundGameViHelper viHelper(transitionMatrix, statesOfCoalition, goal.direction()); // Initialize the x vector and solution vector result. // TODO Fabian: maybe relevant states (later) @@ -73,7 +73,7 @@ namespace storm { assert(xL.size() == psiStates.size()); for (size_t i = 0; i < xL.size(); i++) { - if (psiStates[xL.size() - i]) + if (psiStates[i]) xL[i] = 1; } STORM_LOG_DEBUG("xL " << xL); @@ -81,7 +81,7 @@ namespace storm { storm::storage::BitVector probGreater0 = storm::utility::graph::performProbGreater0(backwardTransitions, phiStates, psiStates); // assigning 1s to the xU vector for all states except the states s where Prob(sEf) = 0 for all goal states f assert(xU.size() == probGreater0.size()); - for (size_t i = 0; i < xL.size(); i++) + for (size_t i = 0; i < xL.size(); i++) // TODO Fabian: do this more efficient { if (probGreater0[i]) xU[i] = 1; diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp index 239a89d31..a3817540b 100644 --- a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp @@ -14,7 +14,7 @@ namespace storm { namespace internal { template - SoundGameViHelper::SoundGameViHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector statesOfCoalition) : _transitionMatrix(transitionMatrix), _statesOfCoalition(statesOfCoalition) { + SoundGameViHelper::SoundGameViHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector statesOfCoalition, OptimizationDirection const& optimizationDirection) : _transitionMatrix(transitionMatrix), _statesOfCoalition(statesOfCoalition), _optimizationDirection(optimizationDirection) { // Intentionally left empty. } @@ -23,6 +23,7 @@ namespace storm { STORM_LOG_DEBUG("\n" << _transitionMatrix); _multiplier = storm::solver::MultiplierFactory().create(env, _transitionMatrix); _x1IsCurrent = false; + _minimizerStates = _optimizationDirection == OptimizationDirection::Maximize ? _statesOfCoalition : ~_statesOfCoalition; } template @@ -77,30 +78,70 @@ namespace storm { template void SoundGameViHelper::performIterationStep(Environment const& env, storm::solver::OptimizationDirection const dir, std::vector* choices) { + storm::storage::BitVector reducedMinimizerActions = {storm::storage::BitVector(this->_transitionMatrix.getRowCount(), true)}; + // under approximation if (!_multiplier) { prepareSolversAndMultipliers(env); } _x1IsCurrent = !_x1IsCurrent; - if (choices == nullptr) { - _multiplier->multiplyAndReduce(env, dir, xOldL(), nullptr, xNewL(), nullptr, &_statesOfCoalition); - } else { - _multiplier->multiplyAndReduce(env, dir, xOldL(), nullptr, xNewL(), choices, &_statesOfCoalition); - } + std::vector choiceValues = xNewL(); + choiceValues.resize(this->_transitionMatrix.getRowCount()); + + _multiplier->multiply(env, xOldL(), nullptr, choiceValues); + reduceChoiceValues(choiceValues, &reducedMinimizerActions); + xNewL() = choiceValues; // over_approximation - if (choices == nullptr) { - _multiplier->multiplyAndReduce(env, dir, xOldU(), nullptr, xNewU(), nullptr, &_statesOfCoalition); - } else { - _multiplier->multiplyAndReduce(env, dir, xOldU(), nullptr, xNewU(), choices, &_statesOfCoalition); - } + _multiplier->multiplyAndReduce(env, dir, xOldU(), nullptr, xNewU(), nullptr, &_statesOfCoalition); // TODO Fabian: find_MSECs() & deflate() + } + + template + void SoundGameViHelper::reduceChoiceValues(std::vector& choiceValues, storm::storage::BitVector* result) + { + // result BitVec should be initialized with 1s outside the function + // restrict rows + + auto rowGroupIndices = this->_transitionMatrix.getRowGroupIndices(); + auto choice_it = choiceValues.begin(); + STORM_LOG_DEBUG("MinStates " << _minimizerStates); + STORM_LOG_DEBUG("init choiceVal " << choiceValues); + + + for(uint state = 0; state < rowGroupIndices.size() - 1; state++) { + uint rowGroupSize = rowGroupIndices[state + 1] - rowGroupIndices[state]; + ValueType optChoice; + if (_minimizerStates[state]) { // check if current state is minimizer state + // getting the optimal minimizer choice for the given state + optChoice = *std::min_element(choice_it, choice_it + rowGroupSize); + + for (uint choice = 0; choice < rowGroupSize; choice++, choice_it++) { + if (*choice_it > optChoice) { + result->set(rowGroupIndices[state] + choice, 0); + } + } + // reducing the xNew() (choiceValues) vector for minimizer states + choiceValues[state] = optChoice; + } + else + { + optChoice = *std::max_element(choice_it, choice_it + rowGroupSize); + // reducing the xNew() (choiceValues) vector for maximizer states + choiceValues[state] = optChoice; + choice_it += rowGroupSize; + } + } + choiceValues.resize(this->_transitionMatrix.getRowGroupCount()); + STORM_LOG_DEBUG("reduced BitVec: " << *result); + STORM_LOG_DEBUG("reduced x Vector: " << choiceValues); } + template bool SoundGameViHelper::checkConvergence(ValueType threshold) const { STORM_LOG_ASSERT(_multiplier, "tried to check for convergence without doing an iteration first."); diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h index f4e3d5b35..21ec6b464 100644 --- a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h @@ -19,7 +19,7 @@ namespace storm { template class SoundGameViHelper { public: - SoundGameViHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector statesOfCoalition); + SoundGameViHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector statesOfCoalition, OptimizationDirection const& optimizationDirection); void prepareSolversAndMultipliers(const Environment& env); @@ -73,6 +73,10 @@ namespace storm { */ void performIterationStep(Environment const& env, storm::solver::OptimizationDirection const dir, std::vector* choices = nullptr); + void reduceChoiceValues(std::vector& choiceValues, storm::storage::BitVector* result); + // + // für alle minimizer states -> reduce zu optimal actions + /*! * Checks whether the curently computed value achieves the desired precision */ @@ -92,6 +96,8 @@ namespace storm { bool _x1IsCurrent; + storm::storage::BitVector _minimizerStates; + /*! * @pre before calling this, a computation call should have been performed during which scheduler production was enabled. * @return the produced scheduler of the most recent call. @@ -108,6 +114,7 @@ namespace storm { storm::storage::BitVector _statesOfCoalition; std::vector _x, _x1L, _x2L, _x1U, _x2U; std::unique_ptr> _multiplier; + OptimizationDirection _optimizationDirection; bool _produceScheduler = false; bool _shieldingTask = false; From 9a414442171ac9b0b7babc4e777435f60241b42f Mon Sep 17 00:00:00 2001 From: Fabian Russold Date: Fri, 19 Jul 2024 17:01:01 +0200 Subject: [PATCH 22/40] finding MSECs done, in progress: deflating the MSECs --- .../rpatl/helper/SparseSmgRpatlHelper.cpp | 2 +- .../helper/internal/SoundGameViHelper.cpp | 44 ++++++++++++++++--- .../rpatl/helper/internal/SoundGameViHelper.h | 8 ++-- 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp index 1a346333b..3b824341f 100644 --- a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp @@ -63,7 +63,7 @@ namespace storm { template SMGSparseModelCheckingHelperReturnType SparseSmgRpatlHelper::computeUntilProbabilitiesSound(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, storm::storage::BitVector statesOfCoalition, bool produceScheduler, ModelCheckerHint const& hint) { - storm::modelchecker::helper::internal::SoundGameViHelper viHelper(transitionMatrix, statesOfCoalition, goal.direction()); + storm::modelchecker::helper::internal::SoundGameViHelper viHelper(transitionMatrix, backwardTransitions, statesOfCoalition, goal.direction()); // Initialize the x vector and solution vector result. // TODO Fabian: maybe relevant states (later) diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp index a3817540b..198550e6f 100644 --- a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp @@ -14,7 +14,7 @@ namespace storm { namespace internal { template - SoundGameViHelper::SoundGameViHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector statesOfCoalition, OptimizationDirection const& optimizationDirection) : _transitionMatrix(transitionMatrix), _statesOfCoalition(statesOfCoalition), _optimizationDirection(optimizationDirection) { + SoundGameViHelper::SoundGameViHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector statesOfCoalition, OptimizationDirection const& optimizationDirection) : _transitionMatrix(transitionMatrix), _backwardTransitions(backwardTransitions), _statesOfCoalition(statesOfCoalition), _optimizationDirection(optimizationDirection) { // Intentionally left empty. } @@ -34,7 +34,6 @@ namespace storm { // Get precision for convergence check. ValueType precision = storm::utility::convertNumber(env.solver().game().getPrecision()); - STORM_LOG_DEBUG("hello" << "world"); uint64_t maxIter = env.solver().game().getMaximalNumberOfIterations(); //_x1.assign(_transitionMatrix.getRowGroupCount(), storm::utility::zero()); _x1L = xL; @@ -97,14 +96,48 @@ namespace storm { _multiplier->multiplyAndReduce(env, dir, xOldU(), nullptr, xNewU(), nullptr, &_statesOfCoalition); + // restricting the none optimal minimizer choices + storage::SparseMatrix restrictedTransMatrix = this->_transitionMatrix.restrictRows(reducedMinimizerActions); + + // storage::SparseMatrix restrictedBackMatrix = this->_backwardTransitions.restrictRows(reducedMinimizerActions); + STORM_LOG_DEBUG("restricted Transition: \n" << restrictedTransMatrix); + // TODO Fabian: find_MSECs() & deflate() + storm::storage::MaximalEndComponentDecomposition MECD = storm::storage::MaximalEndComponentDecomposition(restrictedTransMatrix, _backwardTransitions); + + STORM_LOG_DEBUG("MECD: \n" << MECD); + // deflate(MECD,restrictedTransMatrix, xNewU()); + } + + template + void SoundGameViHelper::deflate(storm::storage::MaximalEndComponentDecomposition const MECD, storage::SparseMatrix const restrictedMatrix, std::vector& xU) + { + /* auto rowGroupIndices = restrictedMatrix.getRowGroupIndices(); + auto mec_it = MECD.begin(); + + + for(uint state = 0; state < rowGroupIndices.size() - 1; state++) { + uint rowGroupSize = rowGroupIndices[state + 1] - rowGroupIndices[state]; + ValueType optChoice; + if (!_minimizerStates[state]) { // check if current state is maximizer state + // getting the optimal minimizer choice for the given state + optChoice = *std::min_element(choice_it, choice_it + rowGroupSize); + + for (uint choice = 0; choice < rowGroupSize; choice++, choice_it++) { + if (*choice_it > optChoice) { + result->set(rowGroupIndices[state] + choice, 0); + } + } + // reducing the xNew() (choiceValues) vector for minimizer states + choiceValues[state] = optChoice; + } + } */ } template void SoundGameViHelper::reduceChoiceValues(std::vector& choiceValues, storm::storage::BitVector* result) { - // result BitVec should be initialized with 1s outside the function - // restrict rows + // result BitVec should be initialized with 1s outside the method auto rowGroupIndices = this->_transitionMatrix.getRowGroupIndices(); auto choice_it = choiceValues.begin(); @@ -137,8 +170,6 @@ namespace storm { } } choiceValues.resize(this->_transitionMatrix.getRowGroupCount()); - STORM_LOG_DEBUG("reduced BitVec: " << *result); - STORM_LOG_DEBUG("reduced x Vector: " << choiceValues); } @@ -177,6 +208,7 @@ namespace storm { _produceScheduler = value; } + template bool SoundGameViHelper::isProduceSchedulerSet() const { return _produceScheduler; diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h index 21ec6b464..f140eb734 100644 --- a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h @@ -4,6 +4,7 @@ #include "storm/solver/LinearEquationSolver.h" #include "storm/solver/MinMaxLinearEquationSolver.h" #include "storm/solver/Multiplier.h" +#include "storm/storage/MaximalEndComponentDecomposition.h" namespace storm { class Environment; @@ -19,7 +20,7 @@ namespace storm { template class SoundGameViHelper { public: - SoundGameViHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector statesOfCoalition, OptimizationDirection const& optimizationDirection); + SoundGameViHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector statesOfCoalition, OptimizationDirection const& optimizationDirection); void prepareSolversAndMultipliers(const Environment& env); @@ -73,9 +74,9 @@ namespace storm { */ void performIterationStep(Environment const& env, storm::solver::OptimizationDirection const dir, std::vector* choices = nullptr); + void deflate(storm::storage::MaximalEndComponentDecomposition const MECD, storage::SparseMatrix const restrictedMatrix, std::vector& xU); + void reduceChoiceValues(std::vector& choiceValues, storm::storage::BitVector* result); - // - // für alle minimizer states -> reduce zu optimal actions /*! * Checks whether the curently computed value achieves the desired precision @@ -111,6 +112,7 @@ namespace storm { std::vector& getProducedOptimalChoices(); storm::storage::SparseMatrix _transitionMatrix; + storm::storage::SparseMatrix _backwardTransitions; storm::storage::BitVector _statesOfCoalition; std::vector _x, _x1L, _x2L, _x1U, _x2U; std::unique_ptr> _multiplier; From 2de38edbff72e97d222e4c76549117bc08321648 Mon Sep 17 00:00:00 2001 From: Fabian Russold Date: Thu, 25 Jul 2024 15:35:50 +0200 Subject: [PATCH 23/40] basic implementation done --- .../rpatl/helper/SparseSmgRpatlHelper.cpp | 2 +- .../helper/internal/SoundGameViHelper.cpp | 63 ++++++++++--------- .../rpatl/helper/internal/SoundGameViHelper.h | 4 +- 3 files changed, 39 insertions(+), 30 deletions(-) diff --git a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp index 3b824341f..29d41b45c 100644 --- a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp @@ -63,7 +63,7 @@ namespace storm { template SMGSparseModelCheckingHelperReturnType SparseSmgRpatlHelper::computeUntilProbabilitiesSound(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, storm::storage::BitVector statesOfCoalition, bool produceScheduler, ModelCheckerHint const& hint) { - storm::modelchecker::helper::internal::SoundGameViHelper viHelper(transitionMatrix, backwardTransitions, statesOfCoalition, goal.direction()); + storm::modelchecker::helper::internal::SoundGameViHelper viHelper(transitionMatrix, backwardTransitions, statesOfCoalition, psiStates, goal.direction()); // Initialize the x vector and solution vector result. // TODO Fabian: maybe relevant states (later) diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp index 198550e6f..d035f6fd7 100644 --- a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp @@ -14,7 +14,7 @@ namespace storm { namespace internal { template - SoundGameViHelper::SoundGameViHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector statesOfCoalition, OptimizationDirection const& optimizationDirection) : _transitionMatrix(transitionMatrix), _backwardTransitions(backwardTransitions), _statesOfCoalition(statesOfCoalition), _optimizationDirection(optimizationDirection) { + SoundGameViHelper::SoundGameViHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector statesOfCoalition, storm::storage::BitVector psiStates, OptimizationDirection const& optimizationDirection) : _transitionMatrix(transitionMatrix), _backwardTransitions(backwardTransitions), _statesOfCoalition(statesOfCoalition), _psiStates(psiStates), _optimizationDirection(optimizationDirection) { // Intentionally left empty. } @@ -98,40 +98,47 @@ namespace storm { // restricting the none optimal minimizer choices storage::SparseMatrix restrictedTransMatrix = this->_transitionMatrix.restrictRows(reducedMinimizerActions); + _multiplierRestricted = storm::solver::MultiplierFactory().create(env, restrictedTransMatrix); - // storage::SparseMatrix restrictedBackMatrix = this->_backwardTransitions.restrictRows(reducedMinimizerActions); - STORM_LOG_DEBUG("restricted Transition: \n" << restrictedTransMatrix); + // storage::SparseMatrix restrictedBackMatrix = this->_backwardTransitions.restrictRows(reducedMinimizerActions); + // STORM_LOG_DEBUG("restricted Transition: \n" << restrictedTransMatrix); - // TODO Fabian: find_MSECs() & deflate() + // find_MSECs() & deflate() storm::storage::MaximalEndComponentDecomposition MECD = storm::storage::MaximalEndComponentDecomposition(restrictedTransMatrix, _backwardTransitions); - STORM_LOG_DEBUG("MECD: \n" << MECD); - // deflate(MECD,restrictedTransMatrix, xNewU()); + // STORM_LOG_DEBUG("MECD: \n" << MECD); + deflate(MECD,restrictedTransMatrix, xNewU()); } template - void SoundGameViHelper::deflate(storm::storage::MaximalEndComponentDecomposition const MECD, storage::SparseMatrix const restrictedMatrix, std::vector& xU) - { - /* auto rowGroupIndices = restrictedMatrix.getRowGroupIndices(); - auto mec_it = MECD.begin(); - - - for(uint state = 0; state < rowGroupIndices.size() - 1; state++) { - uint rowGroupSize = rowGroupIndices[state + 1] - rowGroupIndices[state]; - ValueType optChoice; - if (!_minimizerStates[state]) { // check if current state is maximizer state - // getting the optimal minimizer choice for the given state - optChoice = *std::min_element(choice_it, choice_it + rowGroupSize); - - for (uint choice = 0; choice < rowGroupSize; choice++, choice_it++) { - if (*choice_it > optChoice) { - result->set(rowGroupIndices[state] + choice, 0); + void SoundGameViHelper::deflate(storm::storage::MaximalEndComponentDecomposition const MECD, storage::SparseMatrix const restrictedMatrix, std::vector& xU) { + auto rowGroupIndices = restrictedMatrix.getRowGroupIndices(); + + // iterating over all MSECs + for (auto smec_it : MECD) { + ValueType bestExit = 0; + for (uint state = 0; state < rowGroupIndices.size() - 1; state++) { + uint rowGroupSize = rowGroupIndices[state + 1] - rowGroupIndices[state]; + if (!_minimizerStates[state] && smec_it.containsState(state)) { // check if current state is maximizer state + // getting the optimal minimizer choice for the given state + + for (uint choice = 0; choice < rowGroupSize; choice++) { + if (!smec_it.containsChoice(state, choice + rowGroupIndices[state])) { + ValueType choiceValue = 0; + _multiplierRestricted->multiplyRow(choice + rowGroupIndices[state], xU, choiceValue); + if (choiceValue > bestExit) + bestExit = choiceValue; + } } } - // reducing the xNew() (choiceValues) vector for minimizer states - choiceValues[state] = optChoice; } - } */ + auto stateSet = smec_it.getStateSet(); + for (auto smec_state : stateSet) + { + if (!_psiStates[smec_state]) + xU[smec_state] = std::min(xU[smec_state], bestExit); + } + } } template @@ -178,9 +185,9 @@ namespace storm { STORM_LOG_ASSERT(_multiplier, "tried to check for convergence without doing an iteration first."); // Now check whether the currently produced results are precise enough STORM_LOG_ASSERT(threshold > storm::utility::zero(), "Did not expect a non-positive threshold."); - auto x1It = xOldL().begin(); - auto x1Ite = xOldL().end(); - auto x2It = xNewL().begin(); + auto x1It = xNewL().begin(); + auto x1Ite = xNewL().end(); + auto x2It = xNewU().begin(); ValueType maxDiff = (*x2It - *x1It); ValueType minDiff = maxDiff; // The difference between maxDiff and minDiff is zero at this point. Thus, it doesn't make sense to check the threshold now. diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h index f140eb734..5fecd8d87 100644 --- a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h @@ -20,7 +20,7 @@ namespace storm { template class SoundGameViHelper { public: - SoundGameViHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector statesOfCoalition, OptimizationDirection const& optimizationDirection); + SoundGameViHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector statesOfCoalition, storm::storage::BitVector psiStates, OptimizationDirection const& optimizationDirection); void prepareSolversAndMultipliers(const Environment& env); @@ -114,8 +114,10 @@ namespace storm { storm::storage::SparseMatrix _transitionMatrix; storm::storage::SparseMatrix _backwardTransitions; storm::storage::BitVector _statesOfCoalition; + storm::storage::BitVector _psiStates; std::vector _x, _x1L, _x2L, _x1U, _x2U; std::unique_ptr> _multiplier; + std::unique_ptr> _multiplierRestricted; OptimizationDirection _optimizationDirection; bool _produceScheduler = false; From de9a5646b0e9c6fe45d5d6b07b9c5e7d67cdba6b Mon Sep 17 00:00:00 2001 From: Fabian Russold Date: Fri, 26 Jul 2024 09:41:42 +0200 Subject: [PATCH 24/40] small performance fix in deflate() --- .../helper/internal/SoundGameViHelper.cpp | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp index d035f6fd7..10de545e3 100644 --- a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp @@ -80,6 +80,7 @@ namespace storm { storm::storage::BitVector reducedMinimizerActions = {storm::storage::BitVector(this->_transitionMatrix.getRowCount(), true)}; // under approximation + if (!_multiplier) { prepareSolversAndMultipliers(env); } @@ -100,28 +101,26 @@ namespace storm { storage::SparseMatrix restrictedTransMatrix = this->_transitionMatrix.restrictRows(reducedMinimizerActions); _multiplierRestricted = storm::solver::MultiplierFactory().create(env, restrictedTransMatrix); - // storage::SparseMatrix restrictedBackMatrix = this->_backwardTransitions.restrictRows(reducedMinimizerActions); // STORM_LOG_DEBUG("restricted Transition: \n" << restrictedTransMatrix); // find_MSECs() & deflate() - storm::storage::MaximalEndComponentDecomposition MECD = storm::storage::MaximalEndComponentDecomposition(restrictedTransMatrix, _backwardTransitions); + storm::storage::MaximalEndComponentDecomposition MSEC = storm::storage::MaximalEndComponentDecomposition(restrictedTransMatrix, _backwardTransitions); // STORM_LOG_DEBUG("MECD: \n" << MECD); - deflate(MECD,restrictedTransMatrix, xNewU()); + deflate(MSEC,restrictedTransMatrix, xNewU()); } template - void SoundGameViHelper::deflate(storm::storage::MaximalEndComponentDecomposition const MECD, storage::SparseMatrix const restrictedMatrix, std::vector& xU) { + void SoundGameViHelper::deflate(storm::storage::MaximalEndComponentDecomposition const MSEC, storage::SparseMatrix const restrictedMatrix, std::vector& xU) { auto rowGroupIndices = restrictedMatrix.getRowGroupIndices(); // iterating over all MSECs - for (auto smec_it : MECD) { + for (auto smec_it : MSEC) { ValueType bestExit = 0; - for (uint state = 0; state < rowGroupIndices.size() - 1; state++) { + auto stateSet = smec_it.getStateSet(); + for (uint state : stateSet) { uint rowGroupSize = rowGroupIndices[state + 1] - rowGroupIndices[state]; - if (!_minimizerStates[state] && smec_it.containsState(state)) { // check if current state is maximizer state - // getting the optimal minimizer choice for the given state - + if (!_minimizerStates[state]) { // check if current state is maximizer state for (uint choice = 0; choice < rowGroupSize; choice++) { if (!smec_it.containsChoice(state, choice + rowGroupIndices[state])) { ValueType choiceValue = 0; @@ -132,11 +131,10 @@ namespace storm { } } } - auto stateSet = smec_it.getStateSet(); - for (auto smec_state : stateSet) - { - if (!_psiStates[smec_state]) - xU[smec_state] = std::min(xU[smec_state], bestExit); + // deflating the states of the current MSEC + for (uint state : stateSet) { + if (!_psiStates[state]) + xU[state] = std::min(xU[state], bestExit); } } } @@ -149,10 +147,6 @@ namespace storm { auto rowGroupIndices = this->_transitionMatrix.getRowGroupIndices(); auto choice_it = choiceValues.begin(); - STORM_LOG_DEBUG("MinStates " << _minimizerStates); - STORM_LOG_DEBUG("init choiceVal " << choiceValues); - - for(uint state = 0; state < rowGroupIndices.size() - 1; state++) { uint rowGroupSize = rowGroupIndices[state + 1] - rowGroupIndices[state]; ValueType optChoice; From 877067cdcca13bd6204b21cddbb7821b30d985eb Mon Sep 17 00:00:00 2001 From: Fabian Russold Date: Fri, 26 Jul 2024 10:29:46 +0200 Subject: [PATCH 25/40] SparseSmgRpatlHelper.cpp added return value --- src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp | 3 +++ .../modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp index 29d41b45c..566120827 100644 --- a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp @@ -64,6 +64,8 @@ namespace storm { SMGSparseModelCheckingHelperReturnType SparseSmgRpatlHelper::computeUntilProbabilitiesSound(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, storm::storage::BitVector statesOfCoalition, bool produceScheduler, ModelCheckerHint const& hint) { storm::modelchecker::helper::internal::SoundGameViHelper viHelper(transitionMatrix, backwardTransitions, statesOfCoalition, psiStates, goal.direction()); + std::unique_ptr> scheduler; + storm::storage::BitVector relevantStates(psiStates.size(), true); // Initialize the x vector and solution vector result. // TODO Fabian: maybe relevant states (later) @@ -93,6 +95,7 @@ namespace storm { std::vector constrainedChoiceValues; viHelper.performValueIteration(env, xL, xU, goal.direction(), constrainedChoiceValues); + return SMGSparseModelCheckingHelperReturnType(std::move(xU), std::move(relevantStates), std::move(scheduler), std::move(constrainedChoiceValues)); assert(false); } diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp index 10de545e3..5a7109cac 100644 --- a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp @@ -28,7 +28,6 @@ namespace storm { template void SoundGameViHelper::performValueIteration(Environment const& env, std::vector& xL, std::vector& xU, storm::solver::OptimizationDirection const dir, std::vector& constrainedChoiceValues) { - // new pair (x_old, x_new) for over_approximation() prepareSolversAndMultipliers(env); // Get precision for convergence check. From 986d1183aa91485f0d3aa592177b51aa289a48d4 Mon Sep 17 00:00:00 2001 From: Fabian Russold Date: Fri, 9 Aug 2024 11:04:18 +0200 Subject: [PATCH 26/40] bug fixes and optimizations --- .../rpatl/SparseSmgRpatlModelChecker.cpp | 2 + .../rpatl/helper/SparseSmgRpatlHelper.cpp | 16 ++-- .../helper/internal/SoundGameViHelper.cpp | 91 ++++++++++++------- .../rpatl/helper/internal/SoundGameViHelper.h | 5 +- src/storm/storage/MaximalEndComponent.cpp | 16 +++- src/storm/storage/MaximalEndComponent.h | 11 +++ 6 files changed, 96 insertions(+), 45 deletions(-) diff --git a/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp b/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp index cb110be26..30001ce75 100644 --- a/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp +++ b/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp @@ -142,6 +142,7 @@ namespace storm { ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseSmgRpatlHelper::computeUntilProbabilitiesSound(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), statesOfCoalition, checkTask.isProduceSchedulersSet(), checkTask.getHint()); + STORM_LOG_DEBUG(ret.values); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); @@ -151,6 +152,7 @@ namespace storm { if (checkTask.isProduceSchedulersSet() && ret.scheduler) { result->asExplicitQuantitativeCheckResult().setScheduler(std::move(ret.scheduler)); } + //STORM_LOG_DEBUG(result); return result; } diff --git a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp index 566120827..e3dc2d8ee 100644 --- a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp @@ -83,11 +83,13 @@ namespace storm { storm::storage::BitVector probGreater0 = storm::utility::graph::performProbGreater0(backwardTransitions, phiStates, psiStates); // assigning 1s to the xU vector for all states except the states s where Prob(sEf) = 0 for all goal states f assert(xU.size() == probGreater0.size()); - for (size_t i = 0; i < xL.size(); i++) // TODO Fabian: do this more efficient - { - if (probGreater0[i]) - xU[i] = 1; - } + auto xU_begin = xU.begin(); + std::for_each(xU.begin(), xU.end(), [&probGreater0, &xU_begin](ValueType &it) + { + if (probGreater0[&it - &(*xU_begin)]) + it = 1; + }); + STORM_LOG_DEBUG("xU " << xU); std::vector result = std::vector(transitionMatrix.getRowGroupCount(), storm::utility::zero()); @@ -95,9 +97,9 @@ namespace storm { std::vector constrainedChoiceValues; viHelper.performValueIteration(env, xL, xU, goal.direction(), constrainedChoiceValues); - return SMGSparseModelCheckingHelperReturnType(std::move(xU), std::move(relevantStates), std::move(scheduler), std::move(constrainedChoiceValues)); - assert(false); + STORM_LOG_DEBUG(xU); + return SMGSparseModelCheckingHelperReturnType(std::move(xU), std::move(relevantStates), std::move(scheduler), std::move(constrainedChoiceValues)); } template diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp index 5a7109cac..732127ce9 100644 --- a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp @@ -84,62 +84,82 @@ namespace storm { prepareSolversAndMultipliers(env); } _x1IsCurrent = !_x1IsCurrent; + std::vector choiceValuesL = std::vector(this->_transitionMatrix.getRowCount(), storm::utility::zero()); - std::vector choiceValues = xNewL(); - choiceValues.resize(this->_transitionMatrix.getRowCount()); - - _multiplier->multiply(env, xOldL(), nullptr, choiceValues); - reduceChoiceValues(choiceValues, &reducedMinimizerActions); - xNewL() = choiceValues; + _multiplier->multiply(env, xOldL(), nullptr, choiceValuesL); + reduceChoiceValues(choiceValuesL, &reducedMinimizerActions, xNewL()); // over_approximation - _multiplier->multiplyAndReduce(env, dir, xOldU(), nullptr, xNewU(), nullptr, &_statesOfCoalition); + std::vector choiceValuesU = std::vector(this->_transitionMatrix.getRowCount(), storm::utility::zero()); + + _multiplier->multiply(env, xOldU(), nullptr, choiceValuesU); + reduceChoiceValues(choiceValuesU, nullptr, xNewU()); + + //_multiplier->multiplyAndReduce(env, dir, xOldU(), nullptr, xNewU(), nullptr, &_statesOfCoalition); // restricting the none optimal minimizer choices storage::SparseMatrix restrictedTransMatrix = this->_transitionMatrix.restrictRows(reducedMinimizerActions); - _multiplierRestricted = storm::solver::MultiplierFactory().create(env, restrictedTransMatrix); // STORM_LOG_DEBUG("restricted Transition: \n" << restrictedTransMatrix); - // find_MSECs() & deflate() + // find_MSECs() storm::storage::MaximalEndComponentDecomposition MSEC = storm::storage::MaximalEndComponentDecomposition(restrictedTransMatrix, _backwardTransitions); - // STORM_LOG_DEBUG("MECD: \n" << MECD); - deflate(MSEC,restrictedTransMatrix, xNewU()); + // STORM_LOG_DEBUG("MECD: \n" << MSEC); + + // reducing the choiceValuesU + size_t i = 0; + auto new_end = std::remove_if(choiceValuesU.begin(), choiceValuesU.end(), [&reducedMinimizerActions, &i](const auto& item) { + bool ret = !(reducedMinimizerActions[i]); + i++; + return ret; + }); + choiceValuesU.erase(new_end, choiceValuesU.end()); + + // deflating the MSECs + deflate(MSEC, restrictedTransMatrix, xNewU(), choiceValuesU); } template - void SoundGameViHelper::deflate(storm::storage::MaximalEndComponentDecomposition const MSEC, storage::SparseMatrix const restrictedMatrix, std::vector& xU) { + void SoundGameViHelper::deflate(storm::storage::MaximalEndComponentDecomposition const MSEC, storage::SparseMatrix const restrictedMatrix, std::vector& xU, std::vector choiceValues) { auto rowGroupIndices = restrictedMatrix.getRowGroupIndices(); + auto choice_begin = choiceValues.begin(); // iterating over all MSECs for (auto smec_it : MSEC) { ValueType bestExit = 0; + if (smec_it.isErgodic(restrictedMatrix)) continue; // TODO Fabian: ?? isErgodic undefined ref auto stateSet = smec_it.getStateSet(); for (uint state : stateSet) { - uint rowGroupSize = rowGroupIndices[state + 1] - rowGroupIndices[state]; - if (!_minimizerStates[state]) { // check if current state is maximizer state - for (uint choice = 0; choice < rowGroupSize; choice++) { - if (!smec_it.containsChoice(state, choice + rowGroupIndices[state])) { - ValueType choiceValue = 0; - _multiplierRestricted->multiplyRow(choice + rowGroupIndices[state], xU, choiceValue); - if (choiceValue > bestExit) - bestExit = choiceValue; - } - } - } + if (_minimizerStates[state]) continue; + uint rowGroupIndex = rowGroupIndices[state]; + auto exitingCompare = [&state, &smec_it, &choice_begin](const ValueType &lhs, const ValueType &rhs) + { + bool lhsExiting = !smec_it.containsChoice(state, (&lhs - &(*choice_begin))); + bool rhsExiting = !smec_it.containsChoice(state, (&rhs - &(*choice_begin))); + if( lhsExiting && !rhsExiting) return false; + if(!lhsExiting && rhsExiting) return true; + if(!lhsExiting && !rhsExiting) return false; + return lhs < rhs; + }; + uint rowGroupSize = rowGroupIndices[state + 1] - rowGroupIndex; + + auto choice_it = choice_begin + rowGroupIndex; + ValueType newBestExit = *std::max_element(choice_it, choice_it + rowGroupSize, exitingCompare); + if (newBestExit > bestExit) + bestExit = newBestExit; } // deflating the states of the current MSEC for (uint state : stateSet) { - if (!_psiStates[state]) - xU[state] = std::min(xU[state], bestExit); + if (_psiStates[state]) continue; + xU[state] = std::min(xU[state], bestExit); } } } template - void SoundGameViHelper::reduceChoiceValues(std::vector& choiceValues, storm::storage::BitVector* result) + void SoundGameViHelper::reduceChoiceValues(std::vector& choiceValues, storm::storage::BitVector* result, std::vector& x) { // result BitVec should be initialized with 1s outside the method @@ -153,23 +173,26 @@ namespace storm { // getting the optimal minimizer choice for the given state optChoice = *std::min_element(choice_it, choice_it + rowGroupSize); - for (uint choice = 0; choice < rowGroupSize; choice++, choice_it++) { - if (*choice_it > optChoice) { - result->set(rowGroupIndices[state] + choice, 0); + if (result != nullptr) { + for (uint choice = 0; choice < rowGroupSize; choice++, choice_it++) { + if (*choice_it > optChoice) { + result->set(rowGroupIndices[state] + choice, 0); + } } } - // reducing the xNew() (choiceValues) vector for minimizer states - choiceValues[state] = optChoice; + else + choice_it += rowGroupSize; + // reducing the xNew() vector for minimizer states + x[state] = optChoice; } else { optChoice = *std::max_element(choice_it, choice_it + rowGroupSize); - // reducing the xNew() (choiceValues) vector for maximizer states - choiceValues[state] = optChoice; + // reducing the xNew() vector for maximizer states + x[state] = optChoice; choice_it += rowGroupSize; } } - choiceValues.resize(this->_transitionMatrix.getRowGroupCount()); } diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h index 5fecd8d87..f738958ca 100644 --- a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h @@ -74,9 +74,9 @@ namespace storm { */ void performIterationStep(Environment const& env, storm::solver::OptimizationDirection const dir, std::vector* choices = nullptr); - void deflate(storm::storage::MaximalEndComponentDecomposition const MECD, storage::SparseMatrix const restrictedMatrix, std::vector& xU); + void deflate(storm::storage::MaximalEndComponentDecomposition const MECD, storage::SparseMatrix const restrictedMatrix, std::vector& xU, std::vector choiceValues); - void reduceChoiceValues(std::vector& choiceValues, storm::storage::BitVector* result); + void reduceChoiceValues(std::vector& choiceValues, storm::storage::BitVector* result, std::vector& x); /*! * Checks whether the curently computed value achieves the desired precision @@ -117,7 +117,6 @@ namespace storm { storm::storage::BitVector _psiStates; std::vector _x, _x1L, _x2L, _x1U, _x2U; std::unique_ptr> _multiplier; - std::unique_ptr> _multiplierRestricted; OptimizationDirection _optimizationDirection; bool _produceScheduler = false; diff --git a/src/storm/storage/MaximalEndComponent.cpp b/src/storm/storage/MaximalEndComponent.cpp index aa7453277..d4f51e089 100644 --- a/src/storm/storage/MaximalEndComponent.cpp +++ b/src/storm/storage/MaximalEndComponent.cpp @@ -4,7 +4,6 @@ namespace storm { namespace storage { - std::ostream& operator<<(std::ostream& out, storm::storage::FlatSet const& block); MaximalEndComponent::MaximalEndComponent() : stateToChoicesMapping() { @@ -100,6 +99,18 @@ namespace storm { return stateChoicePair->second.find(choice) != stateChoicePair->second.end(); } + template + bool MaximalEndComponent::isErgodic(storm::storage::SparseMatrix transitionMatrix) const { + auto rowGroupIndices = transitionMatrix.getRowGroupIndices(); + for (auto state : this->getStateSet()) + { + if (getChoicesForState(state).size() == (rowGroupIndices[state + 1] - rowGroupIndices[state])) continue; + return false; + } + return true; + } + + MaximalEndComponent::set_type MaximalEndComponent::getStateSet() const { set_type states; states.reserve(stateToChoicesMapping.size()); @@ -136,5 +147,8 @@ namespace storm { MaximalEndComponent::const_iterator MaximalEndComponent::end() const { return stateToChoicesMapping.end(); } + + template bool MaximalEndComponent::isErgodic(storm::storage::SparseMatrix transitionMatrix) const; + template bool MaximalEndComponent::isErgodic(storm::storage::SparseMatrix transitionMatrix) const; } } diff --git a/src/storm/storage/MaximalEndComponent.h b/src/storm/storage/MaximalEndComponent.h index a1d5b37c2..66c1d1c4a 100644 --- a/src/storm/storage/MaximalEndComponent.h +++ b/src/storm/storage/MaximalEndComponent.h @@ -5,6 +5,7 @@ #include "storm/storage/sparse/StateType.h" #include "storm/storage/BoostTypes.h" +#include "storm/storage/SparseMatrix.h" namespace storm { namespace storage { @@ -20,6 +21,7 @@ namespace storm { typedef std::unordered_map map_type; typedef map_type::iterator iterator; typedef map_type::const_iterator const_iterator; + /*! * Creates an empty MEC. @@ -124,6 +126,15 @@ namespace storm { * @return True if the given choice is contained in the MEC. */ bool containsChoice(uint_fast64_t state, uint_fast64_t choice) const; + + /*! + * Retrieves wether the MEC is ergodic or not i.e. wether the MEC is exitable or not + * + * @param transitionMatrix the given transition matrix + * @return True if the MEC is ergodic + */ + template + bool isErgodic(storm::storage::SparseMatrix transitionMatrix) const; /*! * Retrieves the set of states contained in the MEC. From 1e40b9e5a3ca642b0ba5c092e6b1088392171d80 Mon Sep 17 00:00:00 2001 From: Fabian Russold Date: Tue, 20 Aug 2024 11:27:43 +0200 Subject: [PATCH 27/40] SmgRpatlModelCheckerTest.cpp: added test for deflate method of SoundGameViHelper.cpp --- .../examples/testfiles/smg/example_smg.nm | 28 ++++ .../helper/internal/SoundGameViHelper.cpp | 5 +- .../rpatl/helper/internal/SoundGameViHelper.h | 11 +- src/storm/storage/MaximalEndComponent.h | 2 +- .../rpatl/smg/SmgRpatlModelCheckerTest.cpp | 153 ++++++++++++++++++ 5 files changed, 189 insertions(+), 10 deletions(-) create mode 100644 resources/examples/testfiles/smg/example_smg.nm diff --git a/resources/examples/testfiles/smg/example_smg.nm b/resources/examples/testfiles/smg/example_smg.nm new file mode 100644 index 000000000..0050b1028 --- /dev/null +++ b/resources/examples/testfiles/smg/example_smg.nm @@ -0,0 +1,28 @@ +smg + +const double p = 2/3; + +player maxP + [q_action1], [q_action2] +endplayer + +player minP + [p_action1] +endplayer + +player sinkstates + state_space +endplayer + + +module state_space + s : [0..3]; + + [p_action1] s=0 -> (s'=1); + + [q_action1] s=1 -> (s'=0); + [q_action2] s=1 -> (1-p) : (s'=1) + (p/2) : (s'=2) + (p/2) : (s'=3); + + [] s=2 -> true; + [] s=3 -> true; +endmodule diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp index 732127ce9..e305c3be7 100644 --- a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp @@ -96,8 +96,6 @@ namespace storm { _multiplier->multiply(env, xOldU(), nullptr, choiceValuesU); reduceChoiceValues(choiceValuesU, nullptr, xNewU()); - //_multiplier->multiplyAndReduce(env, dir, xOldU(), nullptr, xNewU(), nullptr, &_statesOfCoalition); - // restricting the none optimal minimizer choices storage::SparseMatrix restrictedTransMatrix = this->_transitionMatrix.restrictRows(reducedMinimizerActions); @@ -124,12 +122,11 @@ namespace storm { template void SoundGameViHelper::deflate(storm::storage::MaximalEndComponentDecomposition const MSEC, storage::SparseMatrix const restrictedMatrix, std::vector& xU, std::vector choiceValues) { auto rowGroupIndices = restrictedMatrix.getRowGroupIndices(); - auto choice_begin = choiceValues.begin(); // iterating over all MSECs for (auto smec_it : MSEC) { ValueType bestExit = 0; - if (smec_it.isErgodic(restrictedMatrix)) continue; // TODO Fabian: ?? isErgodic undefined ref + if (smec_it.isErgodic(restrictedMatrix)) continue; auto stateSet = smec_it.getStateSet(); for (uint state : stateSet) { if (_minimizerStates[state]) continue; diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h index f738958ca..d8a0d7907 100644 --- a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h @@ -68,16 +68,18 @@ namespace storm { */ void fillChoiceValuesVector(std::vector& choiceValues, storm::storage::BitVector psiStates, std::vector::index_type> rowGroupIndices); + void deflate(storm::storage::MaximalEndComponentDecomposition const MECD, storage::SparseMatrix const restrictedMatrix, std::vector& xU, std::vector choiceValues); + + void reduceChoiceValues(std::vector& choiceValues, storm::storage::BitVector* result, std::vector& x); + + // multiplier now public for testing + std::unique_ptr> _multiplier; private: /*! * Performs one iteration step for value iteration */ void performIterationStep(Environment const& env, storm::solver::OptimizationDirection const dir, std::vector* choices = nullptr); - void deflate(storm::storage::MaximalEndComponentDecomposition const MECD, storage::SparseMatrix const restrictedMatrix, std::vector& xU, std::vector choiceValues); - - void reduceChoiceValues(std::vector& choiceValues, storm::storage::BitVector* result, std::vector& x); - /*! * Checks whether the curently computed value achieves the desired precision */ @@ -116,7 +118,6 @@ namespace storm { storm::storage::BitVector _statesOfCoalition; storm::storage::BitVector _psiStates; std::vector _x, _x1L, _x2L, _x1U, _x2U; - std::unique_ptr> _multiplier; OptimizationDirection _optimizationDirection; bool _produceScheduler = false; diff --git a/src/storm/storage/MaximalEndComponent.h b/src/storm/storage/MaximalEndComponent.h index 66c1d1c4a..448159804 100644 --- a/src/storm/storage/MaximalEndComponent.h +++ b/src/storm/storage/MaximalEndComponent.h @@ -128,7 +128,7 @@ namespace storm { bool containsChoice(uint_fast64_t state, uint_fast64_t choice) const; /*! - * Retrieves wether the MEC is ergodic or not i.e. wether the MEC is exitable or not + * Retrieves whether the MEC is ergodic or not i.e. wether the MEC is exitable or not * * @param transitionMatrix the given transition matrix * @return True if the MEC is ergodic diff --git a/src/test/storm/modelchecker/rpatl/smg/SmgRpatlModelCheckerTest.cpp b/src/test/storm/modelchecker/rpatl/smg/SmgRpatlModelCheckerTest.cpp index 79217c614..d634ec6b2 100644 --- a/src/test/storm/modelchecker/rpatl/smg/SmgRpatlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/rpatl/smg/SmgRpatlModelCheckerTest.cpp @@ -17,6 +17,11 @@ #include "storm/settings/modules/CoreSettings.h" #include "storm/logic/Formulas.h" #include "storm/exceptions/UncheckedRequirementException.h" +#include "storm/solver/Multiplier.h" +#include "storm/storage/SparseMatrix.h" +#include "storm/utility/graph.h" +#include "storm/storage/MaximalEndComponentDecomposition.h" +#include "storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h" namespace { @@ -114,6 +119,7 @@ namespace { std::vector> getTasks(std::vector> const& formulas) const { std::vector> result; for (auto const& f : formulas) { + std::cout << *f << std::endl; result.emplace_back(*f); } return result; @@ -345,5 +351,152 @@ namespace { EXPECT_NEAR(this->parseNumber("1"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); } + TYPED_TEST(SmgRpatlModelCheckerTest, Deflate) { + typedef double ValueType; + std::string formulasString = " <> Pmax=? [F (s=2)]"; + + auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR "/smg/example_smg.nm", formulasString); + auto model = std::move(modelFormulas.first); + auto tasks = this->getTasks(modelFormulas.second); + auto checker = this->createModelChecker(model); + std::unique_ptr result; + auto transitionMatrix = model->getTransitionMatrix(); + + + auto formulas = std::move(modelFormulas.second); + + storm::logic::GameFormula const& gameFormula = formulas[0]->asGameFormula(); + + storm::modelchecker::CheckTask checkTask(gameFormula); + + storm::storage::BitVector statesOfCoalition = model->computeStatesOfCoalition(gameFormula.getCoalition()); + statesOfCoalition.complement(); + + // TODO Fabian: get optimization direction + + storm::storage::BitVector psiStates = checker->check(this->env(), gameFormula.getSubformula().asProbabilityOperatorFormula().getSubformula().asEventuallyFormula().getSubformula().asStateFormula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector phiStates(model->getNumberOfStates(), true); + + storm::storage::SparseMatrix backwardTransitions = model->getBackwardTransitions(); + storm::OptimizationDirection optimizationDirection = storm::OptimizationDirection::Maximize; + auto minimizerStates = optimizationDirection == storm::OptimizationDirection::Maximize ? statesOfCoalition : ~statesOfCoalition; + + storm::modelchecker::helper::internal::SoundGameViHelper viHelper(transitionMatrix, backwardTransitions, statesOfCoalition, psiStates, optimizationDirection); + viHelper.prepareSolversAndMultipliers(this->env()); + + std::vector xL = std::vector(transitionMatrix.getRowGroupCount(), storm::utility::zero()); + for (size_t i = 0; i < xL.size(); i++) + { + if (psiStates[i]) + xL[i] = 1; + } + + std::vector xU = std::vector(transitionMatrix.getRowGroupCount(), storm::utility::zero()); + storm::storage::BitVector probGreater0 = storm::utility::graph::performProbGreater0(backwardTransitions, phiStates, psiStates); + auto xU_begin = xU.begin(); + std::for_each(xU.begin(), xU.end(), [&probGreater0, &xU_begin](ValueType &it) + { + if (probGreater0[&it - &(*xU_begin)]) + it = 1; + }); + + // performValueIteration + std::vector _x1L = xL; + std::vector _x2L = _x1L; + + std::vector _x1U = xU; + std::vector _x2U = _x1U; + + // perform first iteration step + storm::storage::BitVector reducedMinimizerActions = {storm::storage::BitVector(transitionMatrix.getRowCount(), true)}; + std::vector choiceValuesL = std::vector(transitionMatrix.getRowCount(), storm::utility::zero()); + + viHelper._multiplier->multiply(this->env(), _x2L, nullptr, choiceValuesL); + + viHelper.reduceChoiceValues(choiceValuesL, &reducedMinimizerActions, _x1L); + + + // over approximation + std::vector choiceValuesU = std::vector(transitionMatrix.getRowCount(), storm::utility::zero()); + + viHelper._multiplier->multiply(this->env(), _x2U, nullptr, choiceValuesU); + viHelper.reduceChoiceValues(choiceValuesU, nullptr, _x1U); + + storm::storage::SparseMatrix restrictedTransMatrix = transitionMatrix.restrictRows(reducedMinimizerActions); + + storm::storage::MaximalEndComponentDecomposition MSEC = storm::storage::MaximalEndComponentDecomposition(restrictedTransMatrix, backwardTransitions); + + // reducing the choiceValuesU + size_t i = 0; + auto new_end = std::remove_if(choiceValuesU.begin(), choiceValuesU.end(), [&reducedMinimizerActions, &i](const auto& item) { + bool ret = !(reducedMinimizerActions[i]); + i++; + return ret; + }); + choiceValuesU.erase(new_end, choiceValuesU.end()); + + // deflating the MSECs + viHelper.deflate(MSEC, restrictedTransMatrix, _x1U, choiceValuesU); + + xL = _x1L; + xU = _x1U; + + EXPECT_NEAR(this->parseNumber("0"), xL[0], this->precision()); + EXPECT_NEAR(this->parseNumber("0.333333"), xL[1], this->precision()); + EXPECT_NEAR(this->parseNumber("1"), xL[2], this->precision()); + EXPECT_NEAR(this->parseNumber("0"), xL[3], this->precision()); + + EXPECT_NEAR(this->parseNumber("0.666666"), xU[0], this->precision()); + EXPECT_NEAR(this->parseNumber("0.666666"), xU[1], this->precision()); + EXPECT_NEAR(this->parseNumber("1"), xU[2], this->precision()); + EXPECT_NEAR(this->parseNumber("0"), xU[3], this->precision()); + + // second iteration step + + reducedMinimizerActions = {storm::storage::BitVector(transitionMatrix.getRowCount(), true)}; + choiceValuesL = std::vector(transitionMatrix.getRowCount(), storm::utility::zero()); + + viHelper._multiplier->multiply(this->env(), _x1L, nullptr, choiceValuesL); + + viHelper.reduceChoiceValues(choiceValuesL, &reducedMinimizerActions, _x2L); + + + // over approximation + choiceValuesU = std::vector(transitionMatrix.getRowCount(), storm::utility::zero()); + + viHelper._multiplier->multiply(this->env(), _x1U, nullptr, choiceValuesU); + viHelper.reduceChoiceValues(choiceValuesU, nullptr, _x2U); + + restrictedTransMatrix = transitionMatrix.restrictRows(reducedMinimizerActions); + + MSEC = storm::storage::MaximalEndComponentDecomposition(restrictedTransMatrix, backwardTransitions); + + // reducing the choiceValuesU + i = 0; + new_end = std::remove_if(choiceValuesU.begin(), choiceValuesU.end(), [&reducedMinimizerActions, &i](const auto& item) { + bool ret = !(reducedMinimizerActions[i]); + i++; + return ret; + }); + choiceValuesU.erase(new_end, choiceValuesU.end()); + + // deflating the MSECs + viHelper.deflate(MSEC, restrictedTransMatrix, _x2U, choiceValuesU); + + xL = _x2L; + xU = _x2U; + + EXPECT_NEAR(this->parseNumber("0.333333"), xL[0], this->precision()); + EXPECT_NEAR(this->parseNumber("0.444444"), xL[1], this->precision()); + EXPECT_NEAR(this->parseNumber("1"), xL[2], this->precision()); + EXPECT_NEAR(this->parseNumber("0"), xL[3], this->precision()); + + EXPECT_NEAR(this->parseNumber("0.555555"), xU[0], this->precision()); + EXPECT_NEAR(this->parseNumber("0.555555"), xU[1], this->precision()); + EXPECT_NEAR(this->parseNumber("1"), xU[2], this->precision()); + EXPECT_NEAR(this->parseNumber("0"), xU[3], this->precision()); + + } + // TODO: create more test cases (files) } From 3b0eeb1e882472c489d8919158c01f1e04495252 Mon Sep 17 00:00:00 2001 From: Fabian Russold Date: Tue, 20 Aug 2024 13:23:06 +0200 Subject: [PATCH 28/40] SmgRpatlModelCheckerTest.cpp: google tests for MSECs --- .../rpatl/smg/SmgRpatlModelCheckerTest.cpp | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/src/test/storm/modelchecker/rpatl/smg/SmgRpatlModelCheckerTest.cpp b/src/test/storm/modelchecker/rpatl/smg/SmgRpatlModelCheckerTest.cpp index d634ec6b2..d4f0c8694 100644 --- a/src/test/storm/modelchecker/rpatl/smg/SmgRpatlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/rpatl/smg/SmgRpatlModelCheckerTest.cpp @@ -426,6 +426,73 @@ namespace { storm::storage::MaximalEndComponentDecomposition MSEC = storm::storage::MaximalEndComponentDecomposition(restrictedTransMatrix, backwardTransitions); + // testing MSEC + // ===================================================== + ASSERT_TRUE(MSEC.size() == 3); + storm::storage::MaximalEndComponent const& mec1 = MSEC[0]; + if (mec1.containsState(0)) { + ASSERT_TRUE(mec1.containsState(1)); + ASSERT_FALSE(mec1.containsState(2)); + ASSERT_FALSE(mec1.containsState(3)); + } + else if (mec1.containsState(2)) { + ASSERT_FALSE(mec1.containsState(0)); + ASSERT_FALSE(mec1.containsState(1)); + ASSERT_FALSE(mec1.containsState(3)); + } + else if (mec1.containsState(3)) { + ASSERT_FALSE(mec1.containsState(0)); + ASSERT_FALSE(mec1.containsState(1)); + ASSERT_FALSE(mec1.containsState(2)); + } + else { + // This case must never happen + ASSERT_TRUE(false); + } + + storm::storage::MaximalEndComponent const& mec2 = MSEC[1]; + if (mec2.containsState(0)) { + ASSERT_TRUE(mec2.containsState(1)); + ASSERT_FALSE(mec2.containsState(2)); + ASSERT_FALSE(mec2.containsState(3)); + } + else if (mec2.containsState(2)) { + ASSERT_FALSE(mec2.containsState(0)); + ASSERT_FALSE(mec2.containsState(1)); + ASSERT_FALSE(mec2.containsState(3)); + } + else if (mec2.containsState(3)) { + ASSERT_FALSE(mec2.containsState(0)); + ASSERT_FALSE(mec2.containsState(1)); + ASSERT_FALSE(mec2.containsState(2)); + } + else { + // This case must never happen + ASSERT_TRUE(false); + } + + storm::storage::MaximalEndComponent const& mec3 = MSEC[2]; + if (mec3.containsState(0)) { + ASSERT_TRUE(mec3.containsState(1)); + ASSERT_FALSE(mec3.containsState(2)); + ASSERT_FALSE(mec3.containsState(3)); + } + else if (mec3.containsState(2)) { + ASSERT_FALSE(mec3.containsState(0)); + ASSERT_FALSE(mec3.containsState(1)); + ASSERT_FALSE(mec3.containsState(3)); + } + else if (mec3.containsState(3)) { + ASSERT_FALSE(mec3.containsState(0)); + ASSERT_FALSE(mec3.containsState(1)); + ASSERT_FALSE(mec3.containsState(2)); + } + else { + // This case must never happen + ASSERT_TRUE(false); + } + // ===================================================== + // reducing the choiceValuesU size_t i = 0; auto new_end = std::remove_if(choiceValuesU.begin(), choiceValuesU.end(), [&reducedMinimizerActions, &i](const auto& item) { @@ -471,6 +538,73 @@ namespace { MSEC = storm::storage::MaximalEndComponentDecomposition(restrictedTransMatrix, backwardTransitions); + // testing MSEC + // ===================================================== + ASSERT_TRUE(MSEC.size() == 3); + storm::storage::MaximalEndComponent const& mec4 = MSEC[0]; + if (mec4.containsState(0)) { + ASSERT_TRUE(mec4.containsState(1)); + ASSERT_FALSE(mec4.containsState(2)); + ASSERT_FALSE(mec4.containsState(3)); + } + else if (mec4.containsState(2)) { + ASSERT_FALSE(mec4.containsState(0)); + ASSERT_FALSE(mec4.containsState(1)); + ASSERT_FALSE(mec4.containsState(3)); + } + else if (mec4.containsState(3)) { + ASSERT_FALSE(mec4.containsState(0)); + ASSERT_FALSE(mec4.containsState(1)); + ASSERT_FALSE(mec4.containsState(2)); + } + else { + // This case must never happen + ASSERT_TRUE(false); + } + + storm::storage::MaximalEndComponent const& mec5 = MSEC[1]; + if (mec5.containsState(0)) { + ASSERT_TRUE(mec5.containsState(1)); + ASSERT_FALSE(mec5.containsState(2)); + ASSERT_FALSE(mec5.containsState(3)); + } + else if (mec5.containsState(2)) { + ASSERT_FALSE(mec5.containsState(0)); + ASSERT_FALSE(mec5.containsState(1)); + ASSERT_FALSE(mec5.containsState(3)); + } + else if (mec5.containsState(3)) { + ASSERT_FALSE(mec5.containsState(0)); + ASSERT_FALSE(mec5.containsState(1)); + ASSERT_FALSE(mec5.containsState(2)); + } + else { + // This case must never happen + ASSERT_TRUE(false); + } + + storm::storage::MaximalEndComponent const& mec6 = MSEC[2]; + if (mec6.containsState(0)) { + ASSERT_TRUE(mec6.containsState(1)); + ASSERT_FALSE(mec6.containsState(2)); + ASSERT_FALSE(mec6.containsState(3)); + } + else if (mec6.containsState(2)) { + ASSERT_FALSE(mec6.containsState(0)); + ASSERT_FALSE(mec6.containsState(1)); + ASSERT_FALSE(mec6.containsState(3)); + } + else if (mec6.containsState(3)) { + ASSERT_FALSE(mec6.containsState(0)); + ASSERT_FALSE(mec6.containsState(1)); + ASSERT_FALSE(mec6.containsState(2)); + } + else { + // This case must never happen + ASSERT_TRUE(false); + } + // ===================================================== + // reducing the choiceValuesU i = 0; new_end = std::remove_if(choiceValuesU.begin(), choiceValuesU.end(), [&reducedMinimizerActions, &i](const auto& item) { From 81c0dbc50fa016163fa19f45f2eb13d90fc41a6c Mon Sep 17 00:00:00 2001 From: Fabian Russold Date: Tue, 20 Aug 2024 13:37:22 +0200 Subject: [PATCH 29/40] removed all std::cout --- .../modelchecker/rpatl/smg/SmgRpatlModelCheckerTest.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/test/storm/modelchecker/rpatl/smg/SmgRpatlModelCheckerTest.cpp b/src/test/storm/modelchecker/rpatl/smg/SmgRpatlModelCheckerTest.cpp index d4f0c8694..cd37d9875 100644 --- a/src/test/storm/modelchecker/rpatl/smg/SmgRpatlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/rpatl/smg/SmgRpatlModelCheckerTest.cpp @@ -119,7 +119,6 @@ namespace { std::vector> getTasks(std::vector> const& formulas) const { std::vector> result; for (auto const& f : formulas) { - std::cout << *f << std::endl; result.emplace_back(*f); } return result; @@ -412,7 +411,6 @@ namespace { std::vector choiceValuesL = std::vector(transitionMatrix.getRowCount(), storm::utility::zero()); viHelper._multiplier->multiply(this->env(), _x2L, nullptr, choiceValuesL); - viHelper.reduceChoiceValues(choiceValuesL, &reducedMinimizerActions, _x1L); @@ -518,13 +516,11 @@ namespace { EXPECT_NEAR(this->parseNumber("1"), xU[2], this->precision()); EXPECT_NEAR(this->parseNumber("0"), xU[3], this->precision()); - // second iteration step - + // perform second iteration step reducedMinimizerActions = {storm::storage::BitVector(transitionMatrix.getRowCount(), true)}; choiceValuesL = std::vector(transitionMatrix.getRowCount(), storm::utility::zero()); viHelper._multiplier->multiply(this->env(), _x1L, nullptr, choiceValuesL); - viHelper.reduceChoiceValues(choiceValuesL, &reducedMinimizerActions, _x2L); From 470fd302aa82bb9d3c68374a3d222451f3f00e88 Mon Sep 17 00:00:00 2001 From: Fabian Russold Date: Wed, 21 Aug 2024 10:34:31 +0200 Subject: [PATCH 30/40] getting optimization direction via CheckTask --- resources/examples/testfiles/smg/example_smg.nm | 4 ++++ .../rpatl/smg/SmgRpatlModelCheckerTest.cpp | 11 +++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/resources/examples/testfiles/smg/example_smg.nm b/resources/examples/testfiles/smg/example_smg.nm index 0050b1028..875070051 100644 --- a/resources/examples/testfiles/smg/example_smg.nm +++ b/resources/examples/testfiles/smg/example_smg.nm @@ -1,3 +1,7 @@ +// taken from Julia Eisentraut "Value iteration for simple stochastic games: Stopping criterion +// and learning algorithm" - Fig. 1 + + smg const double p = 2/3; diff --git a/src/test/storm/modelchecker/rpatl/smg/SmgRpatlModelCheckerTest.cpp b/src/test/storm/modelchecker/rpatl/smg/SmgRpatlModelCheckerTest.cpp index cd37d9875..765d08135 100644 --- a/src/test/storm/modelchecker/rpatl/smg/SmgRpatlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/rpatl/smg/SmgRpatlModelCheckerTest.cpp @@ -361,9 +361,7 @@ namespace { std::unique_ptr result; auto transitionMatrix = model->getTransitionMatrix(); - auto formulas = std::move(modelFormulas.second); - storm::logic::GameFormula const& gameFormula = formulas[0]->asGameFormula(); storm::modelchecker::CheckTask checkTask(gameFormula); @@ -371,13 +369,12 @@ namespace { storm::storage::BitVector statesOfCoalition = model->computeStatesOfCoalition(gameFormula.getCoalition()); statesOfCoalition.complement(); - // TODO Fabian: get optimization direction storm::storage::BitVector psiStates = checker->check(this->env(), gameFormula.getSubformula().asProbabilityOperatorFormula().getSubformula().asEventuallyFormula().getSubformula().asStateFormula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); storm::storage::BitVector phiStates(model->getNumberOfStates(), true); storm::storage::SparseMatrix backwardTransitions = model->getBackwardTransitions(); - storm::OptimizationDirection optimizationDirection = storm::OptimizationDirection::Maximize; + storm::OptimizationDirection optimizationDirection = gameFormula.getSubformula().asOperatorFormula().getOptimalityType(); auto minimizerStates = optimizationDirection == storm::OptimizationDirection::Maximize ? statesOfCoalition : ~statesOfCoalition; storm::modelchecker::helper::internal::SoundGameViHelper viHelper(transitionMatrix, backwardTransitions, statesOfCoalition, psiStates, optimizationDirection); @@ -506,6 +503,8 @@ namespace { xL = _x1L; xU = _x1U; + // testing x vectors + // ===================================================== EXPECT_NEAR(this->parseNumber("0"), xL[0], this->precision()); EXPECT_NEAR(this->parseNumber("0.333333"), xL[1], this->precision()); EXPECT_NEAR(this->parseNumber("1"), xL[2], this->precision()); @@ -515,6 +514,7 @@ namespace { EXPECT_NEAR(this->parseNumber("0.666666"), xU[1], this->precision()); EXPECT_NEAR(this->parseNumber("1"), xU[2], this->precision()); EXPECT_NEAR(this->parseNumber("0"), xU[3], this->precision()); + // ===================================================== // perform second iteration step reducedMinimizerActions = {storm::storage::BitVector(transitionMatrix.getRowCount(), true)}; @@ -616,6 +616,8 @@ namespace { xL = _x2L; xU = _x2U; + // testing x vectors + // ===================================================== EXPECT_NEAR(this->parseNumber("0.333333"), xL[0], this->precision()); EXPECT_NEAR(this->parseNumber("0.444444"), xL[1], this->precision()); EXPECT_NEAR(this->parseNumber("1"), xL[2], this->precision()); @@ -625,6 +627,7 @@ namespace { EXPECT_NEAR(this->parseNumber("0.555555"), xU[1], this->precision()); EXPECT_NEAR(this->parseNumber("1"), xU[2], this->precision()); EXPECT_NEAR(this->parseNumber("0"), xU[3], this->precision()); + // ===================================================== } From 5107b5904cf6590ed6f6b6590d5de4914786ac61 Mon Sep 17 00:00:00 2001 From: Fabian Russold Date: Tue, 1 Oct 2024 12:04:49 +0200 Subject: [PATCH 31/40] optimization: searching for MSECs only if policy changed --- .../helper/internal/SoundGameViHelper.cpp | 85 +++++++++++++------ .../rpatl/helper/internal/SoundGameViHelper.h | 14 ++- 2 files changed, 71 insertions(+), 28 deletions(-) diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp index e305c3be7..41dc61b50 100644 --- a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp @@ -14,7 +14,7 @@ namespace storm { namespace internal { template - SoundGameViHelper::SoundGameViHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector statesOfCoalition, storm::storage::BitVector psiStates, OptimizationDirection const& optimizationDirection) : _transitionMatrix(transitionMatrix), _backwardTransitions(backwardTransitions), _statesOfCoalition(statesOfCoalition), _psiStates(psiStates), _optimizationDirection(optimizationDirection) { + SoundGameViHelper::SoundGameViHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector b, storm::storage::BitVector statesOfCoalition, storm::storage::BitVector psiStates, OptimizationDirection const& optimizationDirection) : _transitionMatrix(transitionMatrix), _backwardTransitions(backwardTransitions), _statesOfCoalition(statesOfCoalition), _psiStates(psiStates), _optimizationDirection(optimizationDirection), _b(b) { // Intentionally left empty. } @@ -24,6 +24,8 @@ namespace storm { _multiplier = storm::solver::MultiplierFactory().create(env, _transitionMatrix); _x1IsCurrent = false; _minimizerStates = _optimizationDirection == OptimizationDirection::Maximize ? _statesOfCoalition : ~_statesOfCoalition; + _oldPolicy = storm::storage::BitVector(_transitionMatrix.getRowCount(), false); + _timing = std::vector(5, 0); } template @@ -37,6 +39,8 @@ namespace storm { //_x1.assign(_transitionMatrix.getRowGroupCount(), storm::utility::zero()); _x1L = xL; _x2L = _x1L; + _x1Test = _x1L; + _x2Test = _x1L; _x1U = xU; _x2U = _x1U; @@ -65,8 +69,8 @@ namespace storm { xL = xNewL(); xU = xNewU(); - STORM_LOG_DEBUG("result xL: " << xL); - STORM_LOG_DEBUG("result xU: " << xU); + // for profiling + STORM_PRINT(_timing[0] << ", " << _timing[1] << ", " << _timing[2] << ", " << _timing[3] << ", " << _timing[4] << std::endl); if (isProduceSchedulerSet()) { // We will be doing one more iteration step and track scheduler choices this time. @@ -79,7 +83,7 @@ namespace storm { storm::storage::BitVector reducedMinimizerActions = {storm::storage::BitVector(this->_transitionMatrix.getRowCount(), true)}; // under approximation - + auto start = std::chrono::steady_clock::now(); if (!_multiplier) { prepareSolversAndMultipliers(env); } @@ -89,23 +93,42 @@ namespace storm { _multiplier->multiply(env, xOldL(), nullptr, choiceValuesL); reduceChoiceValues(choiceValuesL, &reducedMinimizerActions, xNewL()); - // over_approximation + // just for debugging + _multiplier->multiplyAndReduce(env, _optimizationDirection, xOldTest(), nullptr, xNewTest(), nullptr, &_statesOfCoalition); + + // over_approximation std::vector choiceValuesU = std::vector(this->_transitionMatrix.getRowCount(), storm::utility::zero()); _multiplier->multiply(env, xOldU(), nullptr, choiceValuesU); reduceChoiceValues(choiceValuesU, nullptr, xNewU()); - // restricting the none optimal minimizer choices - storage::SparseMatrix restrictedTransMatrix = this->_transitionMatrix.restrictRows(reducedMinimizerActions); + auto finish = std::chrono::steady_clock::now(); + double elapsed_seconds = std::chrono::duration_cast< + std::chrono::duration>(finish - start).count(); + _timing[0] += elapsed_seconds; - // STORM_LOG_DEBUG("restricted Transition: \n" << restrictedTransMatrix); + if (reducedMinimizerActions != _oldPolicy) { // new MECs only if Policy changed + start = std::chrono::steady_clock::now(); - // find_MSECs() - storm::storage::MaximalEndComponentDecomposition MSEC = storm::storage::MaximalEndComponentDecomposition(restrictedTransMatrix, _backwardTransitions); + // restricting the none optimal minimizer choices + _restrictedTransitions = this->_transitionMatrix.restrictRows(reducedMinimizerActions); - // STORM_LOG_DEBUG("MECD: \n" << MSEC); + finish = std::chrono::steady_clock::now(); + elapsed_seconds = std::chrono::duration_cast>(finish - start).count(); + _timing[1] += elapsed_seconds; + // STORM_LOG_DEBUG("restricted Transition: \n" << restrictedTransMatrix); + start = std::chrono::steady_clock::now(); + // find_MSECs() + _MSECs = storm::storage::MaximalEndComponentDecomposition(_restrictedTransitions, _restrictedTransitions.transpose(true)); + + finish = std::chrono::steady_clock::now(); + elapsed_seconds = std::chrono::duration_cast>(finish - start).count(); + _timing[2] += elapsed_seconds; + } + + start = std::chrono::steady_clock::now(); // reducing the choiceValuesU size_t i = 0; auto new_end = std::remove_if(choiceValuesU.begin(), choiceValuesU.end(), [&reducedMinimizerActions, &i](const auto& item) { @@ -114,9 +137,19 @@ namespace storm { return ret; }); choiceValuesU.erase(new_end, choiceValuesU.end()); + finish = std::chrono::steady_clock::now(); + elapsed_seconds = std::chrono::duration_cast< + std::chrono::duration>(finish - start).count(); + _timing[3] += elapsed_seconds; + _oldPolicy = reducedMinimizerActions; // deflating the MSECs - deflate(MSEC, restrictedTransMatrix, xNewU(), choiceValuesU); + start = std::chrono::steady_clock::now(); + deflate(_MSECs, _restrictedTransitions, xNewU(), choiceValuesU); + finish = std::chrono::steady_clock::now(); + elapsed_seconds = std::chrono::duration_cast< + std::chrono::duration>(finish - start).count(); + _timing[4] += elapsed_seconds; } template @@ -177,8 +210,9 @@ namespace storm { } } } - else + else { choice_it += rowGroupSize; + } // reducing the xNew() vector for minimizer states x[state] = optChoice; } @@ -201,22 +235,11 @@ namespace storm { auto x1It = xNewL().begin(); auto x1Ite = xNewL().end(); auto x2It = xNewU().begin(); - ValueType maxDiff = (*x2It - *x1It); - ValueType minDiff = maxDiff; // The difference between maxDiff and minDiff is zero at this point. Thus, it doesn't make sense to check the threshold now. - for (++x1It, ++x2It; x1It != x1Ite; ++x1It, ++x2It) { + for (; x1It != x1Ite; x1It++, x2It++) { ValueType diff = (*x2It - *x1It); // Potentially update maxDiff or minDiff - bool skipCheck = false; - if (maxDiff < diff) { - maxDiff = diff; - } else if (minDiff > diff) { - minDiff = diff; - } else { - skipCheck = true; - } - // Check convergence - if (!skipCheck && (maxDiff - minDiff) > threshold) { + if (diff > threshold) { return false; } } @@ -338,6 +361,16 @@ namespace storm { return _x1IsCurrent ? _x2U : _x1U; } + template + std::vector& SoundGameViHelper::xOldTest() { + return _x1IsCurrent ? _x2Test : _x1Test; + } + + template + std::vector& SoundGameViHelper::xNewTest() { + return _x1IsCurrent ? _x1Test : _x2Test; + } + template class SoundGameViHelper; #ifdef STORM_HAVE_CARL template class SoundGameViHelper; diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h index d8a0d7907..ad78bee56 100644 --- a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h @@ -20,7 +20,7 @@ namespace storm { template class SoundGameViHelper { public: - SoundGameViHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector statesOfCoalition, storm::storage::BitVector psiStates, OptimizationDirection const& optimizationDirection); + SoundGameViHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector b, storm::storage::BitVector statesOfCoalition, storm::storage::BitVector psiStates, OptimizationDirection const& optimizationDirection); void prepareSolversAndMultipliers(const Environment& env); @@ -97,6 +97,10 @@ namespace storm { std::vector& xOldU(); std::vector const& xOldU() const; + std::vector& xNewTest(); + + std::vector& xOldTest(); + bool _x1IsCurrent; storm::storage::BitVector _minimizerStates; @@ -115,14 +119,20 @@ namespace storm { storm::storage::SparseMatrix _transitionMatrix; storm::storage::SparseMatrix _backwardTransitions; + storm::storage::SparseMatrix _restrictedTransitions; + storm::storage::BitVector _oldPolicy; storm::storage::BitVector _statesOfCoalition; storm::storage::BitVector _psiStates; - std::vector _x, _x1L, _x2L, _x1U, _x2U; + std::vector _x, _x1L, _x2L, _x1U, _x2U, _x1Test, _x2Test, _b; OptimizationDirection _optimizationDirection; + storm::storage::MaximalEndComponentDecomposition _MSECs; + bool _produceScheduler = false; bool _shieldingTask = false; boost::optional> _producedOptimalChoices; + + std::vector _timing; }; } } From 26094b08ce4393775e27bcd57fc39bc594b6531b Mon Sep 17 00:00:00 2001 From: Fabian Russold Date: Tue, 1 Oct 2024 12:07:24 +0200 Subject: [PATCH 32/40] WIP Sound LRA for games --- .../internal/SparseSmgLraHelper.cpp | 271 ++++++++++++++++++ .../internal/SparseSmgLraHelper.h | 154 ++++++++++ .../rpatl/SparseSmgRpatlModelChecker.cpp | 8 +- 3 files changed, 431 insertions(+), 2 deletions(-) create mode 100644 src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.cpp create mode 100644 src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.h diff --git a/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.cpp b/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.cpp new file mode 100644 index 000000000..92df53597 --- /dev/null +++ b/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.cpp @@ -0,0 +1,271 @@ +#include "SparseSmgLraHelper.h" + +#include "storm/storage/MaximalEndComponent.h" +#include "storm/storage/StronglyConnectedComponent.h" + +#include "storm/utility/graph.h" +#include "storm/utility/vector.h" +#include "storm/utility/macros.h" +#include "storm/utility/SignalHandler.h" + +#include "storm/environment/solver/SolverEnvironment.h" +#include "storm/environment/solver/LongRunAverageSolverEnvironment.h" +#include "storm/environment/solver/MinMaxSolverEnvironment.h" +#include "storm/environment/solver/MultiplierEnvironment.h" +#include "storm/environment/solver/GameSolverEnvironment.h" + +#include "modelchecker/helper/infinitehorizon/SparseNondeterministicInfiniteHorizonHelper.h" +#include "storm/exceptions/UnmetRequirementException.h" + +namespace storm { + namespace modelchecker { + namespace helper { + namespace internal { + + template + SparseSmgLraHelper::SparseSmgLraHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const statesOfCoalition) : _transitionMatrix(transitionMatrix), _x1IsCurrent(false), _x1IsCurrentStrategyVI(false), _statesOfCoalition(statesOfCoalition) { + + } + + template + std::vector SparseSmgLraHelper::computeLongRunAverageRewardsSound(Environment const& env, storm::models::sparse::StandardRewardModel const& rewardModel) { + STORM_LOG_DEBUG("Transition Matrix:\n" << _transitionMatrix); + std::vector result; + std::vector stateRewardsGetter; + if (rewardModel.hasStateRewards()) { + stateRewardsGetter = rewardModel.getStateRewardVector(); + } + ValueGetter actionRewardsGetter; + if (rewardModel.hasStateActionRewards() || rewardModel.hasTransitionRewards()) { + if (rewardModel.hasTransitionRewards()) { + actionRewardsGetter = [&] (uint64_t globalChoiceIndex) { return rewardModel.getStateActionAndTransitionReward(globalChoiceIndex, this->_transitionMatrix); }; + } else { + actionRewardsGetter = [&] (uint64_t globalChoiceIndex) { return rewardModel.getStateActionReward(globalChoiceIndex); }; + } + } else { + actionRewardsGetter = [] (uint64_t) { return storm::utility::zero(); }; + } + STORM_LOG_DEBUG("rewards: " << rewardModel.getStateRewardVector()); + prepareMultiplier(env, rewardModel); + performValueIteration(env, rewardModel, stateRewardsGetter, actionRewardsGetter, result); + + return result; + } + + template + void SparseSmgLraHelper::performValueIteration(Environment const& env, storm::models::sparse::StandardRewardModel const& rewardModel, std::vector const& stateValueGetter, ValueGetter const& actionValueGetter, std::vector& result, std::vector* choices, std::vector* choiceValues) + { + std::vector choicesForStrategies = std::vector(_transitionMatrix.getRowGroupCount(), 0); + ValueType precision = storm::utility::convertNumber(env.solver().game().getPrecision()); + + do + { + _x1IsCurrent = !_x1IsCurrent; + // Convergent recommender procedure + + _multiplier->multiplyAndReduce(env, _optimizationDirection, xOld(), nullptr, xNew(), &choicesForStrategies, &_statesOfCoalition); + for (size_t i = 0; i < xNew().size(); i++) + { + xNew()[i] = xNew()[i] + stateValueGetter[i]; + } + + storm::storage::BitVector fixedMaxStrat = getStrategyFixedBitVec(choicesForStrategies, MinMaxStrategy::MaxStrategy); + storm::storage::BitVector fixedMinStrat = getStrategyFixedBitVec(choicesForStrategies, MinMaxStrategy::MinStrategy); + storm::storage::SparseMatrix restrictedMaxMatrix = _transitionMatrix.restrictRows(fixedMaxStrat); + + storm::storage::SparseMatrix restrictedMinMatrix = _transitionMatrix.restrictRows(fixedMinStrat); + + // compute bounds + storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper MaxSolver(restrictedMaxMatrix); + MaxSolver.setOptimizationDirection(OptimizationDirection::Minimize); + std::vector resultForMax = MaxSolver.computeLongRunAverageRewards(env, rewardModel); + + for (size_t i = 0; i < xNewL().size(); i++) + { + xNewL()[i] = std::max(xOldL()[i], resultForMax[i]); + } + + storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper MinSolver(restrictedMinMatrix); + MinSolver.setOptimizationDirection(OptimizationDirection::Maximize); + std::vector resultForMin = MinSolver.computeLongRunAverageRewards(env, rewardModel); + + for (size_t i = 0; i < xNewU().size(); i++) + { + xNewU()[i] = std::min(xOldU()[i], resultForMin[i]); + } + + STORM_LOG_DEBUG("xL " << xNewL()); + STORM_LOG_DEBUG("xU " << xNewU()); + + } while (!checkConvergence(precision)); + result = xNewU(); + } + + + template + storm::storage::BitVector SparseSmgLraHelper::getStrategyFixedBitVec(std::vector const& choices, MinMaxStrategy strategy) { + storm::storage::BitVector restrictBy(_transitionMatrix.getRowCount(), true); + auto rowGroupIndices = this->_transitionMatrix.getRowGroupIndices(); + STORM_LOG_DEBUG("choices " << choices); + + for(uint state = 0; state < rowGroupIndices.size() - 1; state++) { + if ((_minimizerStates[state] && strategy == MinMaxStrategy::MaxStrategy) || (!_minimizerStates[state] && strategy == MinMaxStrategy::MinStrategy)) + continue; + + uint rowGroupSize = rowGroupIndices[state + 1] - rowGroupIndices[state]; + for(uint rowGroupIndex = 0; rowGroupIndex < rowGroupSize; rowGroupIndex++) { + if ((rowGroupIndex) != choices[state]) { + restrictBy.set(rowGroupIndex + rowGroupIndices[state], false); + } + } + } + return restrictBy; + } + + + template + void SparseSmgLraHelper::prepareMultiplier(const Environment& env, storm::models::sparse::StandardRewardModel const& rewardModel) + { + _multiplier = storm::solver::MultiplierFactory().create(env, _transitionMatrix); + _minimizerStates = _optimizationDirection == OptimizationDirection::Maximize ? _statesOfCoalition : ~_statesOfCoalition; + + _x1L = std::vector(_transitionMatrix.getRowGroupCount(), storm::utility::zero()); + _x2L = _x1L; + _x1 = _x1L; + _x2 = _x1; + + _x1U = std::vector(_transitionMatrix.getRowGroupCount(), std::numeric_limits::infinity()); + _x2U = _x1U; + } + + template + bool SparseSmgLraHelper::checkConvergence(ValueType threshold) const { + STORM_LOG_ASSERT(_multiplier, "tried to check for convergence without doing an iteration first."); + // Now check whether the currently produced results are precise enough + STORM_LOG_ASSERT(threshold > storm::utility::zero(), "Did not expect a non-positive threshold."); + auto x1It = xNewL().begin(); + auto x1Ite = xNewL().end(); + auto x2It = xNewU().begin(); + ValueType maxDiff = ((*x2It) - (*x1It)); + ValueType minDiff = maxDiff; + // The difference between maxDiff and minDiff is zero at this point. Thus, it doesn't make sense to check the threshold now. + for (++x1It, ++x2It; x1It != x1Ite; ++x1It, ++x2It) { + ValueType diff = (*x2It - *x1It); + // Potentially update maxDiff or minDiff + bool skipCheck = false; + if (maxDiff < diff) { + maxDiff = diff; + } else if (minDiff > diff) { + minDiff = diff; + } else { + skipCheck = true; + } + // Check convergence + if (!skipCheck && (maxDiff - minDiff) > threshold) { + return false; + } + } + return true; + } + + template + std::vector& SparseSmgLraHelper::xNewL() { + return _x1IsCurrent ? _x1L : _x2L; + } + + template + std::vector const& SparseSmgLraHelper::xNewL() const { + return _x1IsCurrent ? _x1L : _x2L; + } + + template + std::vector& SparseSmgLraHelper::xOldL() { + return _x1IsCurrent ? _x2L : _x1L; + } + + template + std::vector const& SparseSmgLraHelper::xOldL() const { + return _x1IsCurrent ? _x2L : _x1L; + } + + template + std::vector& SparseSmgLraHelper::xNewU() { + return _x1IsCurrent ? _x1U : _x2U; + } + + template + std::vector const& SparseSmgLraHelper::xNewU() const { + return _x1IsCurrent ? _x1U : _x2U; + } + + template + std::vector& SparseSmgLraHelper::xOldU() { + return _x1IsCurrent ? _x2U : _x1U; + } + + template + std::vector const& SparseSmgLraHelper::xOldU() const { + return _x1IsCurrent ? _x2U : _x1U; + } + + template + std::vector& SparseSmgLraHelper::xOld() { + return _x1IsCurrent ? _x2 : _x1; + } + + template + std::vector const& SparseSmgLraHelper::xOld() const { + return _x1IsCurrent ? _x2 : _x1; + } + + template + std::vector& SparseSmgLraHelper::xNew() { + return _x1IsCurrent ? _x1 : _x2; + } + + template + std::vector const& SparseSmgLraHelper::xNew() const { + return _x1IsCurrent ? _x1 : _x2; + } + + + template + void SparseSmgLraHelper::setRelevantStates(storm::storage::BitVector relevantStates){ + _relevantStates = relevantStates; + } + + template + void SparseSmgLraHelper::setValueThreshold(storm::logic::ComparisonType const& comparisonType, const ValueType &thresholdValue) { + _valueThreshold = std::make_pair(comparisonType, thresholdValue); + } + + template + void SparseSmgLraHelper::setOptimizationDirection(storm::solver::OptimizationDirection const& direction) { + _optimizationDirection = direction; + } + + template + void SparseSmgLraHelper::setProduceScheduler(bool value) { + _produceScheduler = value; + } + + template + void SparseSmgLraHelper::setProduceChoiceValues(bool value) { + _produceChoiceValues = value; + } + + template + void SparseSmgLraHelper::setQualitative(bool value) { + _isQualitativeSet = value; + } + + template class SparseSmgLraHelper; +#ifdef STORM_HAVE_CARL + template class SparseSmgLraHelper; +#endif + + } + } + } +} + diff --git a/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.h b/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.h new file mode 100644 index 000000000..f4bb609e0 --- /dev/null +++ b/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.h @@ -0,0 +1,154 @@ +#pragma once + +#include "storm/storage/SparseMatrix.h" +#include "storm/storage/BitVector.h" +#include "storm/solver/LinearEquationSolver.h" +#include "storm/solver/MinMaxLinearEquationSolver.h" +#include "storm/solver/Multiplier.h" +#include "storm/logic/ComparisonType.h" + + +namespace storm { + class Environment; + + + namespace modelchecker { + namespace helper { + namespace internal { + + enum class MinMaxStrategy { + MaxStrategy, + MinStrategy + }; + + template + class SparseSmgLraHelper { + public: + /// Function mapping from indices to values + typedef std::function ValueGetter; + + SparseSmgLraHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const statesOfCoalition); + + /*! + * Performs value iteration with the given state- and action values. + * @param env The environment, containing information on the precision of this computation. + * @param stateValueGetter function that returns for each state index (w.r.t. the input transition matrix) the reward for staying in state. Will only be called for timed states. + * @param actionValueGetter function that returns for each global choice index (w.r.t. the input transition matrix) the reward for taking that choice + * @param exitRates (as in the constructor) + * @param dir Optimization direction. Must be not nullptr in case of nondeterminism + * @param choices if not nullptr, the optimal choices will be inserted in this vector. The vector's size must then be equal to the number of row groups of the input transition matrix. + * @return The (optimal) long run average value of the specified component. + * @note it is possible to call this method multiple times with different values. However, other changes to the environment or the optimization direction might not have the expected effect due to caching. + */ + void performValueIteration(Environment const& env, storm::models::sparse::StandardRewardModel const& rewardModel, std::vector const& stateValueGetter, ValueGetter const& actionValueGetter, std::vector& result, std::vector* choices = nullptr, std::vector* choiceValues = nullptr); + + + + void prepareMultiplier(const Environment& env, storm::models::sparse::StandardRewardModel const& rewardModel); + + std::vector computeLongRunAverageRewardsSound(Environment const& env, storm::models::sparse::StandardRewardModel const& rewardModel); + + void setRelevantStates(storm::storage::BitVector relevantStates); + + void setValueThreshold(storm::logic::ComparisonType const& comparisonType, ValueType const& thresholdValue); + + void setOptimizationDirection(storm::solver::OptimizationDirection const& direction); + + void setProduceScheduler(bool value); + + void setProduceChoiceValues(bool value); + + void setQualitative(bool value); + + private: + + /*! + * Initializes the value iterations with the provided values. + * Resets all information from potential previous calls. + * Must be called before the first call to performIterationStep. + * @param stateValueGetter Function that returns for each state index (w.r.t. the input transitions) the value (e.g. reward) for that state + * @param stateValueGetter Function that returns for each global choice index (w.r.t. the input transitions) the value (e.g. reward) for that choice + */ + void initializeNewValues(ValueGetter const& stateValueGetter, ValueGetter const& actionValueGetter, std::vector const* exitRates = nullptr); + + bool checkConvergence(ValueType threshold) const; + + + /*! + * Performs a single iteration step. + * @param env The environment. + * @param dir The optimization direction. Has to be given if there is nondeterminism (otherwise it will be ignored) + * @param choices If given, the optimal choices will be inserted at the appropriate states. + * Note that these choices will be inserted w.r.t. the original model states/choices, i.e. the size of the vector should match the state-count of the input model + * @pre when calling this the first time, initializeNewValues must have been called before. Moreover, prepareNextIteration must be called between two calls of this. + */ + void performIterationStep(Environment const& env, storm::solver::OptimizationDirection const* dir = nullptr, std::vector* choices = nullptr, std::vector* choiceValues = nullptr); + + struct ConvergenceCheckResult { + bool isPrecisionAchieved; + ValueType currentValue; + }; + + storm::storage::BitVector getStrategyFixedBitVec(std::vector const& choices, MinMaxStrategy strategy); + + /*! + * Must be called between two calls of performIterationStep. + */ + void prepareNextIteration(Environment const& env); + + /// Prepares the necessary solvers and multipliers for doing the iterations. + void prepareSolversAndMultipliers(Environment const& env, storm::solver::OptimizationDirection const* dir = nullptr); + + void setInputModelChoices(std::vector& choices, std::vector const& localMecChoices, bool setChoiceZeroToMarkovianStates = false, bool setChoiceZeroToProbabilisticStates = false) const; + + void setInputModelChoiceValues(std::vector& choiceValues, std::vector const& localMecChoiceValues) const; + + /// Returns true iff the given state is a timed state + bool isTimedState(uint64_t const& inputModelStateIndex) const; + + std::vector& xNew(); + std::vector const& xNew() const; + + std::vector& xOld(); + std::vector const& xOld() const; + + std::vector& xNewL(); + std::vector const& xNewL() const; + + std::vector& xOldL(); + std::vector const& xOldL() const; + + std::vector& xNewU(); + std::vector const& xNewU() const; + + std::vector& xOldU(); + std::vector const& xOldU() const; + + storm::storage::SparseMatrix const& _transitionMatrix; + storm::storage::BitVector const _statesOfCoalition; + ValueType _strategyVIPrecision; + + + storm::storage::BitVector _relevantStates; + storm::storage::BitVector _minimizerStates; + boost::optional> _valueThreshold; + storm::solver::OptimizationDirection _optimizationDirection; + bool _produceScheduler; + bool _produceChoiceValues; + bool _isQualitativeSet; + + ValueType _uniformizationRate; + std::vector _x1, _x2, _x1L, _x2L, _x1U, _x2U; + std::vector _Tsx1, _Tsx2, _TsChoiceValues; + bool _x1IsCurrent; + bool _x1IsCurrentStrategyVI; + std::vector _Isx, _Isb, _IsChoiceValues; + std::unique_ptr> _multiplier; + std::unique_ptr> _Solver; + std::unique_ptr> _DetIsSolver; + std::unique_ptr _IsSolverEnv; + }; + } + } + } +} diff --git a/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp b/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp index 30001ce75..6cd0a5560 100644 --- a/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp +++ b/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp @@ -14,6 +14,8 @@ #include "storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.h" #include "storm/modelchecker/helper/infinitehorizon/SparseNondeterministicGameInfiniteHorizonHelper.h" +#include "storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.h" + #include "storm/modelchecker/helper/utility/SetInformationFromCheckTask.h" #include "storm/logic/FragmentSpecification.h" @@ -240,11 +242,12 @@ namespace storm { template std::unique_ptr SparseSmgRpatlModelChecker::computeLongRunAverageRewards(Environment const& env, storm::logic::RewardMeasureType rewardMeasureType, CheckTask const& checkTask) { auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); - storm::modelchecker::helper::SparseNondeterministicGameInfiniteHorizonHelper helper(this->getModel().getTransitionMatrix(), statesOfCoalition); + storm::modelchecker::helper::internal::SparseSmgLraHelper helper(this->getModel().getTransitionMatrix(), statesOfCoalition); storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); - auto values = helper.computeLongRunAverageRewards(env, rewardModel.get()); + auto values = helper.computeLongRunAverageRewardsSound(env, rewardModel.get()); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(values))); + /* if(checkTask.isShieldingTask()) { storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); auto shield = tempest::shields::createQuantitativeShield(std::make_shared>(this->getModel()), helper.getChoiceValues(), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, statesOfCoalition); @@ -253,6 +256,7 @@ namespace storm { if (checkTask.isProduceSchedulersSet()) { result->asExplicitQuantitativeCheckResult().setScheduler(std::make_unique>(helper.extractScheduler())); } + */ return result; } From 621e9f679405ddc16b1d7f769bc47e0ac8a7949e Mon Sep 17 00:00:00 2001 From: Fabian Russold Date: Tue, 1 Oct 2024 12:09:17 +0200 Subject: [PATCH 33/40] optimization: WIP relevant states for game VI --- .../rpatl/helper/SparseSmgRpatlHelper.cpp | 56 +++++++++++++------ 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp index e3dc2d8ee..88f2bd1a2 100644 --- a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp @@ -22,8 +22,7 @@ namespace storm { // Relevant states are those states which are phiStates and not PsiStates. storm::storage::BitVector relevantStates = phiStates & ~psiStates; - - // Initialize the x vector and solution vector result. + // Initialize the x vector and solution vector result. std::vector x = std::vector(relevantStates.getNumberOfSetBits(), storm::utility::zero()); std::vector result = std::vector(transitionMatrix.getRowGroupCount(), storm::utility::zero()); std::vector b = transitionMatrix.getConstrainedRowGroupSumVector(relevantStates, psiStates); @@ -62,44 +61,65 @@ namespace storm { template SMGSparseModelCheckingHelperReturnType SparseSmgRpatlHelper::computeUntilProbabilitiesSound(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, storm::storage::BitVector statesOfCoalition, bool produceScheduler, ModelCheckerHint const& hint) { + STORM_LOG_DEBUG("statesOfCoalition: " << statesOfCoalition << std::endl); + + storm::storage::BitVector prob1 = storm::utility::graph::performProb1(backwardTransitions, phiStates, psiStates); + storm::storage::BitVector probGreater0 = storm::utility::graph::performProbGreater0(backwardTransitions, phiStates, psiStates); + STORM_LOG_DEBUG("probGreater0: " << probGreater0 << std::endl); + + - storm::modelchecker::helper::internal::SoundGameViHelper viHelper(transitionMatrix, backwardTransitions, statesOfCoalition, psiStates, goal.direction()); std::unique_ptr> scheduler; - storm::storage::BitVector relevantStates(psiStates.size(), true); + storm::storage::BitVector relevantStates = storm::storage::BitVector(transitionMatrix.getRowGroupCount(), true); // TODO Fabian + + storm::storage::SparseMatrix submatrix = transitionMatrix.getSubmatrix(true, relevantStates, relevantStates, false); // Initialize the x vector and solution vector result. - // TODO Fabian: maybe relevant states (later) - std::vector xL = std::vector(transitionMatrix.getRowGroupCount(), storm::utility::zero()); + std::vector xL = std::vector(relevantStates.getNumberOfSetBits(), storm::utility::zero()); + auto xL_begin = xL.begin(); + std::for_each(xL.begin(), xL.end(), [&prob1, &xL_begin](ValueType &it) + { + if (prob1[&it - &(*xL_begin)]) + it = 1; + }); // std::transform(xL.begin(), xL.end(), psiStates.begin(), xL, [](double& a) { a *= 3; }) // TODO Fabian // assigning 1s to the xL vector for all Goal states - assert(xL.size() == psiStates.size()); - for (size_t i = 0; i < xL.size(); i++) - { - if (psiStates[i]) - xL[i] = 1; - } - STORM_LOG_DEBUG("xL " << xL); std::vector xU = std::vector(transitionMatrix.getRowGroupCount(), storm::utility::zero()); - storm::storage::BitVector probGreater0 = storm::utility::graph::performProbGreater0(backwardTransitions, phiStates, psiStates); // assigning 1s to the xU vector for all states except the states s where Prob(sEf) = 0 for all goal states f - assert(xU.size() == probGreater0.size()); auto xU_begin = xU.begin(); std::for_each(xU.begin(), xU.end(), [&probGreater0, &xU_begin](ValueType &it) { if (probGreater0[&it - &(*xU_begin)]) it = 1; }); - - STORM_LOG_DEBUG("xU " << xU); + /*size_t i = 0; + auto new_end = std::remove_if(xU.begin(), xU.end(), [&relevantStates, &i](const auto& item) { + bool ret = !(relevantStates[i]); + i++; + return ret; + }); + xU.erase(new_end, xU.end()); + xU.resize(relevantStates.getNumberOfSetBits()); */ std::vector result = std::vector(transitionMatrix.getRowGroupCount(), storm::utility::zero()); + std::vector b = transitionMatrix.getConstrainedRowGroupSumVector(relevantStates, psiStates); + + // STORM_LOG_DEBUG(transitionMatrix); + STORM_LOG_DEBUG("b: " << b); + storm::storage::BitVector clippedStatesOfCoalition(relevantStates.getNumberOfSetBits()); + clippedStatesOfCoalition.setClippedStatesOfCoalition(relevantStates, statesOfCoalition); // std::vector constrainedChoiceValues = std::vector(b.size(), storm::utility::zero()); // TODO Fabian: do I need this? std::vector constrainedChoiceValues; + storm::modelchecker::helper::internal::SoundGameViHelper viHelper(transitionMatrix, backwardTransitions, b, statesOfCoalition, psiStates, goal.direction()); + viHelper.performValueIteration(env, xL, xU, goal.direction(), constrainedChoiceValues); + storm::utility::vector::setVectorValues(result, relevantStates, xU); + storm::utility::vector::setVectorValues(result, psiStates, storm::utility::one()); + STORM_LOG_DEBUG(xU); - return SMGSparseModelCheckingHelperReturnType(std::move(xU), std::move(relevantStates), std::move(scheduler), std::move(constrainedChoiceValues)); + return SMGSparseModelCheckingHelperReturnType(std::move(result), std::move(relevantStates), std::move(scheduler), std::move(constrainedChoiceValues)); } template From 8f187f46f12ae95ee50b31a725766361af0cd236 Mon Sep 17 00:00:00 2001 From: Fabian Russold Date: Wed, 9 Oct 2024 21:10:52 +0200 Subject: [PATCH 34/40] debug: Sound Game VI now fully debugged (fixed Find_MSEC), WIP: produce scheduler --- .../rpatl/SparseSmgRpatlModelChecker.cpp | 1 - .../rpatl/helper/SparseSmgRpatlHelper.cpp | 50 +++++------ .../helper/internal/SoundGameViHelper.cpp | 90 ++++++++----------- .../rpatl/helper/internal/SoundGameViHelper.h | 6 +- 4 files changed, 63 insertions(+), 84 deletions(-) diff --git a/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp b/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp index 6cd0a5560..9239f0578 100644 --- a/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp +++ b/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp @@ -154,7 +154,6 @@ namespace storm { if (checkTask.isProduceSchedulersSet() && ret.scheduler) { result->asExplicitQuantitativeCheckResult().setScheduler(std::move(ret.scheduler)); } - //STORM_LOG_DEBUG(result); return result; } diff --git a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp index 88f2bd1a2..31dc8cea7 100644 --- a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp @@ -61,29 +61,30 @@ namespace storm { template SMGSparseModelCheckingHelperReturnType SparseSmgRpatlHelper::computeUntilProbabilitiesSound(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, storm::storage::BitVector statesOfCoalition, bool produceScheduler, ModelCheckerHint const& hint) { - STORM_LOG_DEBUG("statesOfCoalition: " << statesOfCoalition << std::endl); - storm::storage::BitVector prob1 = storm::utility::graph::performProb1(backwardTransitions, phiStates, psiStates); storm::storage::BitVector probGreater0 = storm::utility::graph::performProbGreater0(backwardTransitions, phiStates, psiStates); - STORM_LOG_DEBUG("probGreater0: " << probGreater0 << std::endl); - - - std::unique_ptr> scheduler; - storm::storage::BitVector relevantStates = storm::storage::BitVector(transitionMatrix.getRowGroupCount(), true); // TODO Fabian + storm::storage::BitVector relevantStates = phiStates; storm::storage::SparseMatrix submatrix = transitionMatrix.getSubmatrix(true, relevantStates, relevantStates, false); // Initialize the x vector and solution vector result. - std::vector xL = std::vector(relevantStates.getNumberOfSetBits(), storm::utility::zero()); + std::vector xL = std::vector(transitionMatrix.getRowGroupCount(), storm::utility::zero()); + // assigning 1s to the xL vector for all Goal states auto xL_begin = xL.begin(); - std::for_each(xL.begin(), xL.end(), [&prob1, &xL_begin](ValueType &it) + std::for_each(xL.begin(), xL.end(), [&psiStates, &xL_begin](ValueType &it) { - if (prob1[&it - &(*xL_begin)]) + if (psiStates[&it - &(*xL_begin)]) it = 1; }); - // std::transform(xL.begin(), xL.end(), psiStates.begin(), xL, [](double& a) { a *= 3; }) // TODO Fabian - // assigning 1s to the xL vector for all Goal states + size_t i = 0; + auto new_end = std::remove_if(xL.begin(), xL.end(), [&relevantStates, &i](const auto& item) { + bool ret = !(relevantStates[i]); + i++; + return ret; + }); + xL.erase(new_end, xL.end()); + xL.resize(relevantStates.getNumberOfSetBits()); std::vector xU = std::vector(transitionMatrix.getRowGroupCount(), storm::utility::zero()); // assigning 1s to the xU vector for all states except the states s where Prob(sEf) = 0 for all goal states f auto xU_begin = xU.begin(); @@ -92,33 +93,32 @@ namespace storm { if (probGreater0[&it - &(*xU_begin)]) it = 1; }); - /*size_t i = 0; - auto new_end = std::remove_if(xU.begin(), xU.end(), [&relevantStates, &i](const auto& item) { + i = 0; + auto new_end_U = std::remove_if(xU.begin(), xU.end(), [&relevantStates, &i](const auto& item) { bool ret = !(relevantStates[i]); i++; return ret; }); - xU.erase(new_end, xU.end()); - xU.resize(relevantStates.getNumberOfSetBits()); */ + xU.erase(new_end_U, xU.end()); + xU.resize(relevantStates.getNumberOfSetBits()); + + storm::storage::BitVector clippedPsiStates(relevantStates.getNumberOfSetBits()); + clippedPsiStates.setClippedStatesOfCoalition(relevantStates, psiStates); - std::vector result = std::vector(transitionMatrix.getRowGroupCount(), storm::utility::zero()); std::vector b = transitionMatrix.getConstrainedRowGroupSumVector(relevantStates, psiStates); + std::vector result = std::vector(transitionMatrix.getRowGroupCount(), storm::utility::zero()); - // STORM_LOG_DEBUG(transitionMatrix); - STORM_LOG_DEBUG("b: " << b); storm::storage::BitVector clippedStatesOfCoalition(relevantStates.getNumberOfSetBits()); clippedStatesOfCoalition.setClippedStatesOfCoalition(relevantStates, statesOfCoalition); - // std::vector constrainedChoiceValues = std::vector(b.size(), storm::utility::zero()); // TODO Fabian: do I need this? - std::vector constrainedChoiceValues; + std::vector constrainedChoiceValues = std::vector(b.size(), storm::utility::zero()); - storm::modelchecker::helper::internal::SoundGameViHelper viHelper(transitionMatrix, backwardTransitions, b, statesOfCoalition, psiStates, goal.direction()); + storm::modelchecker::helper::internal::SoundGameViHelper viHelper(submatrix, submatrix.transpose(), b, clippedStatesOfCoalition, clippedPsiStates, goal.direction()); viHelper.performValueIteration(env, xL, xU, goal.direction(), constrainedChoiceValues); - storm::utility::vector::setVectorValues(result, relevantStates, xU); - storm::utility::vector::setVectorValues(result, psiStates, storm::utility::one()); + viHelper.fillChoiceValuesVector(constrainedChoiceValues, relevantStates, transitionMatrix.getRowGroupIndices()); + storm::utility::vector::setVectorValues(result, relevantStates, xL); - STORM_LOG_DEBUG(xU); return SMGSparseModelCheckingHelperReturnType(std::move(result), std::move(relevantStates), std::move(scheduler), std::move(constrainedChoiceValues)); } diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp index 41dc61b50..4cea25c18 100644 --- a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp @@ -20,7 +20,6 @@ namespace storm { template void SoundGameViHelper::prepareSolversAndMultipliers(const Environment& env) { - STORM_LOG_DEBUG("\n" << _transitionMatrix); _multiplier = storm::solver::MultiplierFactory().create(env, _transitionMatrix); _x1IsCurrent = false; _minimizerStates = _optimizationDirection == OptimizationDirection::Maximize ? _statesOfCoalition : ~_statesOfCoalition; @@ -39,13 +38,11 @@ namespace storm { //_x1.assign(_transitionMatrix.getRowGroupCount(), storm::utility::zero()); _x1L = xL; _x2L = _x1L; - _x1Test = _x1L; - _x2Test = _x1L; _x1U = xU; _x2U = _x1U; - if (this->isProduceSchedulerSet()) { + if (this->isProduceSchedulerSet()) { // TODO Fabian scheduler !!! if (!this->_producedOptimalChoices.is_initialized()) { this->_producedOptimalChoices.emplace(); } @@ -53,12 +50,19 @@ namespace storm { } uint64_t iter = 0; - constrainedChoiceValues = std::vector(xL.size(), storm::utility::zero()); // ?? + constrainedChoiceValues = std::vector(xL.size(), storm::utility::zero()); while (iter < maxIter) { performIterationStep(env, dir); if (checkConvergence(precision)) { - //_multiplier->multiply(env, xNewL(), nullptr, constrainedChoiceValues); // TODO Fabian: ??? + // one last iteration for shield + _multiplier->multiply(env, xNewL(), nullptr, constrainedChoiceValues); + storm::storage::BitVector psiStates = _psiStates; + auto xL_begin = xNewL().begin(); + std::for_each(xNewL().begin(), xNewL().end(), [&psiStates, &xL_begin](ValueType &it){ + if (psiStates[&it - &(*xL_begin)]) + it = 1; + }); break; } if (storm::utility::resources::isTerminate()) { @@ -69,13 +73,10 @@ namespace storm { xL = xNewL(); xU = xNewU(); - // for profiling - STORM_PRINT(_timing[0] << ", " << _timing[1] << ", " << _timing[2] << ", " << _timing[3] << ", " << _timing[4] << std::endl); - - if (isProduceSchedulerSet()) { + /* if (isProduceSchedulerSet()) { // We will be doing one more iteration step and track scheduler choices this time. performIterationStep(env, dir, &_producedOptimalChoices.get()); - } + } */ } template @@ -92,21 +93,25 @@ namespace storm { _multiplier->multiply(env, xOldL(), nullptr, choiceValuesL); reduceChoiceValues(choiceValuesL, &reducedMinimizerActions, xNewL()); - - - // just for debugging - _multiplier->multiplyAndReduce(env, _optimizationDirection, xOldTest(), nullptr, xNewTest(), nullptr, &_statesOfCoalition); + storm::storage::BitVector psiStates = _psiStates; + auto xL_begin = xNewL().begin(); + std::for_each(xNewL().begin(), xNewL().end(), [&psiStates, &xL_begin](ValueType &it) + { + if (psiStates[&it - &(*xL_begin)]) + it = 1; + }); // over_approximation std::vector choiceValuesU = std::vector(this->_transitionMatrix.getRowCount(), storm::utility::zero()); _multiplier->multiply(env, xOldU(), nullptr, choiceValuesU); reduceChoiceValues(choiceValuesU, nullptr, xNewU()); - - auto finish = std::chrono::steady_clock::now(); - double elapsed_seconds = std::chrono::duration_cast< - std::chrono::duration>(finish - start).count(); - _timing[0] += elapsed_seconds; + auto xU_begin = xNewU().begin(); + std::for_each(xNewU().begin(), xNewU().end(), [&psiStates, &xU_begin](ValueType &it) + { + if (psiStates[&it - &(*xU_begin)]) + it = 1; + }); if (reducedMinimizerActions != _oldPolicy) { // new MECs only if Policy changed start = std::chrono::steady_clock::now(); @@ -114,21 +119,10 @@ namespace storm { // restricting the none optimal minimizer choices _restrictedTransitions = this->_transitionMatrix.restrictRows(reducedMinimizerActions); - finish = std::chrono::steady_clock::now(); - elapsed_seconds = std::chrono::duration_cast>(finish - start).count(); - _timing[1] += elapsed_seconds; - - // STORM_LOG_DEBUG("restricted Transition: \n" << restrictedTransMatrix); - start = std::chrono::steady_clock::now(); // find_MSECs() _MSECs = storm::storage::MaximalEndComponentDecomposition(_restrictedTransitions, _restrictedTransitions.transpose(true)); - - finish = std::chrono::steady_clock::now(); - elapsed_seconds = std::chrono::duration_cast>(finish - start).count(); - _timing[2] += elapsed_seconds; } - start = std::chrono::steady_clock::now(); // reducing the choiceValuesU size_t i = 0; auto new_end = std::remove_if(choiceValuesU.begin(), choiceValuesU.end(), [&reducedMinimizerActions, &i](const auto& item) { @@ -137,31 +131,28 @@ namespace storm { return ret; }); choiceValuesU.erase(new_end, choiceValuesU.end()); - finish = std::chrono::steady_clock::now(); - elapsed_seconds = std::chrono::duration_cast< - std::chrono::duration>(finish - start).count(); - _timing[3] += elapsed_seconds; + _oldPolicy = reducedMinimizerActions; // deflating the MSECs - start = std::chrono::steady_clock::now(); deflate(_MSECs, _restrictedTransitions, xNewU(), choiceValuesU); - finish = std::chrono::steady_clock::now(); - elapsed_seconds = std::chrono::duration_cast< - std::chrono::duration>(finish - start).count(); - _timing[4] += elapsed_seconds; } template void SoundGameViHelper::deflate(storm::storage::MaximalEndComponentDecomposition const MSEC, storage::SparseMatrix const restrictedMatrix, std::vector& xU, std::vector choiceValues) { + auto rowGroupIndices = restrictedMatrix.getRowGroupIndices(); auto choice_begin = choiceValues.begin(); // iterating over all MSECs for (auto smec_it : MSEC) { ValueType bestExit = 0; - if (smec_it.isErgodic(restrictedMatrix)) continue; + // if (smec_it.isErgodic(restrictedMatrix)) continue; auto stateSet = smec_it.getStateSet(); for (uint state : stateSet) { + if (_psiStates[state]) { + bestExit = 1; + break; + } if (_minimizerStates[state]) continue; uint rowGroupIndex = rowGroupIndices[state]; auto exitingCompare = [&state, &smec_it, &choice_begin](const ValueType &lhs, const ValueType &rhs) @@ -176,13 +167,16 @@ namespace storm { uint rowGroupSize = rowGroupIndices[state + 1] - rowGroupIndex; auto choice_it = choice_begin + rowGroupIndex; - ValueType newBestExit = *std::max_element(choice_it, choice_it + rowGroupSize, exitingCompare); + auto it = std::max_element(choice_it, choice_it + rowGroupSize, exitingCompare); + ValueType newBestExit = 0; + if (!smec_it.containsChoice(state, it - choice_begin)) { + newBestExit = *it; + } if (newBestExit > bestExit) bestExit = newBestExit; } // deflating the states of the current MSEC for (uint state : stateSet) { - if (_psiStates[state]) continue; xU[state] = std::min(xU[state], bestExit); } } @@ -361,16 +355,6 @@ namespace storm { return _x1IsCurrent ? _x2U : _x1U; } - template - std::vector& SoundGameViHelper::xOldTest() { - return _x1IsCurrent ? _x2Test : _x1Test; - } - - template - std::vector& SoundGameViHelper::xNewTest() { - return _x1IsCurrent ? _x1Test : _x2Test; - } - template class SoundGameViHelper; #ifdef STORM_HAVE_CARL template class SoundGameViHelper; diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h index ad78bee56..45d583b7b 100644 --- a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h @@ -97,10 +97,6 @@ namespace storm { std::vector& xOldU(); std::vector const& xOldU() const; - std::vector& xNewTest(); - - std::vector& xOldTest(); - bool _x1IsCurrent; storm::storage::BitVector _minimizerStates; @@ -123,7 +119,7 @@ namespace storm { storm::storage::BitVector _oldPolicy; storm::storage::BitVector _statesOfCoalition; storm::storage::BitVector _psiStates; - std::vector _x, _x1L, _x2L, _x1U, _x2U, _x1Test, _x2Test, _b; + std::vector _x, _x1L, _x2L, _x1U, _x2U, _b; OptimizationDirection _optimizationDirection; storm::storage::MaximalEndComponentDecomposition _MSECs; From bb72102e501e54277ed9c3c5ef0b4b9529af7b59 Mon Sep 17 00:00:00 2001 From: Fabian Russold Date: Fri, 11 Oct 2024 16:49:31 +0200 Subject: [PATCH 35/40] produceShield: small fix, produceScheduler: implemented --- .../rpatl/helper/SparseSmgRpatlHelper.cpp | 15 +++++++++++++-- .../rpatl/helper/SparseSmgRpatlHelper.h | 2 +- .../helper/internal/SoundGameViHelper.cpp | 19 ++++++++++++------- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp index 31dc8cea7..ddf04ea90 100644 --- a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp @@ -114,16 +114,24 @@ namespace storm { storm::modelchecker::helper::internal::SoundGameViHelper viHelper(submatrix, submatrix.transpose(), b, clippedStatesOfCoalition, clippedPsiStates, goal.direction()); + if (produceScheduler) { + viHelper.setProduceScheduler(true); + } + viHelper.performValueIteration(env, xL, xU, goal.direction(), constrainedChoiceValues); viHelper.fillChoiceValuesVector(constrainedChoiceValues, relevantStates, transitionMatrix.getRowGroupIndices()); storm::utility::vector::setVectorValues(result, relevantStates, xL); + if (produceScheduler) { + scheduler = std::make_unique>(expandScheduler(viHelper.extractScheduler(), psiStates, ~phiStates)); + } + return SMGSparseModelCheckingHelperReturnType(std::move(result), std::move(relevantStates), std::move(scheduler), std::move(constrainedChoiceValues)); } template - storm::storage::Scheduler SparseSmgRpatlHelper::expandScheduler(storm::storage::Scheduler scheduler, storm::storage::BitVector psiStates, storm::storage::BitVector notPhiStates) { + storm::storage::Scheduler SparseSmgRpatlHelper::expandScheduler(storm::storage::Scheduler scheduler, storm::storage::BitVector psiStates, storm::storage::BitVector notPhiStates, bool sound) { storm::storage::Scheduler completeScheduler(psiStates.size()); uint_fast64_t maybeStatesCounter = 0; uint schedulerSize = psiStates.size(); @@ -131,6 +139,9 @@ namespace storm { // psiStates already fulfill formulae so we can set an arbitrary action if(psiStates.get(stateCounter)) { completeScheduler.setChoice(0, stateCounter); + if (sound) { + maybeStatesCounter++; + } // ~phiStates do not fulfill formulae so we can set an arbitrary action } else if(notPhiStates.get(stateCounter)) { completeScheduler.setChoice(0, stateCounter); @@ -149,7 +160,7 @@ namespace storm { storm::storage::BitVector notPsiStates = ~psiStates; statesOfCoalition.complement(); - auto result = computeUntilProbabilities(env, std::move(goal), transitionMatrix, backwardTransitions, storm::storage::BitVector(transitionMatrix.getRowGroupCount(), true), notPsiStates, qualitative, statesOfCoalition, produceScheduler, hint); + auto result = computeUntilProbabilitiesSound(env, std::move(goal), transitionMatrix, backwardTransitions, storm::storage::BitVector(transitionMatrix.getRowGroupCount(), true), notPsiStates, qualitative, statesOfCoalition, produceScheduler, hint); for (auto& element : result.values) { element = storm::utility::one() - element; } diff --git a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.h b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.h index 741d5961d..c0216d23f 100644 --- a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.h +++ b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.h @@ -41,7 +41,7 @@ namespace storm { static SMGSparseModelCheckingHelperReturnType computeBoundedGloballyProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& psiStates, bool qualitative, storm::storage::BitVector statesOfCoalition, bool produceScheduler, ModelCheckerHint const& hint, uint64_t lowerBound, uint64_t upperBound); static SMGSparseModelCheckingHelperReturnType computeBoundedUntilProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, storm::storage::BitVector statesOfCoalition, bool produceScheduler, ModelCheckerHint const& hint, uint64_t lowerBound, uint64_t upperBound, bool computeBoundedGlobally = false); private: - static storm::storage::Scheduler expandScheduler(storm::storage::Scheduler scheduler, storm::storage::BitVector psiStates, storm::storage::BitVector notPhiStates); + static storm::storage::Scheduler expandScheduler(storm::storage::Scheduler scheduler, storm::storage::BitVector psiStates, storm::storage::BitVector notPhiStates, bool sound = false); static void expandChoiceValues(std::vector const& rowGroupIndices, storm::storage::BitVector const& relevantStates, std::vector const& constrainedChoiceValues, std::vector& choiceValues); }; } diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp index 4cea25c18..e42179764 100644 --- a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp @@ -50,7 +50,7 @@ namespace storm { } uint64_t iter = 0; - constrainedChoiceValues = std::vector(xL.size(), storm::utility::zero()); + constrainedChoiceValues = std::vector(_transitionMatrix.getRowCount(), storm::utility::zero()); while (iter < maxIter) { performIterationStep(env, dir); @@ -73,10 +73,18 @@ namespace storm { xL = xNewL(); xU = xNewU(); - /* if (isProduceSchedulerSet()) { + if (isProduceSchedulerSet()) { // We will be doing one more iteration step and track scheduler choices this time. - performIterationStep(env, dir, &_producedOptimalChoices.get()); - } */ + _x1IsCurrent = !_x1IsCurrent; + _multiplier->multiplyAndReduce(env, dir, xOldL(), nullptr, xNewL(), &_producedOptimalChoices.get(), &_statesOfCoalition); + storm::storage::BitVector psiStates = _psiStates; + auto xL_begin = xNewL().begin(); + std::for_each(xNewL().begin(), xNewL().end(), [&psiStates, &xL_begin](ValueType &it) + { + if (psiStates[&it - &(*xL_begin)]) + it = 1; + }); + } } template @@ -84,7 +92,6 @@ namespace storm { storm::storage::BitVector reducedMinimizerActions = {storm::storage::BitVector(this->_transitionMatrix.getRowCount(), true)}; // under approximation - auto start = std::chrono::steady_clock::now(); if (!_multiplier) { prepareSolversAndMultipliers(env); } @@ -114,8 +121,6 @@ namespace storm { }); if (reducedMinimizerActions != _oldPolicy) { // new MECs only if Policy changed - start = std::chrono::steady_clock::now(); - // restricting the none optimal minimizer choices _restrictedTransitions = this->_transitionMatrix.restrictRows(reducedMinimizerActions); From 5453d910c315428969717f94b484784e84851c4f Mon Sep 17 00:00:00 2001 From: Fabian Russold Date: Mon, 21 Oct 2024 16:29:21 +0200 Subject: [PATCH 36/40] reach/safety fully implemented --- .../rpatl/SparseSmgRpatlModelChecker.cpp | 48 ++++++++++++++++--- .../rpatl/helper/SparseSmgRpatlHelper.cpp | 43 ++++++++++++----- .../helper/internal/SoundGameViHelper.cpp | 2 +- 3 files changed, 73 insertions(+), 20 deletions(-) diff --git a/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp b/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp index 9239f0578..7fa177d2c 100644 --- a/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp +++ b/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp @@ -143,7 +143,28 @@ namespace storm { ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - auto ret = storm::modelchecker::helper::SparseSmgRpatlHelper::computeUntilProbabilitiesSound(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), statesOfCoalition, checkTask.isProduceSchedulersSet(), checkTask.getHint()); + if (env.solver().isForceSoundness()) { + auto ret = storm::modelchecker::helper::SparseSmgRpatlHelper::computeUntilProbabilitiesSound( + env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), + this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), + checkTask.isQualitativeSet(), statesOfCoalition, checkTask.isProduceSchedulersSet(), checkTask.getHint()); + + std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); + if(checkTask.isShieldingTask()) { + storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); + auto shield = tempest::shields::createShield(std::make_shared>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition); + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); + } + if (checkTask.isProduceSchedulersSet() && ret.scheduler) { + result->asExplicitQuantitativeCheckResult().setScheduler(std::move(ret.scheduler)); + } + return result; + } + + auto ret = storm::modelchecker::helper::SparseSmgRpatlHelper::computeUntilProbabilities( + env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), + this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), + checkTask.isQualitativeSet(), statesOfCoalition, checkTask.isProduceSchedulersSet(), checkTask.getHint()); STORM_LOG_DEBUG(ret.values); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if(checkTask.isShieldingTask()) { @@ -241,12 +262,28 @@ namespace storm { template std::unique_ptr SparseSmgRpatlModelChecker::computeLongRunAverageRewards(Environment const& env, storm::logic::RewardMeasureType rewardMeasureType, CheckTask const& checkTask) { auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); - storm::modelchecker::helper::internal::SparseSmgLraHelper helper(this->getModel().getTransitionMatrix(), statesOfCoalition); - storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); - auto values = helper.computeLongRunAverageRewardsSound(env, rewardModel.get()); + if (env.solver().isForceSoundness()) { + storm::modelchecker::helper::internal::SparseSmgLraHelper helper(this->getModel().getTransitionMatrix(), statesOfCoalition); + auto values = helper.computeLongRunAverageRewardsSound(env, rewardModel.get()); + storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); + std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(values))); + + if(checkTask.isShieldingTask()) { + storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); + auto shield = tempest::shields::createQuantitativeShield(std::make_shared>(this->getModel()), helper.getChoiceValues(), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, statesOfCoalition); + result->asExplicitQuantitativeCheckResult().setShield(std::move(shield)); + } + if (checkTask.isProduceSchedulersSet()) { + result->asExplicitQuantitativeCheckResult().setScheduler(std::make_unique>(helper.extractScheduler())); + } + return result; + } + + storm::modelchecker::helper::SparseNondeterministicGameInfiniteHorizonHelper helper(this->getModel().getTransitionMatrix(), statesOfCoalition); + auto values = helper.computeLongRunAverageRewards(env, rewardModel.get()); + storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(values))); - /* if(checkTask.isShieldingTask()) { storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); auto shield = tempest::shields::createQuantitativeShield(std::make_shared>(this->getModel()), helper.getChoiceValues(), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, statesOfCoalition); @@ -255,7 +292,6 @@ namespace storm { if (checkTask.isProduceSchedulersSet()) { result->asExplicitQuantitativeCheckResult().setScheduler(std::make_unique>(helper.extractScheduler())); } - */ return result; } diff --git a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp index ddf04ea90..e2a349a50 100644 --- a/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp @@ -61,13 +61,10 @@ namespace storm { template SMGSparseModelCheckingHelperReturnType SparseSmgRpatlHelper::computeUntilProbabilitiesSound(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, storm::storage::BitVector statesOfCoalition, bool produceScheduler, ModelCheckerHint const& hint) { - storm::storage::BitVector probGreater0 = storm::utility::graph::performProbGreater0(backwardTransitions, phiStates, psiStates); std::unique_ptr> scheduler; storm::storage::BitVector relevantStates = phiStates; - storm::storage::SparseMatrix submatrix = transitionMatrix.getSubmatrix(true, relevantStates, relevantStates, false); - // Initialize the x vector and solution vector result. std::vector xL = std::vector(transitionMatrix.getRowGroupCount(), storm::utility::zero()); // assigning 1s to the xL vector for all Goal states @@ -112,19 +109,24 @@ namespace storm { clippedStatesOfCoalition.setClippedStatesOfCoalition(relevantStates, statesOfCoalition); std::vector constrainedChoiceValues = std::vector(b.size(), storm::utility::zero()); - storm::modelchecker::helper::internal::SoundGameViHelper viHelper(submatrix, submatrix.transpose(), b, clippedStatesOfCoalition, clippedPsiStates, goal.direction()); + if (!relevantStates.empty()) { + storm::storage::SparseMatrix submatrix = transitionMatrix.getSubmatrix(true, relevantStates, relevantStates, false); + storm::modelchecker::helper::internal::SoundGameViHelper viHelper(submatrix, submatrix.transpose(), b, clippedStatesOfCoalition, + clippedPsiStates, goal.direction()); - if (produceScheduler) { - viHelper.setProduceScheduler(true); - } + if (produceScheduler) { + viHelper.setProduceScheduler(true); + } - viHelper.performValueIteration(env, xL, xU, goal.direction(), constrainedChoiceValues); + viHelper.performValueIteration(env, xL, xU, goal.direction(), constrainedChoiceValues); - viHelper.fillChoiceValuesVector(constrainedChoiceValues, relevantStates, transitionMatrix.getRowGroupIndices()); - storm::utility::vector::setVectorValues(result, relevantStates, xL); + viHelper.fillChoiceValuesVector(constrainedChoiceValues, relevantStates, transitionMatrix.getRowGroupIndices()); + storm::utility::vector::setVectorValues(result, relevantStates, xL); - if (produceScheduler) { - scheduler = std::make_unique>(expandScheduler(viHelper.extractScheduler(), psiStates, ~phiStates)); + if (produceScheduler) { + scheduler = + std::make_unique>(expandScheduler(viHelper.extractScheduler(), psiStates, ~phiStates, true)); + } } return SMGSparseModelCheckingHelperReturnType(std::move(result), std::move(relevantStates), std::move(scheduler), std::move(constrainedChoiceValues)); @@ -160,7 +162,22 @@ namespace storm { storm::storage::BitVector notPsiStates = ~psiStates; statesOfCoalition.complement(); - auto result = computeUntilProbabilitiesSound(env, std::move(goal), transitionMatrix, backwardTransitions, storm::storage::BitVector(transitionMatrix.getRowGroupCount(), true), notPsiStates, qualitative, statesOfCoalition, produceScheduler, hint); + if (env.solver().isForceSoundness()) { + auto result = computeUntilProbabilitiesSound(env, std::move(goal), transitionMatrix, backwardTransitions, + storm::storage::BitVector(transitionMatrix.getRowGroupCount(), true), notPsiStates, + qualitative, statesOfCoalition, produceScheduler, hint); + for (auto& element : result.values) { + element = storm::utility::one() - element; + } + for (auto& element : result.choiceValues) { + element = storm::utility::one() - element; + } + return result; + } + + auto result = computeUntilProbabilities(env, std::move(goal), transitionMatrix, backwardTransitions, + storm::storage::BitVector(transitionMatrix.getRowGroupCount(), true), notPsiStates, + qualitative, statesOfCoalition, produceScheduler, hint); for (auto& element : result.values) { element = storm::utility::one() - element; } diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp index e42179764..a91fc03b6 100644 --- a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp @@ -42,7 +42,7 @@ namespace storm { _x1U = xU; _x2U = _x1U; - if (this->isProduceSchedulerSet()) { // TODO Fabian scheduler !!! + if (this->isProduceSchedulerSet()) { if (!this->_producedOptimalChoices.is_initialized()) { this->_producedOptimalChoices.emplace(); } From c8acbc6834835a5e63440b786b5b99e650b1ef63 Mon Sep 17 00:00:00 2001 From: Fabian Russold Date: Mon, 21 Oct 2024 16:30:09 +0200 Subject: [PATCH 37/40] WIP: LRA fully implemented, scheduler and shield still to be debugged --- .../internal/SparseSmgLraHelper.cpp | 196 ++++++++++++++---- .../internal/SparseSmgLraHelper.h | 20 +- 2 files changed, 169 insertions(+), 47 deletions(-) diff --git a/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.cpp b/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.cpp index 92df53597..307f4d889 100644 --- a/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.cpp +++ b/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.cpp @@ -29,9 +29,9 @@ namespace storm { template std::vector SparseSmgLraHelper::computeLongRunAverageRewardsSound(Environment const& env, storm::models::sparse::StandardRewardModel const& rewardModel) { - STORM_LOG_DEBUG("Transition Matrix:\n" << _transitionMatrix); + // STORM_LOG_DEBUG("Transition Matrix:\n" << _transitionMatrix); std::vector result; - std::vector stateRewardsGetter; + std::vector stateRewardsGetter = std::vector(_transitionMatrix.getRowGroupCount(), storm::utility::zero()); if (rewardModel.hasStateRewards()) { stateRewardsGetter = rewardModel.getStateRewardVector(); } @@ -45,60 +45,104 @@ namespace storm { } else { actionRewardsGetter = [] (uint64_t) { return storm::utility::zero(); }; } - STORM_LOG_DEBUG("rewards: " << rewardModel.getStateRewardVector()); + std::vector b = getBVector(stateRewardsGetter, actionRewardsGetter); + + // If requested, allocate memory for the choices made + if (this->_produceScheduler) { + if (!this->_producedOptimalChoices.is_initialized()) { + _producedOptimalChoices.emplace(); + } + _producedOptimalChoices->resize(_transitionMatrix.getRowGroupCount()); + } + prepareMultiplier(env, rewardModel); - performValueIteration(env, rewardModel, stateRewardsGetter, actionRewardsGetter, result); + performValueIteration(env, rewardModel, b, actionRewardsGetter, result); return result; } template - void SparseSmgLraHelper::performValueIteration(Environment const& env, storm::models::sparse::StandardRewardModel const& rewardModel, std::vector const& stateValueGetter, ValueGetter const& actionValueGetter, std::vector& result, std::vector* choices, std::vector* choiceValues) + std::vector SparseSmgLraHelper::getBVector(std::vector const& stateRewardsGetter, ValueGetter const& actionRewardsGetter) { + std::vector b = std::vector(_transitionMatrix.getRowCount()); + size_t globalChoiceCount = 0; + auto rowGroupIndices = _transitionMatrix.getRowGroupIndices(); + for (size_t state = 0; state < _transitionMatrix.getRowGroupCount(); state++) { + size_t rowGroupSize = rowGroupIndices[state + 1] - rowGroupIndices[state]; + for (size_t choice = 0; choice < rowGroupSize; choice++, globalChoiceCount++) + { + b[globalChoiceCount] = stateRewardsGetter[state] + actionRewardsGetter(globalChoiceCount); + } + } + return b; + } + + template + void SparseSmgLraHelper::performValueIteration(Environment const& env, storm::models::sparse::StandardRewardModel const& rewardModel, std::vector const& b, ValueGetter const& actionValueGetter, std::vector& result, std::vector* choices, std::vector* choiceValues) { std::vector choicesForStrategies = std::vector(_transitionMatrix.getRowGroupCount(), 0); - ValueType precision = storm::utility::convertNumber(env.solver().game().getPrecision()); + auto precision = storm::utility::convertNumber(env.solver().lra().getPrecision()); + Environment envMinMax = env; + envMinMax.solver().lra().setPrecision(precision / 2.0); + STORM_LOG_DEBUG(envMinMax.solver().lra().getPrecision()); do { - _x1IsCurrent = !_x1IsCurrent; + size_t iteration_count = 0; // Convergent recommender procedure - _multiplier->multiplyAndReduce(env, _optimizationDirection, xOld(), nullptr, xNew(), &choicesForStrategies, &_statesOfCoalition); - for (size_t i = 0; i < xNew().size(); i++) - { - xNew()[i] = xNew()[i] + stateValueGetter[i]; - } + _multiplier->multiplyAndReduce(env, _optimizationDirection, xNew(), &b, xNew(), &choicesForStrategies, &_statesOfCoalition); + if (iteration_count % 5 == 0) { // only every 5th iteration storm::storage::BitVector fixedMaxStrat = getStrategyFixedBitVec(choicesForStrategies, MinMaxStrategy::MaxStrategy); storm::storage::BitVector fixedMinStrat = getStrategyFixedBitVec(choicesForStrategies, MinMaxStrategy::MinStrategy); - storm::storage::SparseMatrix restrictedMaxMatrix = _transitionMatrix.restrictRows(fixedMaxStrat); - - storm::storage::SparseMatrix restrictedMinMatrix = _transitionMatrix.restrictRows(fixedMinStrat); // compute bounds - storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper MaxSolver(restrictedMaxMatrix); - MaxSolver.setOptimizationDirection(OptimizationDirection::Minimize); - std::vector resultForMax = MaxSolver.computeLongRunAverageRewards(env, rewardModel); + if (fixedMaxStrat != _fixedMaxStrat) { + storm::storage::SparseMatrix restrictedMaxMatrix = _transitionMatrix.restrictRows(fixedMaxStrat); + + storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper MaxSolver(restrictedMaxMatrix); + MaxSolver.setOptimizationDirection(OptimizationDirection::Minimize); + _resultForMax = MaxSolver.computeLongRunAverageRewards(envMinMax, rewardModel); + STORM_LOG_DEBUG("resultMax: " << _resultForMax); + _fixedMaxStrat = fixedMaxStrat; + + for (size_t i = 0; i < xNewL().size(); i++) { + xNewL()[i] = std::max(xNewL()[i], _resultForMax[i]); + } + } - for (size_t i = 0; i < xNewL().size(); i++) - { - xNewL()[i] = std::max(xOldL()[i], resultForMax[i]); - } + if (fixedMinStrat != _fixedMinStrat) { + storm::storage::SparseMatrix restrictedMinMatrix = _transitionMatrix.restrictRows(fixedMinStrat); - storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper MinSolver(restrictedMinMatrix); - MinSolver.setOptimizationDirection(OptimizationDirection::Maximize); - std::vector resultForMin = MinSolver.computeLongRunAverageRewards(env, rewardModel); + storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper MinSolver(restrictedMinMatrix); + MinSolver.setOptimizationDirection(OptimizationDirection::Maximize); + _resultForMin = MinSolver.computeLongRunAverageRewards(envMinMax, rewardModel); + STORM_LOG_DEBUG("resultMin: " << _resultForMin); + _fixedMinStrat = fixedMinStrat; - for (size_t i = 0; i < xNewU().size(); i++) - { - xNewU()[i] = std::min(xOldU()[i], resultForMin[i]); + for (size_t i = 0; i < xNewU().size(); i++) { + xNewU()[i] = std::min(xNewU()[i], _resultForMin[i]); + } + } } STORM_LOG_DEBUG("xL " << xNewL()); STORM_LOG_DEBUG("xU " << xNewU()); } while (!checkConvergence(precision)); - result = xNewU(); + + if (_produceScheduler) { + _multiplier->multiplyAndReduce(env, _optimizationDirection, xNew(), &b, xNew(), &_producedOptimalChoices.get(), &_statesOfCoalition); + } + + if (_produceChoiceValues) { + if (!this->_choiceValues.is_initialized()) { + this->_choiceValues.emplace(); + } + this->_choiceValues->resize(this->_transitionMatrix.getRowCount()); + _choiceValues = calcChoiceValues(envMinMax, rewardModel); + } + result = xNewL(); } @@ -108,7 +152,7 @@ namespace storm { auto rowGroupIndices = this->_transitionMatrix.getRowGroupIndices(); STORM_LOG_DEBUG("choices " << choices); - for(uint state = 0; state < rowGroupIndices.size() - 1; state++) { + for(uint state = 0; state < _transitionMatrix.getRowGroupCount(); state++) { if ((_minimizerStates[state] && strategy == MinMaxStrategy::MaxStrategy) || (!_minimizerStates[state] && strategy == MinMaxStrategy::MinStrategy)) continue; @@ -122,6 +166,75 @@ namespace storm { return restrictBy; } + template + std::vector SparseSmgLraHelper::calcChoiceValues(Environment const& env, storm::models::sparse::StandardRewardModel const& rewardModel) { + std::vector choiceValues(_transitionMatrix.getRowCount()); + + storm::storage::SparseMatrix restrictedMaxMatrix = _transitionMatrix.restrictRows(_fixedMaxStrat); + storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper MaxSolver(restrictedMaxMatrix); + MaxSolver.setOptimizationDirection(OptimizationDirection::Minimize); + MaxSolver.setProduceChoiceValues(true); + MaxSolver.computeLongRunAverageRewards(env, rewardModel); + std::vector minimizerChoices = MaxSolver.getChoiceValues(); + + storm::storage::SparseMatrix restrictedMinMatrix = _transitionMatrix.restrictRows(_fixedMinStrat); + storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper MinSolver(restrictedMinMatrix); + MinSolver.setOptimizationDirection(OptimizationDirection::Maximize); + MinSolver.setProduceChoiceValues(true); + MinSolver.computeLongRunAverageRewards(env, rewardModel); + std::vector maximizerChoices = MinSolver.getChoiceValues(); + + auto rowGroupIndices = this->_transitionMatrix.getRowGroupIndices(); + + auto minIt = minimizerChoices.begin(); + auto maxIt = maximizerChoices.begin(); + size_t globalCounter = 0; + for(uint state = 0; state < _transitionMatrix.getRowGroupCount(); state++) { + uint rowGroupSize = rowGroupIndices[state + 1] - rowGroupIndices[state]; + for(uint rowGroupIndex = 0; rowGroupIndex < rowGroupSize; rowGroupIndex++) { + if (_minimizerStates[state]) { + choiceValues[globalCounter] = *minIt; + minIt++; + } + else { + choiceValues[globalCounter] = *maxIt; + maxIt++; + } + globalCounter++; + } + if (_minimizerStates[state]) { + maxIt++; + } + else { + minIt++; + } + } + return choiceValues; + } + + template + std::vector SparseSmgLraHelper::getChoiceValues() const { + STORM_LOG_ASSERT(_produceChoiceValues, "Trying to get the computed choice values although this was not requested."); + STORM_LOG_ASSERT(this->_choiceValues.is_initialized(), "Trying to get the computed choice values but none were available. Was there a computation call before?"); + return this->_choiceValues.get(); + } + + template + storm::storage::Scheduler SparseSmgLraHelper::extractScheduler() const{ + auto const& optimalChoices = getProducedOptimalChoices(); + storm::storage::Scheduler scheduler(optimalChoices.size()); + for (uint64_t state = 0; state < optimalChoices.size(); ++state) { + scheduler.setChoice(optimalChoices[state], state); + } + return scheduler; + } + + template + std::vector const& SparseSmgLraHelper::getProducedOptimalChoices() const { + STORM_LOG_ASSERT(_produceScheduler, "Trying to get the produced optimal choices although no scheduler was requested."); + STORM_LOG_ASSERT(this->_producedOptimalChoices.is_initialized(), "Trying to get the produced optimal choices but none were available. Was there a computation call before?"); + return this->_producedOptimalChoices.get(); + } template void SparseSmgLraHelper::prepareMultiplier(const Environment& env, storm::models::sparse::StandardRewardModel const& rewardModel) @@ -134,6 +247,12 @@ namespace storm { _x1 = _x1L; _x2 = _x1; + _fixedMaxStrat = storm::storage::BitVector(_transitionMatrix.getRowCount(), false); + _fixedMinStrat = storm::storage::BitVector(_transitionMatrix.getRowCount(), false); + + _resultForMin = std::vector(_transitionMatrix.getRowGroupCount()); + _resultForMax = std::vector(_transitionMatrix.getRowGroupCount()); + _x1U = std::vector(_transitionMatrix.getRowGroupCount(), std::numeric_limits::infinity()); _x2U = _x1U; } @@ -146,22 +265,9 @@ namespace storm { auto x1It = xNewL().begin(); auto x1Ite = xNewL().end(); auto x2It = xNewU().begin(); - ValueType maxDiff = ((*x2It) - (*x1It)); - ValueType minDiff = maxDiff; - // The difference between maxDiff and minDiff is zero at this point. Thus, it doesn't make sense to check the threshold now. - for (++x1It, ++x2It; x1It != x1Ite; ++x1It, ++x2It) { + for (; x1It != x1Ite; x1It++, x2It++) { ValueType diff = (*x2It - *x1It); - // Potentially update maxDiff or minDiff - bool skipCheck = false; - if (maxDiff < diff) { - maxDiff = diff; - } else if (minDiff > diff) { - minDiff = diff; - } else { - skipCheck = true; - } - // Check convergence - if (!skipCheck && (maxDiff - minDiff) > threshold) { + if (diff > threshold) { return false; } } diff --git a/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.h b/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.h index f4bb609e0..d9be65770 100644 --- a/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.h +++ b/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.h @@ -24,7 +24,7 @@ namespace storm { template class SparseSmgLraHelper { public: - /// Function mapping from indices to values + // Function mapping from indices to values typedef std::function ValueGetter; SparseSmgLraHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const statesOfCoalition); @@ -42,7 +42,11 @@ namespace storm { */ void performValueIteration(Environment const& env, storm::models::sparse::StandardRewardModel const& rewardModel, std::vector const& stateValueGetter, ValueGetter const& actionValueGetter, std::vector& result, std::vector* choices = nullptr, std::vector* choiceValues = nullptr); + std::vector getChoiceValues() const; + storm::storage::Scheduler extractScheduler() const; + + std::vector const& getProducedOptimalChoices() const; void prepareMultiplier(const Environment& env, storm::models::sparse::StandardRewardModel const& rewardModel); @@ -91,6 +95,10 @@ namespace storm { storm::storage::BitVector getStrategyFixedBitVec(std::vector const& choices, MinMaxStrategy strategy); + std::vector getBVector(std::vector const& stateRewardsGetter, ValueGetter const& actionRewardsGetter); + + std::vector calcChoiceValues(Environment const& env, storm::models::sparse::StandardRewardModel const& rewardModel); + /*! * Must be called between two calls of performIterationStep. */ @@ -128,9 +136,14 @@ namespace storm { storm::storage::BitVector const _statesOfCoalition; ValueType _strategyVIPrecision; - storm::storage::BitVector _relevantStates; storm::storage::BitVector _minimizerStates; + + storm::storage::BitVector _fixedMinStrat; + storm::storage::BitVector _fixedMaxStrat; + std::vector _resultForMax; + std::vector _resultForMin; + boost::optional> _valueThreshold; storm::solver::OptimizationDirection _optimizationDirection; bool _produceScheduler; @@ -147,6 +160,9 @@ namespace storm { std::unique_ptr> _Solver; std::unique_ptr> _DetIsSolver; std::unique_ptr _IsSolverEnv; + + boost::optional> _producedOptimalChoices; + boost::optional> _choiceValues; }; } } From 8846a976f28bb2fd76860aa1bc5015be94e74bd4 Mon Sep 17 00:00:00 2001 From: Fabian Russold Date: Tue, 29 Oct 2024 09:05:25 +0100 Subject: [PATCH 38/40] Game LRA Sound algorithm fully debugged --- .../internal/SparseSmgLraHelper.cpp | 129 +++++------------- .../internal/SparseSmgLraHelper.h | 61 +-------- .../rpatl/SparseSmgRpatlModelChecker.cpp | 4 +- .../helper/internal/SoundGameViHelper.cpp | 7 +- 4 files changed, 44 insertions(+), 157 deletions(-) diff --git a/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.cpp b/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.cpp index 307f4d889..ffeacaf3d 100644 --- a/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.cpp +++ b/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.cpp @@ -23,13 +23,12 @@ namespace storm { namespace internal { template - SparseSmgLraHelper::SparseSmgLraHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const statesOfCoalition) : _transitionMatrix(transitionMatrix), _x1IsCurrent(false), _x1IsCurrentStrategyVI(false), _statesOfCoalition(statesOfCoalition) { + SparseSmgLraHelper::SparseSmgLraHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const statesOfCoalition) : _transitionMatrix(transitionMatrix), _statesOfCoalition(statesOfCoalition) { } template std::vector SparseSmgLraHelper::computeLongRunAverageRewardsSound(Environment const& env, storm::models::sparse::StandardRewardModel const& rewardModel) { - // STORM_LOG_DEBUG("Transition Matrix:\n" << _transitionMatrix); std::vector result; std::vector stateRewardsGetter = std::vector(_transitionMatrix.getRowGroupCount(), storm::utility::zero()); if (rewardModel.hasStateRewards()) { @@ -45,7 +44,7 @@ namespace storm { } else { actionRewardsGetter = [] (uint64_t) { return storm::utility::zero(); }; } - std::vector b = getBVector(stateRewardsGetter, actionRewardsGetter); + _b = getBVector(stateRewardsGetter, actionRewardsGetter); // If requested, allocate memory for the choices made if (this->_produceScheduler) { @@ -56,7 +55,7 @@ namespace storm { } prepareMultiplier(env, rewardModel); - performValueIteration(env, rewardModel, b, actionRewardsGetter, result); + performValueIteration(env, rewardModel, _b, actionRewardsGetter, result); return result; } @@ -83,8 +82,7 @@ namespace storm { auto precision = storm::utility::convertNumber(env.solver().lra().getPrecision()); Environment envMinMax = env; - envMinMax.solver().lra().setPrecision(precision / 2.0); - STORM_LOG_DEBUG(envMinMax.solver().lra().getPrecision()); + envMinMax.solver().lra().setPrecision(precision / storm::utility::convertNumber(2)); do { size_t iteration_count = 0; @@ -92,23 +90,28 @@ namespace storm { _multiplier->multiplyAndReduce(env, _optimizationDirection, xNew(), &b, xNew(), &choicesForStrategies, &_statesOfCoalition); - if (iteration_count % 5 == 0) { // only every 5th iteration + if (iteration_count % 50 == 0) { // only every 50th iteration storm::storage::BitVector fixedMaxStrat = getStrategyFixedBitVec(choicesForStrategies, MinMaxStrategy::MaxStrategy); storm::storage::BitVector fixedMinStrat = getStrategyFixedBitVec(choicesForStrategies, MinMaxStrategy::MinStrategy); // compute bounds if (fixedMaxStrat != _fixedMaxStrat) { storm::storage::SparseMatrix restrictedMaxMatrix = _transitionMatrix.restrictRows(fixedMaxStrat); + STORM_LOG_DEBUG("xL " << xNewL()[0]); storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper MaxSolver(restrictedMaxMatrix); + STORM_LOG_DEBUG("xL " << xNewL()[0]); + MaxSolver.setOptimizationDirection(OptimizationDirection::Minimize); + MaxSolver.setProduceChoiceValues(false); _resultForMax = MaxSolver.computeLongRunAverageRewards(envMinMax, rewardModel); - STORM_LOG_DEBUG("resultMax: " << _resultForMax); _fixedMaxStrat = fixedMaxStrat; + STORM_LOG_DEBUG("xL " << xNewL()[0]); for (size_t i = 0; i < xNewL().size(); i++) { xNewL()[i] = std::max(xNewL()[i], _resultForMax[i]); } + STORM_LOG_DEBUG("xL " << xNewL()[0]); } if (fixedMinStrat != _fixedMinStrat) { @@ -116,19 +119,17 @@ namespace storm { storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper MinSolver(restrictedMinMatrix); MinSolver.setOptimizationDirection(OptimizationDirection::Maximize); + MinSolver.setProduceChoiceValues(false); _resultForMin = MinSolver.computeLongRunAverageRewards(envMinMax, rewardModel); - STORM_LOG_DEBUG("resultMin: " << _resultForMin); _fixedMinStrat = fixedMinStrat; for (size_t i = 0; i < xNewU().size(); i++) { xNewU()[i] = std::min(xNewU()[i], _resultForMin[i]); } + STORM_LOG_DEBUG("xU " << xNewU()[0]); } } - STORM_LOG_DEBUG("xL " << xNewL()); - STORM_LOG_DEBUG("xU " << xNewU()); - } while (!checkConvergence(precision)); if (_produceScheduler) { @@ -140,7 +141,7 @@ namespace storm { this->_choiceValues.emplace(); } this->_choiceValues->resize(this->_transitionMatrix.getRowCount()); - _choiceValues = calcChoiceValues(envMinMax, rewardModel); + _choiceValues = calcChoiceValues(env, rewardModel); } result = xNewL(); } @@ -150,7 +151,6 @@ namespace storm { storm::storage::BitVector SparseSmgLraHelper::getStrategyFixedBitVec(std::vector const& choices, MinMaxStrategy strategy) { storm::storage::BitVector restrictBy(_transitionMatrix.getRowCount(), true); auto rowGroupIndices = this->_transitionMatrix.getRowGroupIndices(); - STORM_LOG_DEBUG("choices " << choices); for(uint state = 0; state < _transitionMatrix.getRowGroupCount(); state++) { if ((_minimizerStates[state] && strategy == MinMaxStrategy::MaxStrategy) || (!_minimizerStates[state] && strategy == MinMaxStrategy::MinStrategy)) @@ -169,46 +169,8 @@ namespace storm { template std::vector SparseSmgLraHelper::calcChoiceValues(Environment const& env, storm::models::sparse::StandardRewardModel const& rewardModel) { std::vector choiceValues(_transitionMatrix.getRowCount()); + _multiplier->multiply(env, xNewL(), nullptr, choiceValues); - storm::storage::SparseMatrix restrictedMaxMatrix = _transitionMatrix.restrictRows(_fixedMaxStrat); - storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper MaxSolver(restrictedMaxMatrix); - MaxSolver.setOptimizationDirection(OptimizationDirection::Minimize); - MaxSolver.setProduceChoiceValues(true); - MaxSolver.computeLongRunAverageRewards(env, rewardModel); - std::vector minimizerChoices = MaxSolver.getChoiceValues(); - - storm::storage::SparseMatrix restrictedMinMatrix = _transitionMatrix.restrictRows(_fixedMinStrat); - storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper MinSolver(restrictedMinMatrix); - MinSolver.setOptimizationDirection(OptimizationDirection::Maximize); - MinSolver.setProduceChoiceValues(true); - MinSolver.computeLongRunAverageRewards(env, rewardModel); - std::vector maximizerChoices = MinSolver.getChoiceValues(); - - auto rowGroupIndices = this->_transitionMatrix.getRowGroupIndices(); - - auto minIt = minimizerChoices.begin(); - auto maxIt = maximizerChoices.begin(); - size_t globalCounter = 0; - for(uint state = 0; state < _transitionMatrix.getRowGroupCount(); state++) { - uint rowGroupSize = rowGroupIndices[state + 1] - rowGroupIndices[state]; - for(uint rowGroupIndex = 0; rowGroupIndex < rowGroupSize; rowGroupIndex++) { - if (_minimizerStates[state]) { - choiceValues[globalCounter] = *minIt; - minIt++; - } - else { - choiceValues[globalCounter] = *maxIt; - maxIt++; - } - globalCounter++; - } - if (_minimizerStates[state]) { - maxIt++; - } - else { - minIt++; - } - } return choiceValues; } @@ -223,9 +185,11 @@ namespace storm { storm::storage::Scheduler SparseSmgLraHelper::extractScheduler() const{ auto const& optimalChoices = getProducedOptimalChoices(); storm::storage::Scheduler scheduler(optimalChoices.size()); + for (uint64_t state = 0; state < optimalChoices.size(); ++state) { scheduler.setChoice(optimalChoices[state], state); } + return scheduler; } @@ -233,6 +197,7 @@ namespace storm { std::vector const& SparseSmgLraHelper::getProducedOptimalChoices() const { STORM_LOG_ASSERT(_produceScheduler, "Trying to get the produced optimal choices although no scheduler was requested."); STORM_LOG_ASSERT(this->_producedOptimalChoices.is_initialized(), "Trying to get the produced optimal choices but none were available. Was there a computation call before?"); + return this->_producedOptimalChoices.get(); } @@ -240,12 +205,15 @@ namespace storm { void SparseSmgLraHelper::prepareMultiplier(const Environment& env, storm::models::sparse::StandardRewardModel const& rewardModel) { _multiplier = storm::solver::MultiplierFactory().create(env, _transitionMatrix); - _minimizerStates = _optimizationDirection == OptimizationDirection::Maximize ? _statesOfCoalition : ~_statesOfCoalition; + if (_statesOfCoalition.size()) { + _minimizerStates = _optimizationDirection == OptimizationDirection::Maximize ? _statesOfCoalition : ~_statesOfCoalition; + } + else { + _minimizerStates = storm::storage::BitVector(_transitionMatrix.getRowGroupCount(), _optimizationDirection == OptimizationDirection::Minimize); + } - _x1L = std::vector(_transitionMatrix.getRowGroupCount(), storm::utility::zero()); - _x2L = _x1L; - _x1 = _x1L; - _x2 = _x1; + _xL = std::vector(_transitionMatrix.getRowGroupCount(), storm::utility::zero()); + _x = _xL; _fixedMaxStrat = storm::storage::BitVector(_transitionMatrix.getRowCount(), false); _fixedMinStrat = storm::storage::BitVector(_transitionMatrix.getRowCount(), false); @@ -253,8 +221,7 @@ namespace storm { _resultForMin = std::vector(_transitionMatrix.getRowGroupCount()); _resultForMax = std::vector(_transitionMatrix.getRowGroupCount()); - _x1U = std::vector(_transitionMatrix.getRowGroupCount(), std::numeric_limits::infinity()); - _x2U = _x1U; + _xU = std::vector(_transitionMatrix.getRowGroupCount(), std::numeric_limits::infinity()); } template @@ -276,62 +243,32 @@ namespace storm { template std::vector& SparseSmgLraHelper::xNewL() { - return _x1IsCurrent ? _x1L : _x2L; + return _xL; } template std::vector const& SparseSmgLraHelper::xNewL() const { - return _x1IsCurrent ? _x1L : _x2L; - } - - template - std::vector& SparseSmgLraHelper::xOldL() { - return _x1IsCurrent ? _x2L : _x1L; - } - - template - std::vector const& SparseSmgLraHelper::xOldL() const { - return _x1IsCurrent ? _x2L : _x1L; + return _xL; } template std::vector& SparseSmgLraHelper::xNewU() { - return _x1IsCurrent ? _x1U : _x2U; + return _xU; } template std::vector const& SparseSmgLraHelper::xNewU() const { - return _x1IsCurrent ? _x1U : _x2U; - } - - template - std::vector& SparseSmgLraHelper::xOldU() { - return _x1IsCurrent ? _x2U : _x1U; - } - - template - std::vector const& SparseSmgLraHelper::xOldU() const { - return _x1IsCurrent ? _x2U : _x1U; - } - - template - std::vector& SparseSmgLraHelper::xOld() { - return _x1IsCurrent ? _x2 : _x1; - } - - template - std::vector const& SparseSmgLraHelper::xOld() const { - return _x1IsCurrent ? _x2 : _x1; + return _xU; } template std::vector& SparseSmgLraHelper::xNew() { - return _x1IsCurrent ? _x1 : _x2; + return _x; } template std::vector const& SparseSmgLraHelper::xNew() const { - return _x1IsCurrent ? _x1 : _x2; + return _x; } diff --git a/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.h b/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.h index d9be65770..5fb8bf205 100644 --- a/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.h +++ b/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.h @@ -29,17 +29,6 @@ namespace storm { SparseSmgLraHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const statesOfCoalition); - /*! - * Performs value iteration with the given state- and action values. - * @param env The environment, containing information on the precision of this computation. - * @param stateValueGetter function that returns for each state index (w.r.t. the input transition matrix) the reward for staying in state. Will only be called for timed states. - * @param actionValueGetter function that returns for each global choice index (w.r.t. the input transition matrix) the reward for taking that choice - * @param exitRates (as in the constructor) - * @param dir Optimization direction. Must be not nullptr in case of nondeterminism - * @param choices if not nullptr, the optimal choices will be inserted in this vector. The vector's size must then be equal to the number of row groups of the input transition matrix. - * @return The (optimal) long run average value of the specified component. - * @note it is possible to call this method multiple times with different values. However, other changes to the environment or the optimization direction might not have the expected effect due to caching. - */ void performValueIteration(Environment const& env, storm::models::sparse::StandardRewardModel const& rewardModel, std::vector const& stateValueGetter, ValueGetter const& actionValueGetter, std::vector& result, std::vector* choices = nullptr, std::vector* choiceValues = nullptr); std::vector getChoiceValues() const; @@ -66,26 +55,8 @@ namespace storm { private: - /*! - * Initializes the value iterations with the provided values. - * Resets all information from potential previous calls. - * Must be called before the first call to performIterationStep. - * @param stateValueGetter Function that returns for each state index (w.r.t. the input transitions) the value (e.g. reward) for that state - * @param stateValueGetter Function that returns for each global choice index (w.r.t. the input transitions) the value (e.g. reward) for that choice - */ - void initializeNewValues(ValueGetter const& stateValueGetter, ValueGetter const& actionValueGetter, std::vector const* exitRates = nullptr); - bool checkConvergence(ValueType threshold) const; - - /*! - * Performs a single iteration step. - * @param env The environment. - * @param dir The optimization direction. Has to be given if there is nondeterminism (otherwise it will be ignored) - * @param choices If given, the optimal choices will be inserted at the appropriate states. - * Note that these choices will be inserted w.r.t. the original model states/choices, i.e. the size of the vector should match the state-count of the input model - * @pre when calling this the first time, initializeNewValues must have been called before. Moreover, prepareNextIteration must be called between two calls of this. - */ void performIterationStep(Environment const& env, storm::solver::OptimizationDirection const* dir = nullptr, std::vector* choices = nullptr, std::vector* choiceValues = nullptr); struct ConvergenceCheckResult { @@ -99,42 +70,17 @@ namespace storm { std::vector calcChoiceValues(Environment const& env, storm::models::sparse::StandardRewardModel const& rewardModel); - /*! - * Must be called between two calls of performIterationStep. - */ - void prepareNextIteration(Environment const& env); - - /// Prepares the necessary solvers and multipliers for doing the iterations. - void prepareSolversAndMultipliers(Environment const& env, storm::solver::OptimizationDirection const* dir = nullptr); - - void setInputModelChoices(std::vector& choices, std::vector const& localMecChoices, bool setChoiceZeroToMarkovianStates = false, bool setChoiceZeroToProbabilisticStates = false) const; - - void setInputModelChoiceValues(std::vector& choiceValues, std::vector const& localMecChoiceValues) const; - - /// Returns true iff the given state is a timed state - bool isTimedState(uint64_t const& inputModelStateIndex) const; - std::vector& xNew(); std::vector const& xNew() const; - std::vector& xOld(); - std::vector const& xOld() const; - std::vector& xNewL(); std::vector const& xNewL() const; - std::vector& xOldL(); - std::vector const& xOldL() const; - std::vector& xNewU(); std::vector const& xNewU() const; - std::vector& xOldU(); - std::vector const& xOldU() const; - storm::storage::SparseMatrix const& _transitionMatrix; storm::storage::BitVector const _statesOfCoalition; - ValueType _strategyVIPrecision; storm::storage::BitVector _relevantStates; storm::storage::BitVector _minimizerStates; @@ -144,17 +90,16 @@ namespace storm { std::vector _resultForMax; std::vector _resultForMin; + std::vector _b; + boost::optional> _valueThreshold; storm::solver::OptimizationDirection _optimizationDirection; bool _produceScheduler; bool _produceChoiceValues; bool _isQualitativeSet; - ValueType _uniformizationRate; - std::vector _x1, _x2, _x1L, _x2L, _x1U, _x2U; + std::vector _x, _xL, _xU; std::vector _Tsx1, _Tsx2, _TsChoiceValues; - bool _x1IsCurrent; - bool _x1IsCurrentStrategyVI; std::vector _Isx, _Isb, _IsChoiceValues; std::unique_ptr> _multiplier; std::unique_ptr> _Solver; diff --git a/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp b/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp index 7fa177d2c..754ca74b2 100644 --- a/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp +++ b/src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp @@ -265,8 +265,8 @@ namespace storm { if (env.solver().isForceSoundness()) { storm::modelchecker::helper::internal::SparseSmgLraHelper helper(this->getModel().getTransitionMatrix(), statesOfCoalition); - auto values = helper.computeLongRunAverageRewardsSound(env, rewardModel.get()); storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); + auto values = helper.computeLongRunAverageRewardsSound(env, rewardModel.get()); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(values))); if(checkTask.isShieldingTask()) { @@ -281,8 +281,8 @@ namespace storm { } storm::modelchecker::helper::SparseNondeterministicGameInfiniteHorizonHelper helper(this->getModel().getTransitionMatrix(), statesOfCoalition); - auto values = helper.computeLongRunAverageRewards(env, rewardModel.get()); storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); + auto values = helper.computeLongRunAverageRewards(env, rewardModel.get()); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(values))); if(checkTask.isShieldingTask()) { storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true); diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp index a91fc03b6..c87b31d5f 100644 --- a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp @@ -22,7 +22,12 @@ namespace storm { void SoundGameViHelper::prepareSolversAndMultipliers(const Environment& env) { _multiplier = storm::solver::MultiplierFactory().create(env, _transitionMatrix); _x1IsCurrent = false; - _minimizerStates = _optimizationDirection == OptimizationDirection::Maximize ? _statesOfCoalition : ~_statesOfCoalition; + if (_statesOfCoalition.size()) { + _minimizerStates = _optimizationDirection == OptimizationDirection::Maximize ? _statesOfCoalition : ~_statesOfCoalition; + } + else { + _minimizerStates = storm::storage::BitVector(_transitionMatrix.getRowGroupCount(), _optimizationDirection == OptimizationDirection::Minimize); + } _oldPolicy = storm::storage::BitVector(_transitionMatrix.getRowCount(), false); _timing = std::vector(5, 0); } From 54f36dd36980ab5bcefa90284554e820a85d418b Mon Sep 17 00:00:00 2001 From: Fabian Russold Date: Tue, 29 Oct 2024 09:32:27 +0100 Subject: [PATCH 39/40] SparseSmgLraHelper: cleaned up --- .../internal/SparseSmgLraHelper.cpp | 19 ++++++++----------- .../internal/SparseSmgLraHelper.h | 9 +-------- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.cpp b/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.cpp index ffeacaf3d..6b8f63739 100644 --- a/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.cpp +++ b/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.cpp @@ -17,6 +17,8 @@ #include "modelchecker/helper/infinitehorizon/SparseNondeterministicInfiniteHorizonHelper.h" #include "storm/exceptions/UnmetRequirementException.h" +#define SOLVE_MDP 50 + namespace storm { namespace modelchecker { namespace helper { @@ -55,7 +57,7 @@ namespace storm { } prepareMultiplier(env, rewardModel); - performValueIteration(env, rewardModel, _b, actionRewardsGetter, result); + performValueIteration(env, rewardModel, _b, result); return result; } @@ -76,7 +78,7 @@ namespace storm { } template - void SparseSmgLraHelper::performValueIteration(Environment const& env, storm::models::sparse::StandardRewardModel const& rewardModel, std::vector const& b, ValueGetter const& actionValueGetter, std::vector& result, std::vector* choices, std::vector* choiceValues) + void SparseSmgLraHelper::performValueIteration(Environment const& env, storm::models::sparse::StandardRewardModel const& rewardModel, std::vector const& b, std::vector& result) { std::vector choicesForStrategies = std::vector(_transitionMatrix.getRowGroupCount(), 0); auto precision = storm::utility::convertNumber(env.solver().lra().getPrecision()); @@ -90,28 +92,24 @@ namespace storm { _multiplier->multiplyAndReduce(env, _optimizationDirection, xNew(), &b, xNew(), &choicesForStrategies, &_statesOfCoalition); - if (iteration_count % 50 == 0) { // only every 50th iteration - storm::storage::BitVector fixedMaxStrat = getStrategyFixedBitVec(choicesForStrategies, MinMaxStrategy::MaxStrategy); - storm::storage::BitVector fixedMinStrat = getStrategyFixedBitVec(choicesForStrategies, MinMaxStrategy::MinStrategy); + if (iteration_count % SOLVE_MDP == 0) { // only every 50th iteration + storm::storage::BitVector fixedMaxStrat = getStrategyFixedBitVec(choicesForStrategies, MinMaxStrategy::MaxStrategy); + storm::storage::BitVector fixedMinStrat = getStrategyFixedBitVec(choicesForStrategies, MinMaxStrategy::MinStrategy); - // compute bounds + // compute bounds if (fixedMaxStrat != _fixedMaxStrat) { storm::storage::SparseMatrix restrictedMaxMatrix = _transitionMatrix.restrictRows(fixedMaxStrat); - STORM_LOG_DEBUG("xL " << xNewL()[0]); storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper MaxSolver(restrictedMaxMatrix); - STORM_LOG_DEBUG("xL " << xNewL()[0]); MaxSolver.setOptimizationDirection(OptimizationDirection::Minimize); MaxSolver.setProduceChoiceValues(false); _resultForMax = MaxSolver.computeLongRunAverageRewards(envMinMax, rewardModel); _fixedMaxStrat = fixedMaxStrat; - STORM_LOG_DEBUG("xL " << xNewL()[0]); for (size_t i = 0; i < xNewL().size(); i++) { xNewL()[i] = std::max(xNewL()[i], _resultForMax[i]); } - STORM_LOG_DEBUG("xL " << xNewL()[0]); } if (fixedMinStrat != _fixedMinStrat) { @@ -126,7 +124,6 @@ namespace storm { for (size_t i = 0; i < xNewU().size(); i++) { xNewU()[i] = std::min(xNewU()[i], _resultForMin[i]); } - STORM_LOG_DEBUG("xU " << xNewU()[0]); } } diff --git a/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.h b/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.h index 5fb8bf205..4a6537945 100644 --- a/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.h +++ b/src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.h @@ -29,7 +29,7 @@ namespace storm { SparseSmgLraHelper(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const statesOfCoalition); - void performValueIteration(Environment const& env, storm::models::sparse::StandardRewardModel const& rewardModel, std::vector const& stateValueGetter, ValueGetter const& actionValueGetter, std::vector& result, std::vector* choices = nullptr, std::vector* choiceValues = nullptr); + void performValueIteration(Environment const& env, storm::models::sparse::StandardRewardModel const& rewardModel, std::vector const& b, std::vector& result); std::vector getChoiceValues() const; @@ -57,13 +57,6 @@ namespace storm { bool checkConvergence(ValueType threshold) const; - void performIterationStep(Environment const& env, storm::solver::OptimizationDirection const* dir = nullptr, std::vector* choices = nullptr, std::vector* choiceValues = nullptr); - - struct ConvergenceCheckResult { - bool isPrecisionAchieved; - ValueType currentValue; - }; - storm::storage::BitVector getStrategyFixedBitVec(std::vector const& choices, MinMaxStrategy strategy); std::vector getBVector(std::vector const& stateRewardsGetter, ValueGetter const& actionRewardsGetter); From 7e5867252d6298df9d3095d1c4cc0bf304a3af01 Mon Sep 17 00:00:00 2001 From: Fabian Russold Date: Tue, 29 Oct 2024 09:39:48 +0100 Subject: [PATCH 40/40] SoundGameViHelper: cleaned up --- .../modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp | 4 ---- .../modelchecker/rpatl/helper/internal/SoundGameViHelper.h | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp index c87b31d5f..aab2935d6 100644 --- a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp @@ -40,7 +40,6 @@ namespace storm { ValueType precision = storm::utility::convertNumber(env.solver().game().getPrecision()); uint64_t maxIter = env.solver().game().getMaximalNumberOfIterations(); - //_x1.assign(_transitionMatrix.getRowGroupCount(), storm::utility::zero()); _x1L = xL; _x2L = _x1L; @@ -156,7 +155,6 @@ namespace storm { // iterating over all MSECs for (auto smec_it : MSEC) { ValueType bestExit = 0; - // if (smec_it.isErgodic(restrictedMatrix)) continue; auto stateSet = smec_it.getStateSet(); for (uint state : stateSet) { if (_psiStates[state]) { @@ -239,10 +237,8 @@ namespace storm { auto x1It = xNewL().begin(); auto x1Ite = xNewL().end(); auto x2It = xNewU().begin(); - // The difference between maxDiff and minDiff is zero at this point. Thus, it doesn't make sense to check the threshold now. for (; x1It != x1Ite; x1It++, x2It++) { ValueType diff = (*x2It - *x1It); - // Potentially update maxDiff or minDiff if (diff > threshold) { return false; } diff --git a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h index 45d583b7b..e90099fde 100644 --- a/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h +++ b/src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h @@ -72,8 +72,6 @@ namespace storm { void reduceChoiceValues(std::vector& choiceValues, storm::storage::BitVector* result, std::vector& x); - // multiplier now public for testing - std::unique_ptr> _multiplier; private: /*! * Performs one iteration step for value iteration @@ -113,6 +111,8 @@ namespace storm { */ std::vector& getProducedOptimalChoices(); + std::unique_ptr> _multiplier; + storm::storage::SparseMatrix _transitionMatrix; storm::storage::SparseMatrix _backwardTransitions; storm::storage::SparseMatrix _restrictedTransitions;