Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
SparseCbAchievabilityQuery.cpp
Go to the documentation of this file.
2
18
19namespace storm {
20namespace modelchecker {
21namespace multiobjective {
22
23template<class SparseModelType>
31
32template<class SparseModelType>
33std::unique_ptr<CheckResult> SparseCbAchievabilityQuery<SparseModelType>::check(Environment const& env) {
34 bool result = this->checkAchievability();
35
36 return std::unique_ptr<CheckResult>(new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), result));
37}
38
39template<class SparseModelType>
41 STORM_LOG_INFO("Building constraint system to check achievability.");
42 // this->preprocessedModel->writeDotToStream(std::cout);
43 storm::utility::Stopwatch swInitialization(true);
44 initializeConstraintSystem();
45 STORM_LOG_INFO("Constraint system consists of " << expectedChoiceVariables.size() << " + " << bottomStateVariables.size() << " variables");
46 addObjectiveConstraints();
47 swInitialization.stop();
48
49 storm::utility::Stopwatch swCheck(true);
50 STORM_LOG_INFO("Invoking SMT Solver.");
51 storm::solver::SmtSolver::CheckResult result = solver->check();
52 swCheck.stop();
53
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
56 << " seconds.\n");
57 }
58
59 switch (result) {
61 // std::cout << "\nSatisfying assignment: \n" << solver->getModelAsValuation().toString(true) << '\n';
62 return true;
64 // std::cout << "\nUnsatisfiability core: {\n";
65 // for (auto const& expr : solver->getUnsatCore()) {
66 // std::cout << "\t " << expr << '\n';
67 // }
68 // std::cout << "}\n";
69 return false;
70 default:
71 STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "SMT solver yielded an unexpected result");
72 }
73
74 return false;
75}
76
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.");
83 storm::expressions::Expression zero = this->expressionManager->rational(storm::utility::zero<ValueType>());
84 storm::expressions::Expression one = this->expressionManager->rational(storm::utility::one<ValueType>());
85
86 // Declare the variables for the choices and bottom states
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)));
90 }
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)));
94 }
95
96 // assert that the values are greater zero and that the bottom state values sum up to one
97 for (auto& var : expectedChoiceVariables) {
98 solver->add(var.getExpression() >= zero);
99 }
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());
105 }
106 auto bottomStateSum = storm::expressions::sum(bottomStateVarsAsExpression).simplify();
107 solver->add(bottomStateSum == one);
108
109 // assert that the "incoming" value of each state equals the "outgoing" value
110 storm::storage::SparseMatrix<ValueType> backwardsTransitions = this->preprocessedModel->getTransitionMatrix().transpose();
111 auto bottomStateVariableIt = bottomStateVariables.begin();
112 std::vector<storm::expressions::Expression> valueSummands; // initialization here to avoid re-allocations
113 for (uint_fast64_t state = 0; state < numStates; ++state) {
114 // get the "incomming" value
115 valueSummands.clear();
116 if (this->preprocessedModel->getInitialStates().get(state)) {
117 valueSummands.push_back(one);
118 }
119 for (auto const& backwardsEntry : backwardsTransitions.getRow(state)) {
120 valueSummands.push_back(this->expressionManager->rational(backwardsEntry.getValue()) *
121 expectedChoiceVariables[backwardsEntry.getColumn()].getExpression());
122 }
123
124 // subtract the "outgoing" value
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]);
128 }
129 if (this->reward0EStates.get(state)) {
130 valueSummands.push_back(-(*bottomStateVariableIt));
131 ++bottomStateVariableIt;
132 }
133 solver->add(storm::expressions::sum(valueSummands) == zero);
134 }
135 assert(bottomStateVariableIt == bottomStateVariables.end());
136}
137
138template<class SparseModelType>
139void SparseCbAchievabilityQuery<SparseModelType>::addObjectiveConstraints() {
140 storm::expressions::Expression zero = this->expressionManager->rational(storm::utility::zero<ValueType>());
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());
150
151 // Get the sum of all objective values
152 std::vector<storm::expressions::Expression> objectiveValues;
153 for (uint_fast64_t choice = 0; choice < rewards.size(); ++choice) {
154 if (!storm::utility::isZero(rewards[choice])) {
155 objectiveValues.push_back(this->expressionManager->rational(rewards[choice]) * expectedChoiceVariables[choice].getExpression());
156 }
157 }
158 if (objectiveValues.empty()) {
159 objectiveValues.push_back(this->expressionManager->rational(storm::utility::zero<storm::RationalNumber>()));
160 }
161 auto objValue = storm::expressions::sum(objectiveValues).simplify();
162
163 // We need to actually evaluate the threshold as rational number. Otherwise a threshold like '<=16/9' might be considered as 1 due to integer division
164 storm::expressions::Expression threshold = this->expressionManager->rational(obj.formula->getThreshold().evaluateAsRational());
165 switch (obj.formula->getBound().comparisonType) {
167 solver->add(objValue > threshold);
168 break;
170 solver->add(objValue >= threshold);
171 break;
173 solver->add(objValue < threshold);
174 break;
176 solver->add(objValue <= threshold);
177 break;
178 default:
179 STORM_LOG_THROW(false, storm::exceptions::InvalidOperationException, "One or more objectives have an invalid comparison type");
180 }
181 }
182}
183
184template<>
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());
187}
188
189template<>
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()) {
198 // Note that state rewards are earned over time and thus play no role for probabilistic states
199 for (auto markovianState : this->preprocessedModel->getMarkovianStates()) {
200 result[this->preprocessedModel->getTransitionMatrix().getRowGroupIndices()[markovianState]] +=
201 rewModel.getStateReward(markovianState) / this->preprocessedModel->getExitRate(markovianState);
202 }
203 }
204 return result;
205}
206
207template<>
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()) {
216 // Note that state rewards are earned over time and thus play no role for probabilistic states
217 for (auto markovianState : this->preprocessedModel->getMarkovianStates()) {
218 result[this->preprocessedModel->getTransitionMatrix().getRowGroupIndices()[markovianState]] +=
219 rewModel.getStateReward(markovianState) / this->preprocessedModel->getExitRate(markovianState);
220 }
221 }
222 return result;
223}
224
225template<>
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());
229}
230
231template class SparseCbAchievabilityQuery<storm::models::sparse::Mdp<double>>;
232template class SparseCbAchievabilityQuery<storm::models::sparse::MarkovAutomaton<double>>;
233
234template class SparseCbAchievabilityQuery<storm::models::sparse::Mdp<storm::RationalNumber>>;
235template class SparseCbAchievabilityQuery<storm::models::sparse::MarkovAutomaton<storm::RationalNumber>>;
236} // namespace multiobjective
237} // namespace modelchecker
238} // namespace storm
Expression simplify() const
Simplifies the expression according to some basic rules.
SparseCbAchievabilityQuery(preprocessing::SparseMultiObjectivePreprocessorResult< SparseModelType > const &preprocessorResult)
virtual std::unique_ptr< CheckResult > check(Environment const &env) override
std::shared_ptr< storm::expressions::ExpressionManager > expressionManager
CheckResult
possible check results
Definition SmtSolver.h:25
A class that holds a possibly non-square matrix in the compressed row storage format.
storm::storage::SparseMatrix< value_type > transpose(bool joinGroups=false, bool keepZeros=false) const
Transposes the matrix.
A class that provides convenience operations to display run times.
Definition Stopwatch.h:14
virtual std::unique_ptr< storm::solver::SmtSolver > create(storm::expressions::ExpressionManager &manager) const
Creates a new SMT solver instance.
Definition solver.cpp:124
#define STORM_LOG_INFO(message)
Definition logging.h:24
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
#define STORM_PRINT_AND_LOG(message)
Definition macros.h:68
Expression sum(std::vector< storm::expressions::Expression > const &expressions)
bool isZero(ValueType const &a)
Definition constants.cpp:39
ValueType zero()
Definition constants.cpp:24