Browse Source
Merge pull request 'boundedGlobally' (#19) from next_formulae into main
Merge pull request 'boundedGlobally' (#19) from next_formulae into main
Reviewed-on: https://git.pranger.xyz/TEMPEST/tempest-devel/pulls/19main
34 changed files with 790 additions and 15 deletions
-
4src/storm-parsers/parser/FormulaParser.cpp
-
18src/storm-parsers/parser/FormulaParserGrammar.cpp
-
2src/storm-parsers/parser/FormulaParserGrammar.h
-
280src/storm/logic/BoundedGloballyFormula.cpp
-
76src/storm/logic/BoundedGloballyFormula.h
-
28src/storm/logic/CloneVisitor.cpp
-
1src/storm/logic/CloneVisitor.h
-
12src/storm/logic/Formula.cpp
-
6src/storm/logic/Formula.h
-
4src/storm/logic/FormulaInformationVisitor.cpp
-
1src/storm/logic/FormulaInformationVisitor.h
-
1src/storm/logic/FormulaVisitor.h
-
1src/storm/logic/Formulas.h
-
1src/storm/logic/FormulasForwardDeclarations.h
-
10src/storm/logic/FragmentChecker.cpp
-
1src/storm/logic/FragmentChecker.h
-
10src/storm/logic/FragmentSpecification.cpp
-
4src/storm/logic/FragmentSpecification.h
-
18src/storm/logic/LiftableTransitionRewardsVisitor.cpp
-
1src/storm/logic/LiftableTransitionRewardsVisitor.h
-
4src/storm/logic/ToExpressionVisitor.cpp
-
1src/storm/logic/ToExpressionVisitor.h
-
9src/storm/modelchecker/AbstractModelChecker.cpp
-
3src/storm/modelchecker/AbstractModelChecker.h
-
14src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp
-
1src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.h
-
46src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp
-
1src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.h
-
117src/storm/modelchecker/rpatl/helper/internal/BoundedGloballyGameViHelper.cpp
-
71src/storm/modelchecker/rpatl/helper/internal/BoundedGloballyGameViHelper.h
-
6src/storm/modelchecker/rpatl/helper/internal/GameViHelper.cpp
-
4src/storm/modelchecker/rpatl/helper/internal/GameViHelper.h
-
48src/storm/storage/jani/JSONExporter.cpp
-
1src/storm/storage/jani/JSONExporter.h
@ -0,0 +1,280 @@ |
|||||
|
#include "storm/logic/BoundedGloballyFormula.h"
|
||||
|
|
||||
|
#include "storm/utility/constants.h"
|
||||
|
#include "storm/utility/macros.h"
|
||||
|
#include "storm/exceptions/InvalidArgumentException.h"
|
||||
|
|
||||
|
#include "storm/logic/FormulaVisitor.h"
|
||||
|
|
||||
|
#include "storm/exceptions/InvalidPropertyException.h"
|
||||
|
#include "storm/exceptions/InvalidOperationException.h"
|
||||
|
|
||||
|
namespace storm { |
||||
|
namespace logic { |
||||
|
BoundedGloballyFormula::BoundedGloballyFormula(std::shared_ptr<Formula const> const& subformula, boost::optional<TimeBound> const& lowerBound, boost::optional<TimeBound> const& upperBound, TimeBoundReference const& timeBoundReference) : UnaryPathFormula(subformula), subformula({subformula}), timeBoundReference({timeBoundReference}), lowerBound({lowerBound}), upperBound({upperBound}) { |
||||
|
STORM_LOG_THROW(lowerBound || upperBound, storm::exceptions::InvalidArgumentException, "Bounded until formula requires at least one bound."); |
||||
|
} |
||||
|
|
||||
|
BoundedGloballyFormula::BoundedGloballyFormula(std::shared_ptr<Formula const> const& subformula, std::vector<boost::optional<TimeBound>> const& lowerBounds, std::vector<boost::optional<TimeBound>> const& upperBounds, std::vector<TimeBoundReference> const& timeBoundReferences) : UnaryPathFormula(subformula), subformula({subformula}), timeBoundReference(timeBoundReferences), lowerBound(lowerBounds), upperBound(upperBounds) { |
||||
|
assert(timeBoundReferences.size() == upperBound.size()); |
||||
|
assert(timeBoundReferences.size() == lowerBound.size()); |
||||
|
} |
||||
|
|
||||
|
// TODO handle the input for a vector of subformulas to UnaryPathFormula
|
||||
|
BoundedGloballyFormula::BoundedGloballyFormula(std::vector<std::shared_ptr<Formula const>> const& subformulas, std::vector<boost::optional<TimeBound>> const& lowerBounds, std::vector<boost::optional<TimeBound>> const& upperBounds, std::vector<TimeBoundReference> const& timeBoundReferences) : UnaryPathFormula(subformulas.at(0)), subformula({subformula}), timeBoundReference(timeBoundReferences), lowerBound(lowerBounds), upperBound(upperBounds) { |
||||
|
assert(subformula.size() == timeBoundReference.size()); |
||||
|
assert(timeBoundReference.size() == lowerBound.size()); |
||||
|
assert(lowerBound.size() == upperBound.size()); |
||||
|
STORM_LOG_THROW(this->getDimension() != 0, storm::exceptions::InvalidArgumentException, "Bounded until formula requires at least one dimension."); |
||||
|
for (unsigned i = 0; i < timeBoundReferences.size(); ++i) { |
||||
|
STORM_LOG_THROW(hasLowerBound(i) || hasUpperBound(i), storm::exceptions::InvalidArgumentException, "Bounded until formula requires at least one bound in each dimension."); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
bool BoundedGloballyFormula::isBoundedGloballyFormula() const { |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
bool BoundedGloballyFormula::isProbabilityPathFormula() const { |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
boost::any BoundedGloballyFormula::accept(FormulaVisitor const& visitor, boost::any const& data) const { |
||||
|
return visitor.visit(*this, data); |
||||
|
} |
||||
|
|
||||
|
bool BoundedGloballyFormula::isMultiDimensional() const { |
||||
|
assert(timeBoundReference.size() != 0); |
||||
|
return timeBoundReference.size() > 1; |
||||
|
} |
||||
|
|
||||
|
bool BoundedGloballyFormula::hasMultiDimensionalSubformulas() const { |
||||
|
assert(subformula.size() != 0); |
||||
|
return subformula.size() > 1; |
||||
|
} |
||||
|
|
||||
|
unsigned BoundedGloballyFormula::getDimension() const { |
||||
|
return timeBoundReference.size(); |
||||
|
} |
||||
|
|
||||
|
Formula const& BoundedGloballyFormula::getSubformula() const { |
||||
|
STORM_LOG_ASSERT(subformula.size() == 1, "The subformula is not unique."); |
||||
|
return *subformula.at(0); |
||||
|
} |
||||
|
|
||||
|
Formula const& BoundedGloballyFormula::getSubformula(unsigned i) const { |
||||
|
if (subformula.size() == 1 && i < getDimension()) { |
||||
|
return getSubformula(); |
||||
|
} else { |
||||
|
return *subformula.at(i); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
TimeBoundReference const& BoundedGloballyFormula::getTimeBoundReference(unsigned i) const { |
||||
|
assert(i < timeBoundReference.size()); |
||||
|
return timeBoundReference.at(i); |
||||
|
} |
||||
|
|
||||
|
bool BoundedGloballyFormula::isLowerBoundStrict(unsigned i) const { |
||||
|
assert(i < lowerBound.size()); |
||||
|
if (!hasLowerBound(i)) { return false; } |
||||
|
return lowerBound.at(i).get().isStrict(); |
||||
|
} |
||||
|
|
||||
|
bool BoundedGloballyFormula::hasLowerBound() const { |
||||
|
for(auto const& lb : lowerBound) { |
||||
|
if (static_cast<bool>(lb)) { |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
bool BoundedGloballyFormula::hasLowerBound(unsigned i) const { |
||||
|
return static_cast<bool>(lowerBound.at(i)); |
||||
|
} |
||||
|
|
||||
|
bool BoundedGloballyFormula::hasIntegerLowerBound(unsigned i) const { |
||||
|
if (!hasLowerBound(i)) { return true; } |
||||
|
return lowerBound.at(i).get().getBound().hasIntegerType(); |
||||
|
} |
||||
|
|
||||
|
bool BoundedGloballyFormula::isUpperBoundStrict(unsigned i) const { |
||||
|
return upperBound.at(i).get().isStrict(); |
||||
|
} |
||||
|
|
||||
|
bool BoundedGloballyFormula::hasUpperBound() const { |
||||
|
for (auto const& ub : upperBound) { |
||||
|
if (static_cast<bool>(ub)) { |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
bool BoundedGloballyFormula::hasUpperBound(unsigned i) const { |
||||
|
return static_cast<bool>(upperBound.at(i)); |
||||
|
} |
||||
|
|
||||
|
bool BoundedGloballyFormula::hasIntegerUpperBound(unsigned i) const { |
||||
|
return upperBound.at(i).get().getBound().hasIntegerType(); |
||||
|
} |
||||
|
|
||||
|
storm::expressions::Expression const& BoundedGloballyFormula::getLowerBound(unsigned i) const { |
||||
|
return lowerBound.at(i).get().getBound(); |
||||
|
} |
||||
|
|
||||
|
storm::expressions::Expression const& BoundedGloballyFormula::getUpperBound(unsigned i) const { |
||||
|
return upperBound.at(i).get().getBound(); |
||||
|
} |
||||
|
|
||||
|
template <> |
||||
|
double BoundedGloballyFormula::getLowerBound(unsigned i) const { |
||||
|
if (!hasLowerBound(i)) { return 0.0; } |
||||
|
checkNoVariablesInBound(this->getLowerBound()); |
||||
|
double bound = this->getLowerBound(i).evaluateAsDouble(); |
||||
|
STORM_LOG_THROW(bound >= 0, storm::exceptions::InvalidPropertyException, "Time-bound must not evaluate to negative number."); |
||||
|
return bound; |
||||
|
} |
||||
|
|
||||
|
template <> |
||||
|
double BoundedGloballyFormula::getUpperBound(unsigned i) const { |
||||
|
checkNoVariablesInBound(this->getUpperBound()); |
||||
|
double bound = this->getUpperBound(i).evaluateAsDouble(); |
||||
|
STORM_LOG_THROW(bound >= 0, storm::exceptions::InvalidPropertyException, "Time-bound must not evaluate to negative number."); |
||||
|
return bound; |
||||
|
} |
||||
|
|
||||
|
template <> |
||||
|
storm::RationalNumber BoundedGloballyFormula::getLowerBound(unsigned i) const { |
||||
|
if (!hasLowerBound(i)) { return storm::utility::zero<storm::RationalNumber>(); } |
||||
|
checkNoVariablesInBound(this->getLowerBound(i)); |
||||
|
storm::RationalNumber bound = this->getLowerBound(i).evaluateAsRational(); |
||||
|
STORM_LOG_THROW(bound >= storm::utility::zero<storm::RationalNumber>(), storm::exceptions::InvalidPropertyException, "Time-bound must not evaluate to negative number."); |
||||
|
return bound; |
||||
|
} |
||||
|
|
||||
|
template <> |
||||
|
storm::RationalNumber BoundedGloballyFormula::getUpperBound(unsigned i) const { |
||||
|
checkNoVariablesInBound(this->getUpperBound(i)); |
||||
|
storm::RationalNumber bound = this->getUpperBound(i).evaluateAsRational(); |
||||
|
STORM_LOG_THROW(bound >= storm::utility::zero<storm::RationalNumber>(), storm::exceptions::InvalidPropertyException, "Time-bound must not evaluate to negative number."); |
||||
|
return bound; |
||||
|
} |
||||
|
|
||||
|
template <> |
||||
|
uint64_t BoundedGloballyFormula::getLowerBound(unsigned i) const { |
||||
|
if (!hasLowerBound(i)) { return 0; } |
||||
|
checkNoVariablesInBound(this->getLowerBound(i)); |
||||
|
int_fast64_t bound = this->getLowerBound(i).evaluateAsInt(); |
||||
|
STORM_LOG_THROW(bound >= 0, storm::exceptions::InvalidPropertyException, "Time-bound must not evaluate to negative number."); |
||||
|
return static_cast<uint64_t>(bound); |
||||
|
} |
||||
|
|
||||
|
template <> |
||||
|
uint64_t BoundedGloballyFormula::getUpperBound(unsigned i) const { |
||||
|
checkNoVariablesInBound(this->getUpperBound(i)); |
||||
|
int_fast64_t bound = this->getUpperBound(i).evaluateAsInt(); |
||||
|
STORM_LOG_THROW(bound >= 0, storm::exceptions::InvalidPropertyException, "Time-bound must not evaluate to negative number."); |
||||
|
return static_cast<uint64_t>(bound); |
||||
|
} |
||||
|
|
||||
|
template <> |
||||
|
double BoundedGloballyFormula::getNonStrictUpperBound(unsigned i) const { |
||||
|
double bound = getUpperBound<double>(i); |
||||
|
STORM_LOG_THROW(!isUpperBoundStrict(i) || bound > 0, storm::exceptions::InvalidPropertyException, "Cannot retrieve non-strict bound from strict zero-bound."); |
||||
|
return bound; |
||||
|
} |
||||
|
|
||||
|
template <> |
||||
|
uint64_t BoundedGloballyFormula::getNonStrictUpperBound(unsigned i) const { |
||||
|
int_fast64_t bound = getUpperBound<uint64_t>(i); |
||||
|
if (isUpperBoundStrict(i)) { |
||||
|
STORM_LOG_THROW(bound > 0, storm::exceptions::InvalidPropertyException, "Cannot retrieve non-strict bound from strict zero-bound."); |
||||
|
return bound - 1; |
||||
|
} else { |
||||
|
return bound; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template <> |
||||
|
double BoundedGloballyFormula::getNonStrictLowerBound(unsigned i) const { |
||||
|
double bound = getLowerBound<double>(i); |
||||
|
STORM_LOG_THROW(!isLowerBoundStrict(i), storm::exceptions::InvalidPropertyException, "Cannot retrieve non-strict lower bound from strict lower-bound."); |
||||
|
return bound; |
||||
|
} |
||||
|
|
||||
|
template <> |
||||
|
uint64_t BoundedGloballyFormula::getNonStrictLowerBound(unsigned i) const { |
||||
|
int_fast64_t bound = getLowerBound<uint64_t>(i); |
||||
|
if (isLowerBoundStrict(i)) { |
||||
|
return bound + 1; |
||||
|
} else { |
||||
|
return bound; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void BoundedGloballyFormula::checkNoVariablesInBound(storm::expressions::Expression const& bound) { |
||||
|
STORM_LOG_THROW(!bound.containsVariables(), storm::exceptions::InvalidOperationException, "Cannot evaluate time-bound '" << bound << "' as it contains undefined constants."); |
||||
|
} |
||||
|
|
||||
|
std::ostream& BoundedGloballyFormula::writeToStream(std::ostream& out) const { |
||||
|
out << "G" ; |
||||
|
if (this->isMultiDimensional()) { |
||||
|
out << "^{"; |
||||
|
} |
||||
|
for (unsigned i = 0; i < this->getDimension(); ++i) { |
||||
|
if (i > 0) { |
||||
|
out << ", "; |
||||
|
} |
||||
|
if (this->getTimeBoundReference(i).isRewardBound()) { |
||||
|
out << "rew"; |
||||
|
if (this->getTimeBoundReference(i).hasRewardAccumulation()) { |
||||
|
out << "[" << this->getTimeBoundReference(i).getRewardAccumulation() << "]"; |
||||
|
} |
||||
|
out << "{\"" << this->getTimeBoundReference(i).getRewardName() << "\"}"; |
||||
|
} else if (this->getTimeBoundReference(i).isStepBound()) { |
||||
|
out << "steps"; |
||||
|
} |
||||
|
if (this->hasLowerBound(i)) { |
||||
|
if (this->hasUpperBound(i)) { |
||||
|
if (this->isLowerBoundStrict(i)) { |
||||
|
out << "("; |
||||
|
} else { |
||||
|
out << "["; |
||||
|
} |
||||
|
out << this->getLowerBound(i); |
||||
|
out << ", "; |
||||
|
out << this->getUpperBound(i); |
||||
|
if (this->isUpperBoundStrict(i)) { |
||||
|
out << ")"; |
||||
|
} else { |
||||
|
out << "]"; |
||||
|
} |
||||
|
} else { |
||||
|
if (this->isLowerBoundStrict(i)) { |
||||
|
out << ">"; |
||||
|
} else { |
||||
|
out << ">="; |
||||
|
} |
||||
|
out << getLowerBound(i); |
||||
|
} |
||||
|
} else { |
||||
|
if (this->isUpperBoundStrict(i)) { |
||||
|
out << "<"; |
||||
|
} else { |
||||
|
out << "<="; |
||||
|
} |
||||
|
out << this->getUpperBound(i); |
||||
|
} |
||||
|
out << " "; |
||||
|
} |
||||
|
if (this->isMultiDimensional()) { |
||||
|
out << "}"; |
||||
|
} |
||||
|
this->getSubformula().writeToStream(out); |
||||
|
|
||||
|
return out; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,76 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include <boost/optional.hpp> |
||||
|
|
||||
|
#include "storm/logic/UnaryPathFormula.h" |
||||
|
|
||||
|
#include "storm/logic/TimeBound.h" |
||||
|
#include "storm/logic/TimeBoundType.h" |
||||
|
|
||||
|
namespace storm { |
||||
|
namespace logic { |
||||
|
class BoundedGloballyFormula : public UnaryPathFormula { |
||||
|
public: |
||||
|
BoundedGloballyFormula(std::shared_ptr<Formula const> const& subformula, boost::optional<TimeBound> const& lowerBound, boost::optional<TimeBound> const& upperBound, TimeBoundReference const& timeBoundReference); |
||||
|
BoundedGloballyFormula(std::shared_ptr<Formula const> const& subformula, std::vector<boost::optional<TimeBound>> const& lowerBounds, std::vector<boost::optional<TimeBound>> const& upperBounds, std::vector<TimeBoundReference> const& timeBoundReferences); |
||||
|
BoundedGloballyFormula(std::vector<std::shared_ptr<Formula const>> const& subformulas, std::vector<boost::optional<TimeBound>> const& lowerBounds, std::vector<boost::optional<TimeBound>> const& upperBounds, std::vector<TimeBoundReference> const& timeBoundReferences); |
||||
|
|
||||
|
virtual ~BoundedGloballyFormula() { |
||||
|
// Intentionally left empty. |
||||
|
} |
||||
|
|
||||
|
virtual bool isBoundedGloballyFormula() const override; |
||||
|
virtual bool isProbabilityPathFormula() const override; |
||||
|
|
||||
|
virtual boost::any accept(FormulaVisitor const &visitor, boost::any const &data) const override; |
||||
|
|
||||
|
|
||||
|
|
||||
|
bool isMultiDimensional() const; |
||||
|
bool hasMultiDimensionalSubformulas() const; |
||||
|
unsigned getDimension() const; |
||||
|
|
||||
|
Formula const& getSubformula() const; |
||||
|
Formula const& getSubformula(unsigned i) const; |
||||
|
|
||||
|
TimeBoundReference const& getTimeBoundReference(unsigned i = 0) const; |
||||
|
|
||||
|
bool isLowerBoundStrict(unsigned i = 0) const; |
||||
|
bool hasLowerBound() const; |
||||
|
bool hasLowerBound(unsigned i) const; |
||||
|
bool hasIntegerLowerBound(unsigned i = 0) const; |
||||
|
|
||||
|
bool isUpperBoundStrict(unsigned i = 0) const; |
||||
|
bool hasUpperBound() const; |
||||
|
bool hasUpperBound(unsigned i) const; |
||||
|
bool hasIntegerUpperBound(unsigned i = 0) const; |
||||
|
|
||||
|
storm::expressions::Expression const& getLowerBound(unsigned i = 0) const; |
||||
|
storm::expressions::Expression const& getUpperBound(unsigned i = 0) const; |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
ValueType getLowerBound(unsigned i = 0) const; |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
ValueType getUpperBound(unsigned i = 0) const; |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
ValueType getNonStrictUpperBound(unsigned i = 0) const; |
||||
|
|
||||
|
template<typename ValueType> |
||||
|
ValueType getNonStrictLowerBound(unsigned i = 0) const; |
||||
|
|
||||
|
|
||||
|
|
||||
|
virtual std::ostream &writeToStream(std::ostream &out) const override; |
||||
|
|
||||
|
private: |
||||
|
static void checkNoVariablesInBound(storm::expressions::Expression const& bound); |
||||
|
|
||||
|
std::vector<std::shared_ptr<Formula const>> subformula; |
||||
|
std::vector<TimeBoundReference> timeBoundReference; |
||||
|
std::vector<boost::optional<TimeBound>> lowerBound; |
||||
|
std::vector<boost::optional<TimeBound>> upperBound; |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,117 @@ |
|||||
|
#include "BoundedGloballyGameViHelper.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> |
||||
|
BoundedGloballyGameViHelper<ValueType>::BoundedGloballyGameViHelper(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::BitVector statesOfCoalition) : _transitionMatrix(transitionMatrix), _statesOfCoalition(statesOfCoalition) { |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void BoundedGloballyGameViHelper<ValueType>::prepareSolversAndMultipliers(const Environment& env) { |
||||
|
_multiplier = storm::solver::MultiplierFactory<ValueType>().create(env, _transitionMatrix); |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void BoundedGloballyGameViHelper<ValueType>::performValueIteration(Environment const& env, std::vector<ValueType>& x, storm::solver::OptimizationDirection const dir, uint64_t upperBound, std::vector<ValueType>& constrainedChoiceValues) { |
||||
|
prepareSolversAndMultipliers(env); |
||||
|
_x = x; |
||||
|
|
||||
|
if (this->isProduceSchedulerSet()) { |
||||
|
if (!this->_producedOptimalChoices.is_initialized()) { |
||||
|
this->_producedOptimalChoices.emplace(); |
||||
|
} |
||||
|
this->_producedOptimalChoices->resize(this->_transitionMatrix.getRowGroupCount()); |
||||
|
} |
||||
|
|
||||
|
for (uint64_t iter = 0; iter < upperBound; iter++) { |
||||
|
if(iter == upperBound - 1) { |
||||
|
_multiplier->multiply(env, _x, nullptr, constrainedChoiceValues); |
||||
|
} |
||||
|
performIterationStep(env, dir); |
||||
|
} |
||||
|
|
||||
|
x = _x; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void BoundedGloballyGameViHelper<ValueType>::performIterationStep(Environment const& env, storm::solver::OptimizationDirection const dir, std::vector<uint64_t>* choices) { |
||||
|
if (!_multiplier) { |
||||
|
prepareSolversAndMultipliers(env); |
||||
|
} |
||||
|
|
||||
|
// multiplyandreducegaussseidel
|
||||
|
// Ax = x'
|
||||
|
if (choices == nullptr) { |
||||
|
_multiplier->multiplyAndReduce(env, dir, _x, nullptr, _x, nullptr, &_statesOfCoalition); |
||||
|
} else { |
||||
|
// Also keep track of the choices made.
|
||||
|
_multiplier->multiplyAndReduce(env, dir, _x, nullptr, _x, choices, &_statesOfCoalition); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void BoundedGloballyGameViHelper<ValueType>::fillResultVector(std::vector<ValueType>& result, storm::storage::BitVector psiStates) |
||||
|
{ |
||||
|
std::vector<ValueType> filledVector = std::vector<ValueType>(psiStates.size(), storm::utility::zero<ValueType>()); |
||||
|
uint bitIndex = 0; |
||||
|
for(uint i = 0; i < filledVector.size(); i++) { |
||||
|
if (psiStates.get(i)) { |
||||
|
filledVector.at(i) = result.at(bitIndex); |
||||
|
bitIndex++; |
||||
|
} |
||||
|
} |
||||
|
result = filledVector; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void BoundedGloballyGameViHelper<ValueType>::setProduceScheduler(bool value) { |
||||
|
_produceScheduler = value; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
bool BoundedGloballyGameViHelper<ValueType>::isProduceSchedulerSet() const { |
||||
|
return _produceScheduler; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<uint64_t> const& BoundedGloballyGameViHelper<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>& BoundedGloballyGameViHelper<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> BoundedGloballyGameViHelper<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 class BoundedGloballyGameViHelper<double>; |
||||
|
#ifdef STORM_HAVE_CARL
|
||||
|
template class BoundedGloballyGameViHelper<storm::RationalNumber>; |
||||
|
#endif
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,71 @@ |
|||||
|
#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 BoundedGloballyGameViHelper { |
||||
|
public: |
||||
|
BoundedGloballyGameViHelper(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::BitVector statesOfCoalition); |
||||
|
|
||||
|
void prepareSolversAndMultipliers(const Environment& env); |
||||
|
|
||||
|
void performValueIteration(Environment const& env, std::vector<ValueType>& x, storm::solver::OptimizationDirection const dir, uint64_t upperBound, std::vector<ValueType>& constrainedChoiceValues); |
||||
|
|
||||
|
/*! |
||||
|
* Fills the result vector to the original size with ones for being psiStates, zeros for being not phiStates |
||||
|
*/ |
||||
|
void fillResultVector(std::vector<ValueType>& result, storm::storage::BitVector psiStates); |
||||
|
|
||||
|
/*! |
||||
|
* 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; |
||||
|
|
||||
|
storm::storage::Scheduler<ValueType> extractScheduler() const; |
||||
|
|
||||
|
private: |
||||
|
void performIterationStep(Environment const& env, storm::solver::OptimizationDirection const dir, std::vector<uint64_t>* choices = nullptr); |
||||
|
|
||||
|
/*! |
||||
|
* @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; |
||||
|
std::unique_ptr<storm::solver::Multiplier<ValueType>> _multiplier; |
||||
|
|
||||
|
bool _produceScheduler = false; |
||||
|
boost::optional<std::vector<uint64_t>> _producedOptimalChoices; |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue