18namespace modelchecker {
19template<
typename ValueType>
23template<
typename ValueType>
29template<
typename ValueType>
36template<
typename ValueType>
38 std::vector<ValueType>* actionBasedRewards) {
39 std::vector<ValueType> choiceValues((pomdp.getNumberOfChoices()));
40 pomdp.getTransitionMatrix().multiplyWithVector(stateValues, choiceValues, actionBasedRewards);
44template<
typename ValueType>
48 ValueType
const& scoreThreshold,
bool relativeScore) {
52 auto choiceValues = getChoiceValues(stateValues, actionBasedRewards);
53 auto const& choiceIndices = pomdp.getTransitionMatrix().getRowGroupIndices();
54 std::vector<storm::storage::Distribution<ValueType, uint_fast64_t>> choiceDistributions(pomdp.getNrObservations());
55 for (uint64_t state = 0; state < pomdp.getNumberOfStates(); ++state) {
56 auto& choiceDistribution = choiceDistributions[pomdp.getObservation(state)];
57 ValueType
const& stateValue = stateValues[state];
58 assert(stateValue >= storm::utility::zero<ValueType>());
59 for (
auto choice = choiceIndices[state]; choice < choiceIndices[state + 1]; ++choice) {
60 ValueType
const& choiceValue = choiceValues[choice];
61 assert(choiceValue >= storm::utility::zero<ValueType>());
67 choiceDistribution.addProbability(choice - choiceIndices[state], scoreThreshold);
69 ValueType choiceScore = info.
minimize() ? (choiceValue - stateValue) : (stateValue - choiceValue);
71 ValueType avg = (stateValue + choiceValue) / storm::utility::convertNumber<ValueType, uint64_t>(2);
76 choiceScore = storm::utility::one<ValueType>() - choiceScore;
77 if (choiceScore >= scoreThreshold) {
78 choiceDistribution.addProbability(choice - choiceIndices[state], choiceScore);
83 if (choiceDistribution.size() == 0) {
84 for (
auto choice = choiceIndices[state]; choice < choiceIndices[state + 1]; ++choice) {
85 choiceDistribution.addProbability(choice - choiceIndices[state], scoreThreshold);
88 STORM_LOG_ASSERT(choiceDistribution.size() > 0,
"Empty choice distribution.");
91 for (
auto& choiceDistribution : choiceDistributions) {
92 choiceDistribution.normalize();
95 for (uint64_t state = 0; state < pomdp.getNumberOfStates(); ++state) {
96 pomdpScheduler.setChoice(choiceDistributions[pomdp.getObservation(state)], state);
98 STORM_LOG_ASSERT(!pomdpScheduler.isPartialScheduler(),
"Expected a fully defined scheduler.");
99 auto scheduledModel = underlyingMdp->applyScheduler(pomdpScheduler,
false);
101 auto resultPtr = storm::api::verifyWithSparseEngine<ValueType>(env, scheduledModel, storm::api::createTask<ValueType>(formula.
asSharedPointer(),
false));
102 STORM_LOG_THROW(resultPtr, storm::exceptions::UnexpectedException,
"No check result obtained.");
103 STORM_LOG_THROW(resultPtr->isExplicitQuantitativeCheckResult(), storm::exceptions::UnexpectedException,
"Unexpected Check result Type");
104 std::vector<ValueType> pomdpSchedulerResult = std::move(resultPtr->template asExplicitQuantitativeCheckResult<ValueType>().getValueVector());
105 return std::make_pair(pomdpSchedulerResult, pomdpScheduler);
108template<
typename ValueType>
114 STORM_LOG_DEBUG(
"Computing the unfolding for memory bound " << memoryBound);
118 auto memPomdp = memoryUnfolder.transform(
false);
121 std::vector<uint64_t> obsChoiceVector(memPomdp->getNrObservations());
122 std::random_device rd;
123 auto engine = std::mt19937(rd());
124 for (uint64_t obs = 0; obs < memPomdp->getNrObservations(); ++obs) {
125 uint64_t nrChoices = memPomdp->getNumberOfChoices(memPomdp->getStatesWithObservation(obs).front());
126 std::uniform_int_distribution<uint64_t> uniform_dist(0, nrChoices - 1);
127 obsChoiceVector[obs] = uniform_dist(engine);
129 for (uint64_t state = 0; state < memPomdp->getNumberOfStates(); ++state) {
130 pomdpScheduler.setChoice(obsChoiceVector[memPomdp->getObservation(state)], state);
135 std::make_shared<storm::models::sparse::Mdp<ValueType>>(memPomdp->getTransitionMatrix(), memPomdp->getStateLabeling(), memPomdp->getRewardModels());
136 auto scheduledModel = underlyingMdp->applyScheduler(pomdpScheduler,
false);
137 auto resultPtr = storm::api::verifyWithSparseEngine<ValueType>(env, scheduledModel, storm::api::createTask<ValueType>(formula.
asSharedPointer(),
false));
138 STORM_LOG_THROW(resultPtr, storm::exceptions::UnexpectedException,
"No check result obtained.");
139 STORM_LOG_THROW(resultPtr->isExplicitQuantitativeCheckResult(), storm::exceptions::UnexpectedException,
"Unexpected Check result Type");
140 std::vector<ValueType> pomdpSchedulerResult = std::move(resultPtr->template asExplicitQuantitativeCheckResult<ValueType>().getValueVector());
143 std::vector<ValueType> res(pomdp.getNumberOfStates(), info.
minimize() ? storm::utility::infinity<ValueType>() : -
storm::utility::
infinity<
ValueType>());
144 for (uint64_t memPomdpState = 0; memPomdpState < pomdpSchedulerResult.size(); ++memPomdpState) {
145 uint64_t modelState = memPomdpState / memoryBound;
146 if ((info.
minimize() && pomdpSchedulerResult[memPomdpState] < res[modelState]) ||
147 (!info.
minimize() && pomdpSchedulerResult[memPomdpState] > res[modelState])) {
148 res[modelState] = pomdpSchedulerResult[memPomdpState];
151 return std::make_pair(res, pomdpScheduler);
154template<
typename ValueType>
156PreprocessingPomdpValueBoundsModelChecker<ValueType>::computeValuesForRandomMemorylessPolicy(
160 std::vector<uint64_t> obsChoiceVector(pomdp.getNrObservations());
162 std::random_device rd;
163 auto engine = std::mt19937(rd());
164 for (uint64_t obs = 0; obs < pomdp.getNrObservations(); ++obs) {
165 uint64_t nrChoices = pomdp.getNumberOfChoices(pomdp.getStatesWithObservation(obs).front());
166 std::uniform_int_distribution<uint64_t> uniform_dist(0, nrChoices - 1);
167 obsChoiceVector[obs] = uniform_dist(engine);
170 for (uint64_t state = 0; state < pomdp.getNumberOfStates(); ++state) {
171 STORM_LOG_DEBUG(
"State " << state <<
" -- Random Choice " << obsChoiceVector[pomdp.getObservation(state)]);
172 pomdpScheduler.setChoice(obsChoiceVector[pomdp.getObservation(state)], state);
175 auto scheduledModel = underlyingMdp->applyScheduler(pomdpScheduler,
false);
177 auto resultPtr = storm::api::verifyWithSparseEngine<ValueType>(env, scheduledModel, storm::api::createTask<ValueType>(formula.
asSharedPointer(),
false));
178 STORM_LOG_THROW(resultPtr, storm::exceptions::UnexpectedException,
"No check result obtained.");
179 STORM_LOG_THROW(resultPtr->isExplicitQuantitativeCheckResult(), storm::exceptions::UnexpectedException,
"Unexpected Check result Type");
180 std::vector<ValueType> pomdpSchedulerResult = std::move(resultPtr->template asExplicitQuantitativeCheckResult<ValueType>().getValueVector());
182 STORM_LOG_DEBUG(
"Initial Value for guessed Policy: " << pomdpSchedulerResult[pomdp.getInitialStates().getNextSetIndex(0)]);
184 return std::make_pair(pomdpSchedulerResult, pomdpScheduler);
187template<
typename ValueType>
191 "The property type is not supported for this analysis.");
197 std::make_shared<storm::models::sparse::Mdp<ValueType>>(pomdp.getTransitionMatrix(), pomdp.getStateLabeling(), pomdp.getRewardModels());
198 auto resultPtr = storm::api::verifyWithSparseEngine<ValueType>(env, underlyingMdp, storm::api::createTask<ValueType>(formula.
asSharedPointer(),
false));
199 STORM_LOG_THROW(resultPtr, storm::exceptions::UnexpectedException,
"No check result obtained.");
200 STORM_LOG_THROW(resultPtr->isExplicitQuantitativeCheckResult(), storm::exceptions::UnexpectedException,
"Unexpected Check result Type");
201 std::vector<ValueType> fullyObservableResult = std::move(resultPtr->template asExplicitQuantitativeCheckResult<ValueType>().getValueVector());
203 std::vector<ValueType> actionBasedRewards;
204 std::vector<ValueType>* actionBasedRewardsPtr =
nullptr;
206 actionBasedRewards = pomdp.getRewardModel(info.
getRewardModelName()).getTotalRewardVector(pomdp.getTransitionMatrix());
207 actionBasedRewardsPtr = &actionBasedRewards;
209 std::vector<std::vector<ValueType>> guessedSchedulerValues;
210 std::vector<storm::storage::Scheduler<ValueType>> guessedSchedulers;
212 std::vector<std::pair<double, bool>> guessParameters({{0.875,
false}, {0.875,
true}, {0.75,
false}, {0.75,
true}});
213 for (
auto const& pars : guessParameters) {
215 computeValuesForGuessedScheduler(env, fullyObservableResult, actionBasedRewardsPtr, formula, info, underlyingMdp,
216 storm::utility::convertNumber<ValueType>(pars.first), pars.second));
217 guessedSchedulerValues.push_back(guessedSchedulerPair->first);
218 guessedSchedulers.push_back(guessedSchedulerPair->second);
222 uint64_t bestGuess = 0;
223 ValueType bestGuessSum = std::accumulate(guessedSchedulerValues.front().begin(), guessedSchedulerValues.front().end(), storm::utility::zero<ValueType>());
224 for (uint64_t guess = 1; guess < guessedSchedulerValues.size(); ++guess) {
225 ValueType guessSum = std::accumulate(guessedSchedulerValues[guess].begin(), guessedSchedulerValues[guess].end(), storm::utility::zero<ValueType>());
226 if ((info.
minimize() && guessSum < bestGuessSum) || (info.
maximize() && guessSum > bestGuessSum)) {
228 bestGuessSum = guessSum;
232 computeValuesForGuessedScheduler(env, guessedSchedulerValues[bestGuess], actionBasedRewardsPtr, formula, info, underlyingMdp,
233 storm::utility::convertNumber<ValueType>(guessParameters[bestGuess].first), guessParameters[bestGuess].second));
234 guessedSchedulerValues.push_back(guessedSchedulerPair->first);
235 guessedSchedulers.push_back(guessedSchedulerPair->second);
237 computeValuesForGuessedScheduler(env, guessedSchedulerValues.back(), actionBasedRewardsPtr, formula, info, underlyingMdp,
238 storm::utility::convertNumber<ValueType>(guessParameters[bestGuess].first), guessParameters[bestGuess].second));
239 guessedSchedulerValues.push_back(guessedSchedulerPair->first);
240 guessedSchedulers.push_back(guessedSchedulerPair->second);
242 computeValuesForGuessedScheduler(env, guessedSchedulerValues.back(), actionBasedRewardsPtr, formula, info, underlyingMdp,
243 storm::utility::convertNumber<ValueType>(guessParameters[bestGuess].first), guessParameters[bestGuess].second));
244 guessedSchedulerValues.push_back(guessedSchedulerPair->first);
245 guessedSchedulers.push_back(guessedSchedulerPair->second);
250 for (uint64_t i = 0; i < guessedSchedulerValues.size() - 1; ++i) {
251 if (!keptGuesses.
get(i)) {
254 for (uint64_t j = i + 1; j < guessedSchedulerValues.size(); ++j) {
255 if (!keptGuesses.
get(j)) {
261 keptGuesses.
set(j,
false);
264 keptGuesses.
set(i,
false);
269 keptGuesses.
set(i,
false);
272 keptGuesses.
set(j,
false);
279 std::vector<storm::storage::Scheduler<ValueType>> filteredSchedulers;
280 for (uint64_t i = 0; i < guessedSchedulers.size(); ++i) {
281 if (keptGuesses[i]) {
282 filteredSchedulers.push_back(guessedSchedulers[i]);
289 result.
lower.push_back(std::move(fullyObservableResult));
290 result.
upper = std::move(guessedSchedulerValues);
293 result.
lower = std::move(guessedSchedulerValues);
294 result.
upper.push_back(std::move(fullyObservableResult));
298 "Lower bound is larger than upper bound");
302template<
typename ValueType>
306 return getExtremeValueBound(env, formula);
309template<
typename ValueType>
315template<
typename ValueType>
329 auto formulaPtr = std::make_shared<storm::logic::RewardOperatorFormula>(newFormula);
331 std::make_shared<storm::models::sparse::Mdp<ValueType>>(pomdp.getTransitionMatrix(), pomdp.getStateLabeling(), pomdp.getRewardModels());
332 auto resultPtr = storm::api::verifyWithSparseEngine<ValueType>(env, underlyingMdp, storm::api::createTask<ValueType>(formulaPtr,
false));
333 STORM_LOG_THROW(resultPtr, storm::exceptions::UnexpectedException,
"No check result obtained.");
334 STORM_LOG_THROW(resultPtr->isExplicitQuantitativeCheckResult(), storm::exceptions::UnexpectedException,
"Unexpected Check result Type");
335 std::vector<ValueType> resultVec = std::move(resultPtr->template asExplicitQuantitativeCheckResult<ValueType>().getValueVector());
343 res.
values = std::move(resultVec);
This class represents a (discrete-time) Markov decision process.
This class represents a partially observable Markov decision process.
PreprocessingPomdpValueBoundsModelChecker(storm::models::sparse::Pomdp< ValueType > const &pomdp)
ExtremeValueBound getExtremeValueBound(storm::logic::Formula const &formula)
ValueBounds getValueBounds(storm::logic::Formula const &formula)
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.
PomdpMemory build(PomdpMemoryPattern pattern, uint64_t numStates) const
This class defines which action is chosen in a particular state of a non-deterministic model.
#define STORM_LOG_INFO(message)
#define STORM_LOG_DEBUG(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
#define STORM_LOG_WARN_COND_DEBUG(cond, message)
SFTBDDChecker::ValueType ValueType
FormulaInformation getFormulaInformation(PomdpType const &pomdp, storm::logic::ProbabilityOperatorFormula const &formula)
bool compareElementWise(std::vector< T > const &left, std::vector< T > const &right, Comparator comp=std::less< T >())
storm::storage::BitVector filterInfinity(std::vector< T > const &values)
Retrieves a bit vector containing all the indices for which the value at this position is equal to on...
void filterVectorInPlace(std::vector< Type > &v, storm::storage::BitVector const &filter)
bool isZero(ValueType const &a)
bool isInfinity(ValueType const &a)
Struct to store the extreme bound values needed for the reward correction values when clipping is use...
std::vector< ValueType > values
storm::storage::BitVector isInfinite
Struct for storing precomputed values bounding the actual values on the POMDP.
std::vector< std::vector< ValueType > > upper
std::vector< std::vector< ValueType > > lower
std::vector< storm::storage::Scheduler< ValueType > > lowerSchedulers
std::vector< storm::storage::Scheduler< ValueType > > upperSchedulers