23namespace modelchecker {
25template<
typename SparseModelType,
typename ConstantType>
31template<
typename SparseModelType,
typename ConstantType>
34 : solverFactory(
std::move(solverFactory)) {
38template<
typename SparseModelType,
typename ConstantType>
42 result &= parametricModel->isSparseModel();
43 result &= parametricModel->supportsParameters();
44 auto mdp = parametricModel->template as<SparseModelType>();
45 result &=
static_cast<bool>(mdp);
58template<
typename SparseModelType,
typename ConstantType>
60 Environment const& env, std::shared_ptr<storm::models::ModelBase> parametricModel,
62 auto mdp = parametricModel->template as<SparseModelType>();
63 specify_internal(env, mdp, checkTask, !allowModelSimplifications);
66template<
typename SparseModelType,
typename ConstantType>
68 Environment const& env, std::shared_ptr<SparseModelType> parametricModel,
70 STORM_LOG_ASSERT(this->canHandle(parametricModel, checkTask),
"specified model and formula can not be handled by this.");
74 if (skipModelSimplification) {
75 this->parametricModel = parametricModel;
76 this->specifyFormula(env, checkTask);
79 if (!simplifier.simplify(checkTask.
getFormula())) {
80 STORM_LOG_THROW(
false, storm::exceptions::UnexpectedException,
"Simplifying the model was not successfull.");
82 this->parametricModel = simplifier.getSimplifiedModel();
83 this->specifyFormula(env, checkTask.
substituteFormula(*simplifier.getSimplifiedFormula()));
87template<
typename SparseModelType,
typename ConstantType>
91 STORM_LOG_THROW(!checkTask.
getFormula().hasLowerBound(), storm::exceptions::NotSupportedException,
"Lower step bounds are not supported.");
92 STORM_LOG_THROW(checkTask.
getFormula().hasUpperBound(), storm::exceptions::NotSupportedException,
"Expected a bounded until formula with an upper bound.");
94 "Expected a bounded until formula with step bounds.");
95 stepBound = checkTask.
getFormula().getUpperBound().evaluateAsInt();
96 STORM_LOG_THROW(*stepBound > 0, storm::exceptions::NotSupportedException,
97 "Can not apply parameter lifting on step bounded formula: The step bound has to be positive.");
98 if (checkTask.
getFormula().isUpperBoundStrict()) {
99 STORM_LOG_THROW(*stepBound > 0, storm::exceptions::NotSupportedException,
"Expected a strict upper step bound that is greater than zero.");
102 STORM_LOG_THROW(*stepBound > 0, storm::exceptions::NotSupportedException,
103 "Can not apply parameter lifting on step bounded formula: The step bound has to be positive.");
109 storm::exceptions::NotSupportedException,
"Parameter lifting with non-propositional subformulas is not supported");
111 std::move(propositionalChecker.
check(checkTask.
getFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector());
113 std::move(propositionalChecker.
check(checkTask.
getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector());
118 this->parametricModel->getTransitionMatrix().getRowGroupIndices(),
119 this->parametricModel->getBackwardTransitions(), phiStates, psiStates,
true, *stepBound)
121 maybeStates &= ~psiStates;
124 resultsForNonMaybeStates = std::vector<ConstantType>(this->parametricModel->getNumberOfStates(), storm::utility::zero<ConstantType>());
128 if (!maybeStates.empty()) {
130 std::vector<typename SparseModelType::ValueType> b = this->parametricModel->getTransitionMatrix().getConstrainedRowSumVector(
133 parameterLifter = std::make_unique<storm::transformer::ParameterLifter<typename SparseModelType::ValueType, ConstantType>>(
134 this->parametricModel->getTransitionMatrix(), b, this->parametricModel->getTransitionMatrix().getRowFilter(maybeStates), maybeStates);
135 computePlayer1Matrix();
137 applyPreviousResultAsHint =
false;
141 lowerResultBound = storm::utility::zero<ConstantType>();
142 upperResultBound = storm::utility::one<ConstantType>();
145template<
typename SparseModelType,
typename ConstantType>
152 storm::exceptions::NotSupportedException,
"Parameter lifting with non-propositional subformulas is not supported");
154 std::move(propositionalChecker.
check(checkTask.
getFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector());
156 std::move(propositionalChecker.
check(checkTask.
getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector());
159 std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01 =
162 this->parametricModel->getTransitionMatrix().getRowGroupIndices(),
163 this->parametricModel->getBackwardTransitions(), phiStates, psiStates)
165 this->parametricModel->getTransitionMatrix().getRowGroupIndices(),
166 this->parametricModel->getBackwardTransitions(), phiStates, psiStates);
167 maybeStates = ~(statesWithProbability01.first | statesWithProbability01.second);
170 resultsForNonMaybeStates = std::vector<ConstantType>(this->parametricModel->getNumberOfStates(), storm::utility::zero<ConstantType>());
174 if (!maybeStates.empty()) {
176 std::vector<typename SparseModelType::ValueType> b = this->parametricModel->getTransitionMatrix().getConstrainedRowSumVector(
177 storm::storage::BitVector(this->parametricModel->getTransitionMatrix().getRowCount(),
true), statesWithProbability01.second);
179 parameterLifter = std::make_unique<storm::transformer::ParameterLifter<typename SparseModelType::ValueType, ConstantType>>(
180 this->parametricModel->getTransitionMatrix(), b, this->parametricModel->getTransitionMatrix().getRowFilter(maybeStates), maybeStates);
181 computePlayer1Matrix();
184 applyPreviousResultAsHint =
187 this->parametricModel->getTransitionMatrix().getRowGroupIndices(),
188 this->parametricModel->getBackwardTransitions(), maybeStates, ~maybeStates)
193 lowerResultBound = storm::utility::zero<ConstantType>();
194 upperResultBound = storm::utility::one<ConstantType>();
197template<
typename SparseModelType,
typename ConstantType>
203 "Parameter lifting with non-propositional subformulas is not supported");
205 std::move(propositionalChecker.
check(checkTask.
getFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector());
211 this->parametricModel->getTransitionMatrix(), this->parametricModel->getTransitionMatrix().getRowGroupIndices(),
212 this->parametricModel->getBackwardTransitions(),
storm::storage::BitVector(this->parametricModel->getNumberOfStates(),
true), targetStates)
214 this->parametricModel->getTransitionMatrix(), this->parametricModel->getTransitionMatrix().getRowGroupIndices(),
215 this->parametricModel->getBackwardTransitions(),
storm::storage::BitVector(this->parametricModel->getNumberOfStates(),
true), targetStates);
217 maybeStates = ~(targetStates | infinityStates);
220 resultsForNonMaybeStates = std::vector<ConstantType>(this->parametricModel->getNumberOfStates(), storm::utility::zero<ConstantType>());
224 if (!maybeStates.empty()) {
227 (!checkTask.
isRewardModelSet() && this->parametricModel->hasUniqueRewardModel()),
228 storm::exceptions::InvalidPropertyException,
"The reward model specified by the CheckTask is not available in the given model.");
230 typename SparseModelType::RewardModelType
const& rewardModel =
233 std::vector<typename SparseModelType::ValueType> b = rewardModel.getTotalRewardVector(this->parametricModel->getTransitionMatrix());
238 storm::storage::BitVector selectedRows = this->parametricModel->getTransitionMatrix().getRowFilter(maybeStates, ~infinityStates);
240 parameterLifter = std::make_unique<storm::transformer::ParameterLifter<typename SparseModelType::ValueType, ConstantType>>(
241 this->parametricModel->getTransitionMatrix(), b, selectedRows, maybeStates);
242 computePlayer1Matrix(selectedRows);
245 applyPreviousResultAsHint =
248 this->parametricModel->getTransitionMatrix().getRowGroupIndices(),
249 this->parametricModel->getBackwardTransitions(), maybeStates, ~maybeStates)
254 lowerResultBound = storm::utility::zero<ConstantType>();
257template<
typename SparseModelType,
typename ConstantType>
261 stepBound = checkTask.
getFormula().getBound().evaluateAsInt();
263 STORM_LOG_THROW(*stepBound > 0, storm::exceptions::NotSupportedException,
"Expected a strict upper step bound that is greater than zero.");
266 STORM_LOG_THROW(*stepBound > 0, storm::exceptions::NotSupportedException,
267 "Can not apply parameter lifting on step bounded formula: The step bound has to be positive.");
271 resultsForNonMaybeStates = std::vector<ConstantType>(this->parametricModel->getNumberOfStates());
275 (!checkTask.
isRewardModelSet() && this->parametricModel->hasUniqueRewardModel()),
276 storm::exceptions::InvalidPropertyException,
"The reward model specified by the CheckTask is not available in the given model.");
277 typename SparseModelType::RewardModelType
const& rewardModel =
279 std::vector<typename SparseModelType::ValueType> b = rewardModel.getTotalRewardVector(this->parametricModel->getTransitionMatrix());
281 parameterLifter = std::make_unique<storm::transformer::ParameterLifter<typename SparseModelType::ValueType, ConstantType>>(
282 this->parametricModel->getTransitionMatrix(), b,
storm::storage::BitVector(this->parametricModel->getTransitionMatrix().getRowCount(),
true),
284 computePlayer1Matrix();
286 applyPreviousResultAsHint =
false;
289 lowerResultBound = storm::utility::zero<ConstantType>();
292template<
typename SparseModelType,
typename ConstantType>
295 if (!instantiationChecker) {
296 instantiationChecker = std::make_unique<storm::modelchecker::SparseMdpInstantiationModelChecker<SparseModelType, ConstantType>>(*this->parametricModel);
297 instantiationChecker->
specifyFormula(this->currentCheckTask->template convertValueType<typename SparseModelType::ValueType>());
298 instantiationChecker->setInstantiationsAreGraphPreserving(
true);
300 return *instantiationChecker;
303template<
typename SparseModelType,
typename ConstantType>
308 localMonotonicityResult) {
309 if (maybeStates.empty()) {
310 return std::make_unique<storm::modelchecker::ExplicitQuantitativeCheckResult<ConstantType>>(resultsForNonMaybeStates);
313 parameterLifter->specifyRegion(region, dirForParameters);
316 auto solver = solverFactory->create(env, player1Matrix, parameterLifter->getMatrix());
317 if (lowerResultBound)
318 solver->setLowerBound(lowerResultBound.get());
319 if (upperResultBound)
320 solver->setUpperBound(upperResultBound.get());
321 if (applyPreviousResultAsHint) {
322 solver->setTrackSchedulers(
true);
323 x.resize(maybeStates.getNumberOfSetBits(), storm::utility::zero<ConstantType>());
325 solver->setSchedulerHints(std::move(player1SchedChoices.get()), std::move(minSchedChoices.get()));
327 solver->setSchedulerHints(std::move(player1SchedChoices.get()), std::move(maxSchedChoices.get()));
329 x.assign(maybeStates.getNumberOfSetBits(), storm::utility::zero<ConstantType>());
331 if (this->currentCheckTask->isBoundSet() && this->currentCheckTask->getOptimizationDirection() == dirForParameters && solver->hasSchedulerHints()) {
333 std::unique_ptr<storm::solver::TerminationCondition<ConstantType>> termCond;
335 ? this->parametricModel->getInitialStates() % maybeStates
339 termCond = std::make_unique<storm::solver::TerminateIfFilteredExtremumBelowThreshold<ConstantType>>(
340 relevantStatesInSubsystem,
true, this->currentCheckTask->getBoundThreshold(),
false);
343 termCond = std::make_unique<storm::solver::TerminateIfFilteredExtremumExceedsThreshold<ConstantType>>(
344 relevantStatesInSubsystem,
true, this->currentCheckTask->getBoundThreshold(),
true);
346 solver->setTerminationCondition(std::move(termCond));
352 solver->repeatedMultiply(env, this->currentCheckTask->getOptimizationDirection(), dirForParameters, x, ¶meterLifter->getVector(), *stepBound);
354 solver->solveGame(env, this->currentCheckTask->getOptimizationDirection(), dirForParameters, x, parameterLifter->getVector());
355 if (applyPreviousResultAsHint) {
357 minSchedChoices = solver->getPlayer2SchedulerChoices();
359 maxSchedChoices = solver->getPlayer2SchedulerChoices();
361 player1SchedChoices = solver->getPlayer1SchedulerChoices();
366 std::vector<ConstantType> result = resultsForNonMaybeStates;
367 auto maybeStateResIt = x.begin();
368 for (
auto const& maybeState : maybeStates) {
369 result[maybeState] = *maybeStateResIt;
373 return std::make_unique<storm::modelchecker::ExplicitQuantitativeCheckResult<ConstantType>>(std::move(result));
376template<
typename SparseModelType,
typename ConstantType>
378 boost::optional<storm::storage::BitVector>
const& selectedRows) {
382 n = selectedRows->getNumberOfSetBits();
384 for (
auto const& maybeState : maybeStates) {
385 n += this->parametricModel->getTransitionMatrix().getRowGroupSize(maybeState);
391 uint_fast64_t p1MatrixRow = 0;
392 for (
auto maybeState : maybeStates) {
393 matrixBuilder.newRowGroup(p1MatrixRow);
395 for (uint_fast64_t row = selectedRows->getNextSetIndex(this->parametricModel->getTransitionMatrix().getRowGroupIndices()[maybeState]);
396 row < this->parametricModel->getTransitionMatrix().getRowGroupIndices()[maybeState + 1]; row = selectedRows->getNextSetIndex(row + 1)) {
397 matrixBuilder.addNextValue(p1MatrixRow, p1MatrixRow, storm::utility::one<storm::storage::sparse::state_type>());
401 for (uint_fast64_t endOfGroup = p1MatrixRow + this->parametricModel->getTransitionMatrix().getRowGroupSize(maybeState); p1MatrixRow < endOfGroup;
403 matrixBuilder.addNextValue(p1MatrixRow, p1MatrixRow, storm::utility::one<storm::storage::sparse::state_type>());
407 player1Matrix = matrixBuilder.build();
410template<
typename SparseModelType,
typename ConstantType>
412 maybeStates.resize(0);
413 resultsForNonMaybeStates.clear();
414 stepBound = boost::none;
415 instantiationChecker =
nullptr;
417 parameterLifter =
nullptr;
418 minSchedChoices = boost::none;
419 maxSchedChoices = boost::none;
421 lowerResultBound = boost::none;
422 upperResultBound = boost::none;
423 applyPreviousResultAsHint =
false;
426template<
typename SparseModelType,
typename ConstantType>
428 if (!minSchedChoices) {
433 uint_fast64_t state = 0;
434 for (
auto const& schedulerChoice : minSchedChoices.get()) {
435 result.
setChoice(schedulerChoice, state);
442template<
typename SparseModelType,
typename ConstantType>
444 if (!maxSchedChoices) {
449 uint_fast64_t state = 0;
450 for (
auto const& schedulerChoice : maxSchedChoices.get()) {
451 result.
setChoice(schedulerChoice, state);
458template<
typename SparseModelType,
typename ConstantType>
460 if (!player1SchedChoices) {
465 uint_fast64_t state = 0;
466 for (
auto const& schedulerChoice : player1SchedChoices.get()) {
467 result.
setChoice(schedulerChoice, state);
FragmentSpecification & setStepBoundedUntilFormulasAllowed(bool newValue)
FragmentSpecification & setTimeBoundedUntilFormulasAllowed(bool newValue)
FragmentSpecification & setCumulativeRewardFormulasAllowed(bool newValue)
FragmentSpecification & setReachabilityRewardFormulasAllowed(bool newValue)
FragmentSpecification & setRewardOperatorsAllowed(bool newValue)
FragmentSpecification & setBoundedUntilFormulasAllowed(bool newValue)
FragmentSpecification & setTimeBoundedCumulativeRewardFormulasAllowed(bool newValue)
FragmentSpecification & setStepBoundedCumulativeRewardFormulasAllowed(bool newValue)
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).
storm::storage::ParameterRegion< ParametricType >::VariableType VariableType
Class to efficiently check a formula on a parametric model with different parameter instantiations.
void specifyFormula(CheckTask< storm::logic::Formula, typename SparseModelType::ValueType > const &checkTask)
virtual void specifyReachabilityRewardFormula(Environment const &env, CheckTask< storm::logic::EventuallyFormula, ConstantType > const &checkTask) override
SparseMdpParameterLiftingModelChecker()
virtual storm::modelchecker::SparseInstantiationModelChecker< SparseModelType, ConstantType > & getInstantiationChecker() override
virtual void reset() override
virtual void specify(Environment const &env, std::shared_ptr< storm::models::ModelBase > parametricModel, CheckTask< storm::logic::Formula, typename SparseModelType::ValueType > const &checkTask, bool generateRegionSplitEstimates=false, bool allowModelSimplification=true) override
virtual std::unique_ptr< CheckResult > computeQuantitativeValues(Environment const &env, storm::storage::ParameterRegion< typename SparseModelType::ValueType > const ®ion, storm::solver::OptimizationDirection const &dirForParameters, std::shared_ptr< storm::analysis::LocalMonotonicityResult< typename RegionModelChecker< typename SparseModelType::ValueType >::VariableType > > localMonotonicityResult=nullptr) override
boost::optional< storm::storage::Scheduler< ConstantType > > getCurrentMaxScheduler()
virtual void specifyUntilFormula(Environment const &env, CheckTask< storm::logic::UntilFormula, ConstantType > const &checkTask) override
boost::optional< storm::storage::Scheduler< ConstantType > > getCurrentMinScheduler()
virtual void specifyBoundedUntilFormula(const CheckTask< storm::logic::BoundedUntilFormula, ConstantType > &checkTask) override
virtual void specifyCumulativeRewardFormula(const CheckTask< storm::logic::CumulativeRewardFormula, ConstantType > &checkTask) override
boost::optional< storm::storage::Scheduler< ConstantType > > getCurrentPlayer1Scheduler()
virtual bool canHandle(std::shared_ptr< storm::models::ModelBase > parametricModel, CheckTask< storm::logic::Formula, typename SparseModelType::ValueType > const &checkTask) const override
void specify_internal(Environment const &env, std::shared_ptr< SparseModelType > parametricModel, CheckTask< storm::logic::Formula, typename SparseModelType::ValueType > const &checkTask, bool skipModelSimplification)
virtual bool canHandle(CheckTask< storm::logic::Formula, SolutionType > const &checkTask) const override
Determines whether the model checker can handle the given verification task.
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.
This class defines which action is chosen in a particular state of a non-deterministic model.
void setChoice(SchedulerChoice< ValueType > const &choice, uint_fast64_t modelState, uint_fast64_t memoryState=0)
Sets the choice defined by the scheduler for the given state.
A class that can be used to build a sparse matrix by adding value by value.
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()
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< T > const &values)
Sets the provided values at the provided positions in the given vector.