29template<
typename SparseModelType>
32 std::shared_ptr<SparseModelType> model;
33 std::optional<storm::storage::SparseModelMemoryProductReverseData> memoryIncorporationReverseData;
39 if (produceScheduler) {
40 std::tie(model, memoryIncorporationReverseData) =
47 STORM_LOG_THROW(!produceScheduler, storm::exceptions::NotImplementedException,
"Cannot produce schedulers for the provided memory pattern.");
50 STORM_LOG_THROW(!produceScheduler, storm::exceptions::NotImplementedException,
"Cannot produce schedulers for the provided memory pattern.");
52 }
else if (schedRestr.isPositional()) {
53 model = std::make_shared<SparseModelType>(originalModel);
55 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"The given scheduler restriction has not been implemented.");
58 if (produceScheduler) {
59 std::tie(model, memoryIncorporationReverseData) =
67 boost::optional<std::string> deadlockLabel;
68 if (!produceScheduler) {
70 removeIrrelevantStates(model, deadlockLabel, originalFormula);
73 PreprocessorData data(model);
74 data.deadlockLabel = deadlockLabel;
75 data.memoryIncorporationReverseData = std::move(memoryIncorporationReverseData);
81 data.objectives.back()->originalFormula = subFormula;
82 data.finiteRewardCheckObjectives.
resize(data.objectives.size(),
false);
83 STORM_LOG_THROW(data.objectives.back()->originalFormula->isOperatorFormula(), storm::exceptions::InvalidPropertyException,
84 "Could not preprocess the subformula " << *subFormula <<
" of " << originalFormula <<
" because it is not supported.");
85 preprocessOperatorFormula(data.objectives.back()->originalFormula->asOperatorFormula(), data);
89 std::set<std::string> relevantRewardModels;
90 for (
auto const& obj : data.objectives) {
91 obj->formula->gatherReferencedRewardModels(relevantRewardModels);
93 data.model->restrictRewardModels(relevantRewardModels);
96 return buildResult(originalModel, originalFormula, data);
99template<
typename SparseModelType>
109template<
typename SparseModelType>
110void SparseMultiObjectivePreprocessor<SparseModelType>::removeIrrelevantStates(std::shared_ptr<SparseModelType>& model,
111 boost::optional<std::string>& deadlockLabel,
121 STORM_LOG_THROW(opFormula->isOperatorFormula(), storm::exceptions::InvalidPropertyException,
122 "Could not preprocess the subformula " << *opFormula <<
" of " << originalFormula <<
" because it is not supported.");
123 auto const& pathFormula = opFormula->asOperatorFormula().getSubformula();
124 if (opFormula->isProbabilityOperatorFormula()) {
125 if (pathFormula.isUntilFormula()) {
127 mc.check(pathFormula.asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
129 mc.check(pathFormula.asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
132 }
else if (pathFormula.isBoundedUntilFormula()) {
133 if (pathFormula.asBoundedUntilFormula().hasMultiDimensionalSubformulas()) {
136 for (uint64_t i = 0; i < pathFormula.asBoundedUntilFormula().getDimension(); ++i) {
137 auto subPathFormula = pathFormula.asBoundedUntilFormula().restrictToDimension(i);
138 auto lhs = mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula(i))
139 ->template asExplicitQualitativeCheckResult<ValueType>()
140 .getTruthValuesVector();
141 auto rhs = mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula(i))
142 ->template asExplicitQualitativeCheckResult<ValueType>()
143 .getTruthValuesVector();
145 if (pathFormula.asBoundedUntilFormula().hasLowerBound(i)) {
150 absorbingStatesForSubformula &= absorbingStatesForSubSubformula;
153 auto lhs = mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula())
154 ->template asExplicitQualitativeCheckResult<ValueType>()
155 .getTruthValuesVector();
156 auto rhs = mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula())
157 ->template asExplicitQualitativeCheckResult<ValueType>()
158 .getTruthValuesVector();
160 if (pathFormula.asBoundedUntilFormula().hasLowerBound()) {
166 }
else if (pathFormula.isGloballyFormula()) {
168 mc.check(pathFormula.asGloballyFormula().getSubformula())->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
172 }
else if (pathFormula.isEventuallyFormula()) {
174 mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
178 STORM_LOG_THROW(
false, storm::exceptions::InvalidPropertyException,
"The subformula of " << pathFormula <<
" is not supported.");
180 }
else if (opFormula->isRewardOperatorFormula()) {
181 auto const& baseRewardModel = opFormula->asRewardOperatorFormula().hasRewardModelName()
182 ? model->getRewardModel(opFormula->asRewardOperatorFormula().getRewardModelName())
183 : model->getUniqueRewardModel();
184 if (pathFormula.isEventuallyFormula()) {
186 storm::storage::BitVector statesWithoutReward = rewardModel.get().getStatesWithZeroReward(model->getTransitionMatrix());
190 mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
193 model->getTransitionMatrix(), model->getTransitionMatrix().getRowGroupIndices(), backwardTransitions, statesWithoutReward, phi);
196 }
else if (pathFormula.isCumulativeRewardFormula()) {
199 storm::storage::BitVector statesWithoutReward = rewardModel.
get().getStatesWithZeroReward(model->getTransitionMatrix());
201 }
else if (pathFormula.isTotalRewardFormula()) {
203 storm::storage::BitVector statesWithoutReward = rewardModel.
get().getStatesWithZeroReward(model->getTransitionMatrix());
205 }
else if (pathFormula.isLongRunAverageRewardFormula()) {
208 storm::storage::BitVector statesWithoutReward = rewardModel.
get().getStatesWithZeroReward(model->getTransitionMatrix());
211 absorbingStatesForSubformula =
213 storm::storage::BitVector(model->getNumberOfStates(),
true), forallGloballyStatesWithoutReward);
215 STORM_LOG_THROW(
false, storm::exceptions::InvalidPropertyException,
"The subformula of " << pathFormula <<
" is not supported.");
217 }
else if (opFormula->isTimeOperatorFormula()) {
218 if (pathFormula.isEventuallyFormula()) {
220 mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
223 STORM_LOG_THROW(
false, storm::exceptions::InvalidPropertyException,
"The subformula of " << pathFormula <<
" is not supported.");
225 }
else if (opFormula->isLongRunAverageOperatorFormula()) {
226 auto lraStates = mc.check(pathFormula)->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
230 backwardTransitions, ~lraStates, forallGloballyNotLraStates);
233 "Could not preprocess the subformula " << *opFormula <<
" of " << originalFormula <<
" because it is not supported.");
235 absorbingStates &= absorbingStatesForSubformula;
236 if (absorbingStates.empty()) {
241 if (!absorbingStates.empty()) {
243 storm::storage::BitVector subsystemActions(model->getNumberOfChoices(),
true);
244 for (uint64_t absorbingState : absorbingStates) {
245 for (uint64_t action = model->getTransitionMatrix().getRowGroupIndices()[absorbingState];
246 action < model->getTransitionMatrix().getRowGroupIndices()[absorbingState + 1]; ++action) {
247 subsystemActions.set(action,
false);
250 storm::transformer::SubsystemBuilderOptions options;
252 auto const& submodel =
254 STORM_LOG_INFO(
"Making states absorbing reduced the state space from " << model->getNumberOfStates() <<
" to " << submodel.model->getNumberOfStates()
256 model = submodel.model->template as<SparseModelType>();
257 deadlockLabel = submodel.deadlockLabel;
261template<
typename SparseModelType>
262SparseMultiObjectivePreprocessor<SparseModelType>::PreprocessorData::PreprocessorData(std::shared_ptr<SparseModelType> model) : model(model) {
264 rewardModelNamePrefix =
"obj";
266 bool prefixIsUnique =
true;
267 for (
auto const& rewardModels : model->getRewardModels()) {
268 if (rewardModelNamePrefix.size() <= rewardModels.first.size()) {
269 if (std::mismatch(rewardModelNamePrefix.begin(), rewardModelNamePrefix.end(), rewardModels.first.begin()).first ==
270 rewardModelNamePrefix.end()) {
271 prefixIsUnique =
false;
272 rewardModelNamePrefix =
"_" + rewardModelNamePrefix;
277 if (prefixIsUnique) {
288 if (considerComplementaryEvent) {
290 switch (opInfo.
bound->comparisonType) {
304 STORM_LOG_THROW(
false, storm::exceptions::InvalidPropertyException,
"Current objective " << formula <<
" has unexpected comparison type.");
308 opInfo.
optimalityType = storm::solver::OptimizationDirection::Maximize;
310 opInfo.
optimalityType = storm::solver::OptimizationDirection::Minimize;
313 "Optimization direction of formula " << formula <<
" ignored as the formula also specifies a threshold.");
317 if (considerComplementaryEvent) {
321 STORM_LOG_THROW(
false, storm::exceptions::InvalidPropertyException,
"Objective " << formula <<
" does not specify whether to minimize or maximize.");
326template<
typename SparseModelType>
327void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessOperatorFormula(
storm::logic::OperatorFormula const& formula, PreprocessorData& data) {
346 "Could not preprocess the objective " << formula <<
" because it is not supported.");
350template<
typename SparseModelType>
351void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessProbabilityOperatorFormula(storm::logic::ProbabilityOperatorFormula
const& formula,
352 storm::logic::OperatorInformation
const& opInfo,
353 PreprocessorData& data) {
367 STORM_LOG_THROW(
false, storm::exceptions::InvalidPropertyException,
"The subformula of " << formula <<
" is not supported.");
371template<
typename SparseModelType>
372void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessRewardOperatorFormula(storm::logic::RewardOperatorFormula
const& formula,
373 storm::logic::OperatorInformation
const& opInfo,
374 PreprocessorData& data) {
375 std::string rewardModelName;
378 STORM_LOG_THROW(data.model->hasRewardModel(rewardModelName), storm::exceptions::InvalidPropertyException,
379 "The reward model specified by formula " << formula <<
" does not exist in the model.");
383 auto prefixOf = [](std::string
const& left, std::string
const& right) {
384 return std::mismatch(left.begin(), left.end(), right.begin()).first == left.end();
386 bool uniqueRewardModelFound =
false;
387 for (
auto const& rewModel : data.model->getRewardModels()) {
388 if (prefixOf(data.rewardModelNamePrefix, rewModel.first)) {
392 STORM_LOG_THROW(!uniqueRewardModelFound, storm::exceptions::InvalidOperationException,
393 "The formula " << formula <<
" does not specify a reward model name and the reward model is not unique.");
394 uniqueRewardModelFound =
true;
395 rewardModelName = rewModel.first;
397 STORM_LOG_THROW(uniqueRewardModelFound, storm::exceptions::InvalidOperationException,
398 "The formula " << formula <<
" refers to an unnamed reward model but no reward model has been defined.");
410 STORM_LOG_THROW(
false, storm::exceptions::InvalidPropertyException,
"The subformula of " << formula <<
" is not supported.");
414template<
typename SparseModelType>
415void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessTimeOperatorFormula(storm::logic::TimeOperatorFormula
const& formula,
416 storm::logic::OperatorInformation
const& opInfo, PreprocessorData& data) {
422 STORM_LOG_THROW(
false, storm::exceptions::InvalidPropertyException,
"The subformula of " << formula <<
" is not supported.");
426template<
typename SparseModelType>
427void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessLongRunAverageOperatorFormula(storm::logic::LongRunAverageOperatorFormula
const& formula,
428 storm::logic::OperatorInformation
const& opInfo,
429 PreprocessorData& data) {
435 std::string rewardModelName = data.rewardModelNamePrefix + std::to_string(data.objectives.size());
436 auto lraRewardFormula = std::make_shared<storm::logic::LongRunAverageRewardFormula>();
437 data.objectives.back()->formula = std::make_shared<storm::logic::RewardOperatorFormula>(lraRewardFormula, rewardModelName, opInfo);
440 storm::modelchecker::SparsePropositionalModelChecker<SparseModelType> mc(*data.model);
441 storm::storage::BitVector subFormulaResult =
442 mc.check(formula.
getSubformula())->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
445 data.model->addRewardModel(rewardModelName,
typename SparseModelType::RewardModelType(std::move(lraRewards)));
448template<
typename SparseModelType>
449void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessUntilFormula(storm::logic::UntilFormula
const& formula,
450 storm::logic::OperatorInformation
const& opInfo, PreprocessorData& data,
451 std::shared_ptr<storm::logic::Formula const> subformula) {
454 storm::modelchecker::SparsePropositionalModelChecker<SparseModelType> mc(*data.model);
455 storm::storage::BitVector rightSubformulaResult =
456 mc.check(formula.
getRightSubformula())->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
459 STORM_LOG_THROW((data.model->getInitialStates() & rightSubformulaResult).empty(), storm::exceptions::NotImplementedException,
460 "The Probability for the objective "
461 << *data.objectives.back()->originalFormula
462 <<
" is always one as the rhs of the until formula is true in the initial state. This (trivial) case is currently not implemented.");
466 storm::storage::BitVector notLeftOrRight =
467 mc.check(formula.
getLeftSubformula())->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
469 notLeftOrRight |= rightSubformulaResult;
472 storm::storage::BitVector allStates(data.model->getNumberOfStates(),
true), noStates(data.model->getNumberOfStates(),
false);
473 storm::storage::BitVector reachableFromGoal =
476 storm::storage::BitVector reachableFromInit =
479 reachableFromInit &= ~notLeftOrRight;
481 if ((reachableFromInit & reachableFromGoal).empty()) {
482 STORM_LOG_INFO(
"Objective " << *data.objectives.back()->originalFormula <<
" is transformed to an expected total/cumulative reward property.");
486 std::vector<typename SparseModelType::ValueType> objectiveRewards(data.model->getTransitionMatrix().getRowCount(),
488 for (uint64_t state : reachableFromInit) {
489 for (uint_fast64_t row = data.model->getTransitionMatrix().getRowGroupIndices()[state];
490 row < data.model->getTransitionMatrix().getRowGroupIndices()[state + 1]; ++row) {
491 objectiveRewards[row] = data.model->getTransitionMatrix().getConstrainedRowSum(row, rightSubformulaResult);
494 std::string rewardModelName = data.rewardModelNamePrefix + std::to_string(data.objectives.size());
495 data.model->addRewardModel(rewardModelName,
typename SparseModelType::RewardModelType(std::nullopt, std::move(objectiveRewards)));
496 if (subformula ==
nullptr) {
497 subformula = std::make_shared<storm::logic::TotalRewardFormula>();
499 data.objectives.back()->formula = std::make_shared<storm::logic::RewardOperatorFormula>(subformula, rewardModelName, opInfo);
501 STORM_LOG_INFO(
"Objective " << *data.objectives.back()->originalFormula <<
" can not be transformed to an expected total/cumulative reward property.");
502 data.objectives.back()->formula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(formula.
asSharedPointer(), opInfo);
506template<
typename SparseModelType>
507void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessBoundedUntilFormula(storm::logic::BoundedUntilFormula
const& formula,
508 storm::logic::OperatorInformation
const& opInfo, PreprocessorData& data) {
512 data.objectives.back()->formula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(formula.
asSharedPointer(), opInfo);
514 std::shared_ptr<storm::logic::Formula const> subformula;
517 subformula = std::make_shared<storm::logic::TotalRewardFormula>();
520 storm::exceptions::InvalidPropertyException,
521 "Bounded until formulas for Markov Automata are only allowed when time bounds are considered.");
523 subformula = std::make_shared<storm::logic::CumulativeRewardFormula>(bound, formula.
getTimeBoundReference());
526 opInfo, data, subformula);
528 STORM_LOG_THROW(
false, storm::exceptions::InvalidPropertyException,
"Property " << formula <<
"is not supported.");
532template<
typename SparseModelType>
533void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessGloballyFormula(storm::logic::GloballyFormula
const& formula,
534 storm::logic::OperatorInformation
const& opInfo, PreprocessorData& data) {
536 auto negatedSubformula = std::make_shared<storm::logic::UnaryBooleanStateFormula>(storm::logic::UnaryBooleanStateFormula::OperatorType::Not,
542template<
typename SparseModelType>
543void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessEventuallyFormula(storm::logic::EventuallyFormula
const& formula,
544 storm::logic::OperatorInformation
const& opInfo, PreprocessorData& data,
545 boost::optional<std::string>
const& optionalRewardModelName) {
547 preprocessUntilFormula(
553 storm::modelchecker::SparsePropositionalModelChecker<SparseModelType> mc(*data.model);
554 storm::storage::BitVector subFormulaResult =
555 mc.check(formula.
getSubformula())->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
558 storm::storage::BitVector allStates(data.model->getNumberOfStates(),
true), noStates(data.model->getNumberOfStates(),
false);
559 storm::storage::BitVector reachableFromGoal =
562 storm::storage::BitVector reachableFromInit =
565 reachableFromInit &= ~subFormulaResult;
568 if ((reachableFromInit & reachableFromGoal).empty()) {
570 STORM_LOG_INFO(
"Objective " << *data.objectives.back()->originalFormula <<
" is transformed to an expected total reward property.");
571 std::string
const rewardModelName = data.rewardModelNamePrefix + std::to_string(data.objectives.size());
572 auto const totalRewardFormula = std::make_shared<storm::logic::TotalRewardFormula>();
573 data.objectives.back()->formula = std::make_shared<storm::logic::RewardOperatorFormula>(totalRewardFormula, rewardModelName, opInfo);
579 STORM_LOG_ASSERT(optionalRewardModelName.is_initialized(),
"Optional reward model name not initialized.");
580 auto objectiveRewards =
584 objectiveRewards.reduceToStateBasedRewards(data.model->getTransitionMatrix(),
false);
585 STORM_LOG_ASSERT(!objectiveRewards.hasTransitionRewards(),
"Expected no transition rewards after reducing to state-based rewards.");
587 if (objectiveRewards.hasStateRewards()) {
592 if (objectiveRewards.hasStateActionRewards()) {
593 for (uint64_t state : reachableFromGoal) {
594 std::fill_n(objectiveRewards.getStateActionRewardVector().begin() + data.model->getTransitionMatrix().getRowGroupIndices()[state],
599 data.model->addRewardModel(rewardModelName, std::move(objectiveRewards));
602 std::vector<typename SparseModelType::ValueType> timeRewards(data.model->getNumberOfStates(),
607 dynamic_cast<storm::models::sparse::MarkovAutomaton<typename SparseModelType::ValueType> const&
>(*data.model).getMarkovianStates() &
613 data.model->addRewardModel(rewardModelName,
typename SparseModelType::RewardModelType(std::move(timeRewards)));
616 "The formula " << formula <<
" neither considers reachability probabilities nor reachability rewards "
618 <<
". This is not supported.");
621 STORM_LOG_INFO(
"Objective " << *data.objectives.back()->originalFormula <<
" can not be transformed to an expected total/cumulative reward property.");
624 STORM_LOG_ASSERT(optionalRewardModelName.is_initialized(),
"Optional reward model name not initialized.");
625 if (data.deadlockLabel) {
628 std::shared_ptr<storm::logic::Formula const> newSubSubformula =
629 std::make_shared<storm::logic::AtomicLabelFormula const>(data.deadlockLabel.get());
630 std::shared_ptr<storm::logic::Formula const> newSubformula = std::make_shared<storm::logic::BinaryBooleanStateFormula const>(
632 boost::optional<storm::logic::RewardAccumulation> newRewardAccumulation;
636 std::shared_ptr<storm::logic::Formula const> newFormula =
637 std::make_shared<storm::logic::EventuallyFormula const>(newSubformula, formula.
getContext(), newRewardAccumulation);
638 data.objectives.back()->formula = std::make_shared<storm::logic::RewardOperatorFormula>(newFormula, optionalRewardModelName.get(), opInfo);
640 data.objectives.back()->formula =
641 std::make_shared<storm::logic::RewardOperatorFormula>(formula.
asSharedPointer(), optionalRewardModelName.get(), opInfo);
645 std::string rewardModelName = data.rewardModelNamePrefix + std::to_string(data.objectives.size());
647 if (data.deadlockLabel) {
650 std::shared_ptr<storm::logic::Formula const> newSubSubformula =
651 std::make_shared<storm::logic::AtomicLabelFormula const>(data.deadlockLabel.get());
652 newSubformula = std::make_shared<storm::logic::BinaryBooleanStateFormula const>(storm::logic::BinaryBooleanStateFormula::OperatorType::Or,
656 data.objectives.back()->formula = std::make_shared<storm::logic::RewardOperatorFormula>(newFormula, rewardModelName, opInfo);
657 std::vector<typename SparseModelType::ValueType> timeRewards;
662 dynamic_cast<storm::models::sparse::MarkovAutomaton<typename SparseModelType::ValueType> const&
>(*data.model).getMarkovianStates(),
667 data.model->addRewardModel(rewardModelName,
typename SparseModelType::RewardModelType(std::move(timeRewards)));
670 "The formula " << formula <<
" neither considers reachability probabilities nor reachability rewards "
672 <<
". This is not supported.");
675 data.finiteRewardCheckObjectives.
set(data.objectives.size() - 1,
true);
678template<
typename SparseModelType>
679void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessCumulativeRewardFormula(storm::logic::CumulativeRewardFormula
const& formula,
680 storm::logic::OperatorInformation
const& opInfo,
681 PreprocessorData& data,
682 boost::optional<std::string>
const& optionalRewardModelName) {
684 "Cumulative reward formulas are not supported for the given model type.");
685 std::string rewardModelName = optionalRewardModelName.get();
688 if (filteredRewards.isDifferentFromUnfilteredModel()) {
689 rewardModelName = data.rewardModelNamePrefix + std::to_string(data.objectives.size());
690 data.model->addRewardModel(rewardModelName, std::move(filteredRewards.extract()));
693 auto& rewardModel = data.model->getRewardModel(rewardModelName);
694 rewardModel.reduceToStateBasedRewards(data.model->getTransitionMatrix(),
false);
695 STORM_LOG_ASSERT(!rewardModel.hasTransitionRewards(),
"Expected no transition rewards after reducing to state-based rewards.");
697 std::vector<storm::logic::TimeBoundReference> newTimeBoundReferences;
698 bool onlyRewardBounds =
true;
701 if (oldTbr.isRewardBound()) {
702 if (oldTbr.hasRewardAccumulation()) {
704 oldTbr.getRewardAccumulation(), data.model->isDiscreteTimeModel());
705 if (filteredBoundRewards.isDifferentFromUnfilteredModel()) {
706 std::string freshRewardModelName =
707 data.rewardModelNamePrefix + std::to_string(data.objectives.size()) + std::string(
"_" + std::to_string(i));
708 data.model->addRewardModel(freshRewardModelName, std::move(filteredBoundRewards.extract()));
709 newTimeBoundReferences.emplace_back(freshRewardModelName);
712 newTimeBoundReferences.emplace_back(oldTbr.getRewardName());
715 newTimeBoundReferences.push_back(oldTbr);
718 onlyRewardBounds =
false;
719 newTimeBoundReferences.push_back(oldTbr);
723 auto newFormula = std::make_shared<storm::logic::CumulativeRewardFormula>(formula.
getBounds(), newTimeBoundReferences);
724 data.objectives.back()->formula = std::make_shared<storm::logic::RewardOperatorFormula>(newFormula, rewardModelName, opInfo);
726 if (onlyRewardBounds) {
727 data.finiteRewardCheckObjectives.set(data.objectives.size() - 1,
true);
731template<
typename SparseModelType>
732void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessTotalRewardFormula(storm::logic::TotalRewardFormula
const& formula,
733 storm::logic::OperatorInformation
const& opInfo, PreprocessorData& data,
734 boost::optional<std::string>
const& optionalRewardModelName) {
735 std::string rewardModelName = optionalRewardModelName.get();
737 if (filteredRewards.isDifferentFromUnfilteredModel()) {
738 rewardModelName = data.rewardModelNamePrefix + std::to_string(data.objectives.size());
739 data.model->addRewardModel(rewardModelName, filteredRewards.extract());
742 auto& rewardModel = data.model->getRewardModel(rewardModelName);
743 rewardModel.reduceToStateBasedRewards(data.model->getTransitionMatrix(),
false);
744 STORM_LOG_ASSERT(!rewardModel.hasTransitionRewards(),
"Expected no transition rewards after reducing to state-based rewards.");
746 data.objectives.back()->formula = std::make_shared<storm::logic::RewardOperatorFormula>(formula.
stripRewardAccumulation(), rewardModelName, opInfo);
747 data.finiteRewardCheckObjectives.set(data.objectives.size() - 1,
true);
750template<
typename SparseModelType>
751void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessLongRunAverageRewardFormula(storm::logic::LongRunAverageRewardFormula
const& formula,
752 storm::logic::OperatorInformation
const& opInfo,
753 PreprocessorData& data,
754 boost::optional<std::string>
const& optionalRewardModelName) {
755 std::string rewardModelName = optionalRewardModelName.get();
757 if (filteredRewards.isDifferentFromUnfilteredModel()) {
758 std::string rewardModelName = data.rewardModelNamePrefix + std::to_string(data.objectives.size());
759 data.model->addRewardModel(rewardModelName, std::move(filteredRewards.extract()));
762 auto& rewardModel = data.model->getRewardModel(rewardModelName);
763 rewardModel.reduceToStateBasedRewards(data.model->getTransitionMatrix(),
false);
764 STORM_LOG_ASSERT(!rewardModel.hasTransitionRewards(),
"Expected no transition rewards after reducing to state-based rewards.");
766 data.objectives.back()->formula = std::make_shared<storm::logic::RewardOperatorFormula>(formula.
stripRewardAccumulation(), rewardModelName, opInfo);
769template<
typename SparseModelType>
770typename SparseMultiObjectivePreprocessor<SparseModelType>::ReturnType SparseMultiObjectivePreprocessor<SparseModelType>::buildResult(
771 SparseModelType
const& originalModel, storm::logic::MultiObjectiveFormula
const& originalFormula, PreprocessorData& data) {
772 ReturnType result(originalFormula, originalModel);
773 auto backwardTransitions = data.model->getBackwardTransitions();
774 result.preprocessedModel = data.model;
775 result.memoryIncorporationReverseData = data.memoryIncorporationReverseData;
777 for (
auto& obj : data.objectives) {
778 result.objectives.push_back(std::move(*obj));
780 result.queryType = getQueryType(result.objectives);
781 result.maybeInfiniteRewardObjectives = std::move(data.finiteRewardCheckObjectives);
786template<
typename SparseModelType>
787typename SparseMultiObjectivePreprocessor<SparseModelType>::ReturnType::QueryType SparseMultiObjectivePreprocessor<SparseModelType>::getQueryType(
789 uint_fast64_t numOfObjectivesWithThreshold = 0;
790 for (
auto& obj : objectives) {
791 if (obj.formula->hasBound()) {
792 ++numOfObjectivesWithThreshold;
795 if (numOfObjectivesWithThreshold == objectives.size()) {
796 return ReturnType::QueryType::Achievability;
797 }
else if (numOfObjectivesWithThreshold + 1 == objectives.size()) {
799 return ReturnType::QueryType::Quantitative;
800 }
else if (numOfObjectivesWithThreshold == 0) {
801 return ReturnType::QueryType::Pareto;
804 "Invalid Multi-objective query: The numer of qualitative objectives should be either 0 (Pareto query), 1 (quantitative query), or "
805 "#objectives (achievability query).");
809template class SparseMultiObjectivePreprocessor<storm::models::sparse::Mdp<double>>;
810template class SparseMultiObjectivePreprocessor<storm::models::sparse::MarkovAutomaton<double>>;
812template class SparseMultiObjectivePreprocessor<storm::models::sparse::Mdp<storm::RationalNumber>>;
813template class SparseMultiObjectivePreprocessor<storm::models::sparse::MarkovAutomaton<storm::RationalNumber>>;
ModelCheckerEnvironment & modelchecker()
MultiObjectiveModelCheckerEnvironment & multi()
bool isSchedulerRestrictionSet() const
storm::storage::SchedulerClass const & getSchedulerRestriction() const
bool isRewardBound() const
static ReturnType preprocess(Environment const &env, SparseModelType const &originalModel, storm::logic::MultiObjectiveFormula const &originalFormula, bool produceScheduler)
Preprocesses the given model w.r.t.
SparseMultiObjectivePreprocessorResult< SparseModelType > ReturnType
A bit vector that is internally represented as a vector of 64-bit values.
void complement()
Negates all bits in the bit vector.
bool isSubsetOf(BitVector const &other) const
Checks whether all bits that are set in the current bit vector are also set in the given bit vector.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
size_t size() const
Retrieves the number of bits this bit vector can store.
void resize(uint64_t newLength, bool init=false)
Resizes the bit vector to hold the given new number of bits.
bool get(uint64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
A class that holds a possibly non-square matrix in the compressed row storage format.
#define STORM_LOG_INFO(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_WARN_COND(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
bool isLowerBound(ComparisonType t)
storm::storage::BitVector getOnlyReachableViaPhi(SparseModelType const &model, storm::storage::BitVector const &phi)
storm::logic::OperatorInformation getOperatorInformation(storm::logic::OperatorFormula const &formula, bool considerComplementaryEvent)
OptimizationDirection constexpr invert(OptimizationDirection d)
storm::storage::BitVector getReachableStates(storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::BitVector const &initialStates, storm::storage::BitVector const &constraintStates, storm::storage::BitVector const &targetStates, bool useStepBound, uint_fast64_t maximalSteps, boost::optional< storm::storage::BitVector > const &choiceFilter)
Performs a forward depth-first search through the underlying graph structure to identify the states t...
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 performProb0A(storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
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.
FilteredRewardModel< RewardModelType > createFilteredRewardModel(RewardModelType const &baseRewardModel, storm::logic::RewardAccumulation const &acc, bool isDiscreteTimeModel)
bool isZero(ValueType const &a)
bool considersComplementaryEvent