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()];
109 "Expected condition (II) to hold in state " << state <<
", but " << w[state] <<
" < " << rewardSum <<
".");
111 "Expected condition (II) to hold in state " << state <<
", but " << probSum <<
" != " << p[state] <<
".");
118template<
typename ValueType>
123template<
typename ValueType>
131 ValueType pa = dsmpi.targetProbabilities[a];
132 ValueType pb = dsmpi.targetProbabilities[b];
135 }
else if (pa == pb) {
136 return dsmpi.rewards[a] > dsmpi.rewards[b];
145template<
typename ValueType>
154 while (!queue.
empty()) {
159 visited.
set(currentState);
162 w[currentState] = rewards[currentState];
163 p[currentState] = targetProbabilities[currentState];
165 for (
auto const& e : backwardTransitions.getRow(currentState)) {
166 if (visited.
get(e.getColumn())) {
171 rewards[e.getColumn()] += e.getValue() * w[currentState];
172 targetProbabilities[e.getColumn()] += e.getValue() * p[currentState];
180template<
typename ValueType>
182 std::vector<ValueType>
const& rewards,
183 std::vector<ValueType>
const& oneStepTargetProbabilities)
188 for (uint64_t state = 0; state <
transitionMatrix.getRowGroupCount(); ++state) {
191 boost::optional<ValueType> minReward;
192 ValueType maxProb = storm::utility::zero<ValueType>();
194 for (uint64_t row = choice, endRow =
transitionMatrix.getRowGroupIndices()[state + 1]; row < endRow; ++row) {
195 choiceToState[row] = state;
199 minReward = this->rewards[row];
201 }
else if (this->
targetProbabilities[row] == maxProb && (!minReward || minReward.get() > this->rewards[row])) {
202 minReward = this->rewards[row];
207 setChoiceInState(state, choice);
211template<
typename ValueType>
213 ValueType lambda = storm::utility::zero<ValueType>();
215 lambda = std::max(lambda, this->computeLambdaForChoice(this->getChoiceInState(state)));
220template<
typename ValueType>
221uint64_t DsMpiMdpUpperRewardBoundsComputer<ValueType>::getStateForChoice(uint64_t choice)
const {
222 return choiceToState[choice];
225template<
typename ValueType>
233 uint64_t choiceA = dsmpi.getChoiceInState(a);
234 uint64_t choiceB = dsmpi.getChoiceInState(b);
236 ValueType pa = dsmpi.targetProbabilities[choiceA];
237 ValueType pb = dsmpi.targetProbabilities[choiceB];
240 }
else if (pa == pb) {
241 return dsmpi.rewards[choiceB] > dsmpi.rewards[choiceB];
250template<
typename ValueType>
251void DsMpiMdpUpperRewardBoundsComputer<ValueType>::sweep() {
254 DsMpiMdpPriorityLess<ValueType>(*
this));
259 while (!queue.empty()) {
264 visited.set(currentState);
267 uint64_t choiceInCurrentState = this->getChoiceInState(currentState);
268 this->w[currentState] = this->rewards[choiceInCurrentState];
269 this->p[currentState] = this->targetProbabilities[choiceInCurrentState];
271 for (
auto const& choiceEntry : this->backwardTransitions.getRow(currentState)) {
272 uint64_t predecessor = this->getStateForChoice(choiceEntry.getColumn());
273 if (visited.get(predecessor)) {
278 this->rewards[choiceEntry.getColumn()] += choiceEntry.getValue() * this->w[currentState];
279 this->targetProbabilities[choiceEntry.getColumn()] += choiceEntry.getValue() * this->p[currentState];
283 uint64_t currentChoiceInPredecessor = this->getChoiceInState(predecessor);
284 if (currentChoiceInPredecessor != choiceEntry.getColumn()) {
286 ValueType
const& newTargetProbability = this->targetProbabilities[choiceEntry.getColumn()];
287 ValueType
const& newReward = this->rewards[choiceEntry.getColumn()];
288 ValueType
const& currentTargetProbability = this->targetProbabilities[this->getChoiceInState(predecessor)];
289 ValueType
const& currentReward = this->rewards[this->getChoiceInState(predecessor)];
291 if (newTargetProbability > currentTargetProbability || (newTargetProbability == currentTargetProbability && newReward < currentReward)) {
292 setChoiceInState(predecessor, choiceEntry.getColumn());
297 queue.increase(predecessor);
302template<
typename ValueType>
303uint64_t DsMpiMdpUpperRewardBoundsComputer<ValueType>::getChoiceInState(uint64_t state)
const {
304 return policy[state];
307template<
typename ValueType>
308void DsMpiMdpUpperRewardBoundsComputer<ValueType>::setChoiceInState(uint64_t state, uint64_t choice) {
309 policy[state] = choice;
312template class DsMpiDtmcUpperRewardBoundsComputer<double>;
313template class DsMpiMdpUpperRewardBoundsComputer<double>;
315#ifdef STORM_HAVE_CARL
316template class DsMpiDtmcUpperRewardBoundsComputer<storm::RationalNumber>;
317template 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(uint_fast64_t index, bool value=true)
Sets the given truth value at the given index.
bool get(uint_fast64_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.
#define STORM_LOG_TRACE(message)
#define STORM_LOG_WARN_COND(cond, message)
bool isZero(ValueType const &a)