Browse Source

Merge pull request 'Refactoring Shields Choices and Scheduler' (#48) from shield_refactoring into main

Reviewed-on: https://git.pranger.xyz/TEMPEST/tempest-devel/pulls/48
main
Stefan Pranger 4 years ago
parent
commit
037343ba97
  1. 8
      resources/examples/testfiles/shields/mdp-shields/dieSelectionPostSafetylambda07Pmin.shield
  2. 2
      resources/examples/testfiles/shields/mdp-shields/dieSelectionPreSafetygamma08Pmin.shield
  3. 7
      resources/examples/testfiles/shields/mdp-shields/dieSelectionPreSafetylambda08Pmin.shield
  4. 3
      resources/examples/testfiles/shields/smg-shields/rightDecisionPostSafetyGamma05PminF5.shield
  5. 6
      resources/examples/testfiles/shields/smg-shields/rightDecisionPostSafetyGamma09PminF3.shield
  6. 9
      resources/examples/testfiles/shields/smg-shields/rightDecisionPostSafetyLambda05PminF5.shield
  7. 9
      resources/examples/testfiles/shields/smg-shields/rightDecisionPostSafetyLambda09PminF3.shield
  8. 3
      resources/examples/testfiles/shields/smg-shields/rightDecisionPreSafetyGamma05PminF5.shield
  9. 6
      resources/examples/testfiles/shields/smg-shields/rightDecisionPreSafetyGamma09PminF3.shield
  10. 9
      resources/examples/testfiles/shields/smg-shields/rightDecisionPreSafetyLambda05PminF5.shield
  11. 9
      resources/examples/testfiles/shields/smg-shields/rightDecisionPreSafetyLambda09PminF3.shield
  12. 2
      src/storm-cli-utilities/model-handling.h
  13. 16
      src/storm-parsers/parser/FormulaParserGrammar.cpp
  14. 2
      src/storm-parsers/parser/FormulaParserGrammar.h
  15. 22
      src/storm/logic/ShieldExpression.cpp
  16. 9
      src/storm/logic/ShieldExpression.h
  17. 10
      src/storm/modelchecker/helper/SingleValueModelCheckerHelper.cpp
  18. 11
      src/storm/modelchecker/helper/SingleValueModelCheckerHelper.h
  19. 1
      src/storm/modelchecker/helper/infinitehorizon/SparseInfiniteHorizonHelper.h
  20. 21
      src/storm/modelchecker/helper/infinitehorizon/SparseNondeterministicGameInfiniteHorizonHelper.cpp
  21. 5
      src/storm/modelchecker/helper/infinitehorizon/SparseNondeterministicGameInfiniteHorizonHelper.h
  22. 20
      src/storm/modelchecker/helper/infinitehorizon/SparseNondeterministicInfiniteHorizonHelper.cpp
  23. 5
      src/storm/modelchecker/helper/infinitehorizon/SparseNondeterministicInfiniteHorizonHelper.h
  24. 56
      src/storm/modelchecker/helper/infinitehorizon/internal/LraViHelper.cpp
  25. 6
      src/storm/modelchecker/helper/infinitehorizon/internal/LraViHelper.h
  26. 3
      src/storm/modelchecker/helper/utility/SetInformationFromCheckTask.h
  27. 5
      src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp
  28. 2
      src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp
  29. 12
      src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp
  30. 2
      src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp
  31. 12
      src/storm/modelchecker/rpatl/helper/internal/GameViHelper.cpp
  32. 11
      src/storm/modelchecker/rpatl/helper/internal/GameViHelper.h
  33. 8
      src/storm/shields/AbstractShield.h
  34. 54
      src/storm/shields/OptimalShield.cpp
  35. 10
      src/storm/shields/OptimalShield.h
  36. 39
      src/storm/shields/PostShield.cpp
  37. 4
      src/storm/shields/PostShield.h
  38. 38
      src/storm/shields/PreShield.cpp
  39. 4
      src/storm/shields/PreShield.h
  40. 19
      src/storm/shields/ShieldHandling.cpp
  41. 6
      src/storm/shields/ShieldHandling.h
  42. 29
      src/storm/solver/Multiplier.cpp
  43. 2
      src/storm/solver/Multiplier.h
  44. 60
      src/storm/storage/PostScheduler.cpp
  45. 22
      src/storm/storage/PostScheduler.h
  46. 63
      src/storm/storage/PostSchedulerChoice.cpp
  47. 46
      src/storm/storage/PostSchedulerChoice.h
  48. 43
      src/storm/storage/PreScheduler.cpp
  49. 28
      src/storm/storage/PreScheduler.h
  50. 56
      src/storm/storage/PreSchedulerChoice.cpp
  51. 42
      src/storm/storage/PreSchedulerChoice.h
  52. 16
      src/test/storm/modelchecker/rpatl/smg/ShieldGenerationSmgRpatlModelCheckerTest.cpp
  53. 3
      src/test/storm/parser/GameShieldingParserTest.cpp
  54. 3
      src/test/storm/parser/MdpShieldingParserTest.cpp

8
resources/examples/testfiles/shields/mdp-shields/dieSelectionPostSafetylambda07Pmin.shield

@ -1,8 +1,8 @@
___________________________________________________________________
Post-Safety-Shield with relative comparison (lambda = 0.700000):
model state: correction [<action>: (<corrected action>)}:
0 0: 2; 1: 2; 2: 2
1 0: 0; 1: 0; 2: 0
3 0: 2; 1: 2; 2: 2
4 0: 2; 1: 2; 2: 2
0 0: 0; 1: 1; 2: 2
1 0: 0; 1: 1; 2: 2
3 0: 0; 1: 1; 2: 2
4 0: 0; 1: 1; 2: 2
___________________________________________________________________

2
resources/examples/testfiles/shields/mdp-shields/dieSelectionPreSafetygamma08Pmin.shield

@ -2,5 +2,7 @@ ___________________________________________________________________
Pre-Safety-Shield with absolute comparison (gamma = 0.800000):
model state: choice(s) [<value>: (<action>)}:
0 0.58: (0); 0.566: (1); 0.552: (2)
1 0.7942: (1); 0.7599: (2)
3 0.755: (0); 0.706: (1); 0.657: (2)
6 0.79: (1); 0.755: (2)
___________________________________________________________________

7
resources/examples/testfiles/shields/mdp-shields/dieSelectionPreSafetylambda08Pmin.shield

@ -1,4 +1,11 @@
___________________________________________________________________
Pre-Safety-Shield with relative comparison (lambda = 0.800000):
model state: choice(s) [<value>: (<action>)}:
0 0.58: (0); 0.566: (1); 0.552: (2)
1 0.8285: (0); 0.7942: (1); 0.7599: (2)
2 0.8775: (0); 0.902: (1); 0.9265: (2)
3 0.755: (0); 0.706: (1); 0.657: (2)
4 1: (0); 1: (1); 1: (2)
5 1: (0); 1: (1); 1: (2)
6 0.825: (0); 0.79: (1); 0.755: (2)
___________________________________________________________________

3
resources/examples/testfiles/shields/smg-shields/rightDecisionPostSafetyGamma05PminF5.shield

@ -1,6 +1,5 @@
___________________________________________________________________
Post-Safety-Shield with absolute comparison (gamma = 0.500000):
model state: correction [<action>: (<corrected action>)}:
4 0: 0
5 0: 0
7 0: 0
___________________________________________________________________

6
resources/examples/testfiles/shields/smg-shields/rightDecisionPostSafetyGamma09PminF3.shield

@ -1,6 +1,8 @@
___________________________________________________________________
Post-Safety-Shield with absolute comparison (gamma = 0.900000):
model state: correction [<action>: (<corrected action>)}:
4 0: 0
5 0: 0
1 0: 0; 1: 0
2 0: 0
7 0: 0
10 0: 0
___________________________________________________________________

9
resources/examples/testfiles/shields/smg-shields/rightDecisionPostSafetyLambda05PminF5.shield

@ -1,8 +1,9 @@
___________________________________________________________________
Post-Safety-Shield with relative comparison (lambda = 0.500000):
model state: correction [<action>: (<corrected action>)}:
0 0: 0; 1: 1
4 0: 0
5 0: 0
9 0: 0; 1: 1
1 0: 0; 1: 1
2 0: 0
7 0: 0
8 0: 0
10 0: 0
___________________________________________________________________

9
resources/examples/testfiles/shields/smg-shields/rightDecisionPostSafetyLambda09PminF3.shield

@ -1,8 +1,9 @@
___________________________________________________________________
Post-Safety-Shield with relative comparison (lambda = 0.900000):
model state: correction [<action>: (<corrected action>)}:
0 0: 0; 1: 1
4 0: 0
5 0: 0
9 0: 0; 1: 1
1 0: 0; 1: 1
2 0: 0
7 0: 0
8 0: 0
10 0: 0
___________________________________________________________________

3
resources/examples/testfiles/shields/smg-shields/rightDecisionPreSafetyGamma05PminF5.shield

@ -1,6 +1,5 @@
___________________________________________________________________
Pre-Safety-Shield with absolute comparison (gamma = 0.500000):
model state: choice(s) [<value>: (<action>)}:
4 0: (0)
5 0: (0)
7 0: (0)
___________________________________________________________________

6
resources/examples/testfiles/shields/smg-shields/rightDecisionPreSafetyGamma09PminF3.shield

@ -1,6 +1,8 @@
___________________________________________________________________
Pre-Safety-Shield with absolute comparison (gamma = 0.900000):
model state: choice(s) [<value>: (<action>)}:
4 0: (0)
5 0: (0)
1 0.9: (0)
2 0: (0)
7 0: (0)
10 0.9: (0)
___________________________________________________________________

9
resources/examples/testfiles/shields/smg-shields/rightDecisionPreSafetyLambda05PminF5.shield

@ -1,8 +1,9 @@
___________________________________________________________________
Pre-Safety-Shield with relative comparison (lambda = 0.500000):
model state: choice(s) [<value>: (<action>)}:
0 0: (1)
4 0: (0)
5 0: (0)
9 0: (1)
1 0.9: (0); 1: (1)
2 1: (0)
7 0: (0)
8 1: (0)
10 0.9: (0)
___________________________________________________________________

9
resources/examples/testfiles/shields/smg-shields/rightDecisionPreSafetyLambda09PminF3.shield

@ -1,8 +1,9 @@
___________________________________________________________________
Pre-Safety-Shield with relative comparison (lambda = 0.900000):
model state: choice(s) [<value>: (<action>)}:
0 0: (1)
4 0: (0)
5 0: (0)
9 0: (1)
1 0.9: (0); 1: (1)
2 0: (0)
7 0: (0)
8 1: (0)
10 0.9: (0)
___________________________________________________________________

2
src/storm-cli-utilities/model-handling.h

@ -838,7 +838,7 @@ namespace storm {
void printModelCheckingProperty(storm::jani::Property const& property) {
if(property.isShieldingProperty()) {
STORM_PRINT(std::endl << "Creating a " << property.getShieldingExpression()->typeToString() << " shield for:");
STORM_PRINT(std::endl << "Creating " << property.getShieldingExpression()->typeToString() << " shield for:");
}
STORM_PRINT(std::endl << "Model checking property \"" << property.getName() << "\": " << *property.getRawFormula() << " ..." << std::endl);
}

16
src/storm-parsers/parser/FormulaParserGrammar.cpp

@ -186,14 +186,19 @@ namespace storm {
shieldingType = (qi::lit("PreSafety")[qi::_val = storm::logic::ShieldingType::PreSafety] |
qi::lit("PostSafety")[qi::_val = storm::logic::ShieldingType::PostSafety] |
qi::lit("Optimal")[qi::_val = storm::logic::ShieldingType::Optimal]) > -qi::lit("Shield");
qi::lit("OptimalPre")[qi::_val = storm::logic::ShieldingType::OptimalPre] |
qi::lit("OptimalPost")[qi::_val = storm::logic::ShieldingType::OptimalPost] |
qi::lit("Optimal")[qi::_val = storm::logic::ShieldingType::OptimalPost]) // backwards compatability, will be disabled in the future
> -qi::lit("Shield");
shieldingType.name("shielding type");
probability = qi::double_[qi::_pass = (qi::_1 >= 0) & (qi::_1 <= 1.0), qi::_val = qi::_1 ];
probability.name("double between 0 and 1");
//probability = qi::double_[qi::_pass = (qi::_1 >= 0) & (qi::_1 <= 1.0), qi::_val = qi::_1 ];
//probability.name("double between 0 and 1");
comparisonValue = qi::double_[qi::_val = qi::_1 ];
comparisonValue.name("double comparison value");
shieldComparison = ((qi::lit("lambda")[qi::_a = storm::logic::ShieldComparison::Relative] |
qi::lit("gamma")[qi::_a = storm::logic::ShieldComparison::Absolute]) > qi::lit("=") > probability)[qi::_val = phoenix::bind(&FormulaParserGrammar::createShieldComparisonStruct, phoenix::ref(*this), qi::_a, qi::_1)];
qi::lit("gamma")[qi::_a = storm::logic::ShieldComparison::Absolute]) > qi::lit("=") > comparisonValue)[qi::_val = phoenix::bind(&FormulaParserGrammar::createShieldComparisonStruct, phoenix::ref(*this), qi::_a, qi::_1)];
shieldComparison.name("shield comparison type");
#pragma clang diagnostic push
@ -649,10 +654,9 @@ namespace storm {
std::shared_ptr<storm::logic::ShieldExpression const> FormulaParserGrammar::createShieldExpression(storm::logic::ShieldingType type, std::string name, boost::optional<std::pair<storm::logic::ShieldComparison, double>> comparisonStruct) {
if(comparisonStruct.is_initialized()) {
STORM_LOG_WARN_COND(type != storm::logic::ShieldingType::Optimal , "Comparison for optimal shield will be ignored.");
return std::shared_ptr<storm::logic::ShieldExpression>(new storm::logic::ShieldExpression(type, name, comparisonStruct.get().first, comparisonStruct.get().second));
} else {
STORM_LOG_THROW(type == storm::logic::ShieldingType::Optimal , storm::exceptions::WrongFormatException, "Construction of safety shield needs a comparison parameter (lambda or gamma)");
STORM_LOG_INFO("Construction of shield without a comparison parameter (lambda or gamma) will default to 'lambda=0'");
return std::shared_ptr<storm::logic::ShieldExpression>(new storm::logic::ShieldExpression(type, name));
}
}

2
src/storm-parsers/parser/FormulaParserGrammar.h

@ -237,7 +237,7 @@ namespace storm {
// Shielding properties
qi::rule<Iterator, std::shared_ptr<storm::logic::ShieldExpression const>(), Skipper> shieldExpression;
qi::rule<Iterator, storm::logic::ShieldingType, Skipper> shieldingType;
qi::rule<Iterator, double, Skipper> probability;
qi::rule<Iterator, double, Skipper> comparisonValue;
qi::rule<Iterator, std::pair<storm::logic::ShieldComparison, double>, qi::locals<storm::logic::ShieldComparison>, Skipper> shieldComparison;
// Start symbol

22
src/storm/logic/ShieldExpression.cpp

@ -27,7 +27,15 @@ namespace storm {
}
bool ShieldExpression::isOptimalShield() const {
return type == storm::logic::ShieldingType::Optimal;
return type == storm::logic::ShieldingType::OptimalPre || type == storm::logic::ShieldingType::OptimalPost;
}
bool ShieldExpression::isOptimalPreShield() const {
return type == storm::logic::ShieldingType::OptimalPre;
}
bool ShieldExpression::isOptimalPostShield() const {
return type == storm::logic::ShieldingType::OptimalPost;
}
double ShieldExpression::getValue() const {
@ -36,9 +44,10 @@ namespace storm {
std::string ShieldExpression::typeToString() const {
switch(type) {
case storm::logic::ShieldingType::PostSafety: return "PostSafety";
case storm::logic::ShieldingType::PreSafety: return "PreSafety";
case storm::logic::ShieldingType::Optimal: return "Optimal";
case storm::logic::ShieldingType::PostSafety: return "Post";
case storm::logic::ShieldingType::PreSafety: return "Pre";
case storm::logic::ShieldingType::OptimalPre: return "OptimalPre";
case storm::logic::ShieldingType::OptimalPost: return "OptimalPost";
}
}
@ -59,12 +68,11 @@ namespace storm {
switch(type) {
case storm::logic::ShieldingType::PostSafety: prettyString += "Post-Safety"; break;
case storm::logic::ShieldingType::PreSafety: prettyString += "Pre-Safety"; break;
case storm::logic::ShieldingType::Optimal: prettyString += "Optimal"; break;
case storm::logic::ShieldingType::OptimalPre: prettyString += "Optimal-Pre"; break;
case storm::logic::ShieldingType::OptimalPost: prettyString += "Optimal-Post"; break;
}
prettyString += "-Shield ";
if(!(type == storm::logic::ShieldingType::Optimal)) {
prettyString += "with " + comparisonType + " comparison (" + comparisonToString() + " = " + std::to_string(value) + "):";
}
return prettyString;
}

9
src/storm/logic/ShieldExpression.h

@ -9,7 +9,8 @@ namespace storm {
enum class ShieldingType {
PostSafety,
PreSafety,
Optimal
OptimalPre,
OptimalPost
};
enum class ShieldComparison { Absolute, Relative };
@ -24,6 +25,8 @@ namespace storm {
bool isPreSafetyShield() const;
bool isPostSafetyShield() const;
bool isOptimalShield() const;
bool isOptimalPreShield() const;
bool isOptimalPostShield() const;
double getValue() const;
@ -36,8 +39,8 @@ namespace storm {
private:
ShieldingType type;
ShieldComparison comparison;
double value;
ShieldComparison comparison = ShieldComparison::Relative;
double value = 0;
std::string filename;
};

10
src/storm/modelchecker/helper/SingleValueModelCheckerHelper.cpp

@ -83,6 +83,16 @@ namespace storm {
return _produceScheduler;
}
template <typename ValueType, storm::models::ModelRepresentation ModelRepresentation>
void SingleValueModelCheckerHelper<ValueType, ModelRepresentation>::setProduceChoiceValues(bool value) {
_produceChoiceValues = value;
}
template <typename ValueType, storm::models::ModelRepresentation ModelRepresentation>
bool SingleValueModelCheckerHelper<ValueType, ModelRepresentation>::isProduceChoiceValuesSet() const {
return _produceChoiceValues;
}
template <typename ValueType, storm::models::ModelRepresentation ModelRepresentation>
void SingleValueModelCheckerHelper<ValueType, ModelRepresentation>::setQualitative(bool value) {
_isQualitativeSet = value;

11
src/storm/modelchecker/helper/SingleValueModelCheckerHelper.h

@ -101,6 +101,16 @@ namespace storm {
*/
bool isProduceSchedulerSet() const;
/*!
* Sets whether all choice values shall be computed
*/
void setProduceChoiceValues(bool value);
/*!
* @return whether all choice values shall be computed
*/
bool isProduceChoiceValuesSet() const;
/*!
* Sets whether the property needs to be checked qualitatively
*/
@ -115,6 +125,7 @@ namespace storm {
boost::optional<storm::solver::OptimizationDirection> _optimizationDirection;
boost::optional<std::pair<storm::logic::ComparisonType, ValueType>> _valueThreshold;
bool _produceScheduler;
bool _produceChoiceValues;
bool _isQualitativeSet;
};
}

1
src/storm/modelchecker/helper/infinitehorizon/SparseInfiniteHorizonHelper.h

@ -132,6 +132,7 @@ namespace storm {
std::unique_ptr<storm::storage::Decomposition<LongRunComponentType>> _computedLongRunComponentDecomposition;
boost::optional<std::vector<uint64_t>> _producedOptimalChoices;
boost::optional<std::vector<ValueType>> _choiceValues;
};

21
src/storm/modelchecker/helper/infinitehorizon/SparseNondeterministicGameInfiniteHorizonHelper.cpp

@ -52,6 +52,12 @@ namespace storm {
return scheduler;
}
template <typename ValueType>
std::vector<ValueType> SparseNondeterministicGameInfiniteHorizonHelper<ValueType>::getChoiceValues() const {
STORM_LOG_ASSERT(this->isProduceChoiceValuesSet(), "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 <typename ValueType>
void SparseNondeterministicGameInfiniteHorizonHelper<ValueType>::createDecomposition() {
@ -65,8 +71,6 @@ namespace storm {
this->_computedLongRunComponentDecomposition = std::make_unique<storm::storage::GameMaximalEndComponentDecomposition<ValueType>>(this->_transitionMatrix, *this->_backwardTransitions);
this->_longRunComponentDecomposition = this->_computedLongRunComponentDecomposition.get();
//STORM_LOG_DEBUG("\n" << this->_transitionMatrix);
STORM_LOG_DEBUG("GMEC: " << *(this->_longRunComponentDecomposition));
}
}
@ -91,6 +95,13 @@ namespace storm {
}
this->_producedOptimalChoices->resize(this->_transitionMatrix.getRowGroupCount());
}
// Allocate memory for the choice values.
if (this->isProduceChoiceValuesSet()) {
if (!this->_choiceValues.is_initialized()) {
this->_choiceValues.emplace();
}
this->_choiceValues->resize(this->_transitionMatrix.getRowCount());
}
storm::solver::LraMethod method = env.solver().lra().getNondetLraMethod();
if (method == storm::solver::LraMethod::LinearProgramming) {
@ -111,13 +122,17 @@ namespace storm {
if (this->isProduceSchedulerSet()) {
optimalChoices = &this->_producedOptimalChoices.get();
}
std::vector<ValueType>* choiceValues = nullptr;
if (this->isProduceChoiceValuesSet()) {
choiceValues = &this->_choiceValues.get();
}
// Now create a helper and perform the algorithm
if (this->isContinuousTime()) {
STORM_LOG_THROW(false, storm::exceptions::InternalException, "We cannot handle continuous time games.");
} else {
storm::modelchecker::helper::internal::LraViHelper<ValueType, storm::storage::MaximalEndComponent, storm::modelchecker::helper::internal::LraViTransitionsType::GameNondetTsNoIs> viHelper(mec, this->_transitionMatrix, aperiodicFactor, nullptr, nullptr, &statesOfCoalition);
return viHelper.performValueIteration(env, stateRewardsGetter, actionRewardsGetter, nullptr, &this->getOptimizationDirection(), optimalChoices);
return viHelper.performValueIteration(env, stateRewardsGetter, actionRewardsGetter, nullptr, &this->getOptimizationDirection(), optimalChoices, choiceValues);
}
}

5
src/storm/modelchecker/helper/infinitehorizon/SparseNondeterministicGameInfiniteHorizonHelper.h

@ -58,6 +58,11 @@ namespace storm {
*/
storm::storage::Scheduler<ValueType> extractScheduler() const;
/*!
* @return the computed choice values for the states.
*/
std::vector<ValueType> getChoiceValues() const;
ValueType computeLraForComponent(Environment const& env, ValueGetter const& stateValuesGetter, ValueGetter const& actionValuesGetter, storm::storage::MaximalEndComponent const& component);
ValueType computeLraVi(Environment const& env, ValueGetter const& stateValuesGetter, ValueGetter const& actionValuesGetter, storm::storage::MaximalEndComponent const& mec);

20
src/storm/modelchecker/helper/infinitehorizon/SparseNondeterministicInfiniteHorizonHelper.cpp

@ -57,6 +57,13 @@ namespace storm {
return scheduler;
}
template <typename ValueType>
std::vector<ValueType> SparseNondeterministicInfiniteHorizonHelper<ValueType>::getChoiceValues() const {
STORM_LOG_ASSERT(this->isProduceChoiceValuesSet(), "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 <typename ValueType>
void SparseNondeterministicInfiniteHorizonHelper<ValueType>::createDecomposition() {
if (this->_longRunComponentDecomposition == nullptr) {
@ -81,6 +88,13 @@ namespace storm {
}
this->_producedOptimalChoices->resize(this->_transitionMatrix.getRowGroupCount());
}
// Allocate memory for the choice values.
if (this->isProduceChoiceValuesSet()) {
if (!this->_choiceValues.is_initialized()) {
this->_choiceValues.emplace();
}
this->_choiceValues->resize(this->_transitionMatrix.getRowCount());
}
auto trivialResult = this->computeLraForTrivialMec(env, stateRewardsGetter, actionRewardsGetter, component);
if (trivialResult.first) {
@ -156,6 +170,10 @@ namespace storm {
if (this->isProduceSchedulerSet()) {
optimalChoices = &this->_producedOptimalChoices.get();
}
std::vector<ValueType>* choiceValues = nullptr;
if (this->isProduceChoiceValuesSet()) {
choiceValues = &this->_choiceValues.get();
}
// Now create a helper and perform the algorithm
if (this->isContinuousTime()) {
@ -165,7 +183,7 @@ namespace storm {
} else {
// We assume an MDP (with nondeterministic timed states and no instant states)
storm::modelchecker::helper::internal::LraViHelper<ValueType, storm::storage::MaximalEndComponent, storm::modelchecker::helper::internal::LraViTransitionsType::NondetTsNoIs> viHelper(mec, this->_transitionMatrix, aperiodicFactor);
return viHelper.performValueIteration(env, stateRewardsGetter, actionRewardsGetter, nullptr, &this->getOptimizationDirection(), optimalChoices);
return viHelper.performValueIteration(env, stateRewardsGetter, actionRewardsGetter, nullptr, &this->getOptimizationDirection(), optimalChoices, choiceValues);
}
}

5
src/storm/modelchecker/helper/infinitehorizon/SparseNondeterministicInfiniteHorizonHelper.h

@ -52,6 +52,11 @@ namespace storm {
*/
storm::storage::Scheduler<ValueType> extractScheduler() const;
/*!
* @return the computed choice values for the states.
*/
std::vector<ValueType> getChoiceValues() const;
/*!
* @param stateValuesGetter a function returning a value for a given state index
* @param actionValuesGetter a function returning a value for a given (global) choice index

56
src/storm/modelchecker/helper/infinitehorizon/internal/LraViHelper.cpp

@ -159,7 +159,7 @@ namespace storm {
template <typename ValueType, typename ComponentType, LraViTransitionsType TransitionsType>
ValueType LraViHelper<ValueType, ComponentType, TransitionsType>::performValueIteration(Environment const& env, ValueGetter const& stateValueGetter, ValueGetter const& actionValueGetter, std::vector<ValueType> const* exitRates, storm::solver::OptimizationDirection const* dir, std::vector<uint64_t>* choices) {
ValueType LraViHelper<ValueType, ComponentType, TransitionsType>::performValueIteration(Environment const& env, ValueGetter const& stateValueGetter, ValueGetter const& actionValueGetter, std::vector<ValueType> const* exitRates, storm::solver::OptimizationDirection const* dir, std::vector<uint64_t>* choices, std::vector<ValueType>* choiceValues) {
initializeNewValues(stateValueGetter, actionValueGetter, exitRates);
ValueType precision = storm::utility::convertNumber<ValueType>(env.solver().lra().getPrecision());
bool relative = env.solver().lra().getRelativeTerminationCriterion();
@ -214,16 +214,19 @@ namespace storm {
STORM_LOG_TRACE("LRA computation converged after " << iter << " iterations.");
}
if (choices) {
if (choices || choiceValues) {
// We will be doing one more iteration step and track scheduler choices this time.
if(!gameNondetTs()) {
prepareNextIteration(env);
}
performIterationStep(env, dir, choices);
performIterationStep(env, dir, choices, choiceValues);
}
if(gameNondetTs()) {
storm::utility::vector::applyPointwise<ValueType, ValueType>(xNew(), xNew(), [&iter] (ValueType const& x_i) -> ValueType { return x_i / (double)iter; });
result = (xOld().at(0) * _uniformizationRate)/(double)iter; // TODO is "init" always going to be .at(0) ?
if(choiceValues) {
storm::utility::vector::applyPointwise<ValueType, ValueType>(*choiceValues, *choiceValues, [this, &iter] (ValueType const& c_i) -> ValueType { return (c_i * _uniformizationRate) / (double)iter; });
}
}
return result;
}
@ -358,7 +361,23 @@ namespace storm {
}
template <typename ValueType, typename ComponentType, LraViTransitionsType TransitionsType>
void LraViHelper<ValueType, ComponentType, TransitionsType>::performIterationStep(Environment const& env, storm::solver::OptimizationDirection const* dir, std::vector<uint64_t>* choices) {
void LraViHelper<ValueType, ComponentType, TransitionsType>::setInputModelChoiceValues(std::vector<ValueType>& choiceValues, std::vector<ValueType> const& localMecChoiceValues) const {
// Transform the local choiceValues (within this mec) to choice values for the input model
uint64_t localState = 0;
uint64_t choiceValuesOffset = 0;
for (auto const& element : _component) {
uint64_t elementState = element.first;
uint64_t rowIndex = _transitionMatrix.getRowGroupIndices()[elementState];
uint64_t rowGroupSize = _transitionMatrix.getRowGroupEntryCount(elementState);
std::copy(localMecChoiceValues.begin() + choiceValuesOffset, localMecChoiceValues.begin() + choiceValuesOffset + rowGroupSize, &choiceValues.at(rowIndex));
localState++;
choiceValuesOffset += rowGroupSize;
}
}
template <typename ValueType, typename ComponentType, LraViTransitionsType TransitionsType>
void LraViHelper<ValueType, ComponentType, TransitionsType>::performIterationStep(Environment const& env, storm::solver::OptimizationDirection const* dir, std::vector<uint64_t>* choices, std::vector<ValueType>* choiceValues) {
STORM_LOG_ASSERT(!((nondetTs() || nondetIs()) && dir == nullptr), "No optimization direction provided for model with nondeterminism");
// Initialize value vectors, multiplers, and solver if this has not been done, yet
if (!_TsMultiplier) {
@ -373,25 +392,48 @@ namespace storm {
// Compute the values obtained by a single uniformization step between timed states only
if (nondetTs() && !gameNondetTs()) {
if (choices == nullptr) {
if (choices == nullptr && choiceValues == nullptr) {
_TsMultiplier->multiplyAndReduce(env, *dir, xOld(), &_TsChoiceValues, xNew());
} else {
// Also keep track of the choices made.
std::vector<uint64_t> tsChoices(_TsTransitions.getRowGroupCount());
_TsMultiplier->multiplyAndReduce(env, *dir, xOld(), &_TsChoiceValues, xNew(), &tsChoices);
std::vector<ValueType> resultChoiceValues(_TsTransitions.getRowCount());
_TsMultiplier->multiply(env, xOld(), &_TsChoiceValues, resultChoiceValues);
auto rowGroupIndices = this->_TsTransitions.getRowGroupIndices();
rowGroupIndices.erase(rowGroupIndices.begin());
_TsMultiplier->reduce(env, *dir, rowGroupIndices, resultChoiceValues, xNew(), &tsChoices);
// Note that nondeterminism within the timed states means that there can not be instant states (We either have MDPs or MAs)
// Hence, in this branch we don't have to care for choices at instant states.
STORM_LOG_ASSERT(!_hasInstantStates, "Nondeterministic timed states are only supported if there are no instant states.");
if(choices != nullptr) {
setInputModelChoices(*choices, tsChoices);
}
if(choiceValues != nullptr) {
setInputModelChoiceValues(*choiceValues, resultChoiceValues);
}
}
} else if(gameNondetTs()) { // TODO DRYness? exact same behaviour as case above?
if (choices == nullptr) {
_TsMultiplier->multiplyAndReduce(env, *dir, xOld(), &_TsChoiceValues, xNew(), nullptr, _statesOfCoalition);
} else {
// Also keep track of the choices made.
std::vector<uint64_t> tsChoices(_TsTransitions.getRowGroupCount());
_TsMultiplier->multiplyAndReduce(env, *dir, xOld(), &_TsChoiceValues, xNew(), &tsChoices, _statesOfCoalition);
std::vector<ValueType> resultChoiceValues(_TsTransitions.getRowCount());
_TsMultiplier->multiply(env, xOld(), &_TsChoiceValues, resultChoiceValues);
auto rowGroupIndices = this->_TsTransitions.getRowGroupIndices();
rowGroupIndices.erase(rowGroupIndices.begin());
_TsMultiplier->reduce(env, *dir, rowGroupIndices, resultChoiceValues, xNew(), &tsChoices);
if(choices != nullptr) {
setInputModelChoices(*choices, tsChoices); // no components -> no need for that call?
}
if(choiceValues != nullptr) {
setInputModelChoiceValues(*choiceValues, resultChoiceValues);
}
}
} else {
_TsMultiplier->multiply(env, xOld(), &_TsChoiceValues, xNew());
}

6
src/storm/modelchecker/helper/infinitehorizon/internal/LraViHelper.h

@ -68,7 +68,7 @@ namespace storm {
* @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.
*/
ValueType performValueIteration(Environment const& env, ValueGetter const& stateValueGetter, ValueGetter const& actionValueGetter, std::vector<ValueType> const* exitRates = nullptr, storm::solver::OptimizationDirection const* dir = nullptr, std::vector<uint64_t>* choices = nullptr);
ValueType performValueIteration(Environment const& env, ValueGetter const& stateValueGetter, ValueGetter const& actionValueGetter, std::vector<ValueType> const* exitRates = nullptr, storm::solver::OptimizationDirection const* dir = nullptr, std::vector<uint64_t>* choices = nullptr, std::vector<ValueType>* choiceValues = nullptr);
private:
@ -89,7 +89,7 @@ namespace storm {
* 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<uint64_t>* choices = nullptr);
void performIterationStep(Environment const& env, storm::solver::OptimizationDirection const* dir = nullptr, std::vector<uint64_t>* choices = nullptr, std::vector<ValueType>* choiceValues = nullptr);
struct ConvergenceCheckResult {
bool isPrecisionAchieved;
@ -111,6 +111,8 @@ namespace storm {
void setInputModelChoices(std::vector<uint64_t>& choices, std::vector<uint64_t> const& localMecChoices, bool setChoiceZeroToMarkovianStates = false, bool setChoiceZeroToProbabilisticStates = false) const;
void setInputModelChoiceValues(std::vector<ValueType>& choiceValues, std::vector<ValueType> const& localMecChoiceValues) const;
/// Returns true iff the given state is a timed state
bool isTimedState(uint64_t const& inputModelStateIndex) const;

3
src/storm/modelchecker/helper/utility/SetInformationFromCheckTask.h

@ -26,6 +26,9 @@ namespace storm {
// Scheduler Production
helper.setProduceScheduler(checkTask.isProduceSchedulersSet());
// Shield Synthesis
helper.setProduceChoiceValues(checkTask.isShieldingTask());
// Qualitative flag
helper.setQualitative(checkTask.isQualitativeSet());
}

5
src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp

@ -298,7 +298,10 @@ namespace storm {
auto values = helper.computeLongRunAverageProbabilities(env, subResult.getTruthValuesVector());
std::unique_ptr<CheckResult> result(new ExplicitQuantitativeCheckResult<ValueType>(std::move(values)));
if (checkTask.isProduceSchedulersSet()) {
if(checkTask.isShieldingTask()) {
storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true);
tempest::shields::createQuantitativeShield<ValueType>(std::make_shared<storm::models::sparse::Mdp<ValueType>>(this->getModel()), helper.getChoiceValues(), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, allStatesBv);
} else if (checkTask.isProduceSchedulersSet()) {
result->asExplicitQuantitativeCheckResult<ValueType>().setScheduler(std::make_unique<storm::storage::Scheduler<ValueType>>(helper.extractScheduler()));
}
return result;

2
src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp

@ -146,7 +146,7 @@ namespace storm {
if(goal.isShieldingTask()) {
multiplier->multiply(env, result, nullptr, choiceValues);
multiplier->reduce(env, goal.direction(), choiceValues, transitionMatrix.getRowGroupIndices(), result, nullptr);
multiplier->reduce(env, goal.direction(), transitionMatrix.getRowGroupIndices(), choiceValues, result);
}
else {
multiplier->multiplyAndReduce(env, dir, result, nullptr, result);

12
src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp

@ -144,7 +144,8 @@ namespace storm {
auto ret = storm::modelchecker::helper::SparseSmgRpatlHelper<ValueType>::computeUntilProbabilities(env, storm::solver::SolveGoal<ValueType>(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), statesOfCoalition, checkTask.isProduceSchedulersSet(), checkTask.getHint());
std::unique_ptr<CheckResult> result(new ExplicitQuantitativeCheckResult<ValueType>(std::move(ret.values)));
if(checkTask.isShieldingTask()) {
tempest::shields::createShield<ValueType>(std::make_shared<storm::models::sparse::Smg<ValueType>>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.relevantStates), ~statesOfCoalition);
storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true);
tempest::shields::createShield<ValueType>(std::make_shared<storm::models::sparse::Smg<ValueType>>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition);
} else if (checkTask.isProduceSchedulersSet() && ret.scheduler) {
result->asExplicitQuantitativeCheckResult<ValueType>().setScheduler(std::move(ret.scheduler));
}
@ -160,7 +161,8 @@ namespace storm {
auto ret = storm::modelchecker::helper::SparseSmgRpatlHelper<ValueType>::computeGloballyProbabilities(env, storm::solver::SolveGoal<ValueType>(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), statesOfCoalition, checkTask.isProduceSchedulersSet(), checkTask.getHint());
std::unique_ptr<CheckResult> result(new ExplicitQuantitativeCheckResult<ValueType>(std::move(ret.values)));
if(checkTask.isShieldingTask()) {
tempest::shields::createShield<ValueType>(std::make_shared<storm::models::sparse::Smg<ValueType>>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.relevantStates), ~statesOfCoalition);
storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true);
tempest::shields::createShield<ValueType>(std::make_shared<storm::models::sparse::Smg<ValueType>>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition);
} else if (checkTask.isProduceSchedulersSet() && ret.scheduler) {
result->asExplicitQuantitativeCheckResult<ValueType>().setScheduler(std::move(ret.scheduler));
}
@ -194,7 +196,8 @@ namespace storm {
auto ret = storm::modelchecker::helper::SparseSmgRpatlHelper<ValueType>::computeBoundedGloballyProbabilities(env, storm::solver::SolveGoal<ValueType>(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), statesOfCoalition, checkTask.isProduceSchedulersSet(), checkTask.getHint(), pathFormula.getNonStrictLowerBound<uint64_t>(), pathFormula.getNonStrictUpperBound<uint64_t>());
std::unique_ptr<CheckResult> result(new ExplicitQuantitativeCheckResult<ValueType>(std::move(ret.values)));
if(checkTask.isShieldingTask()) {
tempest::shields::createShield<ValueType>(std::make_shared<storm::models::sparse::Smg<ValueType>>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), std::move(ret.relevantStates), ~statesOfCoalition);
storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true);
tempest::shields::createShield<ValueType>(std::make_shared<storm::models::sparse::Smg<ValueType>>(this->getModel()), std::move(ret.choiceValues), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, ~statesOfCoalition);
}
return result;
}
@ -235,7 +238,8 @@ namespace storm {
std::unique_ptr<CheckResult> result(new ExplicitQuantitativeCheckResult<ValueType>(std::move(values)));
if(checkTask.isShieldingTask()) {
tempest::shields::createQuantitativeShield<ValueType>(std::make_shared<storm::models::sparse::Smg<ValueType>>(this->getModel()), helper.getProducedOptimalChoices(), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), statesOfCoalition, statesOfCoalition);
storm::storage::BitVector allStatesBv = storm::storage::BitVector(this->getModel().getTransitionMatrix().getRowGroupCount(), true);
tempest::shields::createQuantitativeShield<ValueType>(std::make_shared<storm::models::sparse::Smg<ValueType>>(this->getModel()), helper.getChoiceValues(), checkTask.getShieldingExpression(), checkTask.getOptimizationDirection(), allStatesBv, statesOfCoalition);
} else if (checkTask.isProduceSchedulersSet()) {
result->asExplicitQuantitativeCheckResult<ValueType>().setScheduler(std::make_unique<storm::storage::Scheduler<ValueType>>(helper.extractScheduler()));
}

2
src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp

@ -112,7 +112,7 @@ namespace storm {
auto multiplier = storm::solver::MultiplierFactory<ValueType>().create(env, transitionMatrix);
auto rowGroupIndices = transitionMatrix.getRowGroupIndices();
rowGroupIndices.erase(rowGroupIndices.begin());
multiplier->reduce(env, goal.direction(), b, rowGroupIndices, result, &statesOfCoalition);
multiplier->reduce(env, goal.direction(), rowGroupIndices, b, result, nullptr, &statesOfCoalition);
if (goal.isShieldingTask()) {
choiceValues = b;
}

12
src/storm/modelchecker/rpatl/helper/internal/GameViHelper.cpp

@ -50,7 +50,7 @@ namespace storm {
_multiplier->multiply(env, xNew(), &_b, constrainedChoiceValues);
auto rowGroupIndices = this->_transitionMatrix.getRowGroupIndices();
rowGroupIndices.erase(rowGroupIndices.begin());
_multiplier->reduce(env, dir, constrainedChoiceValues, rowGroupIndices, xNew());
_multiplier->reduce(env, dir, rowGroupIndices, constrainedChoiceValues, xNew(), nullptr, &_statesOfCoalition);
break;
}
performIterationStep(env, dir);
@ -125,6 +125,16 @@ namespace storm {
return _produceScheduler;
}
template <typename ValueType>
void GameViHelper<ValueType>::setShieldingTask(bool value) {
_shieldingTask = value;
}
template <typename ValueType>
bool GameViHelper<ValueType>::isShieldingTask() const {
return _shieldingTask;
}
template <typename ValueType>
void GameViHelper<ValueType>::updateTransitionMatrix(storm::storage::SparseMatrix<ValueType> newTransitionMatrix) {
_transitionMatrix = newTransitionMatrix;

11
src/storm/modelchecker/rpatl/helper/internal/GameViHelper.h

@ -38,6 +38,16 @@ namespace storm {
*/
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.
*/
@ -93,6 +103,7 @@ namespace storm {
std::unique_ptr<storm::solver::Multiplier<ValueType>> _multiplier;
bool _produceScheduler = false;
bool _shieldingTask = false;
boost::optional<std::vector<uint64_t>> _producedOptimalChoices;
};
}

8
src/storm/shields/AbstractShield.h

@ -21,9 +21,13 @@ namespace tempest {
namespace utility {
template<typename ValueType, typename Compare, bool relative>
struct ChoiceFilter {
bool operator()(ValueType v, ValueType max, double shieldValue) {
bool operator()(ValueType v, ValueType opt, double shieldValue) {
Compare compare;
if(relative) return compare(v, max * shieldValue);
if(relative && std::is_same<Compare, storm::utility::ElementLessEqual<ValueType>>::value) {
return compare(v, opt + opt * shieldValue);
} else if(relative && std::is_same<Compare, storm::utility::ElementGreaterEqual<ValueType>>::value) {
return compare(v, opt * shieldValue);
}
else return compare(v, shieldValue);
}
};

54
src/storm/shields/OptimalShield.cpp

@ -6,27 +6,65 @@ namespace tempest {
namespace shields {
template<typename ValueType, typename IndexType>
OptimalShield<ValueType, IndexType>::OptimalShield(std::vector<IndexType> const& rowGroupIndices, std::vector<uint64_t> const& precomputedChoices, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates) : AbstractShield<ValueType, IndexType>(rowGroupIndices, shieldingExpression, optimizationDirection, relevantStates, coalitionStates), precomputedChoices(precomputedChoices) {
OptimalShield<ValueType, IndexType>::OptimalShield(std::vector<IndexType> const& rowGroupIndices, std::vector<ValueType> const& choiceValues, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates) : AbstractShield<ValueType, IndexType>(rowGroupIndices, shieldingExpression, optimizationDirection, relevantStates, coalitionStates), choiceValues(choiceValues) {
// Intentionally left empty.
}
template<typename ValueType, typename IndexType>
storm::storage::OptimalScheduler<ValueType> OptimalShield<ValueType, IndexType>::construct() {
storm::storage::OptimalScheduler<ValueType> shield(this->rowGroupIndices.size() - 1);
// TODO Needs fixing as soon as we support MDPs
storm::storage::PostScheduler<ValueType> OptimalShield<ValueType, IndexType>::construct() {
if (this->getOptimizationDirection() == storm::OptimizationDirection::Minimize) {
if(this->shieldingExpression->isRelative()) {
return constructWithCompareType<storm::utility::ElementLessEqual<ValueType>, true>();
} else {
return constructWithCompareType<storm::utility::ElementLessEqual<ValueType>, false>();
}
} else {
if(this->shieldingExpression->isRelative()) {
return constructWithCompareType<storm::utility::ElementGreaterEqual<ValueType>, true>();
} else {
return constructWithCompareType<storm::utility::ElementGreaterEqual<ValueType>, false>();
}
}
}
template<typename ValueType, typename IndexType>
template<typename Compare, bool relative>
storm::storage::PostScheduler<ValueType> OptimalShield<ValueType, IndexType>::constructWithCompareType() {
tempest::shields::utility::ChoiceFilter<ValueType, Compare, relative> choiceFilter;
storm::storage::PostScheduler<ValueType> shield(this->rowGroupIndices.size() - 1, this->computeRowGroupSizes());
auto choice_it = this->choiceValues.begin();
if(this->coalitionStates.is_initialized()) {
this->relevantStates = ~this->relevantStates;
this->relevantStates &= this->coalitionStates.get();
}
for(uint state = 0; state < this->rowGroupIndices.size() - 1; state++) {
uint rowGroupSize = this->rowGroupIndices[state + 1] - this->rowGroupIndices[state];
if(this->relevantStates.get(state)) {
shield.setChoice(precomputedChoices[state], state);
auto maxProbabilityIndex = std::max_element(choice_it, choice_it + rowGroupSize) - choice_it;
ValueType maxProbability = *(choice_it + maxProbabilityIndex);
if(!relative && !choiceFilter(maxProbability, maxProbability, this->shieldingExpression->getValue())) {
STORM_LOG_WARN("No shielding action possible with absolute comparison for state with index " << state);
shield.setChoice(storm::storage::PostSchedulerChoice<ValueType>(), state, 0);
choice_it += rowGroupSize;
continue;
}
storm::storage::PostSchedulerChoice<ValueType> choiceMapping;
for(uint choice = 0; choice < rowGroupSize; choice++, choice_it++) {
if(choiceFilter(*choice_it, maxProbability, this->shieldingExpression->getValue())) {
choiceMapping.addChoice(choice, choice);
} else {
shield.setChoice(storm::storage::Distribution<ValueType, IndexType>(), state);
choiceMapping.addChoice(choice, maxProbabilityIndex);
}
}
shield.setChoice(choiceMapping, state, 0);
} else {
shield.setChoice(storm::storage::PostSchedulerChoice<ValueType>(), state, 0);
choice_it += rowGroupSize;
}
}
return shield;
}
// Explicitly instantiate appropriate
// Explicitly instantiate appropriate classes
template class OptimalShield<double, typename storm::storage::SparseMatrix<double>::index_type>;
#ifdef STORM_HAVE_CARL
template class OptimalShield<storm::RationalNumber, typename storm::storage::SparseMatrix<storm::RationalNumber>::index_type>;

10
src/storm/shields/OptimalShield.h

@ -1,7 +1,7 @@
#pragma once
#include "storm/shields/AbstractShield.h"
#include "storm/storage/OptimalScheduler.h"
#include "storm/storage/PostScheduler.h"
namespace tempest {
namespace shields {
@ -9,11 +9,13 @@ namespace tempest {
template<typename ValueType, typename IndexType>
class OptimalShield : public AbstractShield<ValueType, IndexType> {
public:
OptimalShield(std::vector<IndexType> const& rowGroupIndices, std::vector<uint64_t> const& precomputedChoices, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates);
OptimalShield(std::vector<IndexType> const& rowGroupIndices, std::vector<ValueType> const& choiceValues, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates);
storm::storage::OptimalScheduler<ValueType> construct();
storm::storage::PostScheduler<ValueType> construct();
template<typename Compare, bool relative>
storm::storage::PostScheduler<ValueType> constructWithCompareType();
private:
std::vector<uint64_t> precomputedChoices;
std::vector<ValueType> choiceValues;
};
}
}

39
src/storm/shields/PostSafetyShield.cpp → src/storm/shields/PostShield.cpp

@ -1,4 +1,4 @@
#include "storm/shields/PostSafetyShield.h"
#include "storm/shields/PostShield.h"
#include <algorithm>
@ -6,12 +6,12 @@ namespace tempest {
namespace shields {
template<typename ValueType, typename IndexType>
PostSafetyShield<ValueType, IndexType>::PostSafetyShield(std::vector<IndexType> const& rowGroupIndices, std::vector<ValueType> const& choiceValues, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates) : AbstractShield<ValueType, IndexType>(rowGroupIndices, shieldingExpression, optimizationDirection, relevantStates, coalitionStates), choiceValues(choiceValues) {
PostShield<ValueType, IndexType>::PostShield(std::vector<IndexType> const& rowGroupIndices, std::vector<ValueType> const& choiceValues, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates) : AbstractShield<ValueType, IndexType>(rowGroupIndices, shieldingExpression, optimizationDirection, relevantStates, coalitionStates), choiceValues(choiceValues) {
// Intentionally left empty.
}
template<typename ValueType, typename IndexType>
storm::storage::PostScheduler<ValueType> PostSafetyShield<ValueType, IndexType>::construct() {
storm::storage::PostScheduler<ValueType> PostShield<ValueType, IndexType>::construct() {
if (this->getOptimizationDirection() == storm::OptimizationDirection::Minimize) {
if(this->shieldingExpression->isRelative()) {
return constructWithCompareType<storm::utility::ElementLessEqual<ValueType>, true>();
@ -29,45 +29,48 @@ namespace tempest {
template<typename ValueType, typename IndexType>
template<typename Compare, bool relative>
storm::storage::PostScheduler<ValueType> PostSafetyShield<ValueType, IndexType>::constructWithCompareType() {
storm::storage::PostScheduler<ValueType> PostShield<ValueType, IndexType>::constructWithCompareType() {
tempest::shields::utility::ChoiceFilter<ValueType, Compare, relative> choiceFilter;
storm::storage::PostScheduler<ValueType> shield(this->rowGroupIndices.size() - 1, this->computeRowGroupSizes());
auto choice_it = this->choiceValues.begin();
if(this->coalitionStates.is_initialized()) {
this->relevantStates &= this->coalitionStates.get();
this->relevantStates &= ~this->coalitionStates.get();
}
for(uint state = 0; state < this->rowGroupIndices.size() - 1; state++) {
uint rowGroupSize = this->rowGroupIndices[state + 1] - this->rowGroupIndices[state];
if(this->relevantStates.get(state)) {
auto maxProbabilityIndex = std::max_element(choice_it, choice_it + rowGroupSize) - choice_it;
ValueType maxProbability = *(choice_it + maxProbabilityIndex);
if(!relative && !choiceFilter(maxProbability, maxProbability, this->shieldingExpression->getValue())) {
auto optProbabilityIndex = std::min_element(choice_it, choice_it + rowGroupSize) - choice_it;
if(std::is_same<Compare, storm::utility::ElementGreaterEqual<ValueType>>::value) {
optProbabilityIndex = std::max_element(choice_it, choice_it + rowGroupSize) - choice_it;
}
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);
shield.setChoice(0, storm::storage::Distribution<ValueType, IndexType>(), state);
shield.setChoice(storm::storage::PostSchedulerChoice<ValueType>(), state, 0);
choice_it += rowGroupSize;
continue;
}
storm::storage::PostSchedulerChoice<ValueType> choiceMapping;
for(uint choice = 0; choice < rowGroupSize; choice++, choice_it++) {
storm::storage::Distribution<ValueType, IndexType> actionDistribution;
if(choiceFilter(*choice_it, maxProbability, this->shieldingExpression->getValue())) {
actionDistribution.addProbability(choice, 1);
if(choiceFilter(*choice_it, optProbability, this->shieldingExpression->getValue())) {
choiceMapping.addChoice(choice, choice);
} else {
actionDistribution.addProbability(maxProbabilityIndex, 1);
choiceMapping.addChoice(choice, optProbabilityIndex);
}
shield.setChoice(choice, storm::storage::SchedulerChoice<ValueType>(actionDistribution), state);
}
shield.setChoice(choiceMapping, state, 0);
} else {
shield.setChoice(0, storm::storage::Distribution<ValueType, IndexType>(), state);
shield.setChoice(storm::storage::PostSchedulerChoice<ValueType>(), state, 0);
choice_it += rowGroupSize;
}
}
return shield;
}
// Explicitly instantiate appropriate
template class PostSafetyShield<double, typename storm::storage::SparseMatrix<double>::index_type>;
// Explicitly instantiate appropriate classes
template class PostShield<double, typename storm::storage::SparseMatrix<double>::index_type>;
#ifdef STORM_HAVE_CARL
template class PostSafetyShield<storm::RationalNumber, typename storm::storage::SparseMatrix<storm::RationalNumber>::index_type>;
template class PostShield<storm::RationalNumber, typename storm::storage::SparseMatrix<storm::RationalNumber>::index_type>;
#endif
}
}

4
src/storm/shields/PostSafetyShield.h → src/storm/shields/PostShield.h

@ -7,9 +7,9 @@ namespace tempest {
namespace shields {
template<typename ValueType, typename IndexType>
class PostSafetyShield : public AbstractShield<ValueType, IndexType> {
class PostShield : public AbstractShield<ValueType, IndexType> {
public:
PostSafetyShield(std::vector<IndexType> const& rowGroupIndices, std::vector<ValueType> const& choiceValues, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates);
PostShield(std::vector<IndexType> const& rowGroupIndices, std::vector<ValueType> const& choiceValues, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates);
storm::storage::PostScheduler<ValueType> construct();
template<typename Compare, bool relative>

38
src/storm/shields/PreSafetyShield.cpp → src/storm/shields/PreShield.cpp

@ -1,4 +1,4 @@
#include "storm/shields/PreSafetyShield.h"
#include "storm/shields/PreShield.h"
#include <algorithm>
@ -6,12 +6,12 @@ namespace tempest {
namespace shields {
template<typename ValueType, typename IndexType>
PreSafetyShield<ValueType, IndexType>::PreSafetyShield(std::vector<IndexType> const& rowGroupIndices, std::vector<ValueType> const& choiceValues, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates) : AbstractShield<ValueType, IndexType>(rowGroupIndices, shieldingExpression, optimizationDirection, relevantStates, coalitionStates), choiceValues(choiceValues) {
PreShield<ValueType, IndexType>::PreShield(std::vector<IndexType> const& rowGroupIndices, std::vector<ValueType> const& choiceValues, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates) : AbstractShield<ValueType, IndexType>(rowGroupIndices, shieldingExpression, optimizationDirection, relevantStates, coalitionStates), choiceValues(choiceValues) {
// Intentionally left empty.
}
template<typename ValueType, typename IndexType>
storm::storage::PreScheduler<ValueType> PreSafetyShield<ValueType, IndexType>::construct() {
storm::storage::PreScheduler<ValueType> PreShield<ValueType, IndexType>::construct() {
if (this->getOptimizationDirection() == storm::OptimizationDirection::Minimize) {
if(this->shieldingExpression->isRelative()) {
return constructWithCompareType<storm::utility::ElementLessEqual<ValueType>, true>();
@ -29,42 +29,48 @@ namespace tempest {
template<typename ValueType, typename IndexType>
template<typename Compare, bool relative>
storm::storage::PreScheduler<ValueType> PreSafetyShield<ValueType, IndexType>::constructWithCompareType() {
storm::storage::PreScheduler<ValueType> PreShield<ValueType, IndexType>::constructWithCompareType() {
tempest::shields::utility::ChoiceFilter<ValueType, Compare, relative> choiceFilter;
storm::storage::PreScheduler<ValueType> shield(this->rowGroupIndices.size() - 1);
auto choice_it = this->choiceValues.begin();
if(this->coalitionStates.is_initialized()) {
this->relevantStates &= this->coalitionStates.get();
this->relevantStates &= ~this->coalitionStates.get();
}
for(uint state = 0; state < this->rowGroupIndices.size() - 1; state++) {
uint rowGroupSize = this->rowGroupIndices[state + 1] - this->rowGroupIndices[state];
if(this->relevantStates.get(state)) {
storm::storage::Distribution<ValueType, IndexType> actionDistribution;
ValueType maxProbability = *std::max_element(choice_it, choice_it + rowGroupSize);
if(!relative && !choiceFilter(maxProbability, maxProbability, this->shieldingExpression->getValue())) {
storm::storage::PreSchedulerChoice<ValueType> enabledChoices;
ValueType optProbability;
if(std::is_same<Compare, storm::utility::ElementGreaterEqual<ValueType>>::value) {
optProbability = *std::max_element(choice_it, choice_it + rowGroupSize);
} else {
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);
shield.setChoice(storm::storage::Distribution<ValueType, IndexType>(), state);
shield.setChoice(storm::storage::PreSchedulerChoice<ValueType>(), state, 0);
choice_it += rowGroupSize;
continue;
}
for(uint choice = 0; choice < rowGroupSize; choice++, choice_it++) {
if(choiceFilter(*choice_it, maxProbability, this->shieldingExpression->getValue())) {
actionDistribution.addProbability(choice, *choice_it);
if(choiceFilter(*choice_it, optProbability, this->shieldingExpression->getValue())) {
enabledChoices.addChoice(choice, *choice_it);
}
}
shield.setChoice(storm::storage::SchedulerChoice<ValueType>(actionDistribution), state);
shield.setChoice(enabledChoices, state, 0);
} else {
shield.setChoice(storm::storage::Distribution<ValueType, IndexType>(), state);
shield.setChoice(storm::storage::PreSchedulerChoice<ValueType>(), state, 0);
choice_it += rowGroupSize;
}
}
return shield;
}
// Explicitly instantiate appropriate
template class PreSafetyShield<double, typename storm::storage::SparseMatrix<double>::index_type>;
// Explicitly instantiate appropriate classes
template class PreShield<double, typename storm::storage::SparseMatrix<double>::index_type>;
#ifdef STORM_HAVE_CARL
template class PreSafetyShield<storm::RationalNumber, typename storm::storage::SparseMatrix<storm::RationalNumber>::index_type>;
template class PreShield<storm::RationalNumber, typename storm::storage::SparseMatrix<storm::RationalNumber>::index_type>;
#endif
}
}

4
src/storm/shields/PreSafetyShield.h → src/storm/shields/PreShield.h

@ -7,9 +7,9 @@ namespace tempest {
namespace shields {
template<typename ValueType, typename IndexType>
class PreSafetyShield : public AbstractShield<ValueType, IndexType> {
class PreShield : public AbstractShield<ValueType, IndexType> {
public:
PreSafetyShield(std::vector<IndexType> const& rowGroupIndices, std::vector<ValueType> const& choiceValues, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates);
PreShield(std::vector<IndexType> const& rowGroupIndices, std::vector<ValueType> const& choiceValues, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates);
storm::storage::PreScheduler<ValueType> construct();
template<typename Compare, bool relative>

19
src/storm/shields/ShieldHandling.cpp

@ -10,11 +10,12 @@ namespace tempest {
void createShield(std::shared_ptr<storm::models::sparse::Model<ValueType>> model, std::vector<ValueType> const& choiceValues, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates) {
std::ofstream stream;
storm::utility::openFile(shieldFilename(shieldingExpression), stream);
if(coalitionStates.is_initialized()) coalitionStates.get().complement();
if(shieldingExpression->isPreSafetyShield()) {
PreSafetyShield<ValueType, IndexType> shield(model->getTransitionMatrix().getRowGroupIndices(), choiceValues, shieldingExpression, optimizationDirection, relevantStates, coalitionStates);
PreShield<ValueType, IndexType> shield(model->getTransitionMatrix().getRowGroupIndices(), choiceValues, shieldingExpression, optimizationDirection, relevantStates, coalitionStates);
shield.construct().printToStream(stream, shieldingExpression, model);
} else if(shieldingExpression->isPostSafetyShield()) {
PostSafetyShield<ValueType, IndexType> shield(model->getTransitionMatrix().getRowGroupIndices(), choiceValues, shieldingExpression, optimizationDirection, relevantStates, coalitionStates);
PostShield<ValueType, IndexType> 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());
@ -24,11 +25,15 @@ namespace tempest {
}
template<typename ValueType, typename IndexType>
void createQuantitativeShield(std::shared_ptr<storm::models::sparse::Model<ValueType>> model, std::vector<uint64_t> const& precomputedChoices, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates) {
void createQuantitativeShield(std::shared_ptr<storm::models::sparse::Model<ValueType>> model, std::vector<ValueType> const& choiceValues, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates) {
std::ofstream stream;
storm::utility::openFile(shieldFilename(shieldingExpression), stream);
if(shieldingExpression->isOptimalShield()) {
OptimalShield<ValueType, IndexType> shield(model->getTransitionMatrix().getRowGroupIndices(), precomputedChoices, shieldingExpression, optimizationDirection, relevantStates, coalitionStates);
if(coalitionStates.is_initialized()) coalitionStates.get().complement(); // TODO CHECK THIS!!!
if(shieldingExpression->isOptimalPreShield()) {
PreShield<ValueType, IndexType> shield(model->getTransitionMatrix().getRowGroupIndices(), choiceValues, shieldingExpression, optimizationDirection, relevantStates, coalitionStates);
shield.construct().printToStream(stream, shieldingExpression, model);
} else if(shieldingExpression->isOptimalPostShield()) {
PostShield<ValueType, IndexType> 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());
@ -38,10 +43,10 @@ namespace tempest {
}
// Explicitly instantiate appropriate
template void createShield<double, typename storm::storage::SparseMatrix<double>::index_type>(std::shared_ptr<storm::models::sparse::Model<double>> model, std::vector<double> const& choiceValues, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates);
template void createQuantitativeShield<double, typename storm::storage::SparseMatrix<double>::index_type>(std::shared_ptr<storm::models::sparse::Model<double>> model, std::vector<uint64_t> const& precomputedChoices, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates);
template void createQuantitativeShield<double, typename storm::storage::SparseMatrix<double>::index_type>(std::shared_ptr<storm::models::sparse::Model<double>> model, std::vector<double> const& choiceValues, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates);
#ifdef STORM_HAVE_CARL
template void createShield<storm::RationalNumber, typename storm::storage::SparseMatrix<storm::RationalNumber>::index_type>(std::shared_ptr<storm::models::sparse::Model<storm::RationalNumber>> model, std::vector<storm::RationalNumber> const& choiceValues, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates);
template void createQuantitativeShield<storm::RationalNumber, typename storm::storage::SparseMatrix<storm::RationalNumber>::index_type>(std::shared_ptr<storm::models::sparse::Model<storm::RationalNumber>> model, std::vector<uint64_t> const& precomputedChoices, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates);
template void createQuantitativeShield<storm::RationalNumber, typename storm::storage::SparseMatrix<storm::RationalNumber>::index_type>(std::shared_ptr<storm::models::sparse::Model<storm::RationalNumber>> model, std::vector<storm::RationalNumber> const& choiceValues, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates);
#endif
}
}

6
src/storm/shields/ShieldHandling.h

@ -10,8 +10,8 @@
#include "storm/logic/ShieldExpression.h"
#include "storm/shields/AbstractShield.h"
#include "storm/shields/PreSafetyShield.h"
#include "storm/shields/PostSafetyShield.h"
#include "storm/shields/PreShield.h"
#include "storm/shields/PostShield.h"
#include "storm/shields/OptimalShield.h"
#include "storm/io/file.h"
@ -27,6 +27,6 @@ namespace tempest {
void createShield(std::shared_ptr<storm::models::sparse::Model<ValueType>> model, std::vector<ValueType> const& choiceValues, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates);
template<typename ValueType, typename IndexType = storm::storage::sparse::state_type>
void createQuantitativeShield(std::shared_ptr<storm::models::sparse::Model<ValueType>> model, std::vector<uint64_t> const& precomputedChoices, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates);
void createQuantitativeShield(std::shared_ptr<storm::models::sparse::Model<ValueType>> model, std::vector<ValueType> const& choiceValues, std::shared_ptr<storm::logic::ShieldExpression const> const& shieldingExpression, storm::OptimizationDirection optimizationDirection, storm::storage::BitVector relevantStates, boost::optional<storm::storage::BitVector> coalitionStates);
}
}

29
src/storm/solver/Multiplier.cpp

@ -75,7 +75,7 @@ namespace storm {
progress.startNewMeasurement(0);
for (uint64_t i = 0; i < n; ++i) {
multiply(env, x, b, choiceValues);
reduce(env, dir, choiceValues, rowGroupIndices, x);
reduce(env, dir, rowGroupIndices, choiceValues, x);
if (storm::utility::resources::isTerminate()) {
STORM_LOG_WARN("Aborting after " << i << " of " << n << " multiplications");
break;
@ -90,33 +90,34 @@ namespace storm {
}
template<typename ValueType>
void Multiplier<ValueType>::reduce(Environment const& env, OptimizationDirection const& dir, std::vector<ValueType> const& choiceValues, std::vector<storm::storage::SparseMatrix<double>::index_type> rowGroupIndices, std::vector<ValueType>& result, storm::storage::BitVector const* dirOverride) const {
auto choice_it = choiceValues.begin();
void Multiplier<ValueType>::reduce(Environment const& env, OptimizationDirection const& dir, std::vector<storm::storage::SparseMatrix<double>::index_type> const& rowGroupIndices, std::vector<ValueType> const& choiceValues, std::vector<ValueType>& result, std::vector<uint_fast64_t>* choices, storm::storage::BitVector const* dirOverride) const {
auto choiceValue_it = choiceValues.begin();
auto optChoice_it = choiceValues.begin();
for(uint state = 0; state < rowGroupIndices.size(); state++) {
uint rowGroupSize;
if(state == 0) {
rowGroupSize = rowGroupIndices[state];
} else {
rowGroupSize = rowGroupIndices[state] - rowGroupIndices[state-1];
rowGroupSize = rowGroupIndices[state] - rowGroupIndices[state - 1];
}
if(dirOverride != nullptr) {
if((dir == storm::OptimizationDirection::Minimize && !dirOverride->get(state)) || (dir == storm::OptimizationDirection::Maximize && dirOverride->get(state))) {
result.at(state) = *std::min_element(choice_it, choice_it + rowGroupSize);
choice_it += rowGroupSize;
}
else {
result.at(state) = *std::max_element(choice_it, choice_it + rowGroupSize);
choice_it += rowGroupSize;
optChoice_it = std::min_element(choiceValue_it, choiceValue_it + rowGroupSize);
} else {
optChoice_it = std::max_element(choiceValue_it, choiceValue_it + rowGroupSize);
}
} else {
if(dir == storm::OptimizationDirection::Minimize) {
result.at(state) = *std::min_element(choice_it, choice_it + rowGroupSize);
choice_it += rowGroupSize;
optChoice_it = std::min_element(choiceValue_it, choiceValue_it + rowGroupSize);
} else {
result.at(state) = *std::max_element(choice_it, choice_it + rowGroupSize);
choice_it += rowGroupSize;
optChoice_it = std::max_element(choiceValue_it, choiceValue_it + rowGroupSize);
}
}
result.at(state) = *optChoice_it;
if(choices) {
choices->at(state) = std::distance(choiceValue_it, optChoice_it);
}
choiceValue_it += rowGroupSize;
}
}

2
src/storm/solver/Multiplier.h

@ -141,7 +141,7 @@ namespace storm {
*/
virtual void multiplyRow2(uint64_t const& rowIndex, std::vector<ValueType> const& x1, ValueType& val1, std::vector<ValueType> const& x2, ValueType& val2) const;
void reduce(Environment const& env, OptimizationDirection const& dir, std::vector<ValueType> const& choiceValues, std::vector<storm::storage::SparseMatrix<double>::index_type> rowGroupIndices, std::vector<ValueType>& result, storm::storage::BitVector const* dirOverride = nullptr) const;
void reduce(Environment const& env, OptimizationDirection const& dir, std::vector<storm::storage::SparseMatrix<double>::index_type> const& rowGroupIndices, std::vector<ValueType> const& choiceValues, std::vector<ValueType>& result, std::vector<uint_fast64_t>* choices = nullptr, storm::storage::BitVector const* dirOverride = nullptr) const;
protected:
mutable std::unique_ptr<std::vector<ValueType>> cachedVector;

60
src/storm/storage/PostScheduler.cpp

@ -9,14 +9,10 @@ namespace storm {
namespace storage {
template <typename ValueType>
PostScheduler<ValueType>::PostScheduler(uint_fast64_t numberOfModelStates, std::vector<uint_fast64_t> numberOfChoicesPerState, boost::optional<storm::storage::MemoryStructure> const& memoryStructure) : Scheduler<ValueType>(numberOfModelStates, memoryStructure) {
STORM_LOG_DEBUG(numberOfChoicesPerState.size() << " " << numberOfModelStates);
STORM_LOG_ASSERT(numberOfChoicesPerState.size() == numberOfModelStates, "Need to know amount of choices per model state");
PostScheduler<ValueType>::PostScheduler(uint_fast64_t numberOfModelStates, std::vector<uint_fast64_t> numberOfChoicesPerState, boost::optional<storm::storage::MemoryStructure> const& memoryStructure) : memoryStructure(memoryStructure) {
//STORM_LOG_ASSERT(numberOfChoicesPerState.size() == numberOfModelStates, "Need to know amount of choices per model state");
uint_fast64_t numOfMemoryStates = memoryStructure ? memoryStructure->getNumberOfStates() : 1;
schedulerChoiceMapping = std::vector<std::vector<std::vector<SchedulerChoice<ValueType>>>>(numOfMemoryStates, std::vector<std::vector<SchedulerChoice<ValueType>>>(numberOfModelStates));
for(uint state = 0; state < numberOfModelStates; state++) {
schedulerChoiceMapping[0][state].resize(numberOfChoicesPerState[state]);
}
schedulerChoiceMapping = std::vector<std::vector<PostSchedulerChoice<ValueType>>>(numOfMemoryStates, std::vector<PostSchedulerChoice<ValueType>>(numberOfModelStates));
numberOfChoices = 0;
for(std::vector<uint_fast64_t>::iterator it = numberOfChoicesPerState.begin(); it != numberOfChoicesPerState.end(); ++it)
numberOfChoices += *it;
@ -25,13 +21,10 @@ namespace storm {
}
template <typename ValueType>
PostScheduler<ValueType>::PostScheduler(uint_fast64_t numberOfModelStates, std::vector<uint_fast64_t> numberOfChoicesPerState, boost::optional<storm::storage::MemoryStructure>&& memoryStructure) : Scheduler<ValueType>(numberOfModelStates, std::move(memoryStructure)) {
PostScheduler<ValueType>::PostScheduler(uint_fast64_t numberOfModelStates, std::vector<uint_fast64_t> numberOfChoicesPerState, boost::optional<storm::storage::MemoryStructure>&& memoryStructure) : memoryStructure(std::move(memoryStructure)) {
STORM_LOG_ASSERT(numberOfChoicesPerState.size() == numberOfModelStates, "Need to know amount of choices per model state");
uint_fast64_t numOfMemoryStates = memoryStructure ? memoryStructure->getNumberOfStates() : 1;
schedulerChoiceMapping = std::vector<std::vector<std::vector<SchedulerChoice<ValueType>>>>(numOfMemoryStates, std::vector<std::vector<SchedulerChoice<ValueType>>>(numberOfModelStates));
for(uint state = 0; state < numberOfModelStates; state++) {
schedulerChoiceMapping[0][state].resize(numberOfChoicesPerState[state]);
}
schedulerChoiceMapping = std::vector<std::vector<PostSchedulerChoice<ValueType>>>(numOfMemoryStates, std::vector<PostSchedulerChoice<ValueType>>(numberOfModelStates));
numberOfChoices = 0;
for(std::vector<uint_fast64_t>::iterator it = numberOfChoicesPerState.begin(); it != numberOfChoicesPerState.end(); ++it)
numberOfChoices += *it;
@ -40,21 +33,13 @@ namespace storm {
}
template <typename ValueType>
void PostScheduler<ValueType>::setChoice(OldChoice const& oldChoice, SchedulerChoice<ValueType> const& newChoice, uint_fast64_t modelState, uint_fast64_t memoryState) {
void PostScheduler<ValueType>::setChoice(PostSchedulerChoice<ValueType> const& choice, uint_fast64_t modelState, uint_fast64_t memoryState) {
STORM_LOG_ASSERT(memoryState == 0, "Currently we do not support PostScheduler with memory");
STORM_LOG_ASSERT(modelState < schedulerChoiceMapping[memoryState].size(), "Illegal model state index");
schedulerChoiceMapping[memoryState][modelState][oldChoice] = newChoice;
}
template <typename ValueType>
SchedulerChoice<ValueType> const& PostScheduler<ValueType>::getChoice(uint_fast64_t modelState, OldChoice oldChoice, uint_fast64_t memoryState) {
STORM_LOG_ASSERT(memoryState < this->getNumberOfMemoryStates(), "Illegal memory state index");
STORM_LOG_ASSERT(modelState < schedulerChoiceMapping[memoryState].size(), "Illegal model state index");
return schedulerChoiceMapping[memoryState][modelState][oldChoice];
schedulerChoiceMapping[memoryState][modelState] = choice;
}
template <typename ValueType>
bool PostScheduler<ValueType>::isDeterministicScheduler() const {
return true;
@ -89,7 +74,11 @@ namespace storm {
out << ":" << std::endl;
uint_fast64_t numOfSkippedStatesWithUniqueChoice = 0;
for (uint_fast64_t state = 0; state < schedulerChoiceMapping.front().size(); ++state) {
PostSchedulerChoice<ValueType> const& choices = schedulerChoiceMapping[0][state];
if(choices.isEmpty() && !printUndefinedChoices) continue;
std::stringstream stateString;
// Print the state info
if (stateValuationsGiven) {
stateString << std::setw(widthOfStates) << (std::to_string(state) + ": " + model->getStateValuations().getStateInfo(state));
@ -98,42 +87,37 @@ namespace storm {
}
stateString << " ";
bool firstChoiceIndex = true;
for(uint choiceIndex = 0; choiceIndex < schedulerChoiceMapping[0][state].size(); choiceIndex++) {
SchedulerChoice<ValueType> const& choice = schedulerChoiceMapping[0][state][choiceIndex];
for(auto const& choiceMap : choices.getChoiceMap()) {
if(firstChoiceIndex) {
firstChoiceIndex = false;
} else {
stateString << "; ";
}
if (choice.isDefined()) {
auto choiceProbPair = *(choice.getChoiceAsDistribution().begin());
if(choiceLabelsGiven) {
auto choiceLabels = model->getChoiceLabeling().getLabelsOfChoice(model->getTransitionMatrix().getRowGroupIndices()[state] + choiceIndex);
stateString << std::to_string(choiceIndex) << " {" << boost::join(choiceLabels, ", ") << "}: ";
auto choiceLabels = model->getChoiceLabeling().getLabelsOfChoice(model->getTransitionMatrix().getRowGroupIndices()[state] + std::get<0>(choiceMap));
stateString << std::to_string(std::get<0>(choiceMap)) << " {" << boost::join(choiceLabels, ", ") << "}: ";
} else {
stateString << std::to_string(choiceIndex) << ": ";
stateString << std::to_string(std::get<0>(choiceMap)) << ": ";
}
//stateString << choiceProbPair.second << ": (";
if (choiceOriginsGiven) {
stateString << model->getChoiceOrigins()->getChoiceInfo(model->getTransitionMatrix().getRowGroupIndices()[state] + choiceProbPair.first);
stateString << model->getChoiceOrigins()->getChoiceInfo(model->getTransitionMatrix().getRowGroupIndices()[state] + std::get<1>(choiceMap));
} else {
stateString << choiceProbPair.first;
stateString << std::to_string(std::get<1>(choiceMap));
}
if (choiceLabelsGiven) {
auto choiceLabels = model->getChoiceLabeling().getLabelsOfChoice(model->getTransitionMatrix().getRowGroupIndices()[state] + choiceProbPair.first);
auto choiceLabels = model->getChoiceLabeling().getLabelsOfChoice(model->getTransitionMatrix().getRowGroupIndices()[state] + std::get<1>(choiceMap));
stateString << " {" << boost::join(choiceLabels, ", ") << "}";
}
} else {
if(!this->printUndefinedChoices) goto skipStatesWithUndefinedChoices;
stateString << "undefined.";
}
// Todo: print memory updates
}
out << stateString.str() << std::endl;
// jump to label if we find one undefined choice.
skipStatesWithUndefinedChoices:;
//skipStatesWithUndefinedChoices:;
}
out << "___________________________________________________________________" << std::endl;
}

22
src/storm/storage/PostScheduler.h

@ -2,7 +2,7 @@
#include <cstdint>
#include <map>
#include "storm/storage/SchedulerChoice.h"
#include "storm/storage/PostSchedulerChoice.h"
#include "storm/storage/Scheduler.h"
#include "storm/logic/ShieldExpression.h"
@ -16,7 +16,7 @@ namespace storm {
* A Choice can be undefined, deterministic
*/
template <typename ValueType>
class PostScheduler : public Scheduler<ValueType> {
class PostScheduler {
public:
typedef uint_fast64_t OldChoice;
/*!
@ -35,7 +35,7 @@ namespace storm {
* @param modelState The state of the model for which to set the choice.
* @param memoryState The state of the memoryStructure for which to set the choice.
*/
void setChoice(OldChoice const& oldChoice, SchedulerChoice<ValueType> const& newChoice, uint_fast64_t modelState, uint_fast64_t memoryState = 0);
void setChoice(PostSchedulerChoice<ValueType> const& newChoice, uint_fast64_t modelState, uint_fast64_t memoryState = 0);
/*!
* Is the scheduler defined on the states indicated by the selected-states bitvector?
@ -50,14 +50,6 @@ namespace storm {
*/
void clearChoice(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.
*/
SchedulerChoice<ValueType> const& getChoice(uint_fast64_t modelState, OldChoice oldChoice, uint_fast64_t memoryState = 0) ;
/*!
* Compute the Action Support: A bit vector that indicates all actions that are selected with positive probability in some memory state
*/
@ -92,8 +84,14 @@ namespace storm {
*/
void printToStream(std::ostream& out, std::shared_ptr<storm::logic::ShieldExpression const> shieldingExpression, std::shared_ptr<storm::models::sparse::Model<ValueType>> model = nullptr, bool skipUniqueChoices = false) const;
private:
std::vector<std::vector<std::vector<SchedulerChoice<ValueType>>>> schedulerChoiceMapping;
boost::optional<storm::storage::MemoryStructure> memoryStructure;
std::vector<std::vector<PostSchedulerChoice<ValueType>>> schedulerChoiceMapping;
bool printUndefinedChoices = false;
uint_fast64_t numOfUndefinedChoices;
uint_fast64_t numOfDeterministicChoices;
uint_fast64_t numOfDontCareStates;
std::vector<uint_fast64_t> numberOfChoicesPerState;
uint_fast64_t numberOfChoices;
};

63
src/storm/storage/PostSchedulerChoice.cpp

@ -0,0 +1,63 @@
#include "storm/storage/PostSchedulerChoice.h"
#include "storm/utility/constants.h"
#include "storm/utility/macros.h"
#include "storm/exceptions/InvalidOperationException.h"
#include "storm/adapters/RationalFunctionAdapter.h"
#include "storm/adapters/RationalNumberAdapter.h"
namespace storm {
namespace storage {
template <typename ValueType>
PostSchedulerChoice<ValueType>::PostSchedulerChoice() {
// Intentionally left empty
}
template <typename ValueType>
void PostSchedulerChoice<ValueType>::addChoice(uint_fast64_t oldChoiceIndex, uint_fast64_t newChoiceIndex) {
choiceMap.emplace_back(oldChoiceIndex, newChoiceIndex);
}
template <typename ValueType>
std::vector<std::tuple<uint_fast64_t, uint_fast64_t>> const& PostSchedulerChoice<ValueType>::getChoiceMap() const {
return choiceMap;
}
template <typename ValueType>
std::tuple<uint_fast64_t, uint_fast64_t> const& PostSchedulerChoice<ValueType>::getChoice(uint_fast64_t choiceIndex) const {
return choiceMap.at(choiceIndex);
}
template <typename ValueType>
bool PostSchedulerChoice<ValueType>::isEmpty() const {
return choiceMap.size() == 0;
}
template <typename ValueType>
std::ostream& operator<<(std::ostream& out, PostSchedulerChoice<ValueType> const& schedulerChoice) {
if (!schedulerChoice.isEmpty()) {
bool firstChoice = true;
for(auto const& choice : schedulerChoice.getChoiceMap()) {
if(firstChoice) firstChoice = false;
else out << ", ";
out << std::get<0>(choice) << " -> " << std::get<1>(choice);
}
} else {
out << "undefined";
}
return out;
}
template class PostSchedulerChoice<double>;
template std::ostream& operator<<(std::ostream& out, PostSchedulerChoice<double> const& schedulerChoice);
template class PostSchedulerChoice<float>;
template std::ostream& operator<<(std::ostream& out, PostSchedulerChoice<float> const& schedulerChoice);
template class PostSchedulerChoice<storm::RationalNumber>;
template std::ostream& operator<<(std::ostream& out, PostSchedulerChoice<storm::RationalNumber> const& schedulerChoice);
template class PostSchedulerChoice<storm::RationalFunction>;
template std::ostream& operator<<(std::ostream& out, PostSchedulerChoice<storm::RationalFunction> const& schedulerChoice);
}
}

46
src/storm/storage/PostSchedulerChoice.h

@ -0,0 +1,46 @@
#pragma once
#include "storm/utility/constants.h"
namespace storm {
namespace storage {
template <typename ValueType>
class PostSchedulerChoice {
public:
/*!
* Creates an undefined scheduler choice
*/
PostSchedulerChoice();
/*
*
*/
void addChoice(uint_fast64_t oldChoiceIndex, uint_fast64_t newChoiceIndex);
/*
*
*/
bool isEmpty() const;
/*
*
*/
std::vector<std::tuple<uint_fast64_t, uint_fast64_t>> const& getChoiceMap() const;
/*
*
*/
std::tuple<uint_fast64_t, uint_fast64_t> const& getChoice(uint_fast64_t choiceIndex) const;
private:
//std::vector<std::tuple<uint_fast64_t, storm::storage::Distribution<ValueType, uint_fast64_t>>> choiceMap;
std::vector<std::tuple<uint_fast64_t, uint_fast64_t>> choiceMap;
};
template<typename ValueType>
std::ostream& operator<<(std::ostream& out, PostSchedulerChoice<ValueType> const& schedulerChoice);
}
}

43
src/storm/storage/PreScheduler.cpp

@ -8,11 +8,36 @@
namespace storm {
namespace storage {
template <typename ValueType>
PreScheduler<ValueType>::PreScheduler(uint_fast64_t numberOfModelStates, boost::optional<storm::storage::MemoryStructure> const& memoryStructure) : Scheduler<ValueType>(numberOfModelStates, memoryStructure) {
PreScheduler<ValueType>::PreScheduler(uint_fast64_t numberOfModelStates, boost::optional<storm::storage::MemoryStructure> const& memoryStructure) : memoryStructure(memoryStructure) {
uint_fast64_t numOfMemoryStates = memoryStructure ? memoryStructure->getNumberOfStates() : 1;
schedulerChoices = std::vector<std::vector<PreSchedulerChoice<ValueType>>>(numOfMemoryStates, std::vector<PreSchedulerChoice<ValueType>>(numberOfModelStates));
//dontCareStates = std::vector<storm::storage::BitVector>(numOfMemoryStates, storm::storage::BitVector(numberOfModelStates, false));
numOfUndefinedChoices = numOfMemoryStates * numberOfModelStates;
numOfDeterministicChoices = 0;
numOfDontCareStates = 0;
}
template <typename ValueType>
PreScheduler<ValueType>::PreScheduler(uint_fast64_t numberOfModelStates, boost::optional<storm::storage::MemoryStructure>&& memoryStructure) : Scheduler<ValueType>(numberOfModelStates, std::move(memoryStructure)) {
PreScheduler<ValueType>::PreScheduler(uint_fast64_t numberOfModelStates, boost::optional<storm::storage::MemoryStructure>&& memoryStructure) : memoryStructure(std::move(memoryStructure)) {
}
template <typename ValueType>
bool PreScheduler<ValueType>::isMemorylessScheduler() const {
return getNumberOfMemoryStates() == 1;
}
template <typename ValueType>
uint_fast64_t PreScheduler<ValueType>::getNumberOfMemoryStates() const {
return memoryStructure ? memoryStructure->getNumberOfStates() : 1;
}
template <typename ValueType>
void PreScheduler<ValueType>::setChoice(PreSchedulerChoice<ValueType> const& choice, uint_fast64_t modelState, uint_fast64_t memoryState) {
STORM_LOG_ASSERT(memoryState < this->getNumberOfMemoryStates(), "Illegal memory state index");
STORM_LOG_ASSERT(modelState < this->schedulerChoices[memoryState].size(), "Illegal model state index");
auto& schedulerChoice = schedulerChoices[memoryState][modelState];
schedulerChoice = choice;
}
template <typename ValueType>
@ -67,23 +92,23 @@ namespace storm {
}
// Print choice info
SchedulerChoice<ValueType> const& choice = this->schedulerChoices[memoryState][state];
if (choice.isDefined()) {
PreSchedulerChoice<ValueType> const& choices = this->schedulerChoices[memoryState][state];
if (!choices.isEmpty()) {
bool firstChoice = true;
for (auto const& choiceProbPair : choice.getChoiceAsDistribution()) {
for (auto const& choiceProbPair : choices.getChoiceMap()) {
if (firstChoice) {
firstChoice = false;
} else {
stateString << "; ";
}
stateString << choiceProbPair.second << ": (";
stateString << std::get<0>(choiceProbPair) << ": (";
if (choiceOriginsGiven) {
stateString << model->getChoiceOrigins()->getChoiceInfo(model->getTransitionMatrix().getRowGroupIndices()[state] + choiceProbPair.first);
stateString << model->getChoiceOrigins()->getChoiceInfo(model->getTransitionMatrix().getRowGroupIndices()[state] + std::get<1>(choiceProbPair));
} else {
stateString << choiceProbPair.first;
stateString << std::get<1>(choiceProbPair);
}
if (choiceLabelsGiven) {
auto choiceLabels = model->getChoiceLabeling().getLabelsOfChoice(model->getTransitionMatrix().getRowGroupIndices()[state] + choiceProbPair.first);
auto choiceLabels = model->getChoiceLabeling().getLabelsOfChoice(model->getTransitionMatrix().getRowGroupIndices()[state] + std::get<1>(choiceProbPair));
stateString << " {" << boost::join(choiceLabels, ", ") << "}";
}
stateString << ")";

28
src/storm/storage/PreScheduler.h

@ -3,7 +3,7 @@
#include <cstdint>
#include <map>
#include <memory>
#include "storm/storage/SchedulerChoice.h"
#include "storm/storage/PreSchedulerChoice.h"
#include "storm/storage/Scheduler.h"
#include "storm/logic/ShieldExpression.h"
@ -12,14 +12,11 @@ namespace storm {
/*
* TODO needs obvious changes in all comment blocks
* This class defines which action is chosen in a particular state of a non-deterministic model. More concretely, a scheduler maps a state s to i
* if the scheduler takes the i-th action available in s (i.e. the choices are relative to the states).
* A Choice can be undefined, deterministic
*/
template <typename ValueType>
class PreScheduler : public Scheduler<ValueType> {
class PreScheduler {
public:
typedef uint_fast64_t OldChoice;
/*!
* Initializes a scheduler for the given number of model states.
*
@ -29,14 +26,25 @@ namespace storm {
PreScheduler(uint_fast64_t numberOfModelStates, boost::optional<storm::storage::MemoryStructure> const& memoryStructure = boost::none);
PreScheduler(uint_fast64_t numberOfModelStates, boost::optional<storm::storage::MemoryStructure>&& memoryStructure);
bool isMemorylessScheduler() const;
uint_fast64_t getNumberOfMemoryStates() const;
void setChoice(PreSchedulerChoice<ValueType> const& choice, uint_fast64_t modelState, uint_fast64_t memoryState);
/*!
* Prints the scheduler to the given output stream.
* @param out The output stream
* @param model If given, provides additional information for printing (e.g., displaying the state valuations instead of state indices)
* @param skipUniqueChoices If true, the (unique) choice for deterministic states (i.e., states with only one enabled choice) is not printed explicitly.
* Requires a model to be given.
*/
void printToStream(std::ostream& out, std::shared_ptr<storm::logic::ShieldExpression const> shieldingExpression, std::shared_ptr<storm::models::sparse::Model<ValueType>> model = nullptr, bool skipUniqueChoices = false) const;
private:
boost::optional<storm::storage::MemoryStructure> memoryStructure;
std::vector<std::vector<PreSchedulerChoice<ValueType>>> schedulerChoices;
bool printUndefinedChoices = false;
uint_fast64_t numOfUndefinedChoices;
uint_fast64_t numOfDeterministicChoices;
uint_fast64_t numOfDontCareStates;
};
}
}

56
src/storm/storage/PreSchedulerChoice.cpp

@ -0,0 +1,56 @@
#include "storm/storage/PreSchedulerChoice.h"
#include "storm/utility/constants.h"
#include "storm/utility/macros.h"
#include "storm/exceptions/InvalidOperationException.h"
#include "storm/adapters/RationalFunctionAdapter.h"
#include "storm/adapters/RationalNumberAdapter.h"
namespace storm {
namespace storage {
template <typename ValueType>
PreSchedulerChoice<ValueType>::PreSchedulerChoice() {
// Intentionally left empty
}
template <typename ValueType>
void PreSchedulerChoice<ValueType>::addChoice(uint_fast64_t choiceIndex, ValueType probToSatisfy) {
choiceMap.emplace_back(probToSatisfy, choiceIndex);
}
template <typename ValueType>
std::vector<std::tuple<ValueType, uint_fast64_t>> const& PreSchedulerChoice<ValueType>::getChoiceMap() const {
return choiceMap;
}
template <typename ValueType>
bool PreSchedulerChoice<ValueType>::isEmpty() const {
return choiceMap.size() == 0;
}
template <typename ValueType>
std::ostream& operator<<(std::ostream& out, PreSchedulerChoice<ValueType> const& schedulerChoice) {
out << schedulerChoice.getChoiceMap().size();
if (!schedulerChoice.isEmpty()) {
for(auto const& choice : schedulerChoice.getChoiceMap()) {
out << std::get<0>(choice) << ": " << std::get<1>(choice);
}
} else {
out << "undefined";
}
return out;
}
template class PreSchedulerChoice<double>;
template std::ostream& operator<<(std::ostream& out, PreSchedulerChoice<double> const& schedulerChoice);
template class PreSchedulerChoice<float>;
template std::ostream& operator<<(std::ostream& out, PreSchedulerChoice<float> const& schedulerChoice);
template class PreSchedulerChoice<storm::RationalNumber>;
template std::ostream& operator<<(std::ostream& out, PreSchedulerChoice<storm::RationalNumber> const& schedulerChoice);
template class PreSchedulerChoice<storm::RationalFunction>;
template std::ostream& operator<<(std::ostream& out, PreSchedulerChoice<storm::RationalFunction> const& schedulerChoice);
}
}

42
src/storm/storage/PreSchedulerChoice.h

@ -0,0 +1,42 @@
#pragma once
#include "storm/utility/constants.h"
namespace storm {
namespace storage {
template <typename ValueType>
class PreSchedulerChoice {
public:
/*!
* Creates an undefined scheduler choice
*/
PreSchedulerChoice();
/*
*
*/
void addChoice(uint_fast64_t choiceIndex, ValueType probToSatisfy);
/*
*
*/
bool isEmpty() const;
/*
*
*/
std::vector<std::tuple<ValueType, uint_fast64_t>> const& getChoiceMap() const;
private:
// For now we only consider shields with deterministic choices.
//std::map<ValueType, storm::storage::Distribution<ValueType, uint_fast64_t>> choiceMap;
std::vector<std::tuple<ValueType, uint_fast64_t>> choiceMap;
};
template<typename ValueType>
std::ostream& operator<<(std::ostream& out, PreSchedulerChoice<ValueType> const& schedulerChoice);
}
}

16
src/test/storm/modelchecker/rpatl/smg/ShieldGenerationSmgRpatlModelCheckerTest.cpp

@ -108,22 +108,22 @@ namespace {
// testing create shielding expressions
std::string formulasString = "<" + fileNames[0] + ", PreSafety, lambda=0.9> <<hiker>> Pmax=? [ F <=3 \"target\" ]";
formulasString += "; <" + fileNames[1] + ", PreSafety, lambda=0.9> <<hiker>> Pmin=? [ F <=3 \"target\" ]";
formulasString += "; <" + fileNames[1] + ", PreSafety, lambda=0.9> <<native>> Pmin=? [ F <=3 \"target\" ]";
formulasString += "; <" + fileNames[2] + ", PreSafety, gamma=0.9> <<hiker>> Pmax=? [ F <=3 \"target\" ]";
formulasString += "; <" + fileNames[3] + ", PreSafety, gamma=0.9> <<hiker>> Pmin=? [ F <=3 \"target\" ]";
formulasString += "; <" + fileNames[3] + ", PreSafety, gamma=0.9> <<native>> Pmin=? [ F <=3 \"target\" ]";
formulasString += "; <" + fileNames[4] + ", PostSafety, lambda=0.9> <<hiker>> Pmax=? [ F <=3 \"target\" ]";
formulasString += "; <" + fileNames[5] + ", PostSafety, lambda=0.9> <<hiker>> Pmin=? [ F <=3 \"target\" ]";
formulasString += "; <" + fileNames[5] + ", PostSafety, lambda=0.9> <<native>> Pmin=? [ F <=3 \"target\" ]";
formulasString += "; <" + fileNames[6] + ", PostSafety, gamma=0.9> <<hiker>> Pmax=? [ F <=3 \"target\" ]";
formulasString += "; <" + fileNames[7] + ", PostSafety, gamma=0.9> <<hiker>> Pmin=? [ F <=3 \"target\" ]";
formulasString += "; <" + fileNames[7] + ", PostSafety, gamma=0.9> <<native>> Pmin=? [ F <=3 \"target\" ]";
formulasString += "; <" + fileNames[8] + ", PreSafety, lambda=0.5> <<hiker>> Pmax=? [ F <=5 \"target\" ]";
formulasString += "; <" + fileNames[9] + ", PreSafety, lambda=0.5> <<hiker>> Pmin=? [ F <=5 \"target\" ]";
formulasString += "; <" + fileNames[9] + ", PreSafety, lambda=0.5> <<native>> Pmin=? [ F <=5 \"target\" ]";
formulasString += "; <" + fileNames[10] + ", PreSafety, gamma=0.5> <<hiker>> Pmax=? [ F <=5 \"target\" ]";
formulasString += "; <" + fileNames[11] + ", PreSafety, gamma=0.5> <<hiker>> Pmin=? [ F <=5 \"target\" ]";
formulasString += "; <" + fileNames[11] + ", PreSafety, gamma=0.5> <<native>> Pmin=? [ F <=5 \"target\" ]";
formulasString += "; <" + fileNames[12] + ", PostSafety, lambda=0.5> <<hiker>> Pmax=? [ F <=5 \"target\" ]";
formulasString += "; <" + fileNames[13] + ", PostSafety, lambda=0.5> <<hiker>> Pmin=? [ F <=5 \"target\" ]";
formulasString += "; <" + fileNames[13] + ", PostSafety, lambda=0.5> <<native>> Pmin=? [ F <=5 \"target\" ]";
formulasString += "; <" + fileNames[14] + ", PostSafety, gamma=0.5> <<hiker>> Pmax=? [ F <=5 \"target\" ]";
formulasString += "; <" + fileNames[15] + ", PostSafety, gamma=0.5> <<hiker>> Pmin=? [ F <=5 \"target\" ]";
formulasString += "; <" + fileNames[15] + ", PostSafety, gamma=0.5> <<native>> Pmin=? [ F <=5 \"target\" ]";
auto modelFormulas = this->buildModelFormulas(STORM_TEST_RESOURCES_DIR "/smg/rightDecision.nm", formulasString);
auto smg = std::move(modelFormulas.first);

3
src/test/storm/parser/GameShieldingParserTest.cpp

@ -28,7 +28,7 @@ TEST(GameShieldingParserTest, PreSafetyShieldTest) {
EXPECT_EQ(filename, shieldExpression->getFilename());
}
TEST(GameShieldingParserTest, PostSafetyShieldTest) {
TEST(GameShieldingParserTest, PostShieldTest) {
storm::parser::FormulaParser formulaParser;
std::string filename = "postSafetyShieldFileName";
@ -76,6 +76,5 @@ TEST(GameShieldingParserTest, OptimalShieldTest) {
EXPECT_FALSE(shieldExpression->isPreSafetyShield());
EXPECT_FALSE(shieldExpression->isPostSafetyShield());
EXPECT_TRUE(shieldExpression->isOptimalShield());
EXPECT_FALSE(shieldExpression->isRelative());
EXPECT_EQ(filename, shieldExpression->getFilename());
}

3
src/test/storm/parser/MdpShieldingParserTest.cpp

@ -25,7 +25,7 @@ TEST(MdpShieldingParserTest, PreSafetyShieldTest) {
EXPECT_EQ(filename, shieldExpression->getFilename());
}
TEST(MdpShieldingParserTest, PostSafetyShieldTest) {
TEST(MdpShieldingParserTest, PostShieldTest) {
storm::parser::FormulaParser formulaParser;
std::string filename = "postSafetyShieldFileName";
@ -67,6 +67,5 @@ TEST(MdpShieldingParserTest, OptimalShieldTest) {
EXPECT_FALSE(shieldExpression->isPreSafetyShield());
EXPECT_FALSE(shieldExpression->isPostSafetyShield());
EXPECT_TRUE(shieldExpression->isOptimalShield());
EXPECT_FALSE(shieldExpression->isRelative());
EXPECT_EQ(filename, shieldExpression->getFilename());
}
Loading…
Cancel
Save