5 changed files with 414 additions and 2 deletions
			
			
		- 
					3src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp
- 
					38src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp
- 
					1src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.h
- 
					255src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp
- 
					119src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h
| @ -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 <typename ValueType> | |||
|                 SoundGameViHelper<ValueType>::SoundGameViHelper(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::BitVector statesOfCoalition) : _transitionMatrix(transitionMatrix), _statesOfCoalition(statesOfCoalition) { | |||
|                     // Intentionally left empty.
 | |||
|                 } | |||
| 
 | |||
|                 template <typename ValueType> | |||
|                 void SoundGameViHelper<ValueType>::prepareSolversAndMultipliers(const Environment& env) { | |||
|                     STORM_LOG_DEBUG("\n" << _transitionMatrix); | |||
|                     _multiplier = storm::solver::MultiplierFactory<ValueType>().create(env, _transitionMatrix); | |||
|                     _x1IsCurrent = false; | |||
|                 } | |||
| 
 | |||
|                 template <typename ValueType> | |||
|                 void SoundGameViHelper<ValueType>::performValueIteration(Environment const& env, std::vector<ValueType>& xL, std::vector<ValueType>& xU, storm::solver::OptimizationDirection const dir, std::vector<ValueType>& constrainedChoiceValues) { | |||
|                     // new pair (x_old, x_new) for over_approximation()
 | |||
| 
 | |||
|                     prepareSolversAndMultipliers(env); | |||
|                     // Get precision for convergence check.
 | |||
|                     ValueType precision = storm::utility::convertNumber<ValueType>(env.solver().game().getPrecision()); | |||
| 
 | |||
|                     STORM_LOG_DEBUG("hello" << "world"); | |||
|                     uint64_t maxIter = env.solver().game().getMaximalNumberOfIterations(); | |||
|                     //_x1.assign(_transitionMatrix.getRowGroupCount(), storm::utility::zero<ValueType>());
 | |||
|                     _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<ValueType>(xL.size(), storm::utility::zero<ValueType>()); // ??
 | |||
| 
 | |||
|                     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 <typename ValueType> | |||
|                 void SoundGameViHelper<ValueType>::performIterationStep(Environment const& env, storm::solver::OptimizationDirection const dir, std::vector<uint64_t>* 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 <typename ValueType> | |||
|                 bool SoundGameViHelper<ValueType>::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<ValueType>(), "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 <typename ValueType> | |||
|                 void SoundGameViHelper<ValueType>::setProduceScheduler(bool value) { | |||
|                     _produceScheduler = value; | |||
|                 } | |||
| 
 | |||
|                 template <typename ValueType> | |||
|                 bool SoundGameViHelper<ValueType>::isProduceSchedulerSet() const { | |||
|                     return _produceScheduler; | |||
|                 } | |||
| 
 | |||
|                 template <typename ValueType> | |||
|                 void SoundGameViHelper<ValueType>::setShieldingTask(bool value) { | |||
|                     _shieldingTask = value; | |||
|                 } | |||
| 
 | |||
|                 template <typename ValueType> | |||
|                 bool SoundGameViHelper<ValueType>::isShieldingTask() const { | |||
|                     return _shieldingTask; | |||
|                 } | |||
| 
 | |||
|                 template <typename ValueType> | |||
|                 void SoundGameViHelper<ValueType>::updateTransitionMatrix(storm::storage::SparseMatrix<ValueType> newTransitionMatrix) { | |||
|                     _transitionMatrix = newTransitionMatrix; | |||
|                 } | |||
| 
 | |||
|                 template <typename ValueType> | |||
|                 void SoundGameViHelper<ValueType>::updateStatesOfCoalition(storm::storage::BitVector newStatesOfCoalition) { | |||
|                     _statesOfCoalition = newStatesOfCoalition; | |||
|                 } | |||
| 
 | |||
|                 template <typename ValueType> | |||
|                 std::vector<uint64_t> const& SoundGameViHelper<ValueType>::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 <typename ValueType> | |||
|                 std::vector<uint64_t>& SoundGameViHelper<ValueType>::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 <typename ValueType> | |||
|                 storm::storage::Scheduler<ValueType> SoundGameViHelper<ValueType>::extractScheduler() const{ | |||
|                     auto const& optimalChoices = getProducedOptimalChoices(); | |||
|                     storm::storage::Scheduler<ValueType> scheduler(optimalChoices.size()); | |||
|                     for (uint64_t state = 0; state < optimalChoices.size(); ++state) { | |||
|                         scheduler.setChoice(optimalChoices[state], state); | |||
|                     } | |||
|                     return scheduler; | |||
|                 } | |||
| 
 | |||
|                 template <typename ValueType> | |||
|                 void SoundGameViHelper<ValueType>::getChoiceValues(Environment const& env, std::vector<ValueType> const& x, std::vector<ValueType>& choiceValues) { | |||
|                     _multiplier->multiply(env, x, nullptr, choiceValues); | |||
|                 } | |||
| 
 | |||
|                 template <typename ValueType> | |||
|                 void SoundGameViHelper<ValueType>::fillChoiceValuesVector(std::vector<ValueType>& choiceValues, storm::storage::BitVector psiStates, std::vector<storm::storage::SparseMatrix<double>::index_type> rowGroupIndices) { | |||
|                     std::vector<ValueType> allChoices = std::vector<ValueType>(rowGroupIndices.at(rowGroupIndices.size() - 1), storm::utility::zero<ValueType>()); | |||
|                     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 <typename ValueType> | |||
|                 std::vector<ValueType>& SoundGameViHelper<ValueType>::xNewL() { | |||
|                     return _x1IsCurrent ? _x1L : _x2L; | |||
|                 } | |||
| 
 | |||
|                 template <typename ValueType> | |||
|                 std::vector<ValueType> const& SoundGameViHelper<ValueType>::xNewL() const { | |||
|                     return _x1IsCurrent ? _x1L : _x2L; | |||
|                 } | |||
| 
 | |||
|                 template <typename ValueType> | |||
|                 std::vector<ValueType>& SoundGameViHelper<ValueType>::xOldL() { | |||
|                     return _x1IsCurrent ? _x2L : _x1L; | |||
|                 } | |||
| 
 | |||
|                 template <typename ValueType> | |||
|                 std::vector<ValueType> const& SoundGameViHelper<ValueType>::xOldL() const { | |||
|                     return _x1IsCurrent ? _x2L : _x1L; | |||
|                 } | |||
| 
 | |||
|                 template <typename ValueType> | |||
|                 std::vector<ValueType>& SoundGameViHelper<ValueType>::xNewU() { | |||
|                     return _x1IsCurrent ? _x1U : _x2U; | |||
|                 } | |||
| 
 | |||
|                 template <typename ValueType> | |||
|                 std::vector<ValueType> const& SoundGameViHelper<ValueType>::xNewU() const { | |||
|                     return _x1IsCurrent ? _x1U : _x2U; | |||
|                 } | |||
| 
 | |||
|                 template <typename ValueType> | |||
|                 std::vector<ValueType>& SoundGameViHelper<ValueType>::xOldU() { | |||
|                     return _x1IsCurrent ? _x2U : _x1U; | |||
|                 } | |||
| 
 | |||
|                 template <typename ValueType> | |||
|                 std::vector<ValueType> const& SoundGameViHelper<ValueType>::xOldU() const { | |||
|                     return _x1IsCurrent ? _x2U : _x1U; | |||
|                 } | |||
| 
 | |||
|                 template class SoundGameViHelper<double>; | |||
| #ifdef STORM_HAVE_CARL
 | |||
|                 template class SoundGameViHelper<storm::RationalNumber>; | |||
| #endif
 | |||
|             } | |||
|         } | |||
|     } | |||
| } | |||
| @ -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 <typename VT> class Scheduler; | |||
|     } | |||
| 
 | |||
|     namespace modelchecker { | |||
|         namespace helper { | |||
|             namespace internal { | |||
| 
 | |||
|                 template <typename ValueType> | |||
|                 class SoundGameViHelper { | |||
|                 public: | |||
|                     SoundGameViHelper(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::BitVector statesOfCoalition); | |||
| 
 | |||
|                     void prepareSolversAndMultipliers(const Environment& env); | |||
| 
 | |||
|                     /*! | |||
|                      * Perform value iteration until convergence | |||
|                      */ | |||
|                     void performValueIteration(Environment const& env, std::vector<ValueType>& xL, std::vector<ValueType>& xU, storm::solver::OptimizationDirection const dir, std::vector<ValueType>& 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<ValueType> newTransitionMatrix); | |||
| 
 | |||
|                     /*! | |||
|                      * Changes the statesOfCoalition to the given one. | |||
|                      */ | |||
|                     void updateStatesOfCoalition(storm::storage::BitVector newStatesOfCoalition); | |||
| 
 | |||
|                     storm::storage::Scheduler<ValueType> extractScheduler() const; | |||
| 
 | |||
|                     void getChoiceValues(Environment const& env, std::vector<ValueType> const& x, std::vector<ValueType>& choiceValues); | |||
| 
 | |||
|                     /*! | |||
|                      * Fills the choice values vector to the original size with zeros for ~psiState choices. | |||
|                      */ | |||
|                     void fillChoiceValuesVector(std::vector<ValueType>& choiceValues, storm::storage::BitVector psiStates, std::vector<storm::storage::SparseMatrix<double>::index_type> rowGroupIndices); | |||
| 
 | |||
|                 private: | |||
|                     /*! | |||
|                      * Performs one iteration step for value iteration | |||
|                      */ | |||
|                     void performIterationStep(Environment const& env, storm::solver::OptimizationDirection const dir, std::vector<uint64_t>* choices = nullptr); | |||
| 
 | |||
|                     /*! | |||
|                      * Checks whether the curently computed value achieves the desired precision | |||
|                      */ | |||
|                     bool checkConvergence(ValueType precision) const; | |||
| 
 | |||
|                     std::vector<ValueType>& xNewL(); | |||
|                     std::vector<ValueType> const& xNewL() const; | |||
| 
 | |||
|                     std::vector<ValueType>& xOldL(); | |||
|                     std::vector<ValueType> const& xOldL() const; | |||
| 
 | |||
|                     std::vector<ValueType>& xNewU(); | |||
|                     std::vector<ValueType> const& xNewU() const; | |||
| 
 | |||
|                     std::vector<ValueType>& xOldU(); | |||
|                     std::vector<ValueType> 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<uint64_t> 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<uint64_t>& getProducedOptimalChoices(); | |||
| 
 | |||
|                     storm::storage::SparseMatrix<ValueType> _transitionMatrix; | |||
|                     storm::storage::BitVector _statesOfCoalition; | |||
|                     std::vector<ValueType> _x, _x1L, _x2L, _x1U, _x2U; | |||
|                     std::unique_ptr<storm::solver::Multiplier<ValueType>> _multiplier; | |||
| 
 | |||
|                     bool _produceScheduler = false; | |||
|                     bool _shieldingTask = false; | |||
|                     boost::optional<std::vector<uint64_t>> _producedOptimalChoices; | |||
|                 }; | |||
|             } | |||
|         } | |||
|     } | |||
| } | |||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue