41template<
typename SparseModelType,
typename ConstantType,
bool Robust>
47template<
typename SparseModelType,
typename ConstantType,
bool Robust>
50 : solverFactory(
std::move(solverFactory)), solvingRequiresUpperRewardBounds(false) {
54template<
typename SparseModelType,
typename ConstantType,
bool Robust>
61 result &=
static_cast<bool>(dtmc);
63 .setRewardOperatorsAllowed(
true)
64 .setReachabilityRewardFormulasAllowed(
true)
65 .setBoundedUntilFormulasAllowed(
true)
66 .setCumulativeRewardFormulasAllowed(
true)
67 .setStepBoundedCumulativeRewardFormulasAllowed(
true)
68 .setTimeBoundedCumulativeRewardFormulasAllowed(
true)
69 .setTimeBoundedUntilFormulasAllowed(
true)
70 .setStepBoundedUntilFormulasAllowed(
true)
71 .setTimeBoundedUntilFormulasAllowed(
true));
75template<
typename SparseModelType,
typename ConstantType,
bool Robust>
79 bool allowModelSimplifications,
bool graphPreserving) {
81 "Combination of model " <<
parametricModel->getType() <<
" and formula '" << checkTask.
getFormula() <<
"' is not supported.");
84 this->graphPreserving = graphPreserving;
86 if (isOrderBasedMonotonicityBackend()) {
88 "Allowing model simplification when using order-based monotonicity is not useful, as for order-based monotonicity checking model "
89 "simplification is done as preprocessing");
90 getOrderBasedMonotonicityBackend().initializeMonotonicityChecker(dtmc->getTransitionMatrix());
95 if (allowModelSimplifications && graphPreserving) {
97 simplifier.setPreserveParametricTransitions(
true);
98 STORM_LOG_THROW(simplifier.simplify(checkTask.
getFormula()), storm::exceptions::UnexpectedException,
"Simplifying the model was not successfull.");
99 this->parametricModel = simplifier.getSimplifiedModel();
102 this->parametricModel = dtmc;
105 if constexpr (!Robust) {
106 if (isOrderBasedMonotonicityBackend()) {
107 getOrderBasedMonotonicityBackend().registerParameterLifterReference(*parameterLifter);
108 getOrderBasedMonotonicityBackend().registerPLABoundFunction(
114 std::shared_ptr<storm::logic::Formula> formulaWithoutBounds = this->
currentCheckTask->getFormula().clone();
115 formulaWithoutBounds->asOperatorFormula().removeBound();
116 this->currentFormulaNoBound = formulaWithoutBounds->asSharedPointer();
117 this->currentCheckTaskNoBound = std::make_unique<storm::modelchecker::CheckTask<storm::logic::Formula, ParametricType>>(*this->currentFormulaNoBound);
119 this->derivativeChecker =
120 std::make_unique<storm::derivative::SparseDerivativeInstantiationModelChecker<ParametricType, ConstantType>>(*this->parametricModel);
121 this->derivativeChecker->specifyFormula(env, *this->currentCheckTaskNoBound);
125template<
typename SparseModelType,
typename ConstantType,
bool Robust>
130 STORM_LOG_THROW(!checkTask.
getFormula().hasLowerBound(), storm::exceptions::NotSupportedException,
"Lower step bounds are not supported.");
131 STORM_LOG_THROW(checkTask.
getFormula().hasUpperBound(), storm::exceptions::NotSupportedException,
"Expected a bounded until formula with an upper bound.");
133 "Expected a bounded until formula with step bounds.");
134 stepBound = checkTask.
getFormula().getUpperBound().evaluateAsInt();
135 STORM_LOG_THROW(*stepBound > 0, storm::exceptions::NotSupportedException,
136 "Can not apply parameter lifting on step bounded formula: The step bound has to be positive.");
137 if (checkTask.
getFormula().isUpperBoundStrict()) {
138 STORM_LOG_THROW(*stepBound > 0, storm::exceptions::NotSupportedException,
"Expected a strict upper step bound that is greater than zero.");
141 STORM_LOG_THROW(*stepBound > 0, storm::exceptions::NotSupportedException,
142 "Can not apply parameter lifting on step bounded formula: The step bound has to be positive.");
148 storm::exceptions::NotSupportedException,
"Parameter lifting with non-propositional subformulas is not supported.");
150 ->template asExplicitQualitativeCheckResult<typename SparseModelType::ValueType>()
151 .getTruthValuesVector());
153 ->template asExplicitQualitativeCheckResult<typename SparseModelType::ValueType>()
154 .getTruthValuesVector());
158 maybeStates &= ~psiStates;
165 if (Robust || !maybeStates.empty()) {
167 std::vector<ParametricType> b = this->
parametricModel->getTransitionMatrix().getConstrainedRowSumVector(
169 parameterLifter = std::make_unique<ParameterLifterType<ParametricType, ConstantType, Robust>>(
170 this->
parametricModel->getTransitionMatrix(), b, maybeStates, maybeStates,
false, isOrderBasedMonotonicityBackend());
177 solverFactory->setRequirementsChecked(
true);
179 if (isOrderBasedMonotonicityBackend()) {
181 getOrderBasedMonotonicityBackend().initializeOrderExtender(prob1, prob0, this->
parametricModel->getTransitionMatrix());
185template<
typename SparseModelType,
typename ConstantType,
bool Robust>
192 storm::exceptions::NotSupportedException,
"Parameter lifting with non-propositional subformulas is not supported.");
194 ->template asExplicitQualitativeCheckResult<typename SparseModelType::ValueType>()
195 .getTruthValuesVector());
197 ->template asExplicitQualitativeCheckResult<typename SparseModelType::ValueType>()
198 .getTruthValuesVector());
201 std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01 =
203 maybeStates = ~(statesWithProbability01.first | statesWithProbability01.second);
210 if (Robust || !maybeStates.empty()) {
211 if constexpr (Robust) {
217 if (!graphPreserving) {
219 maybeStates = ~statesWithProbability01.first & ~psiStates;
225 auto rowFilter = this->
parametricModel->getTransitionMatrix().getRowFilter(maybeStates);
226 auto filteredMatrix = this->
parametricModel->getTransitionMatrix().filterEntries(rowFilter);
228 maybeStates = allTrue;
230 parameterLifter = std::make_unique<ParameterLifterType<ParametricType, ConstantType, Robust>>(
231 filteredMatrix, target, allTrue, allTrue, isValueDeltaRegionSplitEstimates(), isOrderBasedMonotonicityBackend());
234 std::vector<ParametricType> b = this->
parametricModel->getTransitionMatrix().getConstrainedRowSumVector(
236 parameterLifter = std::make_unique<ParameterLifterType<ParametricType, ConstantType, Robust>>(
237 this->
parametricModel->getTransitionMatrix(), b, maybeStates, maybeStates, isValueDeltaRegionSplitEstimates(),
238 isOrderBasedMonotonicityBackend());
248 auto req = solverFactory->getRequirements(env,
true,
true, boost::none, !Robust);
250 STORM_LOG_THROW(!req.hasEnabledCriticalRequirement(), storm::exceptions::UncheckedRequirementException,
251 "Solver requirements " + req.getEnabledRequirementsAsString() +
" not checked.");
252 solverFactory->setRequirementsChecked(
true);
254 if (isOrderBasedMonotonicityBackend()) {
255 getOrderBasedMonotonicityBackend().initializeOrderExtender(statesWithProbability01.second, statesWithProbability01.first,
256 this->parametricModel->getTransitionMatrix());
260template<
typename SparseModelType,
typename ConstantType,
bool Robust>
266 "Parameter lifting with non-propositional subformulas is not supported.");
268 ->template asExplicitQualitativeCheckResult<typename SparseModelType::ValueType>()
269 .getTruthValuesVector());
274 maybeStates = ~(targetStates | infinityStates);
281 if (Robust || !maybeStates.empty()) {
284 (!checkTask.
isRewardModelSet() && this->parametricModel->hasUniqueRewardModel()),
285 storm::exceptions::InvalidPropertyException,
"The reward model specified by the CheckTask is not available in the given model.");
287 typename SparseModelType::RewardModelType
const& rewardModel =
290 std::vector<ParametricType> b = rewardModel.getTotalRewardVector(this->
parametricModel->getTransitionMatrix());
292 if constexpr (Robust) {
294 if (!graphPreserving) {
295 maybeStates = ~targetStates;
297 auto rowFilter = this->
parametricModel->getTransitionMatrix().getRowFilter(maybeStates);
298 auto filteredMatrix = this->
parametricModel->getTransitionMatrix().filterEntries(rowFilter);
299 maybeStates = allTrue;
301 parameterLifter = std::make_unique<ParameterLifterType<ParametricType, ConstantType, Robust>>(
302 filteredMatrix, b, allTrue, allTrue, isValueDeltaRegionSplitEstimates(), isOrderBasedMonotonicityBackend());
304 parameterLifter = std::make_unique<ParameterLifterType<ParametricType, ConstantType, Robust>>(
305 this->
parametricModel->getTransitionMatrix(), b, maybeStates, maybeStates, isValueDeltaRegionSplitEstimates(),
306 isOrderBasedMonotonicityBackend());
315 auto req = solverFactory->getRequirements(env,
true,
true, boost::none, !Robust);
316 req.clearLowerBounds();
317 if (req.upperBounds()) {
318 solvingRequiresUpperRewardBounds =
true;
319 req.clearUpperBounds();
321 STORM_LOG_THROW(!req.hasEnabledCriticalRequirement(), storm::exceptions::UncheckedRequirementException,
322 "Solver requirements " + req.getEnabledRequirementsAsString() +
" not checked.");
323 solverFactory->setRequirementsChecked(
true);
324 STORM_LOG_WARN_COND(!isOrderBasedMonotonicityBackend(),
"Order-based monotonicity not used for reachability reward formula.");
327template<
typename SparseModelType,
typename ConstantType,
bool Robust>
332 stepBound = checkTask.
getFormula().getBound().evaluateAsInt();
334 STORM_LOG_THROW(*stepBound > 0, storm::exceptions::NotSupportedException,
"Expected a strict upper step bound that is greater than zero.");
337 STORM_LOG_THROW(*stepBound > 0, storm::exceptions::NotSupportedException,
338 "Can not apply parameter lifting on step bounded formula: The step bound has to be positive.");
342 resultsForNonMaybeStates = std::vector<ConstantType>(this->
parametricModel->getNumberOfStates());
346 (!checkTask.
isRewardModelSet() && this->parametricModel->hasUniqueRewardModel()),
347 storm::exceptions::InvalidPropertyException,
"The reward model specified by the CheckTask is not available in the given model.");
348 typename SparseModelType::RewardModelType
const& rewardModel =
350 std::vector<ParametricType> b = rewardModel.getTotalRewardVector(this->
parametricModel->getTransitionMatrix());
353 std::make_unique<ParameterLifterType<ParametricType, ConstantType, Robust>>(this->
parametricModel->getTransitionMatrix(), b, maybeStates, maybeStates);
358 solverFactory->setRequirementsChecked(
true);
360 STORM_LOG_WARN_COND(!isOrderBasedMonotonicityBackend(),
"Order-based monotonicity not used for cumulative reward formula.");
363template<
typename SparseModelType,
typename ConstantType,
bool Robust>
366 if (!instantiationCheckerSAT) {
367 instantiationCheckerSAT =
368 std::make_unique<storm::modelchecker::SparseDtmcInstantiationModelChecker<SparseModelType, ConstantType>>(*this->
parametricModel);
369 instantiationCheckerSAT->specifyFormula(quantitative ? *this->currentCheckTaskNoBound
371 instantiationCheckerSAT->setInstantiationsAreGraphPreserving(
true);
373 return *instantiationCheckerSAT;
376template<
typename SparseModelType,
typename ConstantType,
bool Robust>
379 if (!instantiationCheckerVIO) {
380 instantiationCheckerVIO =
381 std::make_unique<storm::modelchecker::SparseDtmcInstantiationModelChecker<SparseModelType, ConstantType>>(*this->
parametricModel);
382 instantiationCheckerVIO->specifyFormula(quantitative ? *this->currentCheckTaskNoBound
384 instantiationCheckerVIO->setInstantiationsAreGraphPreserving(
true);
386 return *instantiationCheckerVIO;
389template<
typename SparseModelType,
typename ConstantType,
bool Robust>
392 if (!instantiationChecker) {
393 instantiationChecker =
394 std::make_unique<storm::modelchecker::SparseDtmcInstantiationModelChecker<SparseModelType, ConstantType>>(*this->
parametricModel);
395 instantiationChecker->specifyFormula(quantitative ? *this->currentCheckTaskNoBound
397 instantiationChecker->setInstantiationsAreGraphPreserving(
true);
399 return *instantiationChecker;
402template<
typename SparseModelType,
typename ConstantType,
bool Robust>
405 if (maybeStates.empty()) {
407 return resultsForNonMaybeStates;
409 parameterLifter->specifyRegion(
region.region, dirForParameters);
410 auto liftedMatrix = parameterLifter->getMatrix();
411 auto liftedVector = parameterLifter->getVector();
412 bool nonTrivialEndComponents =
false;
413 if constexpr (Robust) {
414 if (parameterLifter->isCurrentRegionAllIllDefined()) {
415 return std::vector<ConstantType>();
417 if (!graphPreserving) {
419 auto const& result = endComponentPreserver.
eliminateMECs(liftedMatrix, liftedVector);
421 liftedMatrix = *result;
422 nonTrivialEndComponents =
true;
426 const uint64_t resultVectorSize = liftedMatrix.getColumnCount();
429 if constexpr (!Robust) {
433 multiplier->repeatedMultiplyAndReduce(env, dirForParameters, x, &liftedVector, *stepBound);
438 auto solver = solverFactory->create(env, liftedMatrix);
439 solver->setHasUniqueSolution();
440 solver->setHasNoEndComponents();
442 solver->setUncertaintyResolutionMode(UncertaintyResolutionMode::Cooperative);
443 if (lowerResultBound) {
444 solver->setLowerBound(lowerResultBound.value());
446 if (upperResultBound) {
447 solver->setUpperBound(upperResultBound.value());
448 }
else if (solvingRequiresUpperRewardBounds) {
449 if constexpr (!Robust) {
451 std::vector<ConstantType> oneStepProbs;
452 oneStepProbs.reserve(liftedMatrix.getRowCount());
453 for (uint64_t row = 0; row < liftedMatrix.getRowCount(); ++row) {
456 if (dirForParameters == storm::OptimizationDirection::Minimize) {
467 solver->setTrackScheduler(
true);
473 if constexpr (!Robust) {
475 if (isOrderBasedMonotonicityBackend()) {
477 if (!choices.has_value()) {
478 choices.emplace(parameterLifter->getRowGroupCount(), 0u);
480 statesWithFixedChoice = getOrderBasedMonotonicityBackend().getChoicesToFixForPLASolver(
region, dirForParameters, *choices);
484 if (choices.has_value()) {
485 solver->setInitialScheduler(std::move(choices.value()));
486 if (statesWithFixedChoice.
size() != 0) {
488 solver->setSchedulerFixedForRowGroup(std::move(statesWithFixedChoice));
493 if (!nonTrivialEndComponents && choices.has_value()) {
494 solver->setInitialScheduler(std::move(choices.value()));
501 std::unique_ptr<storm::solver::TerminationCondition<ConstantType>> termCond;
507 termCond = std::make_unique<storm::solver::TerminateIfFilteredExtremumBelowThreshold<ConstantType>>(
508 relevantStatesInSubsystem,
true, this->
currentCheckTask->getBoundThreshold(),
false);
511 termCond = std::make_unique<storm::solver::TerminateIfFilteredExtremumExceedsThreshold<ConstantType>>(
512 relevantStatesInSubsystem,
true, this->
currentCheckTask->getBoundThreshold(),
true);
514 solver->setTerminationCondition(std::move(termCond));
519 solver->solveEquations(env, dirForParameters, x, liftedVector);
520 if (isValueDeltaRegionSplitEstimates()) {
524 if (!nonTrivialEndComponents) {
525 choices =
solver->getSchedulerChoices();
530 std::vector<ConstantType> result = resultsForNonMaybeStates;
531 auto maybeStateResIt = x.begin();
532 for (uint64_t maybeState : maybeStates) {
533 result[maybeState] = *maybeStateResIt;
537 STORM_LOG_INFO(dirForParameters <<
" " <<
region.region <<
": " << result[this->getUniqueInitialState()]);
543template<
typename SparseModelType,
typename ConstantType,
bool Robust>
545 Environment const& env, std::vector<ConstantType>
const& quantitativeResult, std::vector<uint64_t>
const& schedulerChoices,
547 auto const& matrix = parameterLifter->getMatrix();
548 auto const& vector = parameterLifter->getVector();
555 auto const instantiatedModel = instantiator.
instantiate(
region.getCenterPoint());
558 uint64_t rowIndex = 0;
559 for (uint64_t state : maybeStates) {
560 weighting[rowIndex++] = visitingTimes[state];
567 std::map<VariableType, ConstantType> deltaLower, deltaUpper;
568 for (
auto const& p :
region.getVariables()) {
572 if constexpr (Robust) {
574 static std::map<RationalFunction, RationalFunction> functionDerivatives;
575 static std::vector<std::pair<bool, double>> constantDerivatives;
576 if (constantDerivatives.empty()) {
577 for (uint64_t state : maybeStates) {
578 auto variables = parameterLifter->getOccurringVariablesAtState().at(state);
579 if (variables.size() == 0) {
583 "Cannot compute state-value-delta split estimates in robust mode if there are states with multiple parameters.");
584 auto const p = *variables.begin();
585 for (
auto const& entry : this->
parametricModel->getTransitionMatrix().getRow(state)) {
586 auto const& function = entry.getValue();
587 if (functionDerivatives.count(function)) {
588 constantDerivatives.emplace_back(
false, 0);
591 auto const derivative = function.derivative(p);
595 functionDerivatives.emplace(function,
derivative);
596 constantDerivatives.emplace_back(
false, 0);
598 constantDerivatives.emplace_back(
false, 0);
604 cachedRegionSplitEstimates.clear();
605 for (
auto const& p :
region.getVariables()) {
609 uint64_t entryCount = 0;
611 for (uint64_t state : maybeStates) {
612 auto variables = parameterLifter->getOccurringVariablesAtState().at(state);
613 if (variables.size() == 0) {
617 "Cannot compute state-value-delta split estimates in robust mode if there are states with multiple parameters.");
619 auto const p = *variables.begin();
621 const uint64_t rowIndex = maybeStates.getNumberOfSetBitsBeforeIndex(state);
623 std::vector<ConstantType> derivatives;
624 for (
auto const& entry : this->
parametricModel->getTransitionMatrix().getRow(state)) {
631 auto const& cDer = constantDerivatives.at(entryCount);
633 derivatives.push_back(cDer.second);
642 std::vector<ConstantType> results(0);
647 for (
auto const& direction : {OptimizationDirection::Maximize, OptimizationDirection::Minimize}) {
656 "Non-constant vector indices not supported (this includes parametric rewards).");
658 std::vector<std::pair<ConstantType, std::pair<ConstantType, uint64_t>>> robustOrder;
661 for (
auto const& entry : matrix.getRow(rowIndex)) {
662 auto const lower = entry.getValue().lower();
663 result += quantitativeResult[entry.getColumn()] * lower;
664 remainingValue -= lower;
665 auto const diameter = entry.getValue().upper() - lower;
667 robustOrder.emplace_back(quantitativeResult[entry.getColumn()], std::make_pair(diameter, index));
672 std::sort(robustOrder.begin(), robustOrder.end(),
673 [direction](
const std::pair<ConstantType, std::pair<ConstantType, uint64_t>>& a,
674 const std::pair<ConstantType, std::pair<ConstantType, uint64_t>>& b) {
675 if (direction == OptimizationDirection::Maximize) {
676 return a.first > b.first;
678 return a.first < b.first;
682 for (
auto const& pair : robustOrder) {
683 auto availableMass = std::min(pair.second.first, remainingValue);
684 result += availableMass * pair.first;
687 if (derivatives[pair.second.second] > 1e-6) {
688 distrToPositiveDerivative += availableMass;
689 }
else if (derivatives[pair.second.second] < 1e-6) {
690 distrToNegativeDerivative += availableMass;
693 remainingValue -= availableMass;
696 results.push_back(result);
699 ConstantType diff = std::abs(results[0] - results[1]);
700 if (distrToPositiveDerivative > distrToNegativeDerivative) {
701 deltaUpper[p] += diff * weighting[rowIndex];
703 deltaLower[p] += diff * weighting[rowIndex];
707 auto const& choiceValuations = parameterLifter->getRowLabels();
709 std::vector<ConstantType> stateResults;
710 for (uint64_t state = 0; state < schedulerChoices.size(); ++state) {
711 uint64_t rowOffset = matrix.getRowGroupIndices()[state];
712 uint64_t optimalChoice = schedulerChoices[state];
713 auto const& optimalChoiceVal = choiceValuations[rowOffset + optimalChoice];
714 STORM_LOG_ASSERT(optimalChoiceVal.getUnspecifiedParameters().empty(),
"Expected no unspecified parameters.");
715 stateResults.clear();
716 for (uint64_t row = rowOffset; row < matrix.getRowGroupIndices()[state + 1]; ++row) {
717 stateResults.push_back(matrix.multiplyRowWithVector(row, quantitativeResult) + vector[row]);
720 bool checkUpperParameters =
false;
722 auto const& consideredParameters = checkUpperParameters ? optimalChoiceVal.getUpperParameters() : optimalChoiceVal.getLowerParameters();
723 for (
auto const& p : consideredParameters) {
725 ConstantType bestValue = 0;
726 bool foundBestValue =
false;
727 for (uint64_t choice = 0; choice < stateResults.size(); ++choice) {
728 if (choice != optimalChoice) {
729 auto const& otherBoundParsOfChoice = checkUpperParameters ? choiceValuations[rowOffset + choice].getLowerParameters()
730 : choiceValuations[rowOffset + choice].getUpperParameters();
731 if (otherBoundParsOfChoice.find(p) != otherBoundParsOfChoice.end()) {
732 ConstantType
const& choiceValue = stateResults[choice];
733 if (!foundBestValue ||
735 foundBestValue =
true;
736 bestValue = choiceValue;
741 auto const& optimal = stateResults[optimalChoice];
743 if (foundBestValue) {
744 if (checkUpperParameters) {
745 deltaLower[p] += diff * weighting[state];
747 deltaUpper[p] += diff * weighting[state];
751 checkUpperParameters = !checkUpperParameters;
752 }
while (checkUpperParameters);
756 cachedRegionSplitEstimates.clear();
757 for (
auto const& p :
region.getVariables()) {
759 auto minDelta = std::min(deltaLower[p], deltaUpper[p]);
760 cachedRegionSplitEstimates.emplace(p, minDelta);
769 instantiationModelChecker.
specifyFormula(*this->currentCheckTaskNoBound);
771 auto const center =
region.getCenterPoint();
773 std::unique_ptr<storm::modelchecker::CheckResult> result = instantiationModelChecker.
check(env, center);
774 auto const reachabilityProbabilities = result->asExplicitQuantitativeCheckResult<ConstantType>().getValueVector();
776 STORM_LOG_ASSERT(this->derivativeChecker,
"Derivative checker not intialized.");
778 for (
auto const& param :
region.getVariables()) {
779 auto result = this->derivativeChecker->check(env, center, param, reachabilityProbabilities);
781 result->template asExplicitQuantitativeCheckResult<ConstantType>().getValueVector()[this->derivativeChecker->getInitialState()];
787 STORM_LOG_ERROR(
"Region split estimate kind not handled by SparseDtmcParameterLiftingModelChecker.");
791template<
typename SparseModelType,
typename ConstantType,
bool Robust>
793 maybeStates.resize(0);
794 resultsForNonMaybeStates.clear();
795 stepBound = std::nullopt;
796 instantiationChecker =
nullptr;
797 instantiationCheckerSAT =
nullptr;
798 instantiationCheckerVIO =
nullptr;
799 parameterLifter =
nullptr;
800 minSchedChoices = std::nullopt;
801 maxSchedChoices = std::nullopt;
803 lowerResultBound = std::nullopt;
804 upperResultBound = std::nullopt;
805 cachedRegionSplitEstimates.clear();
808template<
typename ConstantType>
809std::optional<storm::storage::Scheduler<ConstantType>>
getSchedulerHelper(std::optional<std::vector<uint64_t>>
const& choices) {
810 std::optional<storm::storage::Scheduler<ConstantType>> result;
812 result.emplace(choices->size());
814 for (
auto const& choice : choices.value()) {
815 result->setChoice(choice, state);
822template<
typename SparseModelType,
typename ConstantType,
bool Robust>
827template<
typename SparseModelType,
typename ConstantType,
bool Robust>
843 return sub.
isUntilFormula() || sub.isEventuallyFormula() || sub.isBoundedUntilFormula();
848template<
typename SparseModelType,
typename ConstantType,
bool Robust>
857template<
typename SparseModelType,
typename ConstantType,
bool Robust>
864template<
typename SparseModelType,
typename ConstantType,
bool Robust>
865std::vector<typename SparseDtmcParameterLiftingModelChecker<SparseModelType, ConstantType, Robust>::CoefficientType>
867 std::set<VariableType>
const& relevantParameters)
const {
868 if (isValueDeltaRegionSplitEstimates()) {
870 std::vector<CoefficientType> result;
871 for (
auto const& par : relevantParameters) {
872 auto est = cachedRegionSplitEstimates.find(par);
874 "Requested region split estimate for parameter " << par.name() <<
" but none was generated.");
884template<
typename SparseModelType,
typename ConstantType,
bool Robust>
895template<
typename SparseModelType,
typename ConstantType,
bool Robust>
896bool SparseDtmcParameterLiftingModelChecker<SparseModelType, ConstantType, Robust>::isOrderBasedMonotonicityBackend()
const {
900template<
typename SparseModelType,
typename ConstantType,
bool Robust>
901OrderBasedMonotonicityBackend<typename SparseModelType::ValueType, ConstantType>&
902SparseDtmcParameterLiftingModelChecker<SparseModelType, ConstantType, Robust>::getOrderBasedMonotonicityBackend() {
903 return dynamic_cast<OrderBasedMonotonicityBackend<ParametricType, ConstantType>&
>(*this->monotonicityBackend);
906template<
typename SparseModelType,
typename ConstantType,
bool Robust>
907bool SparseDtmcParameterLiftingModelChecker<SparseModelType, ConstantType, Robust>::isValueDeltaRegionSplitEstimates()
const {
908 return this->getSpecifiedRegionSplitEstimateKind().has_value() &&
909 (this->getSpecifiedRegionSplitEstimateKind().value() == RegionSplitEstimateKind::StateValueDelta ||
910 this->getSpecifiedRegionSplitEstimateKind().value() == RegionSplitEstimateKind::StateValueDeltaWeighted ||
911 this->getSpecifiedRegionSplitEstimateKind().value() == RegionSplitEstimateKind::Derivative);
914template class SparseDtmcParameterLiftingModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double,
false>;
915template class SparseDtmcParameterLiftingModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double,
true>;
916template class SparseDtmcParameterLiftingModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, storm::RationalNumber,
false>;
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.
virtual bool requiresInteractionWithRegionModelChecker() const
Returns true, if a region model checker needs to implement specific methods to properly use this back...
virtual bool isRegionSplitEstimateKindSupported(RegionSplitEstimateKind kind, CheckTask< storm::logic::Formula, ParametricType > const &checkTask) const
virtual RegionSplitEstimateKind getDefaultRegionSplitEstimateKind(CheckTask< storm::logic::Formula, ParametricType > const &checkTask) const
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 std::vector< CoefficientType > obtainRegionSplitEstimates(std::set< VariableType > const &relevantParameters) const
Returns an estimate of the benefit of splitting the last checked region with respect to each of the g...
virtual void specifySplitEstimates(std::optional< RegionSplitEstimateKind > splitEstimates, CheckTask< storm::logic::Formula, SparseModelType::ValueType > const &checkTask)
std::optional< RegionSplitEstimateKind > specifiedRegionSplitEstimateKind
Class to efficiently check a formula on a parametric model with different parameter instantiations.
virtual std::unique_ptr< CheckResult > check(Environment const &env, storm::utility::parametric::Valuation< typename SparseModelType::ValueType > const &valuation) override
std::optional< storm::storage::Scheduler< ConstantType > > getCurrentMinScheduler()
virtual bool isRegionSplitEstimateKindSupported(RegionSplitEstimateKind kind, CheckTask< storm::logic::Formula, ParametricType > const &checkTask) const override
typename RegionModelChecker< ParametricType >::CoefficientType CoefficientType
virtual std::vector< CoefficientType > obtainRegionSplitEstimates(std::set< VariableType > const &relevantParameters) const override
Returns an estimate of the benefit of splitting the last checked region with respect to each of the g...
virtual storm::modelchecker::SparseInstantiationModelChecker< SparseModelType, ConstantType > & getInstantiationCheckerSAT(bool qualitative) override
virtual RegionSplitEstimateKind getDefaultRegionSplitEstimateKind(CheckTask< storm::logic::Formula, ParametricType > const &checkTask) const override
virtual bool canHandle(std::shared_ptr< storm::models::ModelBase > parametricModel, CheckTask< storm::logic::Formula, ParametricType > const &checkTask) const override
virtual storm::modelchecker::SparseInstantiationModelChecker< SparseModelType, ConstantType > & getInstantiationCheckerVIO(bool qualitative) override
SparseDtmcParameterLiftingModelChecker()
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, bool graphPreserving=true) override
virtual void specifyBoundedUntilFormula(const CheckTask< storm::logic::BoundedUntilFormula, ConstantType > &checkTask) override
virtual std::vector< ConstantType > computeQuantitativeValues(Environment const &env, AnnotatedRegion< ParametricType > ®ion, storm::solver::OptimizationDirection const &dirForParameters) override
virtual void specifyCumulativeRewardFormula(const CheckTask< storm::logic::CumulativeRewardFormula, ConstantType > &checkTask) override
void computeStateValueDeltaRegionSplitEstimates(Environment const &env, std::vector< ConstantType > const &quantitativeResult, std::vector< uint64_t > const &schedulerChoices, storm::storage::ParameterRegion< ParametricType > const ®ion, storm::solver::OptimizationDirection const &dirForParameters)
std::optional< storm::storage::Scheduler< ConstantType > > getCurrentMaxScheduler()
virtual void specifyReachabilityRewardFormula(Environment const &env, CheckTask< storm::logic::EventuallyFormula, ConstantType > const &checkTask) 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 storm::modelchecker::SparseInstantiationModelChecker< SparseModelType, ConstantType > & getInstantiationChecker(bool qualitative) override
virtual void specifyUntilFormula(Environment const &env, CheckTask< storm::logic::UntilFormula, ConstantType > const &checkTask) override
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)
std::unique_ptr< CheckTask< storm::logic::Formula, ConstantType > > currentCheckTask
void specifyFormula(Environment const &env, CheckTask< storm::logic::Formula, ParametricType > const &checkTask)
void updateKnownValueBoundInRegion(AnnotatedRegion< ParametricType > ®ion, storm::solver::OptimizationDirection dir, std::vector< ConstantType > const &newValues)
std::shared_ptr< SparseModelType > parametricModel
virtual bool canHandle(CheckTask< storm::logic::Formula, SolutionType > const &checkTask) const override
Bounds computeTotalRewardBounds(std::vector< ValueType > const &rewards)
Computes a lower and an upper bound on the expected total rewards.
std::vector< ValueType > computeUpperBounds()
Computes upper bounds on the expected rewards.
Helper class for computing for each state the expected number of times to visit that state assuming a...
std::vector< ValueType > computeExpectedVisitingTimes(Environment const &env, storm::storage::BitVector const &initialStates)
Computes for each state the expected number of times we are visiting that state assuming the given in...
std::unique_ptr< Multiplier< ValueType, SolutionType > > create(Environment const &env, storm::storage::SparseMatrix< ValueType > const &matrix)
A bit vector that is internally represented as a vector of 64-bit values.
void complement()
Negates all bits in the bit vector.
size_t size() const
Retrieves the number of bits this bit vector can store.
This class allows efficient instantiation of the given parametric model.
ConstantSparseModelType const & instantiate(storm::utility::parametric::Valuation< ParametricType > const &valuation)
Evaluates the occurring parametric functions and retrieves the instantiated model.
#define STORM_LOG_INFO(message)
#define STORM_LOG_ERROR(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_WARN_COND(cond, message)
#define STORM_LOG_ERROR_COND(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
FragmentSpecification reachability()
bool supportsStateValueDeltaEstimates(storm::logic::Formula const &f)
bool supportsOrderBasedMonotonicity(storm::logic::Formula const &f)
@ StateValueDeltaWeighted
std::optional< storm::storage::Scheduler< ConstantType > > getSchedulerHelper(std::optional< std::vector< uint64_t > > const &choices)
std::conditional_t< Robust, storm::solver::MinMaxLinearEquationSolverFactory< storm::Interval, ConstantType >, storm::solver::MinMaxLinearEquationSolverFactory< ConstantType > > SolverFactoryType
std::conditional_t< Robust, storm::solver::GeneralMinMaxLinearEquationSolverFactory< storm::Interval, ConstantType >, storm::solver::GeneralMinMaxLinearEquationSolverFactory< ConstantType > > GeneralSolverFactoryType
bool constexpr minimize(OptimizationDirection d)
std::pair< storm::storage::BitVector, storm::storage::BitVector > performProb01(storm::models::sparse::DeterministicModel< T > const &model, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Computes the sets of states that have probability 0 or 1, respectively, of satisfying phi until psi i...
storm::storage::BitVector performProbGreater0(storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, bool useStepBound, uint_fast64_t maximalSteps)
Performs a backward depth-first search trough the underlying graph structure of the given model to de...
storm::storage::BitVector performProb1(storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &, storm::storage::BitVector const &psiStates, storm::storage::BitVector const &statesWithProbabilityGreater0)
Computes the set of states of the given model for which all paths lead to the given set of target sta...
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.
bool isZero(ValueType const &a)
ValueType abs(ValueType const &number)
TargetType convertNumber(SourceType const &number)
solver::OptimizationDirection OptimizationDirection