22template<
typename SparseModelType,
typename ConstantType>
28template<
typename SparseModelType,
typename ConstantType>
31 : solverFactory(
std::move(solverFactory)) {
35template<
typename SparseModelType,
typename ConstantType>
42 result &=
static_cast<bool>(mdp);
44 .setRewardOperatorsAllowed(
true)
45 .setReachabilityRewardFormulasAllowed(
true)
46 .setBoundedUntilFormulasAllowed(
true)
47 .setCumulativeRewardFormulasAllowed(
true)
48 .setStepBoundedUntilFormulasAllowed(
true)
49 .setTimeBoundedCumulativeRewardFormulasAllowed(
true)
50 .setStepBoundedCumulativeRewardFormulasAllowed(
true)
51 .setTimeBoundedUntilFormulasAllowed(
true));
55template<
typename SparseModelType,
typename ConstantType>
61 "Combination of model " <<
parametricModel->getType() <<
" and formula '" << checkTask.
getFormula() <<
"' is not supported.");
63 "Non-graph-preserving regions not implemented for MDPs.");
69 if (allowModelSimplifications) {
71 STORM_LOG_THROW(simplifier.simplify(checkTask.
getFormula()), storm::exceptions::UnexpectedException,
"Simplifying the model was not successfull.");
72 this->parametricModel = simplifier.getSimplifiedModel();
75 this->parametricModel = mdp;
79 std::shared_ptr<storm::logic::Formula> formulaWithoutBounds = this->
currentCheckTask->getFormula().clone();
80 formulaWithoutBounds->asOperatorFormula().removeBound();
81 this->currentFormulaNoBound = formulaWithoutBounds->asSharedPointer();
82 this->currentCheckTaskNoBound = std::make_unique<storm::modelchecker::CheckTask<storm::logic::Formula, ParametricType>>(*this->currentFormulaNoBound);
85template<
typename SparseModelType,
typename ConstantType>
89 STORM_LOG_THROW(!checkTask.
getFormula().hasLowerBound(), storm::exceptions::NotSupportedException,
"Lower step bounds are not supported.");
90 STORM_LOG_THROW(checkTask.
getFormula().hasUpperBound(), storm::exceptions::NotSupportedException,
"Expected a bounded until formula with an upper bound.");
92 "Expected a bounded until formula with step bounds.");
93 stepBound = checkTask.
getFormula().getUpperBound().evaluateAsInt();
94 STORM_LOG_THROW(*stepBound > 0, storm::exceptions::NotSupportedException,
95 "Can not apply parameter lifting on step bounded formula: The step bound has to be positive.");
96 if (checkTask.
getFormula().isUpperBoundStrict()) {
97 STORM_LOG_THROW(*stepBound > 0, storm::exceptions::NotSupportedException,
"Expected a strict upper step bound that is greater than zero.");
100 STORM_LOG_THROW(*stepBound > 0, storm::exceptions::NotSupportedException,
101 "Can not apply parameter lifting on step bounded formula: The step bound has to be positive.");
107 storm::exceptions::NotSupportedException,
"Parameter lifting with non-propositional subformulas is not supported.");
109 ->template asExplicitQualitativeCheckResult<typename SparseModelType::ValueType>()
110 .getTruthValuesVector());
112 ->template asExplicitQualitativeCheckResult<typename SparseModelType::ValueType>()
113 .getTruthValuesVector());
118 this->parametricModel->getTransitionMatrix().getRowGroupIndices(),
119 this->parametricModel->getBackwardTransitions(), phiStates, psiStates,
true, *stepBound)
121 maybeStates &= ~psiStates;
128 if (!maybeStates.empty()) {
130 std::vector<ParametricType> b = this->
parametricModel->getTransitionMatrix().getConstrainedRowSumVector(
133 parameterLifter = std::make_unique<storm::transformer::ParameterLifter<ParametricType, ConstantType>>(
135 computePlayer1Matrix();
137 applyPreviousResultAsHint =
false;
145template<
typename SparseModelType,
typename ConstantType>
152 storm::exceptions::NotSupportedException,
"Parameter lifting with non-propositional subformulas is not supported.");
154 ->template asExplicitQualitativeCheckResult<typename SparseModelType::ValueType>()
155 .getTruthValuesVector());
157 ->template asExplicitQualitativeCheckResult<typename SparseModelType::ValueType>()
158 .getTruthValuesVector());
161 std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01 =
164 this->parametricModel->getTransitionMatrix().getRowGroupIndices(),
165 this->parametricModel->getBackwardTransitions(), phiStates, psiStates)
167 this->parametricModel->getTransitionMatrix().getRowGroupIndices(),
168 this->parametricModel->getBackwardTransitions(), phiStates, psiStates);
169 maybeStates = ~(statesWithProbability01.first | statesWithProbability01.second);
176 if (!maybeStates.empty()) {
178 std::vector<ParametricType> b = this->
parametricModel->getTransitionMatrix().getConstrainedRowSumVector(
181 parameterLifter = std::make_unique<storm::transformer::ParameterLifter<ParametricType, ConstantType>>(
183 computePlayer1Matrix();
186 applyPreviousResultAsHint =
189 this->parametricModel->getTransitionMatrix().getRowGroupIndices(),
190 this->parametricModel->getBackwardTransitions(), maybeStates, ~maybeStates)
199template<
typename SparseModelType,
typename ConstantType>
205 "Parameter lifting with non-propositional subformulas is not supported.");
207 ->template asExplicitQualitativeCheckResult<typename SparseModelType::ValueType>()
208 .getTruthValuesVector());
214 this->
parametricModel->getTransitionMatrix(), this->parametricModel->getTransitionMatrix().getRowGroupIndices(),
215 this->parametricModel->getBackwardTransitions(),
storm::storage::BitVector(this->parametricModel->getNumberOfStates(),
true), targetStates)
217 this->
parametricModel->getTransitionMatrix(), this->parametricModel->getTransitionMatrix().getRowGroupIndices(),
218 this->parametricModel->getBackwardTransitions(),
storm::storage::BitVector(this->parametricModel->getNumberOfStates(),
true), targetStates);
220 maybeStates = ~(targetStates | infinityStates);
227 if (!maybeStates.empty()) {
230 (!checkTask.
isRewardModelSet() && this->parametricModel->hasUniqueRewardModel()),
231 storm::exceptions::InvalidPropertyException,
"The reward model specified by the CheckTask is not available in the given model.");
233 typename SparseModelType::RewardModelType
const& rewardModel =
236 std::vector<ParametricType> b = rewardModel.getTotalRewardVector(this->
parametricModel->getTransitionMatrix());
243 parameterLifter = std::make_unique<storm::transformer::ParameterLifter<ParametricType, ConstantType>>(this->
parametricModel->getTransitionMatrix(), b,
244 selectedRows, maybeStates);
245 computePlayer1Matrix(selectedRows);
248 applyPreviousResultAsHint =
251 this->parametricModel->getTransitionMatrix().getRowGroupIndices(),
252 this->parametricModel->getBackwardTransitions(), maybeStates, ~maybeStates)
260template<
typename SparseModelType,
typename ConstantType>
264 stepBound = checkTask.
getFormula().getBound().evaluateAsInt();
266 STORM_LOG_THROW(*stepBound > 0, storm::exceptions::NotSupportedException,
"Expected a strict upper step bound that is greater than zero.");
269 STORM_LOG_THROW(*stepBound > 0, storm::exceptions::NotSupportedException,
270 "Can not apply parameter lifting on step bounded formula: The step bound has to be positive.");
274 resultsForNonMaybeStates = std::vector<ExtendedConstantType>(this->
parametricModel->getNumberOfStates());
278 (!checkTask.
isRewardModelSet() && this->parametricModel->hasUniqueRewardModel()),
279 storm::exceptions::InvalidPropertyException,
"The reward model specified by the CheckTask is not available in the given model.");
280 typename SparseModelType::RewardModelType
const& rewardModel =
282 std::vector<ParametricType> b = rewardModel.getTotalRewardVector(this->
parametricModel->getTransitionMatrix());
284 parameterLifter = std::make_unique<storm::transformer::ParameterLifter<ParametricType, ConstantType>>(
287 computePlayer1Matrix();
289 applyPreviousResultAsHint =
false;
295template<
typename SparseModelType,
typename ConstantType>
298 if (!instantiationChecker) {
299 instantiationChecker =
300 std::make_unique<storm::modelchecker::SparseMdpInstantiationModelChecker<SparseModelType, ConstantType>>(env, *this->
parametricModel);
301 instantiationChecker->specifyFormula(quantitative ? *this->currentCheckTaskNoBound
303 instantiationChecker->setInstantiationsAreGraphPreserving(
true);
305 return *instantiationChecker;
308template<
typename SparseModelType,
typename ConstantType>
315template<
typename SparseModelType,
typename ConstantType>
316std::vector<typename SparseMdpParameterLiftingModelChecker<SparseModelType, ConstantType>::ExtendedConstantType>
319 if (maybeStates.empty()) {
321 return resultsForNonMaybeStates;
324 parameterLifter->specifyRegion(
region.region, dirForParameters);
327 auto solver = solverFactory->create(env, player1Matrix, parameterLifter->getMatrix());
328 if (lowerResultBound) {
329 solver->setLowerBound(lowerResultBound.value());
331 if (upperResultBound) {
332 solver->setUpperBound(upperResultBound.value());
334 if (applyPreviousResultAsHint) {
335 solver->setTrackSchedulers(
true);
338 solver->setSchedulerHints(std::move(player1SchedChoices.value()), std::move(minSchedChoices.value()));
341 solver->setSchedulerHints(std::move(player1SchedChoices.value()), std::move(maxSchedChoices.value()));
346 if (this->
currentCheckTask->isBoundSet() && this->currentCheckTask->getOptimizationDirection() == dirForParameters &&
solver->hasSchedulerHints()) {
348 std::unique_ptr<storm::solver::TerminationCondition<ConstantType>> termCond;
354 termCond = std::make_unique<storm::solver::TerminateIfFilteredExtremumBelowThreshold<ConstantType>>(
355 relevantStatesInSubsystem,
true, this->
currentCheckTask->getBoundThreshold(),
false);
358 termCond = std::make_unique<storm::solver::TerminateIfFilteredExtremumExceedsThreshold<ConstantType>>(
359 relevantStatesInSubsystem,
true, this->
currentCheckTask->getBoundThreshold(),
true);
361 solver->setTerminationCondition(std::move(termCond));
367 solver->repeatedMultiply(env, this->
currentCheckTask->getOptimizationDirection(), dirForParameters, x, ¶meterLifter->getVector(), *stepBound);
369 solver->solveGame(env, this->
currentCheckTask->getOptimizationDirection(), dirForParameters, x, parameterLifter->getVector());
370 if (applyPreviousResultAsHint) {
372 minSchedChoices =
solver->getPlayer2SchedulerChoices();
374 maxSchedChoices =
solver->getPlayer2SchedulerChoices();
376 player1SchedChoices =
solver->getPlayer1SchedulerChoices();
381 std::vector<ExtendedConstantType> result = resultsForNonMaybeStates;
382 auto maybeStateResIt = x.begin();
383 for (uint64_t maybeState : maybeStates) {
384 result[maybeState] = *maybeStateResIt;
391template<
typename SparseModelType,
typename ConstantType>
392void SparseMdpParameterLiftingModelChecker<SparseModelType, ConstantType>::computePlayer1Matrix(std::optional<storm::storage::BitVector>
const& selectedRows) {
396 n = selectedRows->getNumberOfSetBits();
398 for (uint64_t maybeState : maybeStates) {
399 n += this->parametricModel->getTransitionMatrix().getRowGroupSize(maybeState);
404 storm::storage::SparseMatrixBuilder<storm::storage::sparse::state_type> matrixBuilder(n, n, n,
true,
true, maybeStates.getNumberOfSetBits());
405 uint64_t p1MatrixRow = 0;
406 for (uint64_t maybeState : maybeStates) {
407 matrixBuilder.newRowGroup(p1MatrixRow);
409 for (uint64_t row = selectedRows->getNextSetIndex(this->parametricModel->getTransitionMatrix().getRowGroupIndices()[maybeState]);
410 row < this->parametricModel->getTransitionMatrix().getRowGroupIndices()[maybeState + 1]; row = selectedRows->getNextSetIndex(row + 1)) {
415 for (uint64_t endOfGroup = p1MatrixRow + this->parametricModel->getTransitionMatrix().getRowGroupSize(maybeState); p1MatrixRow < endOfGroup;
421 player1Matrix = matrixBuilder.build();
424template<
typename SparseModelType,
typename ConstantType>
426 maybeStates.resize(0);
427 resultsForNonMaybeStates.clear();
428 stepBound = std::nullopt;
429 instantiationChecker =
nullptr;
431 parameterLifter =
nullptr;
432 minSchedChoices = std::nullopt;
433 maxSchedChoices = std::nullopt;
435 lowerResultBound = std::nullopt;
436 upperResultBound = std::nullopt;
437 applyPreviousResultAsHint =
false;
440template<
typename ConstantType>
441std::optional<storm::storage::Scheduler<ConstantType>>
getSchedulerHelper(std::optional<std::vector<uint64_t>>
const& choices) {
442 std::optional<storm::storage::Scheduler<ConstantType>> result;
444 result.emplace(choices->size());
446 for (
auto const& choice : choices.value()) {
447 result->setChoice(choice, state);
454template<
typename SparseModelType,
typename ConstantType>
459template<
typename SparseModelType,
typename ConstantType>
464template<
typename SparseModelType,
typename ConstantType>
virtual std::unique_ptr< CheckResult > check(Environment const &env, CheckTask< storm::logic::Formula, SolutionType > const &checkTask)
Checks the provided formula.
CheckTask< NewFormulaType, ValueType > substituteFormula(NewFormulaType const &newFormula) const
Copies the check task from the source while replacing the formula with the new one.
bool isRewardModelSet() const
Retrieves whether a reward model was set.
std::string const & getRewardModel() const
Retrieves the reward model over which to perform the checking (if set).
FormulaType const & getFormula() const
Retrieves the formula from this task.
storm::OptimizationDirection const & getOptimizationDirection() const
Retrieves the optimization direction (if set).
virtual bool requiresInteractionWithRegionModelChecker() const
Returns true, if a region model checker needs to implement specific methods to properly use this back...
virtual void specifyMonotonicity(std::shared_ptr< MonotonicityBackend< SparseModelType::ValueType > > backend, CheckTask< storm::logic::Formula, SparseModelType::ValueType > const &checkTask)
std::shared_ptr< MonotonicityBackend< SparseModelType::ValueType > > monotonicityBackend
virtual void specifySplitEstimates(std::optional< RegionSplitEstimateKind > splitEstimates, CheckTask< storm::logic::Formula, SparseModelType::ValueType > const &checkTask)
Class to efficiently check a formula on a parametric model with different parameter instantiations.
std::optional< storm::storage::Scheduler< ConstantType > > getCurrentMinScheduler()
virtual void specifyReachabilityRewardFormula(Environment const &env, CheckTask< storm::logic::EventuallyFormula, ConstantType > const &checkTask) override
std::optional< storm::storage::Scheduler< ConstantType > > getCurrentPlayer1Scheduler()
SparseMdpParameterLiftingModelChecker()
virtual void reset() override
virtual void specify(Environment const &env, std::shared_ptr< storm::models::ModelBase > parametricModel, CheckTask< storm::logic::Formula, ParametricType > const &checkTask, std::optional< RegionSplitEstimateKind > generateRegionSplitEstimates=std::nullopt, std::shared_ptr< MonotonicityBackend< ParametricType > > monotonicityBackend={}, bool allowModelSimplifications=true, storm::pars::analysis::GraphPreservationStatus graphPreservationStatus=storm::pars::analysis::GraphPreservationStatus::GraphPreserving) override
std::optional< storm::storage::Scheduler< ConstantType > > getCurrentMaxScheduler()
virtual std::vector< ExtendedConstantType > computeQuantitativeValues(Environment const &env, AnnotatedRegion< ParametricType > ®ion, storm::solver::OptimizationDirection const &dirForParameters) override
virtual bool isMonotonicitySupported(MonotonicityBackend< ParametricType > const &backend, CheckTask< storm::logic::Formula, ParametricType > const &checkTask) const override
Returns whether this region model checker can work together with the given monotonicity backend.
virtual bool canHandle(std::shared_ptr< storm::models::ModelBase > parametricModel, CheckTask< storm::logic::Formula, ParametricType > const &checkTask) const override
virtual void specifyUntilFormula(Environment const &env, CheckTask< storm::logic::UntilFormula, ConstantType > const &checkTask) override
virtual storm::modelchecker::SparseInstantiationModelChecker< SparseModelType, ConstantType > & getInstantiationChecker(Environment const &env, bool quantitative) override
virtual void specifyBoundedUntilFormula(const CheckTask< storm::logic::BoundedUntilFormula, ConstantType > &checkTask) override
virtual void specifyCumulativeRewardFormula(const CheckTask< storm::logic::CumulativeRewardFormula, ConstantType > &checkTask) override
void updateKnownValueBoundInRegion(AnnotatedRegion< ParametricType > ®ion, storm::solver::OptimizationDirection dir, std::vector< ExtendedConstantType > const &newValues)
std::unique_ptr< CheckTask< storm::logic::Formula, ConstantType > > currentCheckTask
void specifyFormula(Environment const &env, CheckTask< storm::logic::Formula, ParametricType > const &checkTask)
std::shared_ptr< SparseModelType > parametricModel
virtual bool canHandle(CheckTask< storm::logic::Formula, SolutionType > const &checkTask) const override
A bit vector that is internally represented as a vector of 64-bit values.
void complement()
Negates all bits in the bit vector.
bool full() const
Retrieves whether all bits are set in this bit vector.
A class that holds a possibly non-square matrix in the compressed row storage format.
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
FragmentSpecification reachability()
std::optional< storm::storage::Scheduler< ConstantType > > getSchedulerHelper(std::optional< std::vector< uint64_t > > const &choices)
GraphPreservationStatus
Describes to what extent a set of regions is known to be well-defined and to preserve the graph struc...
bool isGraphPreserving(GraphPreservationStatus status)
Returns whether the given status guarantees that the graph structure of the model is preserved.
bool constexpr maximize(OptimizationDirection d)
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 performProbGreater0A(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, bool useStepBound, uint_fast64_t maximalSteps, boost::optional< storm::storage::BitVector > const &choiceConstraint)
Computes the sets of states that have probability greater 0 of satisfying phi until psi under any pos...
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 performProbGreater0E(storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, bool useStepBound, uint_fast64_t maximalSteps)
Computes the sets of states that have probability greater 0 of satisfying phi until psi under at leas...
std::pair< storm::storage::BitVector, storm::storage::BitVector > performProb01Min(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 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...
void setVectorValues(std::vector< T > &vector, storm::storage::BitVector const &positions, std::vector< S > const &values)
Sets the provided values at the provided positions in the given vector.
ExtendedValueType< ValueType > positiveInfinity()