19template<
typename ValueType>
23template<
typename ValueType>
29template<
typename ValueType>
36template<
typename ValueType>
37std::vector<ValueType> PreprocessingPomdpValueBoundsModelChecker<ValueType>::getChoiceValues(std::vector<ValueType>
const& stateValues,
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];
59 for (
auto choice = choiceIndices[state]; choice < choiceIndices[state + 1]; ++choice) {
60 ValueType
const& choiceValue = choiceValues[choice];
67 choiceDistribution.addProbability(choice - choiceIndices[state], scoreThreshold);
69 ValueType choiceScore = info.
minimize() ? (choiceValue - stateValue) : (stateValue - choiceValue);
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);
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>
109std::pair<std::vector<ValueType>, storm::storage::Scheduler<ValueType>> PreprocessingPomdpValueBoundsModelChecker<ValueType>::computeValuesForRandomFMPolicy(
110 storm::Environment
const& env, storm::logic::Formula
const& formula, storm::pomdp::analysis::FormulaInformation
const& info, uint64_t memoryBound) {
112 storm::storage::Scheduler<ValueType> pomdpScheduler(pomdp.getNumberOfStates() * memoryBound);
114 STORM_LOG_DEBUG(
"Computing the unfolding for memory bound " << memoryBound);
116 storm::transformer::PomdpMemoryUnfolder<ValueType> memoryUnfolder(pomdp, memory);
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);
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());
144 storm::storage::BitVector hasValue(pomdp.getNumberOfStates(),
false);
145 for (uint64_t memPomdpState = 0; memPomdpState < pomdpSchedulerResult.size(); ++memPomdpState) {
146 uint64_t modelState = memPomdpState / memoryBound;
147 if (!hasValue.get(modelState) || (info.
minimize() && pomdpSchedulerResult[memPomdpState] < res[modelState]) ||
148 (!info.
minimize() && pomdpSchedulerResult[memPomdpState] > res[modelState])) {
149 res[modelState] = pomdpSchedulerResult[memPomdpState];
150 hasValue.set(modelState);
153 return std::make_pair(res, pomdpScheduler);
156template<
typename ValueType>
157[[maybe_unused]] std::pair<std::vector<ValueType>, storm::storage::Scheduler<ValueType>>
158PreprocessingPomdpValueBoundsModelChecker<ValueType>::computeValuesForRandomMemorylessPolicy(
159 storm::Environment
const& env, storm::logic::Formula
const& formula, storm::pomdp::analysis::FormulaInformation
const& info,
160 std::shared_ptr<storm::models::sparse::Mdp<ValueType>> underlyingMdp) {
161 storm::storage::Scheduler<ValueType> pomdpScheduler(pomdp.getNumberOfStates());
162 std::vector<uint64_t> obsChoiceVector(pomdp.getNrObservations());
164 std::random_device rd;
165 auto engine = std::mt19937(rd());
166 for (uint64_t obs = 0; obs < pomdp.getNrObservations(); ++obs) {
167 uint64_t nrChoices = pomdp.getNumberOfChoices(pomdp.getStatesWithObservation(obs).front());
168 std::uniform_int_distribution<uint64_t> uniform_dist(0, nrChoices - 1);
169 obsChoiceVector[obs] = uniform_dist(engine);
172 for (uint64_t state = 0; state < pomdp.getNumberOfStates(); ++state) {
173 STORM_LOG_DEBUG(
"State " << state <<
" -- Random Choice " << obsChoiceVector[pomdp.getObservation(state)]);
174 pomdpScheduler.setChoice(obsChoiceVector[pomdp.getObservation(state)], state);
177 auto scheduledModel = underlyingMdp->applyScheduler(pomdpScheduler,
false);
180 STORM_LOG_THROW(resultPtr, storm::exceptions::UnexpectedException,
"No check result obtained.");
181 STORM_LOG_THROW(resultPtr->isExplicitQuantitativeCheckResult(), storm::exceptions::UnexpectedException,
"Unexpected Check result Type.");
182 std::vector<ValueType> pomdpSchedulerResult = std::move(resultPtr->template asExplicitQuantitativeCheckResult<ValueType>().getValueVector());
184 STORM_LOG_DEBUG(
"Initial Value for guessed Policy: " << pomdpSchedulerResult[pomdp.getInitialStates().getNextSetIndex(0)]);
186 return std::make_pair(pomdpSchedulerResult, pomdpScheduler);
189template<
typename ValueType>
193 "The property type is not supported for this analysis.");
199 std::make_shared<storm::models::sparse::Mdp<ValueType>>(pomdp.getTransitionMatrix(), pomdp.getStateLabeling(), pomdp.getRewardModels());
201 STORM_LOG_THROW(resultPtr, storm::exceptions::UnexpectedException,
"No check result obtained.");
202 STORM_LOG_THROW(resultPtr->isExplicitQuantitativeCheckResult(), storm::exceptions::UnexpectedException,
"Unexpected Check result Type.");
203 std::vector<ValueType> fullyObservableResult = std::move(resultPtr->template asExplicitQuantitativeCheckResult<ValueType>().getValueVector());
205 std::vector<ValueType> actionBasedRewards;
206 std::vector<ValueType>* actionBasedRewardsPtr =
nullptr;
208 actionBasedRewards = pomdp.getRewardModel(info.
getRewardModelName()).getTotalRewardVector(pomdp.getTransitionMatrix());
209 actionBasedRewardsPtr = &actionBasedRewards;
211 std::vector<std::vector<ValueType>> guessedSchedulerValues;
212 std::vector<storm::storage::Scheduler<ValueType>> guessedSchedulers;
214 std::vector<std::pair<double, bool>> guessParameters({{0.875,
false}, {0.875,
true}, {0.75,
false}, {0.75,
true}});
215 for (
auto const&
pars : guessParameters) {
217 computeValuesForGuessedScheduler(env, fullyObservableResult, actionBasedRewardsPtr, formula, info, underlyingMdp,
219 guessedSchedulerValues.push_back(guessedSchedulerPair->first);
220 guessedSchedulers.push_back(guessedSchedulerPair->second);
224 uint64_t bestGuess = 0;
225 ValueType bestGuessSum = std::accumulate(guessedSchedulerValues.front().begin(), guessedSchedulerValues.front().end(),
storm::utility::zero<ValueType>());
226 for (uint64_t guess = 1; guess < guessedSchedulerValues.size(); ++guess) {
228 if ((info.
minimize() && guessSum < bestGuessSum) || (info.
maximize() && guessSum > bestGuessSum)) {
230 bestGuessSum = guessSum;
234 computeValuesForGuessedScheduler(env, guessedSchedulerValues[bestGuess], actionBasedRewardsPtr, formula, info, underlyingMdp,
236 guessedSchedulerValues.push_back(guessedSchedulerPair->first);
237 guessedSchedulers.push_back(guessedSchedulerPair->second);
239 computeValuesForGuessedScheduler(env, guessedSchedulerValues.back(), actionBasedRewardsPtr, formula, info, underlyingMdp,
241 guessedSchedulerValues.push_back(guessedSchedulerPair->first);
242 guessedSchedulers.push_back(guessedSchedulerPair->second);
244 computeValuesForGuessedScheduler(env, guessedSchedulerValues.back(), actionBasedRewardsPtr, formula, info, underlyingMdp,
246 guessedSchedulerValues.push_back(guessedSchedulerPair->first);
247 guessedSchedulers.push_back(guessedSchedulerPair->second);
252 for (uint64_t i = 0; i < guessedSchedulerValues.size() - 1; ++i) {
253 if (!keptGuesses.
get(i)) {
256 for (uint64_t j = i + 1; j < guessedSchedulerValues.size(); ++j) {
257 if (!keptGuesses.
get(j)) {
263 keptGuesses.
set(j,
false);
266 keptGuesses.
set(i,
false);
271 keptGuesses.
set(i,
false);
274 keptGuesses.
set(j,
false);
281 std::vector<storm::storage::Scheduler<ValueType>> filteredSchedulers;
282 for (uint64_t i = 0; i < guessedSchedulers.size(); ++i) {
283 if (keptGuesses[i]) {
284 filteredSchedulers.push_back(guessedSchedulers[i]);
291 result.
lower.push_back(std::move(fullyObservableResult));
292 result.
upper = std::move(guessedSchedulerValues);
295 result.
lower = std::move(guessedSchedulerValues);
296 result.
upper.push_back(std::move(fullyObservableResult));
300 "Lower bound is larger than upper bound");
304template<
typename ValueType>
311template<
typename ValueType>
317template<
typename ValueType>
331 auto formulaPtr = std::make_shared<storm::logic::RewardOperatorFormula>(newFormula);
333 std::make_shared<storm::models::sparse::Mdp<ValueType>>(pomdp.getTransitionMatrix(), pomdp.getStateLabeling(), pomdp.getRewardModels());
335 STORM_LOG_THROW(resultPtr, storm::exceptions::UnexpectedException,
"No check result obtained.");
336 STORM_LOG_THROW(resultPtr->isExplicitQuantitativeCheckResult(), storm::exceptions::UnexpectedException,
"Unexpected Check result Type.");
337 std::vector<ValueType> resultVec = std::move(resultPtr->template asExplicitQuantitativeCheckResult<ValueType>().getValueVector());
345 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)
pomdp::storage::ExtremePOMDPValueBound< ValueType > ExtremeValueBound
ExtremeValueBound getExtremeValueBound(storm::logic::Formula const &formula)
pomdp::storage::PreprocessingPomdpValueBounds< ValueType > ValueBounds
ValueBounds getValueBounds(storm::logic::Formula const &formula)
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.
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)
storm::modelchecker::CheckTask< storm::logic::Formula, ValueType > createTask(std::shared_ptr< const storm::logic::Formula > const &formula, bool onlyInitialStatesRelevant=false)
std::unique_ptr< storm::modelchecker::CheckResult > verifyWithSparseEngine(storm::Environment const &env, std::shared_ptr< storm::models::sparse::Dtmc< ValueType > > const &dtmc, storm::modelchecker::CheckTask< storm::logic::Formula, ValueType > const &task)
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)
TargetType convertNumber(SourceType const &number)
std::vector< ValueType > values
storm::storage::BitVector isInfinite
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