16template<
typename ValueType>
19template<
typename ValueType>
24 "The formula " << formula <<
" does not specify whether to minimize or maximize.");
32 subformula->asEventuallyFormula().getSubformula().asSharedPointer());
37 return transformMax(subformula->asUntilFormula());
41 return transformMinReward(subformula->asEventuallyFormula());
44 STORM_LOG_THROW(
false, storm::exceptions::InvalidPropertyException,
"Mec elimination is not supported for the property " << formula);
48template<
typename ValueType>
49std::shared_ptr<storm::models::sparse::Pomdp<ValueType>> GlobalPomdpMecChoiceEliminator<ValueType>::transformMinReward(
52 auto backwardTransitions =
pomdp.getBackwardTransitions();
55 allStates, checkPropositionalFormula(formula.
getSubformula()));
56 STORM_LOG_THROW(prob1EStates.full(), storm::exceptions::InvalidPropertyException,
57 "There are states from which the set of target states is not reachable. This is not supported.");
59 allStates, checkPropositionalFormula(formula.
getSubformula()));
61 auto mecs = decomposeEndComponents(~prob1AStates, ~allStates);
67 std::vector<storm::storage::BitVector> mecChoicesPerObservation = getEndComponentChoicesPerObservation(mecs, uniqueOutStates);
71 for (
auto const state : stateFilter) {
72 mecChoicesPerObservation[
pomdp.getObservation(state)].clear();
76 for (
auto& clearedChoices : mecChoicesPerObservation) {
77 STORM_LOG_ASSERT(clearedChoices.size() == 0 || !clearedChoices.full(),
"Tried to clear all choices for an observation.");
82 stateFilter.complement();
83 for (
auto const state : stateFilter) {
84 uint64_t offset = pomdp.getTransitionMatrix().getRowGroupIndices()[state];
85 for (
auto const& choice : mecChoicesPerObservation[pomdp.getObservation(state)]) {
86 choiceFilter.set(offset + choice,
false);
91 auto res = cs.transform(choiceFilter)->template as<storm::models::sparse::Pomdp<ValueType>>();
96template<
typename ValueType>
97std::shared_ptr<storm::models::sparse::Pomdp<ValueType>> GlobalPomdpMecChoiceEliminator<ValueType>::transformMax(
98 storm::logic::UntilFormula
const& formula)
const {
99 auto backwardTransitions = pomdp.getBackwardTransitions();
103 auto mecs = decomposeEndComponents(~(prob01States.first | prob01States.second), prob01States.first);
106 storm::storage::BitVector uniqueOutStates = getEndComponentsWithSingleOutStates(mecs);
109 std::vector<storm::storage::BitVector> mecChoicesPerObservation = getEndComponentChoicesPerObservation(mecs, uniqueOutStates);
112 storm::storage::BitVector stateFilter = ~(uniqueOutStates | prob01States.first);
113 for (
auto const state : stateFilter) {
114 mecChoicesPerObservation[pomdp.getObservation(state)].clear();
118 for (
auto& clearedChoices : mecChoicesPerObservation) {
119 STORM_LOG_ASSERT(clearedChoices.size() == 0 || !clearedChoices.full(),
"Tried to clear all choices for an observation.");
123 storm::storage::BitVector choiceFilter(pomdp.getNumberOfChoices(),
true);
124 stateFilter.complement();
125 for (
auto const state : stateFilter) {
126 uint64_t offset = pomdp.getTransitionMatrix().getRowGroupIndices()[state];
127 for (
auto const& choice : mecChoicesPerObservation[pomdp.getObservation(state)]) {
128 choiceFilter.set(offset + choice,
false);
133 auto res = cs.transform(choiceFilter)->template as<storm::models::sparse::Pomdp<ValueType>>();
138template<
typename ValueType>
139storm::storage::BitVector GlobalPomdpMecChoiceEliminator<ValueType>::getEndComponentsWithSingleOutStates(
140 storm::storage::MaximalEndComponentDecomposition<ValueType>
const& mecs)
const {
141 storm::storage::BitVector result(pomdp.getNumberOfStates(),
false);
142 for (
auto const& mec : mecs) {
143 std::optional<uint64_t> uniqueOutState = std::nullopt;
144 for (
auto const& stateActionsPair : mec) {
146 if (stateActionsPair.second.size() != pomdp.getNumberOfChoices(stateActionsPair.first)) {
147 if (uniqueOutState) {
149 uniqueOutState = std::nullopt;
152 uniqueOutState = stateActionsPair.first;
156 if (uniqueOutState) {
157 result.set(uniqueOutState.value(),
true);
163template<
typename ValueType>
164std::vector<storm::storage::BitVector> GlobalPomdpMecChoiceEliminator<ValueType>::getEndComponentChoicesPerObservation(
165 storm::storage::MaximalEndComponentDecomposition<ValueType>
const& mecs, storm::storage::BitVector
const& consideredStates)
const {
166 std::vector<storm::storage::BitVector> result(pomdp.getNrObservations());
167 for (
auto const& mec : mecs) {
168 for (
auto const& stateActions : mec) {
169 if (consideredStates.
get(stateActions.first)) {
170 storm::storage::BitVector localChoiceIndices(pomdp.getNumberOfChoices(stateActions.first),
false);
171 uint64_t offset = pomdp.getTransitionMatrix().getRowGroupIndices()[stateActions.first];
172 for (
auto const& choice : stateActions.second) {
173 assert(choice >= offset);
174 localChoiceIndices.set(choice - offset,
true);
177 auto& mecChoices = result[pomdp.getObservation(stateActions.first)];
178 if (mecChoices.size() == 0) {
179 mecChoices = localChoiceIndices;
182 "Observation action count does not match for two states with the same observation");
183 mecChoices &= localChoiceIndices;
191template<
typename ValueType>
192storm::storage::MaximalEndComponentDecomposition<ValueType> GlobalPomdpMecChoiceEliminator<ValueType>::decomposeEndComponents(
193 storm::storage::BitVector
const& subsystem, storm::storage::BitVector
const& redirectingStates)
const {
194 if (redirectingStates.
empty()) {
195 return storm::storage::MaximalEndComponentDecomposition<ValueType>(pomdp.getTransitionMatrix(), pomdp.getBackwardTransitions(), subsystem);
198 storm::storage::SparseMatrixBuilder<ValueType> builder(pomdp.getTransitionMatrix().getRowCount(), pomdp.getTransitionMatrix().getColumnCount(), 0,
true,
199 true, pomdp.getTransitionMatrix().getRowGroupCount());
201 for (uint64_t rowGroup = 0; rowGroup < pomdp.getTransitionMatrix().getRowGroupCount(); ++rowGroup) {
202 assert(row == pomdp.getTransitionMatrix().getRowGroupIndices()[rowGroup]);
203 builder.newRowGroup(row);
204 for (; row < pomdp.getTransitionMatrix().getRowGroupIndices()[rowGroup + 1]; ++row) {
205 ValueType redirectedProbabilityMass = pomdp.getTransitionMatrix().getConstrainedRowSum(row, redirectingStates);
207 for (
auto const& entry : pomdp.getTransitionMatrix().getRow(row)) {
208 if (!redirectingStates.
get(entry.getColumn())) {
209 if (insertSelfloop && entry.getColumn() >= rowGroup) {
211 insertSelfloop =
false;
212 if (entry.getColumn() == rowGroup) {
213 builder.addNextValue(row, rowGroup, entry.getValue() + redirectedProbabilityMass);
216 builder.addNextValue(row, rowGroup, redirectedProbabilityMass);
219 builder.addNextValue(row, entry.getColumn(), entry.getValue());
222 if (insertSelfloop) {
223 builder.addNextValue(row, rowGroup, redirectedProbabilityMass);
227 storm::storage::SparseMatrix<ValueType> transitionMatrix = builder.build();
228 return storm::storage::MaximalEndComponentDecomposition<ValueType>(transitionMatrix, transitionMatrix.
transpose(
true), subsystem);
232template<
typename ValueType>
233storm::storage::BitVector GlobalPomdpMecChoiceEliminator<ValueType>::checkPropositionalFormula(storm::logic::Formula
const& propositionalFormula)
const {
234 storm::modelchecker::SparsePropositionalModelChecker<storm::models::sparse::Mdp<ValueType>> mc(pomdp);
235 STORM_LOG_THROW(mc.canHandle(propositionalFormula), storm::exceptions::InvalidPropertyException,
236 "Propositional model checker can not handle formula " << propositionalFormula);
237 return mc.check(propositionalFormula)->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
This class represents a partially observable Markov decision process.
A bit vector that is internally represented as a vector of 64-bit values.
bool empty() const
Retrieves whether no bits are set to true in this bit vector.
bool get(uint64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
storm::storage::SparseMatrix< value_type > transpose(bool joinGroups=false, bool keepZeros=false) const
Transposes the matrix.
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
SFTBDDChecker::ValueType ValueType
bool isLowerBound(ComparisonType t)
bool constexpr minimize(OptimizationDirection d)
std::pair< storm::storage::BitVector, storm::storage::BitVector > performProb01Max(storm::storage::SparseMatrix< T > const &transitionMatrix, std::vector< uint_fast64_t > const &nondeterministicChoiceIndices, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
storm::storage::BitVector performProb1A(storm::models::sparse::NondeterministicModel< T, RM > const &model, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Computes the sets of states that have probability 1 of satisfying phi until psi under all possible re...
storm::storage::BitVector performProb1E(storm::storage::SparseMatrix< T > const &transitionMatrix, std::vector< uint_fast64_t > const &nondeterministicChoiceIndices, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, boost::optional< storm::storage::BitVector > const &choiceConstraint)
Computes the sets of states that have probability 1 of satisfying phi until psi under at least one po...
bool isZero(ValueType const &a)
ComparisonType comparisonType