21namespace multiobjective {
23template<
class SparseModelType>
28 "Invalid query Type");
32template<
class SparseModelType>
34 bool result = this->checkAchievability();
39template<
class SparseModelType>
41 STORM_LOG_INFO(
"Building constraint system to check achievability.");
44 initializeConstraintSystem();
45 STORM_LOG_INFO(
"Constraint system consists of " << expectedChoiceVariables.size() <<
" + " << bottomStateVariables.size() <<
" variables");
46 addObjectiveConstraints();
47 swInitialization.stop();
54 if (storm::settings::getModule<storm::settings::modules::CoreSettings>().isShowStatisticsSet()) {
55 STORM_PRINT_AND_LOG(
"Building the constraintsystem took " << swInitialization <<
" seconds and checking the SMT formula took " << swCheck
71 STORM_LOG_THROW(
false, storm::exceptions::UnexpectedException,
"SMT solver yielded an unexpected result");
77template<
class SparseModelType>
78void SparseCbAchievabilityQuery<SparseModelType>::initializeConstraintSystem() {
79 uint_fast64_t numStates = this->preprocessedModel->getNumberOfStates();
80 uint_fast64_t numChoices = this->preprocessedModel->getNumberOfChoices();
81 uint_fast64_t numBottomStates = this->reward0EStates.getNumberOfSetBits();
82 STORM_LOG_THROW(numBottomStates > 0, storm::exceptions::UnexpectedException,
"No bottom states in the preprocessed model.");
87 expectedChoiceVariables.reserve(numChoices);
88 for (uint_fast64_t choice = 0; choice < numChoices; ++choice) {
89 expectedChoiceVariables.push_back(this->expressionManager->declareRationalVariable(
"y" + std::to_string(choice)));
91 bottomStateVariables.reserve(numBottomStates);
92 for (uint_fast64_t bottomState = 0; bottomState < numBottomStates; ++bottomState) {
93 bottomStateVariables.push_back(this->expressionManager->declareRationalVariable(
"z" + std::to_string(bottomState)));
97 for (
auto& var : expectedChoiceVariables) {
98 solver->add(var.getExpression() >= zero);
100 std::vector<storm::expressions::Expression> bottomStateVarsAsExpression;
101 bottomStateVarsAsExpression.reserve(bottomStateVariables.size());
102 for (
auto& var : bottomStateVariables) {
103 solver->add(var.getExpression() >= zero);
104 bottomStateVarsAsExpression.push_back(var.getExpression());
107 solver->add(bottomStateSum == one);
111 auto bottomStateVariableIt = bottomStateVariables.begin();
112 std::vector<storm::expressions::Expression> valueSummands;
113 for (uint_fast64_t state = 0; state < numStates; ++state) {
115 valueSummands.clear();
116 if (this->preprocessedModel->getInitialStates().get(state)) {
117 valueSummands.push_back(one);
119 for (
auto const& backwardsEntry : backwardsTransitions.getRow(state)) {
120 valueSummands.push_back(this->expressionManager->rational(backwardsEntry.getValue()) *
121 expectedChoiceVariables[backwardsEntry.getColumn()].getExpression());
125 for (uint_fast64_t choice = this->preprocessedModel->getTransitionMatrix().getRowGroupIndices()[state];
126 choice < this->preprocessedModel->getTransitionMatrix().getRowGroupIndices()[state + 1]; ++choice) {
127 valueSummands.push_back(-expectedChoiceVariables[choice]);
129 if (this->reward0EStates.get(state)) {
130 valueSummands.push_back(-(*bottomStateVariableIt));
131 ++bottomStateVariableIt;
135 assert(bottomStateVariableIt == bottomStateVariables.end());
138template<
class SparseModelType>
139void SparseCbAchievabilityQuery<SparseModelType>::addObjectiveConstraints() {
141 for (Objective<ValueType>
const& obj : this->objectives) {
142 STORM_LOG_THROW(obj.formula->isRewardOperatorFormula() && obj.formula->getSubformula().isTotalRewardFormula(),
143 storm::exceptions::InvalidOperationException,
144 "Constraint-based solver only supports total-reward objectives. Got " << *obj.formula <<
" instead.");
145 STORM_LOG_THROW(obj.formula->hasBound(), storm::exceptions::InvalidOperationException,
146 "Invoked achievability query but no bound was specified for at least one objective.");
147 STORM_LOG_THROW(obj.formula->asRewardOperatorFormula().hasRewardModelName(), storm::exceptions::InvalidOperationException,
148 "Expected reward operator with a reward model name. Got " << *obj.formula <<
" instead.");
149 std::vector<ValueType> rewards = getActionBasedExpectedRewards(obj.formula->asRewardOperatorFormula().getRewardModelName());
152 std::vector<storm::expressions::Expression> objectiveValues;
153 for (uint_fast64_t choice = 0; choice < rewards.size(); ++choice) {
155 objectiveValues.push_back(this->expressionManager->rational(rewards[choice]) * expectedChoiceVariables[choice].getExpression());
158 if (objectiveValues.empty()) {
159 objectiveValues.push_back(this->expressionManager->rational(storm::utility::zero<storm::RationalNumber>()));
165 switch (obj.formula->getBound().comparisonType) {
167 solver->add(objValue > threshold);
170 solver->add(objValue >= threshold);
173 solver->add(objValue < threshold);
176 solver->add(objValue <= threshold);
179 STORM_LOG_THROW(
false, storm::exceptions::InvalidOperationException,
"One or more objectives have an invalid comparison type");
185std::vector<double> SparseCbAchievabilityQuery<storm::models::sparse::Mdp<double>>::getActionBasedExpectedRewards(std::string
const& rewardModelName)
const {
186 return this->preprocessedModel->getRewardModel(rewardModelName).getTotalRewardVector(this->preprocessedModel->getTransitionMatrix());
190std::vector<double> SparseCbAchievabilityQuery<storm::models::sparse::MarkovAutomaton<double>>::getActionBasedExpectedRewards(
191 std::string
const& rewardModelName)
const {
192 auto const& rewModel = this->preprocessedModel->getRewardModel(rewardModelName);
193 STORM_LOG_ASSERT(!rewModel.hasTransitionRewards(),
"Preprocessed Reward model has transition rewards which is not expected.");
194 std::vector<double> result = rewModel.hasStateActionRewards()
195 ? rewModel.getStateActionRewardVector()
196 : std::vector<double>(this->preprocessedModel->getNumberOfChoices(), storm::utility::zero<ValueType>());
197 if (rewModel.hasStateRewards()) {
199 for (
auto markovianState : this->preprocessedModel->getMarkovianStates()) {
200 result[this->preprocessedModel->getTransitionMatrix().getRowGroupIndices()[markovianState]] +=
201 rewModel.getStateReward(markovianState) / this->preprocessedModel->getExitRate(markovianState);
208std::vector<storm::RationalNumber> SparseCbAchievabilityQuery<storm::models::sparse::MarkovAutomaton<storm::RationalNumber>>::getActionBasedExpectedRewards(
209 std::string
const& rewardModelName)
const {
210 auto const& rewModel = this->preprocessedModel->getRewardModel(rewardModelName);
211 STORM_LOG_ASSERT(!rewModel.hasTransitionRewards(),
"Preprocessed Reward model has transition rewards which is not expected.");
212 std::vector<storm::RationalNumber> result =
213 rewModel.hasStateActionRewards() ? rewModel.getStateActionRewardVector()
214 : std::vector<storm::RationalNumber>(this->preprocessedModel->getNumberOfChoices(), storm::utility::zero<ValueType>());
215 if (rewModel.hasStateRewards()) {
217 for (
auto markovianState : this->preprocessedModel->getMarkovianStates()) {
218 result[this->preprocessedModel->getTransitionMatrix().getRowGroupIndices()[markovianState]] +=
219 rewModel.getStateReward(markovianState) / this->preprocessedModel->getExitRate(markovianState);
226std::vector<storm::RationalNumber> SparseCbAchievabilityQuery<storm::models::sparse::Mdp<storm::RationalNumber>>::getActionBasedExpectedRewards(
227 std::string
const& rewardModelName)
const {
228 return this->preprocessedModel->getRewardModel(rewardModelName).getTotalRewardVector(this->preprocessedModel->getTransitionMatrix());
231template class SparseCbAchievabilityQuery<storm::models::sparse::Mdp<double>>;
232template class SparseCbAchievabilityQuery<storm::models::sparse::MarkovAutomaton<double>>;
234template class SparseCbAchievabilityQuery<storm::models::sparse::Mdp<storm::RationalNumber>>;
235template class SparseCbAchievabilityQuery<storm::models::sparse::MarkovAutomaton<storm::RationalNumber>>;