3#include "storm-config.h"
18namespace modelchecker {
21template<
typename ValueType>
23 std::vector<ValueType>
const& rewards,
24 std::vector<ValueType>
const& oneStepTargetProbabilities)
25 : transitionMatrix(transitionMatrix),
26 originalRewards(rewards),
27 originalOneStepTargetProbabilities(oneStepTargetProbabilities),
28 backwardTransitions(transitionMatrix.transpose()),
29 p(transitionMatrix.getRowGroupCount()),
30 w(transitionMatrix.getRowGroupCount()),
32 targetProbabilities(oneStepTargetProbabilities) {
36template<
typename ValueType>
39 std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
41 ValueType lambda = computeLambda();
45 std::vector<ValueType> result(transitionMatrix.getRowGroupCount());
46 auto one = storm::utility::one<ValueType>();
48 result[state] = w[state] + (one - p[state]) * lambda;
52 ValueType max = storm::utility::zero<ValueType>();
53 uint64_t nonZeroCount = 0;
54 for (
auto const& e : result) {
57 max = std::max(max, e);
60 STORM_LOG_TRACE(
"DS-MPI computed " << nonZeroCount <<
" non-zero upper bounds and a maximal bound of " << max <<
".");
62 std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
63 STORM_LOG_TRACE(
"Computed upper bounds on rewards in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() <<
"ms.");
67template<
typename ValueType>
69 ValueType lambda = storm::utility::zero<ValueType>();
71 lambda = std::max(lambda, computeLambdaForChoice(state));
76template<
typename ValueType>
78 ValueType localLambda = storm::utility::zero<ValueType>();
79 uint64_t state = this->getStateForChoice(choice);
82 ValueType probSum = originalOneStepTargetProbabilities[choice];
83 for (
auto const& e : transitionMatrix.getRow(choice)) {
84 probSum += e.getValue() * p[e.getColumn()];
87 if (p[state] < probSum) {
88 STORM_LOG_TRACE(
"Condition (I) does apply for state " << state <<
" as " << p[state] <<
" < " << probSum <<
".");
90 localLambda = probSum - p[state];
91 ValueType nominator = originalRewards[choice];
92 for (
auto const& e : transitionMatrix.getRow(choice)) {
93 nominator += e.getValue() * w[e.getColumn()];
95 nominator -= w[state];
96 localLambda = nominator / localLambda;
98 STORM_LOG_TRACE(
"Condition (I) does not apply for state " << state << std::setprecision(30) <<
" as " << probSum <<
" <= " << p[state] <<
".");
104 ValueType rewardSum = originalRewards[choice];
105 for (
auto const& e : transitionMatrix.getRow(choice)) {
106 rewardSum += e.getValue() * w[e.getColumn()];
111 "Expected condition (II) to hold in state " << state <<
", but " << w[state] <<
" < " << rewardSum <<
".");
113 "Expected condition (II) to hold in state " << state <<
", but " << probSum <<
" != " << p[state] <<
".");
120template<
typename ValueType>
125template<
typename ValueType>
133 ValueType pa = dsmpi.targetProbabilities[a];
134 ValueType pb = dsmpi.targetProbabilities[b];
137 }
else if (pa == pb) {
138 return dsmpi.rewards[a] > dsmpi.rewards[b];
147template<
typename ValueType>
156 while (!queue.
empty()) {
161 visited.
set(currentState);
164 w[currentState] = rewards[currentState];
165 p[currentState] = targetProbabilities[currentState];
167 for (
auto const& e : backwardTransitions.getRow(currentState)) {
168 if (visited.
get(e.getColumn())) {
173 rewards[e.getColumn()] += e.getValue() * w[currentState];
174 targetProbabilities[e.getColumn()] += e.getValue() * p[currentState];
182template<
typename ValueType>
184 std::vector<ValueType>
const& rewards,
185 std::vector<ValueType>
const& oneStepTargetProbabilities)
190 for (uint64_t state = 0; state <
transitionMatrix.getRowGroupCount(); ++state) {
193 boost::optional<ValueType> minReward;
194 ValueType maxProb = storm::utility::zero<ValueType>();
196 for (uint64_t row = choice, endRow =
transitionMatrix.getRowGroupIndices()[state + 1]; row < endRow; ++row) {
197 choiceToState[row] = state;
201 minReward = this->rewards[row];
203 }
else if (this->
targetProbabilities[row] == maxProb && (!minReward || minReward.get() > this->rewards[row])) {
204 minReward = this->rewards[row];
209 setChoiceInState(state, choice);
213template<
typename ValueType>
215 ValueType lambda = storm::utility::zero<ValueType>();
217 lambda = std::max(lambda, this->computeLambdaForChoice(this->getChoiceInState(state)));
222template<
typename ValueType>
223uint64_t DsMpiMdpUpperRewardBoundsComputer<ValueType>::getStateForChoice(uint64_t choice)
const {
224 return choiceToState[choice];
227template<
typename ValueType>
235 uint64_t choiceA = dsmpi.getChoiceInState(a);
236 uint64_t choiceB = dsmpi.getChoiceInState(b);
238 ValueType pa = dsmpi.targetProbabilities[choiceA];
239 ValueType pb = dsmpi.targetProbabilities[choiceB];
242 }
else if (pa == pb) {
243 return dsmpi.rewards[choiceB] > dsmpi.rewards[choiceB];
252template<
typename ValueType>
253void DsMpiMdpUpperRewardBoundsComputer<ValueType>::sweep() {
256 DsMpiMdpPriorityLess<ValueType>(*
this));
261 while (!queue.empty()) {
266 visited.set(currentState);
269 uint64_t choiceInCurrentState = this->getChoiceInState(currentState);
270 this->w[currentState] = this->rewards[choiceInCurrentState];
271 this->p[currentState] = this->targetProbabilities[choiceInCurrentState];
273 for (
auto const& choiceEntry : this->backwardTransitions.getRow(currentState)) {
274 uint64_t predecessor = this->getStateForChoice(choiceEntry.getColumn());
275 if (visited.get(predecessor)) {
280 this->rewards[choiceEntry.getColumn()] += choiceEntry.getValue() * this->w[currentState];
281 this->targetProbabilities[choiceEntry.getColumn()] += choiceEntry.getValue() * this->p[currentState];
285 uint64_t currentChoiceInPredecessor = this->getChoiceInState(predecessor);
286 if (currentChoiceInPredecessor != choiceEntry.getColumn()) {
288 ValueType
const& newTargetProbability = this->targetProbabilities[choiceEntry.getColumn()];
289 ValueType
const& newReward = this->rewards[choiceEntry.getColumn()];
290 ValueType
const& currentTargetProbability = this->targetProbabilities[this->getChoiceInState(predecessor)];
291 ValueType
const& currentReward = this->rewards[this->getChoiceInState(predecessor)];
293 if (newTargetProbability > currentTargetProbability || (newTargetProbability == currentTargetProbability && newReward < currentReward)) {
294 setChoiceInState(predecessor, choiceEntry.getColumn());
299 queue.increase(predecessor);
304template<
typename ValueType>
305uint64_t DsMpiMdpUpperRewardBoundsComputer<ValueType>::getChoiceInState(uint64_t state)
const {
306 return policy[state];
309template<
typename ValueType>
310void DsMpiMdpUpperRewardBoundsComputer<ValueType>::setChoiceInState(uint64_t state, uint64_t choice) {
311 policy[state] = choice;
314template class DsMpiDtmcUpperRewardBoundsComputer<double>;
315template class DsMpiMdpUpperRewardBoundsComputer<double>;
317#ifdef STORM_HAVE_CARL
318template class DsMpiDtmcUpperRewardBoundsComputer<storm::RationalNumber>;
319template class DsMpiMdpUpperRewardBoundsComputer<storm::RationalNumber>;
DsMpiDtmcPriorityLess(DsMpiDtmcUpperRewardBoundsComputer< ValueType > const &dsmpi)
bool operator()(storm::storage::sparse::state_type const &a, storm::storage::sparse::state_type const &b)
virtual void sweep()
Performs a Dijkstra sweep.
virtual ValueType computeLambda() const
Computes the lambda used for the estimation.
storm::storage::SparseMatrix< ValueType > const & transitionMatrix
ValueType computeLambdaForChoice(uint64_t choice) const
Computes the lambda just for the provided choice.
std::vector< ValueType > computeUpperBounds()
Computes upper bounds on the expected rewards.
DsMpiDtmcUpperRewardBoundsComputer(storm::storage::SparseMatrix< ValueType > const &transitionMatrix, std::vector< ValueType > const &rewards, std::vector< ValueType > const &oneStepTargetProbabilities)
Creates an object that can compute upper bounds on the expected rewards for the provided DTMC.
std::vector< ValueType > targetProbabilities
virtual uint64_t getStateForChoice(uint64_t choice) const
Retrieves the state associated with the given choice.
bool operator()(storm::storage::sparse::state_type const &a, storm::storage::sparse::state_type const &b)
DsMpiMdpPriorityLess(DsMpiMdpUpperRewardBoundsComputer< ValueType > const &dsmpi)
DsMpiMdpUpperRewardBoundsComputer(storm::storage::SparseMatrix< ValueType > const &transitionMatrix, std::vector< ValueType > const &rewards, std::vector< ValueType > const &oneStepTargetProbabilities)
Creates an object that can compute upper bounds on the minimal expected rewards for the provided MDP.
A bit vector that is internally represented as a vector of 64-bit values.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
bool get(uint64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
void increase(uint64_t element)
A class that holds a possibly non-square matrix in the compressed row storage format.
bool isEqual(ValueType const &value1, ValueType const &value2) const
#define STORM_LOG_TRACE(message)
#define STORM_LOG_WARN_COND(cond, message)
bool isZero(ValueType const &a)