19namespace abstraction {
24 : source(source), predicates(predicates) {
37 this->predicates.insert(this->predicates.end(), newPredicates.begin(), newPredicates.end());
40template<storm::dd::DdType Type,
typename ValueType>
43 : maxProbabilities(maxProbabilities), spanningTree(spanningTree) {
47template<storm::dd::DdType Type>
54template<storm::dd::DdType Type,
typename ValueType>
58 : pivotState(pivotState), fromDirection(fromDirection), symbolicMostProbablePathsResult(symbolicMostProbablePathsResult) {
62template<storm::dd::DdType Type,
typename ValueType>
65 : abstractor(abstractor),
68 splitPredicates(false),
69 rankPredicates(false),
70 addedAllGuardsFlag(false),
71 refinementPredicatesToInject(options.refinementPredicates),
72 pivotSelectionHeuristic(),
74 equivalenceChecker(
std::move(smtSolver)) {
75 auto const& abstractionSettings = storm::settings::getModule<storm::settings::modules::AbstractionSettings>();
77 pivotSelectionHeuristic = abstractionSettings.getPivotSelectionHeuristic();
81 rankPredicates = abstractionSettings.isRankRefinementPredicatesSet();
82 addPredicatesEagerly = abstractionSettings.isUseEagerRefinementSet();
85 if (abstractionSettings.isAddAllGuardsSet()) {
86 std::vector<storm::expressions::Expression> guards;
89 for (uint64_t index = player1Choices.first; index < player1Choices.second; ++index) {
92 guards.push_back(guard);
98 addedAllGuardsFlag =
true;
100 if (abstractionSettings.isAddAllInitialExpressionsSet()) {
106template<storm::dd::DdType Type,
typename ValueType>
111template<storm::dd::DdType Type,
typename ValueType>
121 .
template toAdd<ValueType>() *
125 std::set<storm::expressions::Variable> variablesToAbstract(game.
getRowVariables());
128 while (!border.
isZero()) {
136 maxProbabilities = updateStates.
ite(newMaxProbabilities, maxProbabilities);
145 border = updateStates;
151template<storm::dd::DdType Type,
typename ValueType>
162 if (qualitativeResult) {
163 minPlayer1Strategy = qualitativeResult.get().prob0Min.getPlayer1Strategy();
164 minPlayer2Strategy = qualitativeResult.get().prob0Min.getPlayer2Strategy();
165 maxPlayer1Strategy = qualitativeResult.get().prob1Max.getPlayer1Strategy();
166 maxPlayer2Strategy = qualitativeResult.get().prob1Max.getPlayer2Strategy();
167 }
else if (quantitativeResult) {
168 minPlayer1Strategy = quantitativeResult.get().min.getPlayer1Strategy();
169 minPlayer2Strategy = quantitativeResult.get().min.getPlayer2Strategy();
170 maxPlayer1Strategy = quantitativeResult.get().max.getPlayer1Strategy();
171 maxPlayer2Strategy = quantitativeResult.get().max.getPlayer2Strategy();
173 STORM_LOG_ASSERT(
false,
"Either qualitative or quantitative result is required.");
181 std::set<storm::expressions::Variable>
const& rowVariables = game.
getRowVariables();
182 std::set<storm::expressions::Variable>
const& columnVariables = game.
getColumnVariables();
191 bool foundPivotState = !frontierPivotStates.
isZero();
192 if (foundPivotState) {
194 << pivotStates.getNonZeroCount() <<
" candidates in total.");
196 storm::OptimizationDirection::Minimize);
200 while (!foundPivotState) {
201 frontierMin = frontierMin.
relationalProduct(transitionsMin, rowVariables, columnVariables);
202 frontierMax = frontierMax.
relationalProduct(transitionsMax, rowVariables, columnVariables);
209 if (!frontierMinPivotStates.
isZero() || !frontierMaxPivotStates.
isZero()) {
210 if (quantitativeResult) {
215 frontierMinPivotStatesAdd * quantitativeResult.get().max.values - frontierMinPivotStatesAdd * quantitativeResult.get().min.values;
217 frontierMaxPivotStatesAdd * quantitativeResult.get().max.values - frontierMaxPivotStatesAdd * quantitativeResult.get().min.values;
222 direction = storm::OptimizationDirection::Minimize;
223 diffValue = diffMin.
getMax();
225 direction = storm::OptimizationDirection::Maximize;
226 diffValue = diffMax.
getMax();
229 STORM_LOG_TRACE(
"Picked pivot state with difference " << diffValue <<
" from " << numberOfPivotStateCandidatesOnLevel
230 <<
" candidates on level " << level <<
", " << pivotStates.getNonZeroCount()
231 <<
" candidates in total.");
237 STORM_LOG_TRACE(
"Picked pivot state from " << numberOfPivotStateCandidatesOnLevel <<
" candidates on level " << level <<
", "
238 << pivotStates.getNonZeroCount() <<
" candidates in total.");
241 if (!frontierMinPivotStates.
isZero()) {
242 direction = storm::OptimizationDirection::Minimize;
244 direction = storm::OptimizationDirection::Maximize;
267 score = score * (quantitativeResult.get().max.values - quantitativeResult.get().min.values);
274 if ((selectedPivotStateAsAdd * maxSymbolicMostProbablePathsResult.
maxProbabilities).getMax() >
275 (selectedPivotStateAsAdd * minSymbolicMostProbablePathsResult.
maxProbabilities).getMax()) {
276 fromDirection = storm::OptimizationDirection::Maximize;
280 selectedPivotState, fromDirection,
281 fromDirection == storm::OptimizationDirection::Minimize ? minSymbolicMostProbablePathsResult : maxSymbolicMostProbablePathsResult);
284 STORM_LOG_ASSERT(
false,
"This point must not be reached, because then no pivot state could be found.");
288template<storm::dd::DdType Type,
typename ValueType>
289RefinementPredicates MenuGameRefiner<Type, ValueType>::derivePredicatesFromDifferingChoices(
storm::dd::Bdd<Type> const& player1Choice,
294 bool fromGuard =
false;
297 AbstractionInformation<Type>
const& abstractionInformation = abstractor.get().getAbstractionInformation();
301 auto pl1It = player1ChoiceAsAdd.
begin();
302 uint_fast64_t player1Index = abstractionInformation.decodePlayer1Choice((*pl1It).first, abstractionInformation.getPlayer1VariableCount());
306 bool buttomStateSuccessor =
307 !((abstractionInformation.getBottomStateBdd(
false,
false) && lowerChoice) || (abstractionInformation.getBottomStateBdd(
false,
false) && upperChoice))
312 if (buttomStateSuccessor) {
313 STORM_LOG_TRACE(
"One of the successors is a bottom state, taking a guard as a new predicate.");
314 newPredicate = abstractor.get().getGuard(player1Index);
316 STORM_LOG_DEBUG(
"Derived new predicate (based on guard): " << newPredicate);
318 STORM_LOG_TRACE(
"No bottom state successor. Deriving a new predicate using weakest precondition.");
321 std::map<uint64_t, std::pair<storm::storage::BitVector, ValueType>> lowerChoiceUpdateToSuccessorMapping =
322 abstractionInformation.template decodeChoiceToUpdateSuccessorMapping<ValueType>(lowerChoice);
323 std::map<uint64_t, std::pair<storm::storage::BitVector, ValueType>> upperChoiceUpdateToSuccessorMapping =
324 abstractionInformation.template decodeChoiceToUpdateSuccessorMapping<ValueType>(upperChoice);
326 lowerChoiceUpdateToSuccessorMapping.size() == upperChoiceUpdateToSuccessorMapping.size(),
327 "Mismatching sizes after decode (" << lowerChoiceUpdateToSuccessorMapping.size() <<
" vs. " << upperChoiceUpdateToSuccessorMapping.size() <<
").");
330 std::vector<std::pair<uint64_t, ValueType>> updateIndicesAndMasses;
331 for (
auto const& entry : lowerChoiceUpdateToSuccessorMapping) {
332 updateIndicesAndMasses.emplace_back(entry.first, entry.second.second);
334 std::sort(updateIndicesAndMasses.begin(), updateIndicesAndMasses.end(),
335 [](std::pair<uint64_t, ValueType>
const& a, std::pair<uint64_t, ValueType>
const& b) { return a.second > b.second; });
339 std::set<uint64_t> deviationPredicates;
340 uint64_t orderedUpdateIndex = 0;
341 std::vector<storm::expressions::Expression> possibleRefinementPredicates;
342 for (; orderedUpdateIndex < updateIndicesAndMasses.size(); ++orderedUpdateIndex) {
343 storm::storage::BitVector const& lower = lowerChoiceUpdateToSuccessorMapping.at(updateIndicesAndMasses[orderedUpdateIndex].first).first;
344 storm::storage::BitVector const& upper = upperChoiceUpdateToSuccessorMapping.at(updateIndicesAndMasses[orderedUpdateIndex].first).first;
346 bool deviates = lower != upper;
348 std::map<storm::expressions::Variable, storm::expressions::Expression> variableUpdates =
349 abstractor.
get().getVariableUpdates(player1Index, updateIndicesAndMasses[orderedUpdateIndex].first);
351 for (uint64_t predicateIndex = 0; predicateIndex < lower.
size(); ++predicateIndex) {
352 if (lower[predicateIndex] != upper[predicateIndex]) {
353 possibleRefinementPredicates.push_back(
354 abstractionInformation.getPredicateByIndex(predicateIndex).substitute(variableUpdates).simplify());
355 if (!rankPredicates) {
364 STORM_LOG_ASSERT(!possibleRefinementPredicates.empty(),
"Expected refinement predicates.");
367 for (
auto const& pred : possibleRefinementPredicates) {
371 if (rankPredicates) {
375 std::vector<storm::expressions::Expression> otherRefinementPredicates;
376 for (; orderedUpdateIndex < updateIndicesAndMasses.size(); ++orderedUpdateIndex) {
377 storm::storage::BitVector const& lower = lowerChoiceUpdateToSuccessorMapping.at(updateIndicesAndMasses[orderedUpdateIndex].first).first;
378 storm::storage::BitVector const& upper = upperChoiceUpdateToSuccessorMapping.at(updateIndicesAndMasses[orderedUpdateIndex].first).first;
380 bool deviates = lower != upper;
382 std::map<storm::expressions::Variable, storm::expressions::Expression> newVariableUpdates =
383 abstractor.
get().getVariableUpdates(player1Index, updateIndicesAndMasses[orderedUpdateIndex].first);
384 for (uint64_t predicateIndex = 0; predicateIndex < lower.
size(); ++predicateIndex) {
385 if (lower[predicateIndex] != upper[predicateIndex]) {
386 otherRefinementPredicates.push_back(
387 abstractionInformation.getPredicateByIndex(predicateIndex).substitute(newVariableUpdates).simplify());
394 std::vector<uint64_t> refinementPredicateIndexToCount(possibleRefinementPredicates.size(), 0);
395 for (uint64_t index = 0; index < possibleRefinementPredicates.size(); ++index) {
396 refinementPredicateIndexToCount[index] = 1;
398 for (
auto const& otherPredicate : otherRefinementPredicates) {
399 for (uint64_t index = 0; index < possibleRefinementPredicates.size(); ++index) {
400 if (equivalenceChecker.areEquivalentModuloNegation(otherPredicate, possibleRefinementPredicates[index])) {
401 ++refinementPredicateIndexToCount[index];
407 uint64_t chosenPredicateIndex = 0;
408 for (uint64_t index = 0; index < possibleRefinementPredicates.size(); ++index) {
409 if (refinementPredicateIndexToCount[index] > refinementPredicateIndexToCount[chosenPredicateIndex]) {
410 chosenPredicateIndex = index;
413 newPredicate = possibleRefinementPredicates[chosenPredicateIndex];
414 STORM_LOG_DEBUG(
"Derived new predicate (based on weakest-precondition): " << newPredicate <<
", (equivalent to "
415 << (refinementPredicateIndexToCount[chosenPredicateIndex] - 1)
416 <<
" other refinement predicates).");
418 newPredicate = possibleRefinementPredicates.front();
419 STORM_LOG_DEBUG(
"Derived new predicate (based on weakest-precondition): " << newPredicate <<
".");
428template<storm::dd::DdType Type,
typename ValueType>
435 bool fromGuard =
false;
438 AbstractionInformation<Type>
const& abstractionInformation = abstractor.get().getAbstractionInformation();
442 auto pl1It = player1ChoiceAsAdd.
begin();
443 uint_fast64_t player1Index = abstractionInformation.decodePlayer1Choice((*pl1It).first, abstractionInformation.getPlayer1VariableCount());
447 bool buttomStateSuccessor = !((abstractionInformation.getBottomStateBdd(
false,
false) && choiceSuccessors)).isZero();
449 std::vector<storm::expressions::Expression> possibleRefinementPredicates;
453 if (buttomStateSuccessor) {
454 STORM_LOG_TRACE(
"One of the successors is a bottom state, taking a guard as a new predicate.");
455 possibleRefinementPredicates.emplace_back(abstractor.get().getGuard(player1Index));
457 STORM_LOG_DEBUG(
"Derived new predicate (based on guard): " << possibleRefinementPredicates.back());
459 STORM_LOG_TRACE(
"No bottom state successor. Deriving a new predicate using weakest precondition.");
462 std::map<uint64_t, std::pair<storm::storage::BitVector, ValueType>> choiceUpdateToSuccessorMapping =
463 abstractionInformation.template decodeChoiceToUpdateSuccessorMapping<ValueType>(choiceSuccessors);
464 std::vector<std::pair<uint64_t, ValueType>> sortedChoiceUpdateIndicesAndMasses;
465 for (
auto const& e : choiceUpdateToSuccessorMapping) {
466 sortedChoiceUpdateIndicesAndMasses.emplace_back(e.first, e.second.second);
468 std::sort(sortedChoiceUpdateIndicesAndMasses.begin(), sortedChoiceUpdateIndicesAndMasses.end(),
469 [](std::pair<uint64_t, ValueType>
const& a, std::pair<uint64_t, ValueType>
const& b) { return a.second > b.second; });
472 std::set<storm::expressions::Variable> variablesToAbstract = game.
getRowVariables();
480 std::vector<std::map<uint64_t, std::pair<storm::storage::BitVector, ValueType>>> otherChoicesUpdateToSuccessorMappings =
481 abstractionInformation.template decodeChoicesToUpdateSuccessorMapping<ValueType>(game.
getPlayer2Variables(), otherChoices);
483 for (
auto const& otherChoice : otherChoicesUpdateToSuccessorMappings) {
484 for (uint64_t updateIndex = 0; updateIndex < sortedChoiceUpdateIndicesAndMasses.size(); ++updateIndex) {
486 choiceUpdateToSuccessorMapping.at(sortedChoiceUpdateIndicesAndMasses[updateIndex].first).first;
487 storm::storage::BitVector const& otherChoiceSuccessor = otherChoice.at(sortedChoiceUpdateIndicesAndMasses[updateIndex].first).first;
489 bool deviates = choiceSuccessor != otherChoiceSuccessor;
491 std::map<storm::expressions::Variable, storm::expressions::Expression> variableUpdates =
492 abstractor.
get().getVariableUpdates(player1Index, sortedChoiceUpdateIndicesAndMasses[updateIndex].first);
494 for (uint64_t predicateIndex = 0; predicateIndex < choiceSuccessor.
size(); ++predicateIndex) {
495 if (choiceSuccessor[predicateIndex] != otherChoiceSuccessor[predicateIndex]) {
496 possibleRefinementPredicates.push_back(
497 abstractionInformation.getPredicateByIndex(predicateIndex).substitute(variableUpdates).simplify());
498 if (!rankPredicates) {
509 STORM_LOG_ASSERT(!possibleRefinementPredicates.empty(),
"Expected refinement predicates.");
512 for (
auto const& pred : possibleRefinementPredicates) {
518 {possibleRefinementPredicates});
521template<storm::dd::DdType Type,
typename ValueType>
547 constraint &= minPlayer2Strategy.
exclusiveOr(maxPlayer2Strategy);
555template<storm::dd::DdType Type,
typename ValueType>
556RefinementPredicates MenuGameRefiner<Type, ValueType>::derivePredicatesFromPivotState(
563 bool player1ChoicesDifferent = !(pivotState && minPlayer1Strategy).exclusiveOr(pivotState && maxPlayer1Strategy).isZero();
565 boost::optional<RefinementPredicates> predicates;
569 storm::dd::Bdd<Type> lowerChoice1 = (lowerChoice && minPlayer2Strategy).existsAbstract(variablesToAbstract);
570 storm::dd::Bdd<Type> lowerChoice2 = (lowerChoice && maxPlayer2Strategy).existsAbstract(variablesToAbstract);
572 bool lowerChoicesDifferent = !lowerChoice1.
exclusiveOr(lowerChoice2).isZero() && !lowerChoice1.
isZero() && !lowerChoice2.
isZero();
573 if (lowerChoicesDifferent) {
575 if (this->addPredicatesEagerly) {
576 predicates = derivePredicatesFromChoice(game, pivotState, (pivotState && minPlayer1Strategy).existsAbstract(game.
getRowVariables()),
577 lowerChoice && minPlayer2Strategy, lowerChoice1);
580 derivePredicatesFromDifferingChoices((pivotState && minPlayer1Strategy).existsAbstract(game.
getRowVariables()), lowerChoice1, lowerChoice2);
584 if (predicates && !player1ChoicesDifferent) {
585 return predicates.get();
588 boost::optional<RefinementPredicates> additionalPredicates;
591 storm::dd::Bdd<Type> upperChoice1 = (upperChoice && minPlayer2Strategy).existsAbstract(variablesToAbstract);
592 storm::dd::Bdd<Type> upperChoice2 = (upperChoice && maxPlayer2Strategy).existsAbstract(variablesToAbstract);
594 bool upperChoicesDifferent = !upperChoice1.
exclusiveOr(upperChoice2).isZero() && !upperChoice1.
isZero() && !upperChoice2.
isZero();
595 if (upperChoicesDifferent) {
597 if (this->addPredicatesEagerly) {
598 additionalPredicates = derivePredicatesFromChoice(game, pivotState, (pivotState && maxPlayer1Strategy).existsAbstract(game.
getRowVariables()),
599 upperChoice && maxPlayer2Strategy, upperChoice1);
601 additionalPredicates =
602 derivePredicatesFromDifferingChoices((pivotState && maxPlayer1Strategy).existsAbstract(game.
getRowVariables()), upperChoice1, upperChoice2);
606 if (additionalPredicates) {
608 return additionalPredicates.get();
611 predicates = additionalPredicates;
613 predicates.get().addPredicates(additionalPredicates.get().getPredicates());
618 STORM_LOG_THROW(
static_cast<bool>(predicates), storm::exceptions::InvalidStateException,
"Could not derive predicates for refinement.");
620 return predicates.get();
623template<storm::dd::DdType Type,
typename ValueType>
624std::pair<std::vector<std::vector<storm::expressions::Expression>>, std::map<storm::expressions::Variable, storm::expressions::Expression>>
628 std::vector<std::vector<storm::expressions::Expression>> predicates;
631 AbstractionInformation<Type>
const& abstractionInformation = abstractor.get().getAbstractionInformation();
632 std::set<storm::expressions::Variable> variablesToAbstract(game.
getColumnVariables());
638 std::set<storm::expressions::Variable> oldVariables = initialExpression.
getVariables();
639 for (
auto const& predicate : abstractionInformation.getPredicates()) {
640 std::set<storm::expressions::Variable> usedVariables = predicate.getVariables();
641 oldVariables.insert(usedVariables.begin(), usedVariables.end());
644 std::map<storm::expressions::Variable, storm::expressions::Variable> oldToNewVariables;
645 for (
auto const& variable : oldVariables) {
646 oldToNewVariables[variable] = expressionManager.
getVariable(variable.getName());
648 std::map<storm::expressions::Variable, storm::expressions::Expression> lastSubstitution;
649 for (
auto const& variable : oldToNewVariables) {
650 lastSubstitution[variable.second] = variable.second;
652 std::map<storm::expressions::Variable, storm::expressions::Expression> stepVariableToCopiedVariableMap;
656 predicates.emplace_back(abstractionInformation.getPredicates(decodedTargetState));
657 for (
auto& predicate : predicates.back()) {
658 predicate = predicate.changeManager(expressionManager);
661 for (
auto const& pred : abstractionInformation.getConstraints()) {
662 predicates.back().push_back(pred.changeManager(expressionManager));
669 std::tuple<storm::storage::BitVector, uint64_t, uint64_t> decodedPredecessor =
670 abstractionInformation.decodeStatePlayer1ChoiceAndUpdate(predecessorTransition);
673 std::map<storm::expressions::Variable, storm::expressions::Expression> substitution;
674 for (
auto const& variablePair : oldToNewVariables) {
676 substitution[variablePair.second] = variableCopy;
677 stepVariableToCopiedVariableMap[variableCopy] = variablePair.second;
681 auto variableUpdates = abstractor.get().getVariableUpdates(std::get<1>(decodedPredecessor), std::get<2>(decodedPredecessor));
682 for (
auto const& oldNewVariablePair : oldToNewVariables) {
686 auto updateIt = variableUpdates.find(oldNewVariablePair.first);
687 if (updateIt != variableUpdates.end()) {
688 auto const& update = *updateIt;
690 if (update.second.hasBooleanType()) {
691 predicates.back().push_back(
692 storm::expressions::iff(lastSubstitution.at(newVariable), update.second.changeManager(expressionManager).substitute(substitution)));
694 predicates.back().push_back(lastSubstitution.at(newVariable) == update.second.changeManager(expressionManager).substitute(substitution));
699 predicates.back().push_back(
storm::expressions::iff(lastSubstitution.at(newVariable), substitution.at(newVariable)));
701 predicates.back().push_back(lastSubstitution.at(newVariable) == substitution.at(newVariable));
707 predicates.back().push_back(abstractor.get().getGuard(std::get<1>(decodedPredecessor)).changeManager(expressionManager).substitute(substitution));
710 predicates.emplace_back(abstractionInformation.getPredicates(std::get<0>(decodedPredecessor)));
711 for (
auto& predicate : predicates.back()) {
712 predicate = predicate.changeManager(expressionManager).substitute(substitution);
715 for (
auto const& pred : abstractionInformation.getConstraints()) {
716 predicates.back().push_back(pred.changeManager(expressionManager).substitute(substitution));
719 lastSubstitution = std::move(substitution);
720 currentState = predecessorTransition.
existsAbstract(variablesToAbstract);
724 return std::make_pair(predicates, stepVariableToCopiedVariableMap);
727template<
typename ValueType>
730template<storm::dd::DdType Type,
typename ValueType>
731std::pair<std::vector<uint64_t>, std::vector<uint64_t>> MenuGameRefiner<Type, ValueType>::buildReversedLabeledPath(
732 ExplicitPivotStateResult<ValueType>
const& pivotStateResult)
const {
733 std::pair<std::vector<uint64_t>, std::vector<uint64_t>> result;
734 result.first.emplace_back(pivotStateResult.pivotState);
736 uint64_t currentState = pivotStateResult.predecessors[pivotStateResult.pivotState].first;
737 uint64_t currentAction = pivotStateResult.predecessors[pivotStateResult.pivotState].second;
740 result.first.emplace_back(currentState);
741 result.second.emplace_back(currentAction);
742 currentAction = pivotStateResult.predecessors[currentState].second;
743 currentState = pivotStateResult.predecessors[currentState].first;
746 STORM_LOG_ASSERT(result.first.size() == result.second.size() + 1,
"Path size mismatch.");
750template<storm::dd::DdType Type,
typename ValueType>
751std::pair<std::vector<std::vector<storm::expressions::Expression>>, std::map<storm::expressions::Variable, storm::expressions::Expression>>
753 std::vector<uint64_t>
const& reversedPath, std::vector<uint64_t>
const& reversedLabels,
754 storm::dd::Odd const& odd, std::vector<uint64_t>
const* stateToOffset)
const {
755 STORM_LOG_ASSERT(reversedPath.size() == reversedLabels.size() + 1,
"Path size mismatch.");
757 std::vector<std::vector<storm::expressions::Expression>> predicates;
759 AbstractionInformation<Type>
const& abstractionInformation = abstractor.get().getAbstractionInformation();
762 std::set<storm::expressions::Variable> oldVariables = initialExpression.
getVariables();
763 for (
auto const& predicate : abstractionInformation.getPredicates()) {
764 std::set<storm::expressions::Variable> usedVariables = predicate.getVariables();
765 oldVariables.insert(usedVariables.begin(), usedVariables.end());
768 std::map<storm::expressions::Variable, storm::expressions::Variable> oldToNewVariables;
769 for (
auto const& variable : oldVariables) {
770 oldToNewVariables[variable] = expressionManager.
getVariable(variable.getName());
772 std::map<storm::expressions::Variable, storm::expressions::Expression> currentSubstitution;
773 for (
auto const& variable : oldToNewVariables) {
774 currentSubstitution[variable.second] = variable.second;
776 std::map<storm::expressions::Variable, storm::expressions::Expression> stepVariableToCopiedVariableMap;
778 auto pathIt = reversedPath.rbegin();
784 uint64_t predicateValuationOffset = abstractionInformation.getNumberOfDdSourceLocationVariables() + 1;
786 odd.
getEncoding(stateToOffset ? (*stateToOffset)[*pathIt] : *pathIt, abstractionInformation.getNumberOfPredicates() + predicateValuationOffset);
790 predicates.emplace_back(abstractionInformation.getPredicatesExcludingBottom(extendedPredicateValuation));
791 for (
auto& predicate : predicates.back()) {
792 predicate = predicate.changeManager(expressionManager);
796 for (
auto const& pred : abstractionInformation.getConstraints()) {
797 predicates.back().push_back(pred.changeManager(expressionManager));
801 predicates.back().push_back(initialExpression.
changeManager(expressionManager));
804 auto actionIt = reversedLabels.
rbegin();
805 for (; pathIt != reversedPath.rend(); ++pathIt) {
807 predicates.emplace_back();
810 predicates.back().emplace_back(abstractor.get().getGuard(*actionIt).changeManager(expressionManager).substitute(currentSubstitution));
813 std::set<storm::expressions::Variable>
const& assignedVariables = abstractor.get().getAssignedVariables(*actionIt);
816 std::map<storm::expressions::Variable, storm::expressions::Variable> newVariableMaps;
817 for (
auto const& variable : assignedVariables) {
819 newVariableMaps[oldToNewVariables.at(variable)] = variableCopy;
820 stepVariableToCopiedVariableMap[variableCopy] = variable;
824 auto variableUpdateVector = abstractor.get().getVariableUpdates(*actionIt);
828 for (
auto const& variableUpdates : variableUpdateVector) {
830 for (
auto const& update : variableUpdates) {
831 if (update.second.hasBooleanType()) {
832 variableUpdateExpression =
834 update.second.changeManager(expressionManager).substitute(currentSubstitution));
836 variableUpdateExpression = variableUpdateExpression && newVariableMaps.at(update.first) ==
841 allVariableUpdateExpression = allVariableUpdateExpression || variableUpdateExpression;
844 allVariableUpdateExpression = expressionManager.
boolean(
true);
846 predicates.back().emplace_back(allVariableUpdateExpression);
849 for (
auto const& variablePair : newVariableMaps) {
850 currentSubstitution[variablePair.first] = variablePair.second;
854 extendedPredicateValuation =
855 odd.
getEncoding(stateToOffset ? (*stateToOffset)[*pathIt] : *pathIt, abstractionInformation.getNumberOfPredicates() + predicateValuationOffset);
859 for (uint64_t predicateIndex = 0; predicateIndex < abstractionInformation.getNumberOfPredicates(); ++predicateIndex) {
860 auto const& predicate = abstractionInformation.getPredicateByIndex(predicateIndex);
861 std::set<storm::expressions::Variable> usedVariables = predicate.getVariables();
863 bool containsAssignedVariables =
false;
864 for (
auto usedIt = usedVariables.begin(), assignedIt = assignedVariables.begin();;) {
865 if (usedIt == usedVariables.end() || assignedIt == assignedVariables.end()) {
869 if (*usedIt == *assignedIt) {
870 containsAssignedVariables =
true;
874 if (*usedIt < *assignedIt) {
881 if (containsAssignedVariables) {
882 auto transformedPredicate = predicate.changeManager(expressionManager).substitute(currentSubstitution);
883 predicates.back().emplace_back(extendedPredicateValuation.
get(predicateIndex + predicateValuationOffset) ? transformedPredicate
884 : !transformedPredicate);
889 for (
auto const& constraint : abstractionInformation.getConstraints()) {
890 std::set<storm::expressions::Variable> usedVariables = constraint.getVariables();
892 bool containsAssignedVariables =
false;
893 for (
auto usedIt = usedVariables.begin(), assignedIt = assignedVariables.begin();;) {
894 if (usedIt == usedVariables.end() || assignedIt == assignedVariables.end()) {
898 if (*usedIt == *assignedIt) {
899 containsAssignedVariables =
true;
903 if (*usedIt < *assignedIt) {
910 if (containsAssignedVariables) {
911 auto transformedConstraint = constraint.changeManager(expressionManager).substitute(currentSubstitution);
912 predicates.back().emplace_back(transformedConstraint);
919 return std::make_pair(predicates, stepVariableToCopiedVariableMap);
922template<storm::dd::DdType Type,
typename ValueType>
923boost::optional<RefinementPredicates> MenuGameRefiner<Type, ValueType>::derivePredicatesFromInterpolationFromTrace(
925 std::map<storm::expressions::Variable, storm::expressions::Expression>
const& variableSubstitution)
const {
926 AbstractionInformation<Type>
const& abstractionInformation = abstractor.get().getAbstractionInformation();
928 auto start = std::chrono::high_resolution_clock::now();
929 boost::optional<RefinementPredicates> predicates;
932 auto assertionStart = std::chrono::high_resolution_clock::now();
934 uint64_t stepCounter = 0;
935 for (
auto const& traceElement : trace) {
938 interpolatingSolver.setInterpolationGroup(stepCounter);
939 for (
auto const& predicate : traceElement) {
940 interpolatingSolver.add(predicate);
945 auto assertionEnd = std::chrono::high_resolution_clock::now();
946 STORM_LOG_TRACE(
"Asserting trace formula took " << std::chrono::duration_cast<std::chrono::milliseconds>(assertionEnd - assertionStart).
count() <<
"ms.");
951 STORM_LOG_TRACE(
"Trace formula is unsatisfiable. Starting interpolation.");
953 std::vector<storm::expressions::Expression> interpolants;
954 std::vector<uint64_t> prefix;
955 for (uint64_t step = 0; step < stepCounter; ++step) {
956 prefix.push_back(step);
958 interpolatingSolver.getInterpolant(prefix).
substitute(variableSubstitution).
changeManager(abstractionInformation.getExpressionManager());
961 STORM_LOG_TRACE(
"Trace formula became unsatisfiable at position " << step <<
" of " << stepCounter <<
".");
964 if (!interpolant.
isTrue()) {
965 STORM_LOG_DEBUG(
"Derived new predicate (based on interpolation at step " << step <<
" out of " << stepCounter <<
"): " << interpolant);
966 interpolants.push_back(interpolant);
970 STORM_LOG_ASSERT(!interpolants.empty(),
"Expected to have non-empty set of interpolants.");
974 STORM_LOG_TRACE(
"Trace formula is satisfiable, not using interpolation.");
976 auto end = std::chrono::high_resolution_clock::now();
979 STORM_LOG_TRACE(
"Deriving predicates using interpolation from witness of size "
980 << trace.size() <<
" took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() <<
"ms.");
982 STORM_LOG_TRACE(
"Tried deriving predicates using interpolation but failed in "
983 << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count() <<
"ms.");
989template<storm::dd::DdType Type,
typename ValueType>
990boost::optional<RefinementPredicates> MenuGameRefiner<Type, ValueType>::derivePredicatesFromInterpolation(
995 SymbolicMostProbablePathsResult<Type, ValueType> symbolicMostProbablePathsResult;
996 if (!symbolicPivotStateResult.symbolicMostProbablePathsResult) {
997 symbolicMostProbablePathsResult =
getMostProbablePathSpanningTree(game, symbolicPivotStateResult.fromDirection == storm::OptimizationDirection::Minimize
998 ? minPlayer1Strategy && minPlayer2Strategy
999 : maxPlayer1Strategy && maxPlayer2Strategy);
1001 symbolicMostProbablePathsResult = symbolicPivotStateResult.symbolicMostProbablePathsResult.get();
1005 AbstractionInformation<Type>
const& abstractionInformation = abstractor.get().getAbstractionInformation();
1006 std::shared_ptr<storm::expressions::ExpressionManager> interpolationManager = abstractionInformation.getExpressionManager().
clone();
1009 auto start = std::chrono::high_resolution_clock::now();
1010 std::pair<std::vector<std::vector<storm::expressions::Expression>>, std::map<storm::expressions::Variable, storm::expressions::Expression>>
1011 traceAndVariableSubstitution =
1012 buildTrace(*interpolationManager, game, symbolicMostProbablePathsResult.spanningTree, symbolicPivotStateResult.pivotState);
1013 auto end = std::chrono::high_resolution_clock::now();
1014 STORM_LOG_DEBUG(
"Building the trace and variable substitution for interpolation from symbolic most-probable paths result took "
1015 << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count() <<
"ms.");
1017 return derivePredicatesFromInterpolationFromTrace(*interpolationManager, traceAndVariableSubstitution.first, traceAndVariableSubstitution.second);
1020template<storm::dd::DdType Type,
typename ValueType>
1021boost::optional<RefinementPredicates> MenuGameRefiner<Type, ValueType>::derivePredicatesFromInterpolation(
1026 AbstractionInformation<Type>
const& abstractionInformation = abstractor.get().getAbstractionInformation();
1027 std::shared_ptr<storm::expressions::ExpressionManager> interpolationManager = abstractionInformation.getExpressionManager().clone();
1030 auto start = std::chrono::high_resolution_clock::now();
1031 std::pair<std::vector<uint64_t>, std::vector<uint64_t>> labeledReversedPath = buildReversedLabeledPath(pivotStateResult);
1034 if (labeledReversedPath.first.size() == 1) {
1038 std::pair<std::vector<std::vector<storm::expressions::Expression>>, std::map<storm::expressions::Variable, storm::expressions::Expression>>
1039 traceAndVariableSubstitution = buildTraceFromReversedLabeledPath(*interpolationManager, labeledReversedPath.first, labeledReversedPath.second, odd);
1040 auto end = std::chrono::high_resolution_clock::now();
1041 STORM_LOG_DEBUG(
"Building the trace and variable substitution for interpolation from explicit most-probable paths result took "
1042 << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count() <<
"ms.");
1044 return derivePredicatesFromInterpolationFromTrace(*interpolationManager, traceAndVariableSubstitution.first, traceAndVariableSubstitution.second);
1047template<storm::dd::DdType Type,
typename ValueType>
1059 auto oldMinPlayer1Strategy = minPlayer1Strategy;
1060 minPlayer1Strategy = (maxPlayer1Strategy && qualitativeResult.
prob0Min.getPlayer2States())
1062 .
ite(maxPlayer1Strategy, minPlayer1Strategy);
1066 computePivotStates(game, transitionMatrixBdd, minPlayer1Strategy, minPlayer2Strategy, maxPlayer1Strategy, maxPlayer2Strategy);
1080 pickPivotState<Type, ValueType>(pivotSelectionHeuristic, game, pivotStateCandidatesResult, qualitativeResult, boost::none);
1082 boost::optional<RefinementPredicates> predicates;
1083 if (useInterpolation) {
1085 derivePredicatesFromInterpolation(game, symbolicPivotStateResult, minPlayer1Strategy, minPlayer2Strategy, maxPlayer1Strategy, maxPlayer2Strategy);
1090 predicates = derivePredicatesFromPivotState(game, symbolicPivotStateResult.
pivotState, minPlayer1Strategy, minPlayer2Strategy, maxPlayer1Strategy,
1091 maxPlayer2Strategy);
1093 STORM_LOG_THROW(
static_cast<bool>(predicates), storm::exceptions::InvalidStateException,
"Predicates needed to continue.");
1096 std::vector<storm::expressions::Expression> preparedPredicates = preprocessPredicates(predicates.get().getPredicates(), predicates.get().getSource());
1097 performRefinement(createGlobalRefinement(preparedPredicates));
1101template<
typename ValueType>
1112template<
typename ValueType>
1135template<
typename ValueType>
1137 bool probabilityDistances, std::vector<ValueType>& distances, std::vector<std::pair<uint64_t, uint64_t>>& predecessors,
1138 bool generatePredecessors,
bool lower, uint64_t currentState, ValueType
const& currentDistance, [[maybe_unused]]
bool isPivotState,
1146 STORM_LOG_ASSERT(isPivotState || !otherStrategyPair.getPlayer2Strategy().hasDefinedChoice(player2Successor) ||
1148 "Did not expect deviation in player 2 strategy.");
1149 STORM_LOG_ASSERT(player2Grouping[player2Successor] <= player2Choice && player2Choice < player2Grouping[player2Successor + 1],
1150 "Illegal choice for player 2.");
1152 for (
auto const& entry : transitionMatrix.
getRow(player2Choice)) {
1153 uint64_t player1Successor = entry.getColumn();
1154 if (!relevantStates.
get(player1Successor)) {
1158 ValueType alternateDistance;
1159 if (probabilityDistances) {
1160 alternateDistance = currentDistance * entry.getValue();
1162 alternateDistance = currentDistance + storm::utility::one<ValueType>();
1164 if (probabilityDistances ? alternateDistance > distances[player1Successor] : alternateDistance < distances[player1Successor]) {
1165 distances[player1Successor] = alternateDistance;
1166 if (generatePredecessors) {
1167 predecessors[player1Successor] = std::make_pair(currentState, player1Labeling[player2Successor]);
1169 dijkstraQueue.emplace(alternateDistance, player1Successor, lower);
1173 STORM_LOG_ASSERT(targetStates.get(currentState),
"Expecting min strategy for non-target states.");
1177template<
typename ValueType>
1183 std::vector<ValueType>
const* lowerValues =
nullptr, std::vector<ValueType>
const* upperValues =
nullptr) {
1185 STORM_LOG_ASSERT(!lowerValues || upperValues,
"Expected none or both value results.");
1186 STORM_LOG_ASSERT(!upperValues || lowerValues,
"Expected none or both value results.");
1194 uint64_t numberOfStates = initialStates.
size();
1195 ValueType inftyDistance = probabilityDistances ? storm::utility::zero<ValueType>() : storm::utility::infinity<ValueType>();
1196 ValueType zeroDistance = probabilityDistances ? storm::utility::one<ValueType>() : storm::utility::zero<ValueType>();
1199 std::vector<ValueType> lowerDistances(numberOfStates, inftyDistance);
1200 std::vector<std::pair<uint64_t, uint64_t>> lowerPredecessors;
1201 std::vector<ValueType> upperDistances(numberOfStates, inftyDistance);
1202 std::vector<std::pair<uint64_t, uint64_t>> upperPredecessors;
1204 if (generatePredecessors) {
1205 lowerPredecessors.resize(numberOfStates,
1207 upperPredecessors.resize(numberOfStates,
1214 for (
auto initialState : initialStates) {
1215 if (!relevantStates.
get(initialState)) {
1219 lowerDistances[initialState] = zeroDistance;
1220 upperDistances[initialState] = zeroDistance;
1221 dijkstraQueue.emplace(zeroDistance, initialState,
true);
1222 dijkstraQueue.emplace(zeroDistance, initialState,
false);
1228 lowerValues && upperValues;
1229 bool foundPivotState =
false;
1232 ValueType pivotStateDeviation = storm::utility::zero<ValueType>();
1235 while (!dijkstraQueue.empty()) {
1237 auto currentDijkstraElement = *dijkstraQueue.begin();
1238 ValueType currentDistance = currentDijkstraElement.distance;
1239 uint64_t currentState = currentDijkstraElement.state;
1240 bool currentLower = currentDijkstraElement.lower;
1241 dijkstraQueue.erase(dijkstraQueue.begin());
1243 if (foundPivotState && (probabilityDistances ? currentDistance < pivotState.distance : currentDistance > pivotState.
distance)) {
1250 pivotState.
lower ? std::move(lowerPredecessors) : std::move(upperPredecessors));
1251 }
else if (pivotStateDeviation >= currentDistance) {
1255 pivotState.
lower ? std::move(lowerPredecessors) : std::move(upperPredecessors));
1260 bool isPivotState =
false;
1266 isPivotState =
true;
1274 isPivotState =
true;
1280 if (considerDeviation && foundPivotState) {
1281 ValueType deviationOfCurrentState = (*upperValues)[currentState] - (*lowerValues)[currentState];
1283 if (deviationOfCurrentState > pivotStateDeviation) {
1284 pivotState = currentDijkstraElement;
1285 pivotStateDeviation = deviationOfCurrentState;
1288 pivotStateDeviation *= currentDistance;
1291 }
else if (!foundPivotState) {
1292 pivotState = currentDijkstraElement;
1293 foundPivotState =
true;
1297 if (!considerDeviation) {
1299 pivotState.
lower ? std::move(lowerPredecessors) : std::move(upperPredecessors));
1304 if (!lowerValues || !upperValues || (*lowerValues)[currentState] < (*upperValues)[currentState]) {
1306 performDijkstraStep(dijkstraQueue, probabilityDistances, lowerDistances, lowerPredecessors, generatePredecessors,
true, currentState,
1307 currentDistance, isPivotState, minStrategyPair, maxStrategyPair, player1Labeling, player2Grouping, transitionMatrix,
1308 targetStates, relevantStates);
1310 performDijkstraStep(dijkstraQueue, probabilityDistances, upperDistances, upperPredecessors, generatePredecessors,
false, currentState,
1311 currentDistance, isPivotState, maxStrategyPair, minStrategyPair, player1Labeling, player2Grouping, transitionMatrix,
1312 targetStates, relevantStates);
1317 if (foundPivotState) {
1319 pivotState.
lower ? std::move(lowerPredecessors) : std::move(upperPredecessors));
1324 STORM_LOG_TRACE(
"Did not find pivot state in explicit Dijkstra search.");
1328template<storm::dd::DdType Type,
typename ValueType>
1329boost::optional<RefinementPredicates> MenuGameRefiner<Type, ValueType>::derivePredicatesFromInterpolationReversedPath(
1331 std::vector<uint64_t>
const& stateToOffset, std::vector<uint64_t>
const& reversedLabels)
const {
1333 auto start = std::chrono::high_resolution_clock::now();
1334 std::pair<std::vector<std::vector<storm::expressions::Expression>>, std::map<storm::expressions::Variable, storm::expressions::Expression>>
1335 traceAndVariableSubstitution = buildTraceFromReversedLabeledPath(interpolationManager, reversedPath, reversedLabels, odd, &stateToOffset);
1336 auto end = std::chrono::high_resolution_clock::now();
1337 STORM_LOG_DEBUG(
"Building the trace and variable substitution for interpolation from explicit most-probable paths result took "
1338 << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() <<
"ms.");
1340 return derivePredicatesFromInterpolationFromTrace(interpolationManager, traceAndVariableSubstitution.first, traceAndVariableSubstitution.second);
1343template<storm::dd::DdType Type,
typename ValueType>
1346 [[maybe_unused]] std::vector<uint64_t>
const& player1Grouping, std::vector<uint64_t>
const& player1Labeling,
1353 (void)constraintStates;
1358 boost::optional<ExplicitPivotStateResult<ValueType>> optionalPivotStateResult =
1359 pickPivotState(useInterpolation, pivotSelectionHeuristic, transitionMatrix, player1Labeling, initialStates, relevantStates, targetStates,
1360 minStrategyPair, maxStrategyPair);
1363 if (!optionalPivotStateResult) {
1369 auto const& pivotStateResult = optionalPivotStateResult.get();
1370 STORM_LOG_TRACE(
"Found pivot state " << pivotStateResult.pivotState <<
" with distance " << pivotStateResult.distance <<
".");
1373 auto const& abstractionInformation = abstractor.get().getAbstractionInformation();
1374 uint64_t pivotState = pivotStateResult.pivotState;
1382 STORM_LOG_ASSERT(player1Grouping[pivotState] <= player2State && player2State < player1Grouping[pivotState + 1],
"Illegal choice for player 1.");
1383 minPlayer1Strategy |=
1384 symbolicPivotState && abstractionInformation.encodePlayer1Choice(player1Labeling[player2State], abstractionInformation.getPlayer1VariableCount());
1388 minPlayer2Strategy |=
1389 minPlayer1Strategy && abstractionInformation.encodePlayer2Choice(player2Labeling[player2Choice], 0, game.
getPlayer2Variables().size());
1393 maxPlayer2Strategy |=
1394 minPlayer1Strategy && abstractionInformation.encodePlayer2Choice(player2Labeling[player2Choice], 0, game.
getPlayer2Variables().size());
1399 STORM_LOG_ASSERT(player1Grouping[pivotState] <= player2State && player2State < player1Grouping[pivotState + 1],
"Illegal choice for player 1.");
1400 maxPlayer1Strategy |=
1401 symbolicPivotState && abstractionInformation.encodePlayer1Choice(player1Labeling[player2State], abstractionInformation.getPlayer1VariableCount());
1405 minPlayer2Strategy |=
1406 maxPlayer1Strategy && abstractionInformation.encodePlayer2Choice(player2Labeling[player2Choice], 0, game.
getPlayer2Variables().size());
1410 maxPlayer2Strategy |=
1411 maxPlayer1Strategy && abstractionInformation.encodePlayer2Choice(player2Labeling[player2Choice], 0, game.
getPlayer2Variables().size());
1414 auto end = std::chrono::high_resolution_clock::now();
1416 boost::optional<RefinementPredicates> predicates;
1417 if (useInterpolation) {
1418 predicates = derivePredicatesFromInterpolation(game, pivotStateResult, odd);
1421 predicates = derivePredicatesFromPivotState(game, symbolicPivotState, minPlayer1Strategy, minPlayer2Strategy, maxPlayer1Strategy, maxPlayer2Strategy);
1423 end = std::chrono::high_resolution_clock::now();
1424 STORM_LOG_THROW(
static_cast<bool>(predicates), storm::exceptions::InvalidStateException,
"Predicates needed to continue.");
1426 std::vector<storm::expressions::Expression> preparedPredicates = preprocessPredicates(predicates.get().getPredicates(), predicates.get().getSource());
1427 performRefinement(createGlobalRefinement(preparedPredicates));
1431template<storm::dd::DdType Type,
typename ValueType>
1434 [[maybe_unused]] std::vector<uint64_t>
const& player1Grouping, std::vector<uint64_t>
const& player1Labeling,
1441 (void)constraintStates;
1446 boost::optional<ExplicitPivotStateResult<ValueType>> optionalPivotStateResult =
1447 pickPivotState(useInterpolation, pivotSelectionHeuristic, transitionMatrix, player1Labeling, initialStates, relevantStates, targetStates,
1448 minStrategyPair, maxStrategyPair, &quantitativeResult.
getMin().getValues(), &quantitativeResult.
getMax().getValues());
1450 STORM_LOG_THROW(optionalPivotStateResult, storm::exceptions::InvalidStateException,
"Did not find pivot state to proceed.");
1453 auto const& pivotStateResult = optionalPivotStateResult.get();
1454 STORM_LOG_TRACE(
"Found pivot state " << pivotStateResult.pivotState <<
" with distance " << pivotStateResult.distance <<
".");
1457 auto const& abstractionInformation = abstractor.get().getAbstractionInformation();
1458 uint64_t pivotState = pivotStateResult.pivotState;
1466 STORM_LOG_ASSERT(player1Grouping[pivotState] <= player2State && player2State < player1Grouping[pivotState + 1],
"Illegal choice for player 1.");
1467 minPlayer1Strategy |=
1468 symbolicPivotState && abstractionInformation.encodePlayer1Choice(player1Labeling[player2State], abstractionInformation.getPlayer1VariableCount());
1472 minPlayer2Strategy |=
1473 minPlayer1Strategy && abstractionInformation.encodePlayer2Choice(player2Labeling[player2Choice], 0, game.
getPlayer2Variables().size());
1477 maxPlayer2Strategy |=
1478 minPlayer1Strategy && abstractionInformation.encodePlayer2Choice(player2Labeling[player2Choice], 0, game.
getPlayer2Variables().size());
1483 STORM_LOG_ASSERT(player1Grouping[pivotState] <= player2State && player2State < player1Grouping[pivotState + 1],
"Illegal choice for player 1.");
1484 maxPlayer1Strategy |=
1485 symbolicPivotState && abstractionInformation.encodePlayer1Choice(player1Labeling[player2State], abstractionInformation.getPlayer1VariableCount());
1489 minPlayer2Strategy |=
1490 maxPlayer1Strategy && abstractionInformation.encodePlayer2Choice(player2Labeling[player2Choice], 0, game.
getPlayer2Variables().size());
1494 maxPlayer2Strategy |=
1495 maxPlayer1Strategy && abstractionInformation.encodePlayer2Choice(player2Labeling[player2Choice], 0, game.
getPlayer2Variables().size());
1499 boost::optional<RefinementPredicates> predicates;
1500 if (useInterpolation) {
1501 predicates = derivePredicatesFromInterpolation(game, pivotStateResult, odd);
1504 predicates = derivePredicatesFromPivotState(game, symbolicPivotState, minPlayer1Strategy, minPlayer2Strategy, maxPlayer1Strategy, maxPlayer2Strategy);
1506 STORM_LOG_THROW(
static_cast<bool>(predicates), storm::exceptions::InvalidStateException,
"Predicates needed to continue.");
1508 std::vector<storm::expressions::Expression> preparedPredicates = preprocessPredicates(predicates.get().getPredicates(), predicates.get().getSource());
1509 performRefinement(createGlobalRefinement(preparedPredicates));
1513template<storm::dd::DdType Type,
typename ValueType>
1525 computePivotStates(game, transitionMatrixBdd, minPlayer1Strategy, minPlayer2Strategy, maxPlayer1Strategy, maxPlayer2Strategy);
1531 pickPivotState<Type, ValueType>(pivotSelectionHeuristic, game, pivotStateCandidatesResult, boost::none, quantitativeResult);
1533 boost::optional<RefinementPredicates> predicates;
1534 if (useInterpolation) {
1536 derivePredicatesFromInterpolation(game, symbolicPivotStateResult, minPlayer1Strategy, minPlayer2Strategy, maxPlayer1Strategy, maxPlayer2Strategy);
1541 predicates = derivePredicatesFromPivotState(game, symbolicPivotStateResult.
pivotState, minPlayer1Strategy, minPlayer2Strategy, maxPlayer1Strategy,
1542 maxPlayer2Strategy);
1544 STORM_LOG_THROW(
static_cast<bool>(predicates), storm::exceptions::InvalidStateException,
"Predicates needed to continue.");
1546 std::vector<storm::expressions::Expression> preparedPredicates = preprocessPredicates(predicates.get().getPredicates(), predicates.get().getSource());
1547 performRefinement(createGlobalRefinement(preparedPredicates));
1552 std::size_t
operator()(std::set<storm::expressions::Variable>
const& set)
const {
1557template<storm::dd::DdType Type,
typename ValueType>
1558std::vector<storm::expressions::Expression> MenuGameRefiner<Type, ValueType>::preprocessPredicates(
1565 auto start = std::chrono::high_resolution_clock::now();
1566 AbstractionInformation<Type>
const& abstractionInformation = abstractor.get().getAbstractionInformation();
1567 std::vector<storm::expressions::Expression> cleanedAtoms;
1569 std::unordered_map<std::set<storm::expressions::Variable>, std::vector<storm::expressions::Expression>, VariableSetHash> predicateClasses;
1571 for (
auto const& predicate : predicates) {
1573 std::vector<storm::expressions::Expression> atoms = splitter.split(predicate);
1576 for (
auto const& atom : atoms) {
1577 std::set<storm::expressions::Variable> vars = atom.getVariables();
1578 predicateClasses[vars].push_back(atom);
1583 uint64_t checkCounter = 0;
1584 for (
auto& predicateClass : predicateClasses) {
1585 std::vector<storm::expressions::Expression> cleanedAtomsOfClass;
1587 for (
auto const& predicate : predicateClass.second) {
1588 bool addPredicate =
true;
1589 for (
auto const& atom : cleanedAtomsOfClass) {
1590 if (predicate.areSame(atom)) {
1591 addPredicate =
false;
1596 if (equivalenceChecker.areEquivalentModuloNegation(predicate, atom)) {
1597 addPredicate =
false;
1602 cleanedAtomsOfClass.push_back(predicate);
1606 predicateClass.second = std::move(cleanedAtomsOfClass);
1609 std::unordered_map<std::set<storm::expressions::Variable>, std::vector<storm::expressions::Expression>, VariableSetHash> oldPredicateClasses;
1610 for (
auto const& oldPredicate : abstractionInformation.getPredicates()) {
1611 std::set<storm::expressions::Variable> vars = oldPredicate.getVariables();
1613 oldPredicateClasses[vars].push_back(oldPredicate);
1616 for (
auto const& predicateClass : predicateClasses) {
1617 auto oldPredicateClassIt = oldPredicateClasses.find(predicateClass.first);
1618 if (oldPredicateClassIt != oldPredicateClasses.end()) {
1619 for (
auto const& newAtom : predicateClass.second) {
1620 bool addAtom =
true;
1621 for (
auto const& oldPredicate : oldPredicateClassIt->second) {
1622 if (newAtom.areSame(oldPredicate)) {
1627 if (equivalenceChecker.areEquivalentModuloNegation(newAtom, oldPredicate)) {
1633 cleanedAtoms.push_back(newAtom);
1637 cleanedAtoms.insert(cleanedAtoms.end(), predicateClass.second.begin(), predicateClass.second.end());
1640 auto end = std::chrono::high_resolution_clock::now();
1641 STORM_LOG_TRACE(
"Preprocessing predicates took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count() <<
"ms (" << checkCounter
1644 return cleanedAtoms;
1652template<storm::dd::DdType Type,
typename ValueType>
1653std::vector<RefinementCommand> MenuGameRefiner<Type, ValueType>::createGlobalRefinement(std::vector<storm::expressions::Expression>
const& predicates)
const {
1654 std::vector<RefinementCommand> commands;
1655 commands.emplace_back(predicates);
1659template<storm::dd::DdType Type,
typename ValueType>
1660void MenuGameRefiner<Type, ValueType>::performRefinement(std::vector<RefinementCommand>
const& refinementCommands,
bool allowInjection)
const {
1661 if (!refinementPredicatesToInject.empty() && allowInjection) {
1664 for (
auto const& predicate : refinementPredicatesToInject.back()) {
1668 abstractor.get().refine(RefinementCommand(refinementPredicatesToInject.back()));
1669 refinementPredicatesToInject.pop_back();
1671 for (
auto const& command : refinementCommands) {
1672 STORM_LOG_INFO(
"Refining with " << command.getPredicates().size() <<
" predicates.");
1673 for (
auto const& predicate : command.getPredicates()) {
1676 if (!command.getPredicates().empty()) {
1677 abstractor.get().refine(command);
1683 for (
auto const& predicate : abstractor.get().getAbstractionInformation().getPredicates()) {
1688template<storm::dd::DdType Type,
typename ValueType>
1690 return addedAllGuardsFlag;
ValueType getMax() const
Retrieves the highest function value of any encoding.
Bdd< LibraryType > greater(Add< LibraryType, ValueType > const &other) const
Retrieves the function that maps all evaluations to one whose function value in the first ADD are gre...
Add< LibraryType, ValueType > maximum(Add< LibraryType, ValueType > const &other) const
Retrieves the function that maps all evaluations to the maximum of the function values of the two ADD...
Add< LibraryType, ValueType > maxAbstract(std::set< storm::expressions::Variable > const &metaVariables) const
Max-abstracts from the given meta variables.
AddIterator< LibraryType, ValueType > begin(bool enumerateDontCareMetaVariables=true) const
Retrieves an iterator that points to the first meta variable assignment with a non-zero function valu...
Bdd< LibraryType > toBdd() const
Converts the ADD to a BDD by mapping all values unequal to zero to 1.
Bdd< LibraryType > maxAbstractRepresentative(std::set< storm::expressions::Variable > const &metaVariables) const
Similar to maxAbstract, but does not abstract from the variables but rather picks a valuation of each...
Bdd< LibraryType > existsAbstract(std::set< storm::expressions::Variable > const &metaVariables) const
Existentially abstracts from the given meta variables.
bool isZero() const
Retrieves whether this DD represents the constant zero function.
virtual uint_fast64_t getNonZeroCount() const override
Retrieves the number of encodings that are mapped to a non-zero value.
static Bdd< LibraryType > getEncoding(DdManager< LibraryType > const &ddManager, uint64_t targetOffset, storm::dd::Odd const &odd, std::set< storm::expressions::Variable > const &metaVariables)
Constructs the BDD representation of the encoding with the given offset.
Bdd< LibraryType > swapVariables(std::vector< std::pair< storm::expressions::Variable, storm::expressions::Variable > > const &metaVariablePairs) const
Swaps the given pairs of meta variables in the BDD.
Bdd< LibraryType > existsAbstractRepresentative(std::set< storm::expressions::Variable > const &metaVariables) const
Similar to existsAbstract, but does not abstract from the variables but rather picks a valuation of e...
Bdd< LibraryType > ite(Bdd< LibraryType > const &thenBdd, Bdd< LibraryType > const &elseBdd) const
Performs an if-then-else with the given operands, i.e.
Bdd< LibraryType > exclusiveOr(Bdd< LibraryType > const &other) const
Performs a logical exclusive-or of the current and the given BDD.
Bdd< LibraryType > relationalProduct(Bdd< LibraryType > const &relation, std::set< storm::expressions::Variable > const &rowMetaVariables, std::set< storm::expressions::Variable > const &columnMetaVariables) const
Computes the relational product of the current BDD and the given BDD representing a relation.
uint_fast64_t getTotalOffset() const
Retrieves the total offset, i.e., the sum of the then- and else-offset.
storm::storage::BitVector getEncoding(uint64_t offset, uint64_t variableCount=0) const
Retrieves the encoding for the given offset.
void addConstraints(std::vector< storm::expressions::Expression > const &constraints)
bool isFalse() const
Checks if the expression is equal to the boolean literal false.
std::set< storm::expressions::Variable > getVariables() const
Retrieves the set of all variables that appear in the expression.
Expression changeManager(ExpressionManager const &newExpressionManager) const
Converts the expression to an expression over the variables of the provided expression manager.
Expression substitute(std::map< Variable, Expression > const &variableToExpressionMap) const
Substitutes all occurrences of the variables according to the given map.
bool isTrue() const
Checks if the expression is equal to the boolean literal true.
bool isInitialized() const
Checks whether the object encapsulates a base-expression.
This class is responsible for managing a set of typed variables and all expressions using these varia...
std::shared_ptr< ExpressionManager > clone() const
Creates a new expression manager with the same set of variables.
Variable declareVariableCopy(Variable const &variable)
Declares a variable that is a copy of the provided variable (i.e.
Variable getVariable(std::string const &name) const
Retrieves the expression that represents the variable with the given name.
Expression boolean(bool value) const
Creates an expression that characterizes the given boolean literal.
bool hasBooleanType() const
Checks whether the variable is of boolean type.
virtual storm::storage::BitVector const & getStates() const =0
ExplicitQualitativeResult const & getProb0Max() const
ExplicitQualitativeResult const & getProb1Min() const
ExplicitQualitativeResult const & getProb1Max() const
ExplicitQualitativeResult const & getProb0Min() const
ExplicitQuantitativeResult< ValueType > const & getMin() const
ExplicitQuantitativeResult< ValueType > const & getMax() const
RefinementPredicates()=default
void addPredicates(std::vector< storm::expressions::Expression > const &newPredicates)
std::vector< storm::expressions::Expression > const & getPredicates() const
SymbolicQualitativeGameResult< Type > prob0Min
SymbolicQualitativeGameResult< Type > prob1Max
SymbolicQuantitativeGameResult< Type, ValueType > max
SymbolicQuantitativeGameResult< Type, ValueType > min
storm::dd::DdManager< Type > & getManager() const
Retrieves the manager responsible for the DDs that represent this model.
std::set< storm::expressions::Variable > const & getColumnVariables() const
Retrieves the meta variables used to encode the columns of the transition matrix and the vector indic...
storm::dd::Bdd< Type > const & getInitialStates() const
Retrieves the initial states of the model.
std::vector< std::pair< storm::expressions::Variable, storm::expressions::Variable > > const & getRowColumnMetaVariablePairs() const
Retrieves the pairs of row and column meta variables.
std::set< storm::expressions::Variable > const & getRowVariables() const
Retrieves the meta variables used to encode the rows of the transition matrix and the vector indices.
virtual std::set< storm::expressions::Variable > const & getNondeterminismVariables() const override
Retrieves the meta variables used to encode the nondeterminism in the model.
std::set< storm::expressions::Variable > const & getPlayer1Variables() const
Retrieeves the set of meta variables used to encode the nondeterministic choices of player 1.
std::set< storm::expressions::Variable > const & getPlayer2Variables() const
Retrieeves the set of meta variables used to encode the nondeterministic choices of player 2.
This class represents the settings for the abstraction procedures.
@ NearestMaximalDeviation
A class that captures options that may be passed to the Mathsat solver.
CheckResult
possible check results
A bit vector that is internally represented as a vector of 64-bit values.
const_reverse_iterator rbegin() const
Returns a reverse iterator to the indices of the set bits in the bit vector.
bool full() const
Retrieves whether all bits are set in this bit vector.
size_t size() const
Retrieves the number of bits this bit vector can store.
bool get(uint64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
bool hasDefinedChoice(uint64_t state) const
uint64_t getChoice(uint64_t state) const
ExplicitGameStrategy & getPlayer1Strategy()
ExplicitGameStrategy & getPlayer2Strategy()
A class that holds a possibly non-square matrix in the compressed row storage format.
const_rows getRow(index_type row) const
Returns an object representing the given row.
std::vector< index_type > const & getRowGroupIndices() const
Returns the grouping of rows of this matrix.
#define STORM_LOG_INFO(message)
#define STORM_LOG_DEBUG(message)
#define STORM_LOG_TRACE(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
Expression ite(Expression const &condition, Expression const &thenExpression, Expression const &elseExpression)
Expression iff(Expression const &first, Expression const &second)
SymbolicPivotStateResult< Type, ValueType > pickPivotState(AbstractionSettings::PivotSelectionHeuristic const &heuristic, storm::gbar::abstraction::MenuGame< Type, ValueType > const &game, PivotStateCandidatesResult< Type > const &pivotStateCandidateResult, boost::optional< SymbolicQualitativeGameResultMinMax< Type > > const &qualitativeResult, boost::optional< SymbolicQuantitativeGameResultMinMax< Type, ValueType > > const &quantitativeResult)
PivotStateCandidatesResult< Type > computePivotStates(storm::gbar::abstraction::MenuGame< Type, ValueType > const &game, storm::dd::Bdd< Type > const &transitionMatrixBdd, storm::dd::Bdd< Type > const &minPlayer1Strategy, storm::dd::Bdd< Type > const &minPlayer2Strategy, storm::dd::Bdd< Type > const &maxPlayer1Strategy, storm::dd::Bdd< Type > const &maxPlayer2Strategy)
SymbolicMostProbablePathsResult< Type, ValueType > getMostProbablePathSpanningTree(storm::gbar::abstraction::MenuGame< Type, ValueType > const &game, storm::dd::Bdd< Type > const &transitionFilter)
void performDijkstraStep(std::set< ExplicitDijkstraQueueElement< ValueType >, ExplicitDijkstraQueueElementLess< ValueType > > &dijkstraQueue, bool probabilityDistances, std::vector< ValueType > &distances, std::vector< std::pair< uint64_t, uint64_t > > &predecessors, bool generatePredecessors, bool lower, uint64_t currentState, ValueType const ¤tDistance, bool isPivotState, storm::storage::ExplicitGameStrategyPair const &strategyPair, storm::storage::ExplicitGameStrategyPair const &otherStrategyPair, std::vector< uint64_t > const &player1Labeling, std::vector< uint64_t > const &player2Grouping, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::BitVector const &targetStates, storm::storage::BitVector const &relevantStates)
std::pair< storm::RationalNumber, storm::RationalNumber > count(std::vector< storm::storage::BitVector > const &origSets, std::vector< storm::storage::BitVector > const &intersects, std::vector< storm::storage::BitVector > const &intersectsInfo, storm::RationalNumber val, bool plus, uint64_t remdepth)
std::pair< storm::dd::Bdd< Type >, uint64_t > computeReachableStates(storm::dd::Bdd< Type > const &initialStates, storm::dd::Bdd< Type > const &transitions, std::set< storm::expressions::Variable > const &rowMetaVariables, std::set< storm::expressions::Variable > const &columnMetaVariables)
ExplicitDijkstraQueueElement(ValueType const &distance, uint64_t state, bool lower)
bool operator()(ExplicitDijkstraQueueElement< ValueType > const &a, ExplicitDijkstraQueueElement< ValueType > const &b) const
static const uint64_t NO_PREDECESSOR
The value filled in for states without predecessors in the search.
storm::dd::Bdd< Type > reachableTransitionsMin
storm::dd::Bdd< Type > reachableTransitionsMax
storm::dd::Bdd< Type > pivotStates
SymbolicMostProbablePathsResult()=default
storm::dd::Add< Type, ValueType > maxProbabilities
SymbolicPivotStateResult(storm::dd::Bdd< Type > const &pivotState, storm::OptimizationDirection fromDirection, boost::optional< SymbolicMostProbablePathsResult< Type, ValueType > > const &symbolicMostProbablePathsResult=boost::none)
storm::dd::Bdd< Type > pivotState
std::size_t operator()(std::set< storm::expressions::Variable > const &set) const