22namespace multiobjective {
24template<
class SparseModelType>
29 "Invalid query Type");
33template<
class SparseModelType>
35 bool result = this->checkAchievability();
40template<
class SparseModelType>
42 STORM_LOG_INFO(
"Building constraint system to check achievability.");
45 initializeConstraintSystem();
46 STORM_LOG_INFO(
"Constraint system consists of " << expectedChoiceVariables.size() <<
" + " << bottomStateVariables.size() <<
" variables");
47 addObjectiveConstraints();
48 swInitialization.stop();
56 STORM_PRINT_AND_LOG(
"Building the constraintsystem took " << swInitialization <<
" seconds and checking the SMT formula took " << swCheck
72 STORM_LOG_THROW(
false, storm::exceptions::UnexpectedException,
"SMT solver yielded an unexpected result");
78template<
class SparseModelType>
79void SparseCbAchievabilityQuery<SparseModelType>::initializeConstraintSystem() {
80 uint_fast64_t numStates = this->preprocessedModel->getNumberOfStates();
81 uint_fast64_t numChoices = this->preprocessedModel->getNumberOfChoices();
82 uint_fast64_t numBottomStates = this->reward0EStates.getNumberOfSetBits();
83 STORM_LOG_THROW(numBottomStates > 0, storm::exceptions::UnexpectedException,
"No bottom states in the preprocessed model.");
88 expectedChoiceVariables.reserve(numChoices);
89 for (uint_fast64_t choice = 0; choice < numChoices; ++choice) {
90 expectedChoiceVariables.push_back(this->expressionManager->declareRationalVariable(
"y" + std::to_string(choice)));
92 bottomStateVariables.reserve(numBottomStates);
93 for (uint_fast64_t bottomState = 0; bottomState < numBottomStates; ++bottomState) {
94 bottomStateVariables.push_back(this->expressionManager->declareRationalVariable(
"z" + std::to_string(bottomState)));
98 for (
auto& var : expectedChoiceVariables) {
99 solver->add(var.getExpression() >= zero);
101 std::vector<storm::expressions::Expression> bottomStateVarsAsExpression;
102 bottomStateVarsAsExpression.reserve(bottomStateVariables.size());
103 for (
auto& var : bottomStateVariables) {
104 solver->add(var.getExpression() >= zero);
105 bottomStateVarsAsExpression.push_back(var.getExpression());
108 solver->add(bottomStateSum == one);
112 auto bottomStateVariableIt = bottomStateVariables.begin();
113 std::vector<storm::expressions::Expression> valueSummands;
114 for (uint_fast64_t state = 0; state < numStates; ++state) {
116 valueSummands.clear();
117 if (this->preprocessedModel->getInitialStates().get(state)) {
118 valueSummands.push_back(one);
120 for (
auto const& backwardsEntry : backwardsTransitions.getRow(state)) {
121 valueSummands.push_back(this->expressionManager->rational(backwardsEntry.getValue()) *
122 expectedChoiceVariables[backwardsEntry.getColumn()].getExpression());
126 for (uint_fast64_t choice = this->preprocessedModel->getTransitionMatrix().getRowGroupIndices()[state];
127 choice < this->preprocessedModel->getTransitionMatrix().getRowGroupIndices()[state + 1]; ++choice) {
128 valueSummands.push_back(-expectedChoiceVariables[choice]);
130 if (this->reward0EStates.get(state)) {
131 valueSummands.push_back(-(*bottomStateVariableIt));
132 ++bottomStateVariableIt;
136 assert(bottomStateVariableIt == bottomStateVariables.end());
139template<
class SparseModelType>
140void SparseCbAchievabilityQuery<SparseModelType>::addObjectiveConstraints() {
142 for (Objective<ValueType>
const& obj : this->objectives) {
143 STORM_LOG_THROW(obj.formula->isRewardOperatorFormula() && obj.formula->getSubformula().isTotalRewardFormula(),
144 storm::exceptions::InvalidOperationException,
145 "Constraint-based solver only supports total-reward objectives. Got " << *obj.formula <<
" instead.");
146 STORM_LOG_THROW(obj.formula->hasBound(), storm::exceptions::InvalidOperationException,
147 "Invoked achievability query but no bound was specified for at least one objective.");
148 STORM_LOG_THROW(obj.formula->asRewardOperatorFormula().hasRewardModelName(), storm::exceptions::InvalidOperationException,
149 "Expected reward operator with a reward model name. Got " << *obj.formula <<
" instead.");
150 std::vector<ValueType> rewards = getActionBasedExpectedRewards(obj.formula->asRewardOperatorFormula().getRewardModelName());
153 std::vector<storm::expressions::Expression> objectiveValues;
154 for (uint_fast64_t choice = 0; choice < rewards.size(); ++choice) {
156 objectiveValues.push_back(this->expressionManager->rational(rewards[choice]) * expectedChoiceVariables[choice].getExpression());
159 if (objectiveValues.empty()) {
160 objectiveValues.push_back(this->expressionManager->rational(storm::utility::zero<storm::RationalNumber>()));
166 switch (obj.formula->getBound().comparisonType) {
168 solver->add(objValue > threshold);
171 solver->add(objValue >= threshold);
174 solver->add(objValue < threshold);
177 solver->add(objValue <= threshold);
180 STORM_LOG_THROW(
false, storm::exceptions::InvalidOperationException,
"One or more objectives have an invalid comparison type");
186std::vector<double> SparseCbAchievabilityQuery<storm::models::sparse::Mdp<double>>::getActionBasedExpectedRewards(std::string
const& rewardModelName)
const {
187 return this->preprocessedModel->getRewardModel(rewardModelName).getTotalRewardVector(this->preprocessedModel->getTransitionMatrix());
191std::vector<double> SparseCbAchievabilityQuery<storm::models::sparse::MarkovAutomaton<double>>::getActionBasedExpectedRewards(
192 std::string
const& rewardModelName)
const {
193 auto const& rewModel = this->preprocessedModel->getRewardModel(rewardModelName);
194 STORM_LOG_ASSERT(!rewModel.hasTransitionRewards(),
"Preprocessed Reward model has transition rewards which is not expected.");
195 std::vector<double> result = rewModel.hasStateActionRewards()
196 ? rewModel.getStateActionRewardVector()
197 : std::vector<double>(this->preprocessedModel->getNumberOfChoices(), storm::utility::zero<ValueType>());
198 if (rewModel.hasStateRewards()) {
200 for (
auto markovianState : this->preprocessedModel->getMarkovianStates()) {
201 result[this->preprocessedModel->getTransitionMatrix().getRowGroupIndices()[markovianState]] +=
202 rewModel.getStateReward(markovianState) / this->preprocessedModel->getExitRate(markovianState);
209std::vector<storm::RationalNumber> SparseCbAchievabilityQuery<storm::models::sparse::MarkovAutomaton<storm::RationalNumber>>::getActionBasedExpectedRewards(
210 std::string
const& rewardModelName)
const {
211 auto const& rewModel = this->preprocessedModel->getRewardModel(rewardModelName);
212 STORM_LOG_ASSERT(!rewModel.hasTransitionRewards(),
"Preprocessed Reward model has transition rewards which is not expected.");
213 std::vector<storm::RationalNumber> result =
214 rewModel.hasStateActionRewards() ? rewModel.getStateActionRewardVector()
215 : std::vector<storm::RationalNumber>(this->preprocessedModel->getNumberOfChoices(), storm::utility::zero<ValueType>());
216 if (rewModel.hasStateRewards()) {
218 for (
auto markovianState : this->preprocessedModel->getMarkovianStates()) {
219 result[this->preprocessedModel->getTransitionMatrix().getRowGroupIndices()[markovianState]] +=
220 rewModel.getStateReward(markovianState) / this->preprocessedModel->getExitRate(markovianState);
227std::vector<storm::RationalNumber> SparseCbAchievabilityQuery<storm::models::sparse::Mdp<storm::RationalNumber>>::getActionBasedExpectedRewards(
228 std::string
const& rewardModelName)
const {
229 return this->preprocessedModel->getRewardModel(rewardModelName).getTotalRewardVector(this->preprocessedModel->getTransitionMatrix());
232#ifdef STORM_HAVE_CARL
233template class SparseCbAchievabilityQuery<storm::models::sparse::Mdp<double>>;
234template class SparseCbAchievabilityQuery<storm::models::sparse::MarkovAutomaton<double>>;
236template class SparseCbAchievabilityQuery<storm::models::sparse::Mdp<storm::RationalNumber>>;
237template class SparseCbAchievabilityQuery<storm::models::sparse::MarkovAutomaton<storm::RationalNumber>>;