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 (
auto 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) {
345 STORM_LOG_THROW(
false, storm::exceptions::InvalidPropertyException,
"Could not preprocess the objective " << formula <<
" because it is not supported");
349template<
typename SparseModelType>
350void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessProbabilityOperatorFormula(storm::logic::ProbabilityOperatorFormula
const& formula,
351 storm::logic::OperatorInformation
const& opInfo,
352 PreprocessorData& data) {
366 STORM_LOG_THROW(
false, storm::exceptions::InvalidPropertyException,
"The subformula of " << formula <<
" is not supported.");
370template<
typename SparseModelType>
371void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessRewardOperatorFormula(storm::logic::RewardOperatorFormula
const& formula,
372 storm::logic::OperatorInformation
const& opInfo,
373 PreprocessorData& data) {
374 std::string rewardModelName;
377 STORM_LOG_THROW(data.model->hasRewardModel(rewardModelName), storm::exceptions::InvalidPropertyException,
378 "The reward model specified by formula " << formula <<
" does not exist in the model");
382 auto prefixOf = [](std::string
const& left, std::string
const& right) {
383 return std::mismatch(left.begin(), left.end(), right.begin()).first == left.end();
385 bool uniqueRewardModelFound =
false;
386 for (
auto const& rewModel : data.model->getRewardModels()) {
387 if (prefixOf(data.rewardModelNamePrefix, rewModel.first)) {
391 STORM_LOG_THROW(!uniqueRewardModelFound, storm::exceptions::InvalidOperationException,
392 "The formula " << formula <<
" does not specify a reward model name and the reward model is not unique.");
393 uniqueRewardModelFound =
true;
394 rewardModelName = rewModel.first;
396 STORM_LOG_THROW(uniqueRewardModelFound, storm::exceptions::InvalidOperationException,
397 "The formula " << formula <<
" refers to an unnamed reward model but no reward model has been defined.");
409 STORM_LOG_THROW(
false, storm::exceptions::InvalidPropertyException,
"The subformula of " << formula <<
" is not supported.");
413template<
typename SparseModelType>
414void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessTimeOperatorFormula(storm::logic::TimeOperatorFormula
const& formula,
415 storm::logic::OperatorInformation
const& opInfo, PreprocessorData& data) {
421 STORM_LOG_THROW(
false, storm::exceptions::InvalidPropertyException,
"The subformula of " << formula <<
" is not supported.");
425template<
typename SparseModelType>
426void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessLongRunAverageOperatorFormula(storm::logic::LongRunAverageOperatorFormula
const& formula,
427 storm::logic::OperatorInformation
const& opInfo,
428 PreprocessorData& data) {
434 std::string rewardModelName = data.rewardModelNamePrefix + std::to_string(data.objectives.size());
435 auto lraRewardFormula = std::make_shared<storm::logic::LongRunAverageRewardFormula>();
436 data.objectives.back()->formula = std::make_shared<storm::logic::RewardOperatorFormula>(lraRewardFormula, rewardModelName, opInfo);
439 storm::modelchecker::SparsePropositionalModelChecker<SparseModelType> mc(*data.model);
440 storm::storage::BitVector subFormulaResult =
441 mc.check(formula.
getSubformula())->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
444 data.model->addRewardModel(rewardModelName,
typename SparseModelType::RewardModelType(std::move(lraRewards)));
447template<
typename SparseModelType>
448void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessUntilFormula(storm::logic::UntilFormula
const& formula,
449 storm::logic::OperatorInformation
const& opInfo, PreprocessorData& data,
450 std::shared_ptr<storm::logic::Formula const> subformula) {
453 storm::modelchecker::SparsePropositionalModelChecker<SparseModelType> mc(*data.model);
454 storm::storage::BitVector rightSubformulaResult =
455 mc.check(formula.
getRightSubformula())->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
458 STORM_LOG_THROW((data.model->getInitialStates() & rightSubformulaResult).empty(), storm::exceptions::NotImplementedException,
459 "The Probability for the objective "
460 << *data.objectives.back()->originalFormula
461 <<
" is always one as the rhs of the until formula is true in the initial state. This (trivial) case is currently not implemented.");
465 storm::storage::BitVector notLeftOrRight =
466 mc.check(formula.
getLeftSubformula())->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
468 notLeftOrRight |= rightSubformulaResult;
471 storm::storage::BitVector allStates(data.model->getNumberOfStates(),
true), noStates(data.model->getNumberOfStates(),
false);
472 storm::storage::BitVector reachableFromGoal =
475 storm::storage::BitVector reachableFromInit =
478 reachableFromInit &= ~notLeftOrRight;
480 if ((reachableFromInit & reachableFromGoal).empty()) {
481 STORM_LOG_INFO(
"Objective " << *data.objectives.back()->originalFormula <<
" is transformed to an expected total/cumulative reward property.");
485 std::vector<typename SparseModelType::ValueType> objectiveRewards(data.model->getTransitionMatrix().getRowCount(),
487 for (
auto state : reachableFromInit) {
488 for (uint_fast64_t row = data.model->getTransitionMatrix().getRowGroupIndices()[state];
489 row < data.model->getTransitionMatrix().getRowGroupIndices()[state + 1]; ++row) {
490 objectiveRewards[row] = data.model->getTransitionMatrix().getConstrainedRowSum(row, rightSubformulaResult);
493 std::string rewardModelName = data.rewardModelNamePrefix + std::to_string(data.objectives.size());
494 data.model->addRewardModel(rewardModelName,
typename SparseModelType::RewardModelType(std::nullopt, std::move(objectiveRewards)));
495 if (subformula ==
nullptr) {
496 subformula = std::make_shared<storm::logic::TotalRewardFormula>();
498 data.objectives.back()->formula = std::make_shared<storm::logic::RewardOperatorFormula>(subformula, rewardModelName, opInfo);
500 STORM_LOG_INFO(
"Objective " << *data.objectives.back()->originalFormula <<
" can not be transformed to an expected total/cumulative reward property.");
501 data.objectives.back()->formula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(formula.
asSharedPointer(), opInfo);
505template<
typename SparseModelType>
506void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessBoundedUntilFormula(storm::logic::BoundedUntilFormula
const& formula,
507 storm::logic::OperatorInformation
const& opInfo, PreprocessorData& data) {
511 data.objectives.back()->formula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(formula.
asSharedPointer(), opInfo);
513 std::shared_ptr<storm::logic::Formula const> subformula;
516 subformula = std::make_shared<storm::logic::TotalRewardFormula>();
519 storm::exceptions::InvalidPropertyException,
520 "Bounded until formulas for Markov Automata are only allowed when time bounds are considered.");
522 subformula = std::make_shared<storm::logic::CumulativeRewardFormula>(bound, formula.
getTimeBoundReference());
525 opInfo, data, subformula);
527 STORM_LOG_THROW(
false, storm::exceptions::InvalidPropertyException,
"Property " << formula <<
"is not supported");
531template<
typename SparseModelType>
532void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessGloballyFormula(storm::logic::GloballyFormula
const& formula,
533 storm::logic::OperatorInformation
const& opInfo, PreprocessorData& data) {
535 auto negatedSubformula = std::make_shared<storm::logic::UnaryBooleanStateFormula>(storm::logic::UnaryBooleanStateFormula::OperatorType::Not,
541template<
typename SparseModelType>
542void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessEventuallyFormula(storm::logic::EventuallyFormula
const& formula,
543 storm::logic::OperatorInformation
const& opInfo, PreprocessorData& data,
544 boost::optional<std::string>
const& optionalRewardModelName) {
546 preprocessUntilFormula(
552 storm::modelchecker::SparsePropositionalModelChecker<SparseModelType> mc(*data.model);
553 storm::storage::BitVector subFormulaResult =
554 mc.check(formula.
getSubformula())->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
557 storm::storage::BitVector allStates(data.model->getNumberOfStates(),
true), noStates(data.model->getNumberOfStates(),
false);
558 storm::storage::BitVector reachableFromGoal =
561 storm::storage::BitVector reachableFromInit =
564 reachableFromInit &= ~subFormulaResult;
567 if ((reachableFromInit & reachableFromGoal).empty()) {
569 STORM_LOG_INFO(
"Objective " << *data.objectives.back()->originalFormula <<
" is transformed to an expected total reward property.");
570 std::string
const rewardModelName = data.rewardModelNamePrefix + std::to_string(data.objectives.size());
571 auto const totalRewardFormula = std::make_shared<storm::logic::TotalRewardFormula>();
572 data.objectives.back()->formula = std::make_shared<storm::logic::RewardOperatorFormula>(totalRewardFormula, rewardModelName, opInfo);
578 assert(optionalRewardModelName.is_initialized());
579 auto objectiveRewards =
583 objectiveRewards.reduceToStateBasedRewards(data.model->getTransitionMatrix(),
false);
584 STORM_LOG_ASSERT(!objectiveRewards.hasTransitionRewards(),
"Expected no transition rewards after reducing to state-based rewards");
586 if (objectiveRewards.hasStateRewards()) {
591 if (objectiveRewards.hasStateActionRewards()) {
592 for (
auto state : reachableFromGoal) {
593 std::fill_n(objectiveRewards.getStateActionRewardVector().begin() + data.model->getTransitionMatrix().getRowGroupIndices()[state],
598 data.model->addRewardModel(rewardModelName, std::move(objectiveRewards));
601 std::vector<typename SparseModelType::ValueType> timeRewards(data.model->getNumberOfStates(),
606 dynamic_cast<storm::models::sparse::MarkovAutomaton<typename SparseModelType::ValueType> const&
>(*data.model).getMarkovianStates() &
612 data.model->addRewardModel(rewardModelName,
typename SparseModelType::RewardModelType(std::move(timeRewards)));
615 "The formula " << formula <<
" neither considers reachability probabilities nor reachability rewards "
617 <<
". This is not supported.");
620 STORM_LOG_INFO(
"Objective " << *data.objectives.back()->originalFormula <<
" can not be transformed to an expected total/cumulative reward property.");
623 assert(optionalRewardModelName.is_initialized());
624 if (data.deadlockLabel) {
627 std::shared_ptr<storm::logic::Formula const> newSubSubformula =
628 std::make_shared<storm::logic::AtomicLabelFormula const>(data.deadlockLabel.get());
629 std::shared_ptr<storm::logic::Formula const> newSubformula = std::make_shared<storm::logic::BinaryBooleanStateFormula const>(
631 boost::optional<storm::logic::RewardAccumulation> newRewardAccumulation;
635 std::shared_ptr<storm::logic::Formula const> newFormula =
636 std::make_shared<storm::logic::EventuallyFormula const>(newSubformula, formula.
getContext(), newRewardAccumulation);
637 data.objectives.back()->formula = std::make_shared<storm::logic::RewardOperatorFormula>(newFormula, optionalRewardModelName.get(), opInfo);
639 data.objectives.back()->formula =
640 std::make_shared<storm::logic::RewardOperatorFormula>(formula.
asSharedPointer(), optionalRewardModelName.get(), opInfo);
644 std::string rewardModelName = data.rewardModelNamePrefix + std::to_string(data.objectives.size());
646 if (data.deadlockLabel) {
649 std::shared_ptr<storm::logic::Formula const> newSubSubformula =
650 std::make_shared<storm::logic::AtomicLabelFormula const>(data.deadlockLabel.get());
651 newSubformula = std::make_shared<storm::logic::BinaryBooleanStateFormula const>(storm::logic::BinaryBooleanStateFormula::OperatorType::Or,
655 data.objectives.back()->formula = std::make_shared<storm::logic::RewardOperatorFormula>(newFormula, rewardModelName, opInfo);
656 std::vector<typename SparseModelType::ValueType> timeRewards;
661 dynamic_cast<storm::models::sparse::MarkovAutomaton<typename SparseModelType::ValueType> const&
>(*data.model).getMarkovianStates(),
666 data.model->addRewardModel(rewardModelName,
typename SparseModelType::RewardModelType(std::move(timeRewards)));
669 "The formula " << formula <<
" neither considers reachability probabilities nor reachability rewards "
671 <<
". This is not supported.");
674 data.finiteRewardCheckObjectives.
set(data.objectives.size() - 1,
true);
677template<
typename SparseModelType>
678void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessCumulativeRewardFormula(storm::logic::CumulativeRewardFormula
const& formula,
679 storm::logic::OperatorInformation
const& opInfo,
680 PreprocessorData& data,
681 boost::optional<std::string>
const& optionalRewardModelName) {
683 "Cumulative reward formulas are not supported for the given model type.");
684 std::string rewardModelName = optionalRewardModelName.get();
687 if (filteredRewards.isDifferentFromUnfilteredModel()) {
688 rewardModelName = data.rewardModelNamePrefix + std::to_string(data.objectives.size());
689 data.model->addRewardModel(rewardModelName, std::move(filteredRewards.extract()));
692 auto& rewardModel = data.model->getRewardModel(rewardModelName);
693 rewardModel.reduceToStateBasedRewards(data.model->getTransitionMatrix(),
false);
694 STORM_LOG_ASSERT(!rewardModel.hasTransitionRewards(),
"Expected no transition rewards after reducing to state-based rewards");
696 std::vector<storm::logic::TimeBoundReference> newTimeBoundReferences;
697 bool onlyRewardBounds =
true;
700 if (oldTbr.isRewardBound()) {
701 if (oldTbr.hasRewardAccumulation()) {
703 oldTbr.getRewardAccumulation(), data.model->isDiscreteTimeModel());
704 if (filteredBoundRewards.isDifferentFromUnfilteredModel()) {
705 std::string freshRewardModelName =
706 data.rewardModelNamePrefix + std::to_string(data.objectives.size()) + std::string(
"_" + std::to_string(i));
707 data.model->addRewardModel(freshRewardModelName, std::move(filteredBoundRewards.extract()));
708 newTimeBoundReferences.emplace_back(freshRewardModelName);
711 newTimeBoundReferences.emplace_back(oldTbr.getRewardName());
714 newTimeBoundReferences.push_back(oldTbr);
717 onlyRewardBounds =
false;
718 newTimeBoundReferences.push_back(oldTbr);
722 auto newFormula = std::make_shared<storm::logic::CumulativeRewardFormula>(formula.
getBounds(), newTimeBoundReferences);
723 data.objectives.back()->formula = std::make_shared<storm::logic::RewardOperatorFormula>(newFormula, rewardModelName, opInfo);
725 if (onlyRewardBounds) {
726 data.finiteRewardCheckObjectives.set(data.objectives.size() - 1,
true);
730template<
typename SparseModelType>
731void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessTotalRewardFormula(storm::logic::TotalRewardFormula
const& formula,
732 storm::logic::OperatorInformation
const& opInfo, PreprocessorData& data,
733 boost::optional<std::string>
const& optionalRewardModelName) {
734 std::string rewardModelName = optionalRewardModelName.get();
736 if (filteredRewards.isDifferentFromUnfilteredModel()) {
737 rewardModelName = data.rewardModelNamePrefix + std::to_string(data.objectives.size());
738 data.model->addRewardModel(rewardModelName, filteredRewards.extract());
741 auto& rewardModel = data.model->getRewardModel(rewardModelName);
742 rewardModel.reduceToStateBasedRewards(data.model->getTransitionMatrix(),
false);
743 STORM_LOG_ASSERT(!rewardModel.hasTransitionRewards(),
"Expected no transition rewards after reducing to state-based rewards");
745 data.objectives.back()->formula = std::make_shared<storm::logic::RewardOperatorFormula>(formula.
stripRewardAccumulation(), rewardModelName, opInfo);
746 data.finiteRewardCheckObjectives.set(data.objectives.size() - 1,
true);
749template<
typename SparseModelType>
750void SparseMultiObjectivePreprocessor<SparseModelType>::preprocessLongRunAverageRewardFormula(storm::logic::LongRunAverageRewardFormula
const& formula,
751 storm::logic::OperatorInformation
const& opInfo,
752 PreprocessorData& data,
753 boost::optional<std::string>
const& optionalRewardModelName) {
754 std::string rewardModelName = optionalRewardModelName.get();
756 if (filteredRewards.isDifferentFromUnfilteredModel()) {
757 std::string rewardModelName = data.rewardModelNamePrefix + std::to_string(data.objectives.size());
758 data.model->addRewardModel(rewardModelName, std::move(filteredRewards.extract()));
761 auto& rewardModel = data.model->getRewardModel(rewardModelName);
762 rewardModel.reduceToStateBasedRewards(data.model->getTransitionMatrix(),
false);
763 STORM_LOG_ASSERT(!rewardModel.hasTransitionRewards(),
"Expected no transition rewards after reducing to state-based rewards");
765 data.objectives.back()->formula = std::make_shared<storm::logic::RewardOperatorFormula>(formula.
stripRewardAccumulation(), rewardModelName, opInfo);
768template<
typename SparseModelType>
769typename SparseMultiObjectivePreprocessor<SparseModelType>::ReturnType SparseMultiObjectivePreprocessor<SparseModelType>::buildResult(
770 SparseModelType
const& originalModel, storm::logic::MultiObjectiveFormula
const& originalFormula, PreprocessorData& data) {
771 ReturnType result(originalFormula, originalModel);
772 auto backwardTransitions = data.model->getBackwardTransitions();
773 result.preprocessedModel = data.model;
774 result.memoryIncorporationReverseData = data.memoryIncorporationReverseData;
776 for (
auto& obj : data.objectives) {
777 result.objectives.push_back(std::move(*obj));
779 result.queryType = getQueryType(result.objectives);
780 result.maybeInfiniteRewardObjectives = std::move(data.finiteRewardCheckObjectives);
785template<
typename SparseModelType>
786typename SparseMultiObjectivePreprocessor<SparseModelType>::ReturnType::QueryType SparseMultiObjectivePreprocessor<SparseModelType>::getQueryType(
788 uint_fast64_t numOfObjectivesWithThreshold = 0;
789 for (
auto& obj : objectives) {
790 if (obj.formula->hasBound()) {
791 ++numOfObjectivesWithThreshold;
794 if (numOfObjectivesWithThreshold == objectives.size()) {
795 return ReturnType::QueryType::Achievability;
796 }
else if (numOfObjectivesWithThreshold + 1 == objectives.size()) {
798 return ReturnType::QueryType::Quantitative;
799 }
else if (numOfObjectivesWithThreshold == 0) {
800 return ReturnType::QueryType::Pareto;
803 "Invalid Multi-objective query: The numer of qualitative objectives should be either 0 (Pareto query), 1 (quantitative query), or "
804 "#objectives (achievability query).");
808template class SparseMultiObjectivePreprocessor<storm::models::sparse::Mdp<double>>;
809template class SparseMultiObjectivePreprocessor<storm::models::sparse::MarkovAutomaton<double>>;
811template class SparseMultiObjectivePreprocessor<storm::models::sparse::Mdp<storm::RationalNumber>>;
812template 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