25#include "storm-config.h"
29namespace abstraction {
34 : source(source), predicates(predicates) {
47 this->predicates.insert(this->predicates.end(), newPredicates.begin(), newPredicates.end());
50template<storm::dd::DdType Type,
typename ValueType>
53 : maxProbabilities(maxProbabilities), spanningTree(spanningTree) {
57template<storm::dd::DdType Type>
64template<storm::dd::DdType Type,
typename ValueType>
68 : pivotState(pivotState), fromDirection(fromDirection), symbolicMostProbablePathsResult(symbolicMostProbablePathsResult) {
72template<storm::dd::DdType Type,
typename ValueType>
75 : abstractor(abstractor),
78 splitPredicates(false),
79 rankPredicates(false),
80 addedAllGuardsFlag(false),
81 refinementPredicatesToInject(options.refinementPredicates),
82 pivotSelectionHeuristic(),
84 equivalenceChecker(
std::move(smtSolver)) {
87 pivotSelectionHeuristic = abstractionSettings.getPivotSelectionHeuristic();
91 rankPredicates = abstractionSettings.isRankRefinementPredicatesSet();
92 addPredicatesEagerly = abstractionSettings.isUseEagerRefinementSet();
95 if (abstractionSettings.isAddAllGuardsSet()) {
96 std::vector<storm::expressions::Expression> guards;
99 for (uint64_t index = player1Choices.first; index < player1Choices.second; ++index) {
102 guards.push_back(guard);
108 addedAllGuardsFlag =
true;
110 if (abstractionSettings.isAddAllInitialExpressionsSet()) {
116template<storm::dd::DdType Type,
typename ValueType>
121template<storm::dd::DdType Type,
typename ValueType>
131 .
template toAdd<ValueType>() *
135 std::set<storm::expressions::Variable> variablesToAbstract(game.
getRowVariables());
138 while (!border.
isZero()) {
146 maxProbabilities = updateStates.
ite(newMaxProbabilities, maxProbabilities);
155 border = updateStates;
161template<storm::dd::DdType Type,
typename ValueType>
172 if (qualitativeResult) {
173 minPlayer1Strategy = qualitativeResult.get().prob0Min.getPlayer1Strategy();
174 minPlayer2Strategy = qualitativeResult.get().prob0Min.getPlayer2Strategy();
175 maxPlayer1Strategy = qualitativeResult.get().prob1Max.getPlayer1Strategy();
176 maxPlayer2Strategy = qualitativeResult.get().prob1Max.getPlayer2Strategy();
177 }
else if (quantitativeResult) {
178 minPlayer1Strategy = quantitativeResult.get().min.getPlayer1Strategy();
179 minPlayer2Strategy = quantitativeResult.get().min.getPlayer2Strategy();
180 maxPlayer1Strategy = quantitativeResult.get().max.getPlayer1Strategy();
181 maxPlayer2Strategy = quantitativeResult.get().max.getPlayer2Strategy();
183 STORM_LOG_ASSERT(
false,
"Either qualitative or quantitative result is required.");
191 std::set<storm::expressions::Variable>
const& rowVariables = game.
getRowVariables();
192 std::set<storm::expressions::Variable>
const& columnVariables = game.
getColumnVariables();
201 bool foundPivotState = !frontierPivotStates.
isZero();
202 if (foundPivotState) {
204 << pivotStates.getNonZeroCount() <<
" candidates in total.");
206 storm::OptimizationDirection::Minimize);
210 while (!foundPivotState) {
211 frontierMin = frontierMin.
relationalProduct(transitionsMin, rowVariables, columnVariables);
212 frontierMax = frontierMax.
relationalProduct(transitionsMax, rowVariables, columnVariables);
219 if (!frontierMinPivotStates.
isZero() || !frontierMaxPivotStates.
isZero()) {
220 if (quantitativeResult) {
225 frontierMinPivotStatesAdd * quantitativeResult.get().max.values - frontierMinPivotStatesAdd * quantitativeResult.get().min.values;
227 frontierMaxPivotStatesAdd * quantitativeResult.get().max.values - frontierMaxPivotStatesAdd * quantitativeResult.get().min.values;
232 direction = storm::OptimizationDirection::Minimize;
233 diffValue = diffMin.
getMax();
235 direction = storm::OptimizationDirection::Maximize;
236 diffValue = diffMax.
getMax();
239 STORM_LOG_TRACE(
"Picked pivot state with difference " << diffValue <<
" from " << numberOfPivotStateCandidatesOnLevel
240 <<
" candidates on level " << level <<
", " << pivotStates.getNonZeroCount()
241 <<
" candidates in total.");
247 STORM_LOG_TRACE(
"Picked pivot state from " << numberOfPivotStateCandidatesOnLevel <<
" candidates on level " << level <<
", "
248 << pivotStates.getNonZeroCount() <<
" candidates in total.");
251 if (!frontierMinPivotStates.
isZero()) {
252 direction = storm::OptimizationDirection::Minimize;
254 direction = storm::OptimizationDirection::Maximize;
277 score = score * (quantitativeResult.get().max.values - quantitativeResult.get().min.values);
284 if ((selectedPivotStateAsAdd * maxSymbolicMostProbablePathsResult.
maxProbabilities).getMax() >
285 (selectedPivotStateAsAdd * minSymbolicMostProbablePathsResult.
maxProbabilities).getMax()) {
286 fromDirection = storm::OptimizationDirection::Maximize;
290 selectedPivotState, fromDirection,
291 fromDirection == storm::OptimizationDirection::Minimize ? minSymbolicMostProbablePathsResult : maxSymbolicMostProbablePathsResult);
294 STORM_LOG_ASSERT(
false,
"This point must not be reached, because then no pivot state could be found.");
298template<storm::dd::DdType Type,
typename ValueType>
299RefinementPredicates MenuGameRefiner<Type, ValueType>::derivePredicatesFromDifferingChoices(
storm::dd::Bdd<Type> const& player1Choice,
304 bool fromGuard =
false;
307 AbstractionInformation<Type>
const& abstractionInformation = abstractor.get().getAbstractionInformation();
311 auto pl1It = player1ChoiceAsAdd.
begin();
312 uint_fast64_t player1Index = abstractionInformation.decodePlayer1Choice((*pl1It).first, abstractionInformation.getPlayer1VariableCount());
316 bool buttomStateSuccessor =
317 !((abstractionInformation.getBottomStateBdd(
false,
false) && lowerChoice) || (abstractionInformation.getBottomStateBdd(
false,
false) && upperChoice))
322 if (buttomStateSuccessor) {
323 STORM_LOG_TRACE(
"One of the successors is a bottom state, taking a guard as a new predicate.");
324 newPredicate = abstractor.get().getGuard(player1Index);
326 STORM_LOG_DEBUG(
"Derived new predicate (based on guard): " << newPredicate);
328 STORM_LOG_TRACE(
"No bottom state successor. Deriving a new predicate using weakest precondition.");
331 std::map<uint64_t, std::pair<storm::storage::BitVector, ValueType>> lowerChoiceUpdateToSuccessorMapping =
332 abstractionInformation.template decodeChoiceToUpdateSuccessorMapping<ValueType>(lowerChoice);
333 std::map<uint64_t, std::pair<storm::storage::BitVector, ValueType>> upperChoiceUpdateToSuccessorMapping =
334 abstractionInformation.template decodeChoiceToUpdateSuccessorMapping<ValueType>(upperChoice);
336 lowerChoiceUpdateToSuccessorMapping.size() == upperChoiceUpdateToSuccessorMapping.size(),
337 "Mismatching sizes after decode (" << lowerChoiceUpdateToSuccessorMapping.size() <<
" vs. " << upperChoiceUpdateToSuccessorMapping.size() <<
").");
340 std::vector<std::pair<uint64_t, ValueType>> updateIndicesAndMasses;
341 for (
auto const& entry : lowerChoiceUpdateToSuccessorMapping) {
342 updateIndicesAndMasses.emplace_back(entry.first, entry.second.second);
344 std::sort(updateIndicesAndMasses.begin(), updateIndicesAndMasses.end(),
345 [](std::pair<uint64_t, ValueType>
const& a, std::pair<uint64_t, ValueType>
const& b) { return a.second > b.second; });
349 std::set<uint64_t> deviationPredicates;
350 uint64_t orderedUpdateIndex = 0;
351 std::vector<storm::expressions::Expression> possibleRefinementPredicates;
352 for (; orderedUpdateIndex < updateIndicesAndMasses.size(); ++orderedUpdateIndex) {
353 storm::storage::BitVector const& lower = lowerChoiceUpdateToSuccessorMapping.at(updateIndicesAndMasses[orderedUpdateIndex].first).first;
354 storm::storage::BitVector const& upper = upperChoiceUpdateToSuccessorMapping.at(updateIndicesAndMasses[orderedUpdateIndex].first).first;
356 bool deviates = lower != upper;
358 std::map<storm::expressions::Variable, storm::expressions::Expression> variableUpdates =
359 abstractor.
get().getVariableUpdates(player1Index, updateIndicesAndMasses[orderedUpdateIndex].first);
361 for (uint64_t predicateIndex = 0; predicateIndex < lower.
size(); ++predicateIndex) {
362 if (lower[predicateIndex] != upper[predicateIndex]) {
363 possibleRefinementPredicates.push_back(
364 abstractionInformation.getPredicateByIndex(predicateIndex).substitute(variableUpdates).simplify());
365 if (!rankPredicates) {
374 STORM_LOG_ASSERT(!possibleRefinementPredicates.empty(),
"Expected refinement predicates.");
377 for (
auto const& pred : possibleRefinementPredicates) {
381 if (rankPredicates) {
385 std::vector<storm::expressions::Expression> otherRefinementPredicates;
386 for (; orderedUpdateIndex < updateIndicesAndMasses.size(); ++orderedUpdateIndex) {
387 storm::storage::BitVector const& lower = lowerChoiceUpdateToSuccessorMapping.at(updateIndicesAndMasses[orderedUpdateIndex].first).first;
388 storm::storage::BitVector const& upper = upperChoiceUpdateToSuccessorMapping.at(updateIndicesAndMasses[orderedUpdateIndex].first).first;
390 bool deviates = lower != upper;
392 std::map<storm::expressions::Variable, storm::expressions::Expression> newVariableUpdates =
393 abstractor.
get().getVariableUpdates(player1Index, updateIndicesAndMasses[orderedUpdateIndex].first);
394 for (uint64_t predicateIndex = 0; predicateIndex < lower.
size(); ++predicateIndex) {
395 if (lower[predicateIndex] != upper[predicateIndex]) {
396 otherRefinementPredicates.push_back(
397 abstractionInformation.getPredicateByIndex(predicateIndex).substitute(newVariableUpdates).simplify());
404 std::vector<uint64_t> refinementPredicateIndexToCount(possibleRefinementPredicates.size(), 0);
405 for (uint64_t index = 0; index < possibleRefinementPredicates.size(); ++index) {
406 refinementPredicateIndexToCount[index] = 1;
408 for (
auto const& otherPredicate : otherRefinementPredicates) {
409 for (uint64_t index = 0; index < possibleRefinementPredicates.size(); ++index) {
410 if (equivalenceChecker.areEquivalentModuloNegation(otherPredicate, possibleRefinementPredicates[index])) {
411 ++refinementPredicateIndexToCount[index];
417 uint64_t chosenPredicateIndex = 0;
418 for (uint64_t index = 0; index < possibleRefinementPredicates.size(); ++index) {
419 if (refinementPredicateIndexToCount[index] > refinementPredicateIndexToCount[chosenPredicateIndex]) {
420 chosenPredicateIndex = index;
423 newPredicate = possibleRefinementPredicates[chosenPredicateIndex];
424 STORM_LOG_DEBUG(
"Derived new predicate (based on weakest-precondition): " << newPredicate <<
", (equivalent to "
425 << (refinementPredicateIndexToCount[chosenPredicateIndex] - 1)
426 <<
" other refinement predicates).");
428 newPredicate = possibleRefinementPredicates.front();
429 STORM_LOG_DEBUG(
"Derived new predicate (based on weakest-precondition): " << newPredicate <<
".");
438template<storm::dd::DdType Type,
typename ValueType>
445 bool fromGuard =
false;
448 AbstractionInformation<Type>
const& abstractionInformation = abstractor.get().getAbstractionInformation();
452 auto pl1It = player1ChoiceAsAdd.
begin();
453 uint_fast64_t player1Index = abstractionInformation.decodePlayer1Choice((*pl1It).first, abstractionInformation.getPlayer1VariableCount());
457 bool buttomStateSuccessor = !((abstractionInformation.getBottomStateBdd(
false,
false) && choiceSuccessors)).isZero();
459 std::vector<storm::expressions::Expression> possibleRefinementPredicates;
463 if (buttomStateSuccessor) {
464 STORM_LOG_TRACE(
"One of the successors is a bottom state, taking a guard as a new predicate.");
465 possibleRefinementPredicates.emplace_back(abstractor.get().getGuard(player1Index));
467 STORM_LOG_DEBUG(
"Derived new predicate (based on guard): " << possibleRefinementPredicates.back());
469 STORM_LOG_TRACE(
"No bottom state successor. Deriving a new predicate using weakest precondition.");
472 std::map<uint64_t, std::pair<storm::storage::BitVector, ValueType>> choiceUpdateToSuccessorMapping =
473 abstractionInformation.template decodeChoiceToUpdateSuccessorMapping<ValueType>(choiceSuccessors);
474 std::vector<std::pair<uint64_t, ValueType>> sortedChoiceUpdateIndicesAndMasses;
475 for (
auto const& e : choiceUpdateToSuccessorMapping) {
476 sortedChoiceUpdateIndicesAndMasses.emplace_back(e.first, e.second.second);
478 std::sort(sortedChoiceUpdateIndicesAndMasses.begin(), sortedChoiceUpdateIndicesAndMasses.end(),
479 [](std::pair<uint64_t, ValueType>
const& a, std::pair<uint64_t, ValueType>
const& b) { return a.second > b.second; });
482 std::set<storm::expressions::Variable> variablesToAbstract = game.
getRowVariables();
490 std::vector<std::map<uint64_t, std::pair<storm::storage::BitVector, ValueType>>> otherChoicesUpdateToSuccessorMappings =
491 abstractionInformation.template decodeChoicesToUpdateSuccessorMapping<ValueType>(game.
getPlayer2Variables(), otherChoices);
493 for (
auto const& otherChoice : otherChoicesUpdateToSuccessorMappings) {
494 for (uint64_t updateIndex = 0; updateIndex < sortedChoiceUpdateIndicesAndMasses.size(); ++updateIndex) {
496 choiceUpdateToSuccessorMapping.at(sortedChoiceUpdateIndicesAndMasses[updateIndex].first).first;
497 storm::storage::BitVector const& otherChoiceSuccessor = otherChoice.at(sortedChoiceUpdateIndicesAndMasses[updateIndex].first).first;
499 bool deviates = choiceSuccessor != otherChoiceSuccessor;
501 std::map<storm::expressions::Variable, storm::expressions::Expression> variableUpdates =
502 abstractor.
get().getVariableUpdates(player1Index, sortedChoiceUpdateIndicesAndMasses[updateIndex].first);
504 for (uint64_t predicateIndex = 0; predicateIndex < choiceSuccessor.
size(); ++predicateIndex) {
505 if (choiceSuccessor[predicateIndex] != otherChoiceSuccessor[predicateIndex]) {
506 possibleRefinementPredicates.push_back(
507 abstractionInformation.getPredicateByIndex(predicateIndex).substitute(variableUpdates).simplify());
508 if (!rankPredicates) {
519 STORM_LOG_ASSERT(!possibleRefinementPredicates.empty(),
"Expected refinement predicates.");
522 for (
auto const& pred : possibleRefinementPredicates) {
528 {possibleRefinementPredicates});
531template<storm::dd::DdType Type,
typename ValueType>
557 constraint &= minPlayer2Strategy.
exclusiveOr(maxPlayer2Strategy);
565template<storm::dd::DdType Type,
typename ValueType>
566RefinementPredicates MenuGameRefiner<Type, ValueType>::derivePredicatesFromPivotState(
573 bool player1ChoicesDifferent = !(pivotState && minPlayer1Strategy).exclusiveOr(pivotState && maxPlayer1Strategy).isZero();
575 boost::optional<RefinementPredicates> predicates;
579 storm::dd::Bdd<Type> lowerChoice1 = (lowerChoice && minPlayer2Strategy).existsAbstract(variablesToAbstract);
580 storm::dd::Bdd<Type> lowerChoice2 = (lowerChoice && maxPlayer2Strategy).existsAbstract(variablesToAbstract);
582 bool lowerChoicesDifferent = !lowerChoice1.
exclusiveOr(lowerChoice2).isZero() && !lowerChoice1.
isZero() && !lowerChoice2.
isZero();
583 if (lowerChoicesDifferent) {
585 if (this->addPredicatesEagerly) {
586 predicates = derivePredicatesFromChoice(game, pivotState, (pivotState && minPlayer1Strategy).existsAbstract(game.
getRowVariables()),
587 lowerChoice && minPlayer2Strategy, lowerChoice1);
590 derivePredicatesFromDifferingChoices((pivotState && minPlayer1Strategy).existsAbstract(game.
getRowVariables()), lowerChoice1, lowerChoice2);
594 if (predicates && !player1ChoicesDifferent) {
595 return predicates.get();
598 boost::optional<RefinementPredicates> additionalPredicates;
601 storm::dd::Bdd<Type> upperChoice1 = (upperChoice && minPlayer2Strategy).existsAbstract(variablesToAbstract);
602 storm::dd::Bdd<Type> upperChoice2 = (upperChoice && maxPlayer2Strategy).existsAbstract(variablesToAbstract);
604 bool upperChoicesDifferent = !upperChoice1.
exclusiveOr(upperChoice2).isZero() && !upperChoice1.
isZero() && !upperChoice2.
isZero();
605 if (upperChoicesDifferent) {
607 if (this->addPredicatesEagerly) {
608 additionalPredicates = derivePredicatesFromChoice(game, pivotState, (pivotState && maxPlayer1Strategy).existsAbstract(game.
getRowVariables()),
609 upperChoice && maxPlayer2Strategy, upperChoice1);
611 additionalPredicates =
612 derivePredicatesFromDifferingChoices((pivotState && maxPlayer1Strategy).existsAbstract(game.
getRowVariables()), upperChoice1, upperChoice2);
616 if (additionalPredicates) {
618 return additionalPredicates.get();
621 predicates = additionalPredicates;
623 predicates.get().addPredicates(additionalPredicates.get().getPredicates());
628 STORM_LOG_THROW(
static_cast<bool>(predicates), storm::exceptions::InvalidStateException,
"Could not derive predicates for refinement.");
630 return predicates.get();
633template<storm::dd::DdType Type,
typename ValueType>
634std::pair<std::vector<std::vector<storm::expressions::Expression>>, std::map<storm::expressions::Variable, storm::expressions::Expression>>
638 std::vector<std::vector<storm::expressions::Expression>> predicates;
641 AbstractionInformation<Type>
const& abstractionInformation = abstractor.get().getAbstractionInformation();
642 std::set<storm::expressions::Variable> variablesToAbstract(game.
getColumnVariables());
648 std::set<storm::expressions::Variable> oldVariables = initialExpression.
getVariables();
649 for (
auto const& predicate : abstractionInformation.getPredicates()) {
650 std::set<storm::expressions::Variable> usedVariables = predicate.getVariables();
651 oldVariables.insert(usedVariables.begin(), usedVariables.end());
654 std::map<storm::expressions::Variable, storm::expressions::Variable> oldToNewVariables;
655 for (
auto const& variable : oldVariables) {
656 oldToNewVariables[variable] = expressionManager.
getVariable(variable.getName());
658 std::map<storm::expressions::Variable, storm::expressions::Expression> lastSubstitution;
659 for (
auto const& variable : oldToNewVariables) {
660 lastSubstitution[variable.second] = variable.second;
662 std::map<storm::expressions::Variable, storm::expressions::Expression> stepVariableToCopiedVariableMap;
666 predicates.emplace_back(abstractionInformation.getPredicates(decodedTargetState));
667 for (
auto& predicate : predicates.back()) {
668 predicate = predicate.changeManager(expressionManager);
671 for (
auto const& pred : abstractionInformation.getConstraints()) {
672 predicates.back().push_back(pred.changeManager(expressionManager));
679 std::tuple<storm::storage::BitVector, uint64_t, uint64_t> decodedPredecessor =
680 abstractionInformation.decodeStatePlayer1ChoiceAndUpdate(predecessorTransition);
683 std::map<storm::expressions::Variable, storm::expressions::Expression> substitution;
684 for (
auto const& variablePair : oldToNewVariables) {
686 substitution[variablePair.second] = variableCopy;
687 stepVariableToCopiedVariableMap[variableCopy] = variablePair.second;
691 auto variableUpdates = abstractor.get().getVariableUpdates(std::get<1>(decodedPredecessor), std::get<2>(decodedPredecessor));
692 for (
auto const& oldNewVariablePair : oldToNewVariables) {
696 auto updateIt = variableUpdates.find(oldNewVariablePair.first);
697 if (updateIt != variableUpdates.end()) {
698 auto const& update = *updateIt;
700 if (update.second.hasBooleanType()) {
701 predicates.back().push_back(
702 storm::expressions::iff(lastSubstitution.at(newVariable), update.second.changeManager(expressionManager).substitute(substitution)));
704 predicates.back().push_back(lastSubstitution.at(newVariable) == update.second.changeManager(expressionManager).substitute(substitution));
709 predicates.back().push_back(
storm::expressions::iff(lastSubstitution.at(newVariable), substitution.at(newVariable)));
711 predicates.back().push_back(lastSubstitution.at(newVariable) == substitution.at(newVariable));
717 predicates.back().push_back(abstractor.get().getGuard(std::get<1>(decodedPredecessor)).changeManager(expressionManager).substitute(substitution));
720 predicates.emplace_back(abstractionInformation.getPredicates(std::get<0>(decodedPredecessor)));
721 for (
auto& predicate : predicates.back()) {
722 predicate = predicate.changeManager(expressionManager).substitute(substitution);
725 for (
auto const& pred : abstractionInformation.getConstraints()) {
726 predicates.back().push_back(pred.changeManager(expressionManager).substitute(substitution));
729 lastSubstitution = std::move(substitution);
730 currentState = predecessorTransition.
existsAbstract(variablesToAbstract);
734 return std::make_pair(predicates, stepVariableToCopiedVariableMap);
737template<
typename ValueType>
740template<storm::dd::DdType Type,
typename ValueType>
741std::pair<std::vector<uint64_t>, std::vector<uint64_t>> MenuGameRefiner<Type, ValueType>::buildReversedLabeledPath(
742 ExplicitPivotStateResult<ValueType>
const& pivotStateResult)
const {
743 std::pair<std::vector<uint64_t>, std::vector<uint64_t>> result;
744 result.first.emplace_back(pivotStateResult.pivotState);
746 uint64_t currentState = pivotStateResult.predecessors[pivotStateResult.pivotState].first;
747 uint64_t currentAction = pivotStateResult.predecessors[pivotStateResult.pivotState].second;
750 result.first.emplace_back(currentState);
751 result.second.emplace_back(currentAction);
752 currentAction = pivotStateResult.predecessors[currentState].second;
753 currentState = pivotStateResult.predecessors[currentState].first;
756 STORM_LOG_ASSERT(result.first.size() == result.second.size() + 1,
"Path size mismatch.");
760template<storm::dd::DdType Type,
typename ValueType>
761std::pair<std::vector<std::vector<storm::expressions::Expression>>, std::map<storm::expressions::Variable, storm::expressions::Expression>>
763 std::vector<uint64_t>
const& reversedPath, std::vector<uint64_t>
const& reversedLabels,
764 storm::dd::Odd const& odd, std::vector<uint64_t>
const* stateToOffset)
const {
765 STORM_LOG_ASSERT(reversedPath.size() == reversedLabels.size() + 1,
"Path size mismatch.");
767 std::vector<std::vector<storm::expressions::Expression>> predicates;
769 AbstractionInformation<Type>
const& abstractionInformation = abstractor.get().getAbstractionInformation();
772 std::set<storm::expressions::Variable> oldVariables = initialExpression.
getVariables();
773 for (
auto const& predicate : abstractionInformation.getPredicates()) {
774 std::set<storm::expressions::Variable> usedVariables = predicate.getVariables();
775 oldVariables.insert(usedVariables.begin(), usedVariables.end());
778 std::map<storm::expressions::Variable, storm::expressions::Variable> oldToNewVariables;
779 for (
auto const& variable : oldVariables) {
780 oldToNewVariables[variable] = expressionManager.
getVariable(variable.getName());
782 std::map<storm::expressions::Variable, storm::expressions::Expression> currentSubstitution;
783 for (
auto const& variable : oldToNewVariables) {
784 currentSubstitution[variable.second] = variable.second;
786 std::map<storm::expressions::Variable, storm::expressions::Expression> stepVariableToCopiedVariableMap;
788 auto pathIt = reversedPath.rbegin();
794 uint64_t predicateValuationOffset = abstractionInformation.getNumberOfDdSourceLocationVariables() + 1;
796 odd.
getEncoding(stateToOffset ? (*stateToOffset)[*pathIt] : *pathIt, abstractionInformation.getNumberOfPredicates() + predicateValuationOffset);
800 predicates.emplace_back(abstractionInformation.getPredicatesExcludingBottom(extendedPredicateValuation));
801 for (
auto& predicate : predicates.back()) {
802 predicate = predicate.changeManager(expressionManager);
806 for (
auto const& pred : abstractionInformation.getConstraints()) {
807 predicates.back().push_back(pred.changeManager(expressionManager));
811 predicates.back().push_back(initialExpression.
changeManager(expressionManager));
814 auto actionIt = reversedLabels.
rbegin();
815 for (; pathIt != reversedPath.rend(); ++pathIt) {
817 predicates.emplace_back();
820 predicates.back().emplace_back(abstractor.get().getGuard(*actionIt).changeManager(expressionManager).substitute(currentSubstitution));
823 std::set<storm::expressions::Variable>
const& assignedVariables = abstractor.get().getAssignedVariables(*actionIt);
826 std::map<storm::expressions::Variable, storm::expressions::Variable> newVariableMaps;
827 for (
auto const& variable : assignedVariables) {
829 newVariableMaps[oldToNewVariables.at(variable)] = variableCopy;
830 stepVariableToCopiedVariableMap[variableCopy] = variable;
834 auto variableUpdateVector = abstractor.get().getVariableUpdates(*actionIt);
838 for (
auto const& variableUpdates : variableUpdateVector) {
840 for (
auto const& update : variableUpdates) {
841 if (update.second.hasBooleanType()) {
842 variableUpdateExpression =
844 update.second.changeManager(expressionManager).substitute(currentSubstitution));
846 variableUpdateExpression = variableUpdateExpression && newVariableMaps.at(update.first) ==
851 allVariableUpdateExpression = allVariableUpdateExpression || variableUpdateExpression;
854 allVariableUpdateExpression = expressionManager.
boolean(
true);
856 predicates.back().emplace_back(allVariableUpdateExpression);
859 for (
auto const& variablePair : newVariableMaps) {
860 currentSubstitution[variablePair.first] = variablePair.second;
864 extendedPredicateValuation =
865 odd.
getEncoding(stateToOffset ? (*stateToOffset)[*pathIt] : *pathIt, abstractionInformation.getNumberOfPredicates() + predicateValuationOffset);
869 for (uint64_t predicateIndex = 0; predicateIndex < abstractionInformation.getNumberOfPredicates(); ++predicateIndex) {
870 auto const& predicate = abstractionInformation.getPredicateByIndex(predicateIndex);
871 std::set<storm::expressions::Variable> usedVariables = predicate.getVariables();
873 bool containsAssignedVariables =
false;
874 for (
auto usedIt = usedVariables.begin(), assignedIt = assignedVariables.begin();;) {
875 if (usedIt == usedVariables.end() || assignedIt == assignedVariables.end()) {
879 if (*usedIt == *assignedIt) {
880 containsAssignedVariables =
true;
884 if (*usedIt < *assignedIt) {
891 if (containsAssignedVariables) {
892 auto transformedPredicate = predicate.changeManager(expressionManager).substitute(currentSubstitution);
893 predicates.back().emplace_back(extendedPredicateValuation.
get(predicateIndex + predicateValuationOffset) ? transformedPredicate
894 : !transformedPredicate);
899 for (
auto const& constraint : abstractionInformation.getConstraints()) {
900 std::set<storm::expressions::Variable> usedVariables = constraint.getVariables();
902 bool containsAssignedVariables =
false;
903 for (
auto usedIt = usedVariables.begin(), assignedIt = assignedVariables.begin();;) {
904 if (usedIt == usedVariables.end() || assignedIt == assignedVariables.end()) {
908 if (*usedIt == *assignedIt) {
909 containsAssignedVariables =
true;
913 if (*usedIt < *assignedIt) {
920 if (containsAssignedVariables) {
921 auto transformedConstraint = constraint.changeManager(expressionManager).substitute(currentSubstitution);
922 predicates.back().emplace_back(transformedConstraint);
929 return std::make_pair(predicates, stepVariableToCopiedVariableMap);
932template<storm::dd::DdType Type,
typename ValueType>
933boost::optional<RefinementPredicates> MenuGameRefiner<Type, ValueType>::derivePredicatesFromInterpolationFromTrace(
935 std::map<storm::expressions::Variable, storm::expressions::Expression>
const& variableSubstitution)
const {
936 AbstractionInformation<Type>
const& abstractionInformation = abstractor.get().getAbstractionInformation();
938 auto start = std::chrono::high_resolution_clock::now();
939 boost::optional<RefinementPredicates> predicates;
942 auto assertionStart = std::chrono::high_resolution_clock::now();
944 uint64_t stepCounter = 0;
945 for (
auto const& traceElement : trace) {
948 interpolatingSolver.setInterpolationGroup(stepCounter);
949 for (
auto const& predicate : traceElement) {
950 interpolatingSolver.add(predicate);
955 auto assertionEnd = std::chrono::high_resolution_clock::now();
956 STORM_LOG_TRACE(
"Asserting trace formula took " << std::chrono::duration_cast<std::chrono::milliseconds>(assertionEnd - assertionStart).
count() <<
"ms.");
961 STORM_LOG_TRACE(
"Trace formula is unsatisfiable. Starting interpolation.");
963 std::vector<storm::expressions::Expression> interpolants;
964 std::vector<uint64_t> prefix;
965 for (uint64_t step = 0; step < stepCounter; ++step) {
966 prefix.push_back(step);
968 interpolatingSolver.getInterpolant(prefix).
substitute(variableSubstitution).
changeManager(abstractionInformation.getExpressionManager());
971 STORM_LOG_TRACE(
"Trace formula became unsatisfiable at position " << step <<
" of " << stepCounter <<
".");
974 if (!interpolant.
isTrue()) {
975 STORM_LOG_DEBUG(
"Derived new predicate (based on interpolation at step " << step <<
" out of " << stepCounter <<
"): " << interpolant);
976 interpolants.push_back(interpolant);
980 STORM_LOG_ASSERT(!interpolants.empty(),
"Expected to have non-empty set of interpolants.");
984 STORM_LOG_TRACE(
"Trace formula is satisfiable, not using interpolation.");
986 auto end = std::chrono::high_resolution_clock::now();
989 STORM_LOG_TRACE(
"Deriving predicates using interpolation from witness of size "
990 << trace.size() <<
" took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() <<
"ms.");
992 STORM_LOG_TRACE(
"Tried deriving predicates using interpolation but failed in "
993 << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count() <<
"ms.");
999template<storm::dd::DdType Type,
typename ValueType>
1000boost::optional<RefinementPredicates> MenuGameRefiner<Type, ValueType>::derivePredicatesFromInterpolation(
1005 SymbolicMostProbablePathsResult<Type, ValueType> symbolicMostProbablePathsResult;
1006 if (!symbolicPivotStateResult.symbolicMostProbablePathsResult) {
1007 symbolicMostProbablePathsResult =
getMostProbablePathSpanningTree(game, symbolicPivotStateResult.fromDirection == storm::OptimizationDirection::Minimize
1008 ? minPlayer1Strategy && minPlayer2Strategy
1009 : maxPlayer1Strategy && maxPlayer2Strategy);
1011 symbolicMostProbablePathsResult = symbolicPivotStateResult.symbolicMostProbablePathsResult.get();
1015 AbstractionInformation<Type>
const& abstractionInformation = abstractor.get().getAbstractionInformation();
1016 std::shared_ptr<storm::expressions::ExpressionManager> interpolationManager = abstractionInformation.getExpressionManager().
clone();
1019 auto start = std::chrono::high_resolution_clock::now();
1020 std::pair<std::vector<std::vector<storm::expressions::Expression>>, std::map<storm::expressions::Variable, storm::expressions::Expression>>
1021 traceAndVariableSubstitution =
1022 buildTrace(*interpolationManager, game, symbolicMostProbablePathsResult.spanningTree, symbolicPivotStateResult.pivotState);
1023 auto end = std::chrono::high_resolution_clock::now();
1024 STORM_LOG_DEBUG(
"Building the trace and variable substitution for interpolation from symbolic most-probable paths result took "
1025 << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count() <<
"ms.");
1027 return derivePredicatesFromInterpolationFromTrace(*interpolationManager, traceAndVariableSubstitution.first, traceAndVariableSubstitution.second);
1030template<storm::dd::DdType Type,
typename ValueType>
1031boost::optional<RefinementPredicates> MenuGameRefiner<Type, ValueType>::derivePredicatesFromInterpolation(
1036 AbstractionInformation<Type>
const& abstractionInformation = abstractor.get().getAbstractionInformation();
1037 std::shared_ptr<storm::expressions::ExpressionManager> interpolationManager = abstractionInformation.getExpressionManager().clone();
1040 auto start = std::chrono::high_resolution_clock::now();
1041 std::pair<std::vector<uint64_t>, std::vector<uint64_t>> labeledReversedPath = buildReversedLabeledPath(pivotStateResult);
1044 if (labeledReversedPath.first.size() == 1) {
1048 std::pair<std::vector<std::vector<storm::expressions::Expression>>, std::map<storm::expressions::Variable, storm::expressions::Expression>>
1049 traceAndVariableSubstitution = buildTraceFromReversedLabeledPath(*interpolationManager, labeledReversedPath.first, labeledReversedPath.second, odd);
1050 auto end = std::chrono::high_resolution_clock::now();
1051 STORM_LOG_DEBUG(
"Building the trace and variable substitution for interpolation from explicit most-probable paths result took "
1052 << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count() <<
"ms.");
1054 return derivePredicatesFromInterpolationFromTrace(*interpolationManager, traceAndVariableSubstitution.first, traceAndVariableSubstitution.second);
1057template<storm::dd::DdType Type,
typename ValueType>
1069 auto oldMinPlayer1Strategy = minPlayer1Strategy;
1070 minPlayer1Strategy = (maxPlayer1Strategy && qualitativeResult.
prob0Min.getPlayer2States())
1072 .
ite(maxPlayer1Strategy, minPlayer1Strategy);
1076 computePivotStates(game, transitionMatrixBdd, minPlayer1Strategy, minPlayer2Strategy, maxPlayer1Strategy, maxPlayer2Strategy);
1090 pickPivotState<Type, ValueType>(pivotSelectionHeuristic, game, pivotStateCandidatesResult, qualitativeResult, boost::none);
1092 boost::optional<RefinementPredicates> predicates;
1093 if (useInterpolation) {
1095 derivePredicatesFromInterpolation(game, symbolicPivotStateResult, minPlayer1Strategy, minPlayer2Strategy, maxPlayer1Strategy, maxPlayer2Strategy);
1100 predicates = derivePredicatesFromPivotState(game, symbolicPivotStateResult.
pivotState, minPlayer1Strategy, minPlayer2Strategy, maxPlayer1Strategy,
1101 maxPlayer2Strategy);
1103 STORM_LOG_THROW(
static_cast<bool>(predicates), storm::exceptions::InvalidStateException,
"Predicates needed to continue.");
1106 std::vector<storm::expressions::Expression> preparedPredicates = preprocessPredicates(predicates.get().getPredicates(), predicates.get().getSource());
1107 performRefinement(createGlobalRefinement(preparedPredicates));
1111template<
typename ValueType>
1122template<
typename ValueType>
1145template<
typename ValueType>
1147 bool probabilityDistances, std::vector<ValueType>& distances, std::vector<std::pair<uint64_t, uint64_t>>& predecessors,
1148 bool generatePredecessors,
bool lower, uint64_t currentState, ValueType
const& currentDistance, [[maybe_unused]]
bool isPivotState,
1156 STORM_LOG_ASSERT(isPivotState || !otherStrategyPair.getPlayer2Strategy().hasDefinedChoice(player2Successor) ||
1158 "Did not expect deviation in player 2 strategy.");
1159 STORM_LOG_ASSERT(player2Grouping[player2Successor] <= player2Choice && player2Choice < player2Grouping[player2Successor + 1],
1160 "Illegal choice for player 2.");
1162 for (
auto const& entry : transitionMatrix.
getRow(player2Choice)) {
1163 uint64_t player1Successor = entry.getColumn();
1164 if (!relevantStates.
get(player1Successor)) {
1168 ValueType alternateDistance;
1169 if (probabilityDistances) {
1170 alternateDistance = currentDistance * entry.getValue();
1172 alternateDistance = currentDistance + storm::utility::one<ValueType>();
1174 if (probabilityDistances ? alternateDistance > distances[player1Successor] : alternateDistance < distances[player1Successor]) {
1175 distances[player1Successor] = alternateDistance;
1176 if (generatePredecessors) {
1177 predecessors[player1Successor] = std::make_pair(currentState, player1Labeling[player2Successor]);
1179 dijkstraQueue.emplace(alternateDistance, player1Successor, lower);
1183 STORM_LOG_ASSERT(targetStates.get(currentState),
"Expecting min strategy for non-target states.");
1187template<
typename ValueType>
1193 std::vector<ValueType>
const* lowerValues =
nullptr, std::vector<ValueType>
const* upperValues =
nullptr) {
1195 STORM_LOG_ASSERT(!lowerValues || upperValues,
"Expected none or both value results.");
1196 STORM_LOG_ASSERT(!upperValues || lowerValues,
"Expected none or both value results.");
1204 uint64_t numberOfStates = initialStates.
size();
1205 ValueType inftyDistance = probabilityDistances ? storm::utility::zero<ValueType>() : storm::utility::infinity<ValueType>();
1206 ValueType zeroDistance = probabilityDistances ? storm::utility::one<ValueType>() : storm::utility::zero<ValueType>();
1209 std::vector<ValueType> lowerDistances(numberOfStates, inftyDistance);
1210 std::vector<std::pair<uint64_t, uint64_t>> lowerPredecessors;
1211 std::vector<ValueType> upperDistances(numberOfStates, inftyDistance);
1212 std::vector<std::pair<uint64_t, uint64_t>> upperPredecessors;
1214 if (generatePredecessors) {
1215 lowerPredecessors.resize(numberOfStates,
1217 upperPredecessors.resize(numberOfStates,
1224 for (
auto initialState : initialStates) {
1225 if (!relevantStates.
get(initialState)) {
1229 lowerDistances[initialState] = zeroDistance;
1230 upperDistances[initialState] = zeroDistance;
1231 dijkstraQueue.emplace(zeroDistance, initialState,
true);
1232 dijkstraQueue.emplace(zeroDistance, initialState,
false);
1238 lowerValues && upperValues;
1239 bool foundPivotState =
false;
1242 ValueType pivotStateDeviation = storm::utility::zero<ValueType>();
1245 while (!dijkstraQueue.empty()) {
1247 auto currentDijkstraElement = *dijkstraQueue.begin();
1248 ValueType currentDistance = currentDijkstraElement.distance;
1249 uint64_t currentState = currentDijkstraElement.state;
1250 bool currentLower = currentDijkstraElement.lower;
1251 dijkstraQueue.erase(dijkstraQueue.begin());
1253 if (foundPivotState && (probabilityDistances ? currentDistance < pivotState.distance : currentDistance > pivotState.
distance)) {
1260 pivotState.
lower ? std::move(lowerPredecessors) : std::move(upperPredecessors));
1261 }
else if (pivotStateDeviation >= currentDistance) {
1265 pivotState.
lower ? std::move(lowerPredecessors) : std::move(upperPredecessors));
1270 bool isPivotState =
false;
1276 isPivotState =
true;
1284 isPivotState =
true;
1290 if (considerDeviation && foundPivotState) {
1291 ValueType deviationOfCurrentState = (*upperValues)[currentState] - (*lowerValues)[currentState];
1293 if (deviationOfCurrentState > pivotStateDeviation) {
1294 pivotState = currentDijkstraElement;
1295 pivotStateDeviation = deviationOfCurrentState;
1298 pivotStateDeviation *= currentDistance;
1301 }
else if (!foundPivotState) {
1302 pivotState = currentDijkstraElement;
1303 foundPivotState =
true;
1307 if (!considerDeviation) {
1309 pivotState.
lower ? std::move(lowerPredecessors) : std::move(upperPredecessors));
1314 if (!lowerValues || !upperValues || (*lowerValues)[currentState] < (*upperValues)[currentState]) {
1316 performDijkstraStep(dijkstraQueue, probabilityDistances, lowerDistances, lowerPredecessors, generatePredecessors,
true, currentState,
1317 currentDistance, isPivotState, minStrategyPair, maxStrategyPair, player1Labeling, player2Grouping, transitionMatrix,
1318 targetStates, relevantStates);
1320 performDijkstraStep(dijkstraQueue, probabilityDistances, upperDistances, upperPredecessors, generatePredecessors,
false, currentState,
1321 currentDistance, isPivotState, maxStrategyPair, minStrategyPair, player1Labeling, player2Grouping, transitionMatrix,
1322 targetStates, relevantStates);
1327 if (foundPivotState) {
1329 pivotState.
lower ? std::move(lowerPredecessors) : std::move(upperPredecessors));
1334 STORM_LOG_TRACE(
"Did not find pivot state in explicit Dijkstra search.");
1338template<storm::dd::DdType Type,
typename ValueType>
1339boost::optional<RefinementPredicates> MenuGameRefiner<Type, ValueType>::derivePredicatesFromInterpolationReversedPath(
1341 std::vector<uint64_t>
const& stateToOffset, std::vector<uint64_t>
const& reversedLabels)
const {
1343 auto start = std::chrono::high_resolution_clock::now();
1344 std::pair<std::vector<std::vector<storm::expressions::Expression>>, std::map<storm::expressions::Variable, storm::expressions::Expression>>
1345 traceAndVariableSubstitution = buildTraceFromReversedLabeledPath(interpolationManager, reversedPath, reversedLabels, odd, &stateToOffset);
1346 auto end = std::chrono::high_resolution_clock::now();
1347 STORM_LOG_DEBUG(
"Building the trace and variable substitution for interpolation from explicit most-probable paths result took "
1348 << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() <<
"ms.");
1350 return derivePredicatesFromInterpolationFromTrace(interpolationManager, traceAndVariableSubstitution.first, traceAndVariableSubstitution.second);
1353template<storm::dd::DdType Type,
typename ValueType>
1356 [[maybe_unused]] std::vector<uint64_t>
const& player1Grouping, std::vector<uint64_t>
const& player1Labeling,
1363 (void)constraintStates;
1368 boost::optional<ExplicitPivotStateResult<ValueType>> optionalPivotStateResult =
1369 pickPivotState(useInterpolation, pivotSelectionHeuristic, transitionMatrix, player1Labeling, initialStates, relevantStates, targetStates,
1370 minStrategyPair, maxStrategyPair);
1373 if (!optionalPivotStateResult) {
1379 auto const& pivotStateResult = optionalPivotStateResult.get();
1380 STORM_LOG_TRACE(
"Found pivot state " << pivotStateResult.pivotState <<
" with distance " << pivotStateResult.distance <<
".");
1383 auto const& abstractionInformation = abstractor.get().getAbstractionInformation();
1384 uint64_t pivotState = pivotStateResult.pivotState;
1392 STORM_LOG_ASSERT(player1Grouping[pivotState] <= player2State && player2State < player1Grouping[pivotState + 1],
"Illegal choice for player 1.");
1393 minPlayer1Strategy |=
1394 symbolicPivotState && abstractionInformation.encodePlayer1Choice(player1Labeling[player2State], abstractionInformation.getPlayer1VariableCount());
1398 minPlayer2Strategy |=
1399 minPlayer1Strategy && abstractionInformation.encodePlayer2Choice(player2Labeling[player2Choice], 0, game.
getPlayer2Variables().size());
1403 maxPlayer2Strategy |=
1404 minPlayer1Strategy && abstractionInformation.encodePlayer2Choice(player2Labeling[player2Choice], 0, game.
getPlayer2Variables().size());
1409 STORM_LOG_ASSERT(player1Grouping[pivotState] <= player2State && player2State < player1Grouping[pivotState + 1],
"Illegal choice for player 1.");
1410 maxPlayer1Strategy |=
1411 symbolicPivotState && abstractionInformation.encodePlayer1Choice(player1Labeling[player2State], abstractionInformation.getPlayer1VariableCount());
1415 minPlayer2Strategy |=
1416 maxPlayer1Strategy && abstractionInformation.encodePlayer2Choice(player2Labeling[player2Choice], 0, game.
getPlayer2Variables().size());
1420 maxPlayer2Strategy |=
1421 maxPlayer1Strategy && abstractionInformation.encodePlayer2Choice(player2Labeling[player2Choice], 0, game.
getPlayer2Variables().size());
1424 auto end = std::chrono::high_resolution_clock::now();
1426 boost::optional<RefinementPredicates> predicates;
1427 if (useInterpolation) {
1428 predicates = derivePredicatesFromInterpolation(game, pivotStateResult, odd);
1431 predicates = derivePredicatesFromPivotState(game, symbolicPivotState, minPlayer1Strategy, minPlayer2Strategy, maxPlayer1Strategy, maxPlayer2Strategy);
1433 end = std::chrono::high_resolution_clock::now();
1434 STORM_LOG_THROW(
static_cast<bool>(predicates), storm::exceptions::InvalidStateException,
"Predicates needed to continue.");
1436 std::vector<storm::expressions::Expression> preparedPredicates = preprocessPredicates(predicates.get().getPredicates(), predicates.get().getSource());
1437 performRefinement(createGlobalRefinement(preparedPredicates));
1441template<storm::dd::DdType Type,
typename ValueType>
1444 [[maybe_unused]] std::vector<uint64_t>
const& player1Grouping, std::vector<uint64_t>
const& player1Labeling,
1451 (void)constraintStates;
1456 boost::optional<ExplicitPivotStateResult<ValueType>> optionalPivotStateResult =
1457 pickPivotState(useInterpolation, pivotSelectionHeuristic, transitionMatrix, player1Labeling, initialStates, relevantStates, targetStates,
1458 minStrategyPair, maxStrategyPair, &quantitativeResult.
getMin().getValues(), &quantitativeResult.
getMax().getValues());
1460 STORM_LOG_THROW(optionalPivotStateResult, storm::exceptions::InvalidStateException,
"Did not find pivot state to proceed.");
1463 auto const& pivotStateResult = optionalPivotStateResult.get();
1464 STORM_LOG_TRACE(
"Found pivot state " << pivotStateResult.pivotState <<
" with distance " << pivotStateResult.distance <<
".");
1467 auto const& abstractionInformation = abstractor.get().getAbstractionInformation();
1468 uint64_t pivotState = pivotStateResult.pivotState;
1476 STORM_LOG_ASSERT(player1Grouping[pivotState] <= player2State && player2State < player1Grouping[pivotState + 1],
"Illegal choice for player 1.");
1477 minPlayer1Strategy |=
1478 symbolicPivotState && abstractionInformation.encodePlayer1Choice(player1Labeling[player2State], abstractionInformation.getPlayer1VariableCount());
1482 minPlayer2Strategy |=
1483 minPlayer1Strategy && abstractionInformation.encodePlayer2Choice(player2Labeling[player2Choice], 0, game.
getPlayer2Variables().size());
1487 maxPlayer2Strategy |=
1488 minPlayer1Strategy && abstractionInformation.encodePlayer2Choice(player2Labeling[player2Choice], 0, game.
getPlayer2Variables().size());
1493 STORM_LOG_ASSERT(player1Grouping[pivotState] <= player2State && player2State < player1Grouping[pivotState + 1],
"Illegal choice for player 1.");
1494 maxPlayer1Strategy |=
1495 symbolicPivotState && abstractionInformation.encodePlayer1Choice(player1Labeling[player2State], abstractionInformation.getPlayer1VariableCount());
1499 minPlayer2Strategy |=
1500 maxPlayer1Strategy && abstractionInformation.encodePlayer2Choice(player2Labeling[player2Choice], 0, game.
getPlayer2Variables().size());
1504 maxPlayer2Strategy |=
1505 maxPlayer1Strategy && abstractionInformation.encodePlayer2Choice(player2Labeling[player2Choice], 0, game.
getPlayer2Variables().size());
1509 boost::optional<RefinementPredicates> predicates;
1510 if (useInterpolation) {
1511 predicates = derivePredicatesFromInterpolation(game, pivotStateResult, odd);
1514 predicates = derivePredicatesFromPivotState(game, symbolicPivotState, minPlayer1Strategy, minPlayer2Strategy, maxPlayer1Strategy, maxPlayer2Strategy);
1516 STORM_LOG_THROW(
static_cast<bool>(predicates), storm::exceptions::InvalidStateException,
"Predicates needed to continue.");
1518 std::vector<storm::expressions::Expression> preparedPredicates = preprocessPredicates(predicates.get().getPredicates(), predicates.get().getSource());
1519 performRefinement(createGlobalRefinement(preparedPredicates));
1523template<storm::dd::DdType Type,
typename ValueType>
1535 computePivotStates(game, transitionMatrixBdd, minPlayer1Strategy, minPlayer2Strategy, maxPlayer1Strategy, maxPlayer2Strategy);
1541 pickPivotState<Type, ValueType>(pivotSelectionHeuristic, game, pivotStateCandidatesResult, boost::none, quantitativeResult);
1543 boost::optional<RefinementPredicates> predicates;
1544 if (useInterpolation) {
1546 derivePredicatesFromInterpolation(game, symbolicPivotStateResult, minPlayer1Strategy, minPlayer2Strategy, maxPlayer1Strategy, maxPlayer2Strategy);
1551 predicates = derivePredicatesFromPivotState(game, symbolicPivotStateResult.
pivotState, minPlayer1Strategy, minPlayer2Strategy, maxPlayer1Strategy,
1552 maxPlayer2Strategy);
1554 STORM_LOG_THROW(
static_cast<bool>(predicates), storm::exceptions::InvalidStateException,
"Predicates needed to continue.");
1556 std::vector<storm::expressions::Expression> preparedPredicates = preprocessPredicates(predicates.get().getPredicates(), predicates.get().getSource());
1557 performRefinement(createGlobalRefinement(preparedPredicates));
1562 std::size_t
operator()(std::set<storm::expressions::Variable>
const& set)
const {
1567template<storm::dd::DdType Type,
typename ValueType>
1568std::vector<storm::expressions::Expression> MenuGameRefiner<Type, ValueType>::preprocessPredicates(
1575 auto start = std::chrono::high_resolution_clock::now();
1576 AbstractionInformation<Type>
const& abstractionInformation = abstractor.get().getAbstractionInformation();
1577 std::vector<storm::expressions::Expression> cleanedAtoms;
1579 std::unordered_map<std::set<storm::expressions::Variable>, std::vector<storm::expressions::Expression>, VariableSetHash> predicateClasses;
1581 for (
auto const& predicate : predicates) {
1583 std::vector<storm::expressions::Expression> atoms = splitter.split(predicate);
1586 for (
auto const& atom : atoms) {
1587 std::set<storm::expressions::Variable> vars = atom.getVariables();
1588 predicateClasses[vars].push_back(atom);
1593 uint64_t checkCounter = 0;
1594 for (
auto& predicateClass : predicateClasses) {
1595 std::vector<storm::expressions::Expression> cleanedAtomsOfClass;
1597 for (
auto const& predicate : predicateClass.second) {
1598 bool addPredicate =
true;
1599 for (
auto const& atom : cleanedAtomsOfClass) {
1600 if (predicate.areSame(atom)) {
1601 addPredicate =
false;
1606 if (equivalenceChecker.areEquivalentModuloNegation(predicate, atom)) {
1607 addPredicate =
false;
1612 cleanedAtomsOfClass.push_back(predicate);
1616 predicateClass.second = std::move(cleanedAtomsOfClass);
1619 std::unordered_map<std::set<storm::expressions::Variable>, std::vector<storm::expressions::Expression>, VariableSetHash> oldPredicateClasses;
1620 for (
auto const& oldPredicate : abstractionInformation.getPredicates()) {
1621 std::set<storm::expressions::Variable> vars = oldPredicate.getVariables();
1623 oldPredicateClasses[vars].push_back(oldPredicate);
1626 for (
auto const& predicateClass : predicateClasses) {
1627 auto oldPredicateClassIt = oldPredicateClasses.find(predicateClass.first);
1628 if (oldPredicateClassIt != oldPredicateClasses.end()) {
1629 for (
auto const& newAtom : predicateClass.second) {
1630 bool addAtom =
true;
1631 for (
auto const& oldPredicate : oldPredicateClassIt->second) {
1632 if (newAtom.areSame(oldPredicate)) {
1637 if (equivalenceChecker.areEquivalentModuloNegation(newAtom, oldPredicate)) {
1643 cleanedAtoms.push_back(newAtom);
1647 cleanedAtoms.insert(cleanedAtoms.end(), predicateClass.second.begin(), predicateClass.second.end());
1650 auto end = std::chrono::high_resolution_clock::now();
1651 STORM_LOG_TRACE(
"Preprocessing predicates took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count() <<
"ms (" << checkCounter
1654 return cleanedAtoms;
1662template<storm::dd::DdType Type,
typename ValueType>
1663std::vector<RefinementCommand> MenuGameRefiner<Type, ValueType>::createGlobalRefinement(std::vector<storm::expressions::Expression>
const& predicates)
const {
1664 std::vector<RefinementCommand> commands;
1665 commands.emplace_back(predicates);
1669template<storm::dd::DdType Type,
typename ValueType>
1670void MenuGameRefiner<Type, ValueType>::performRefinement(std::vector<RefinementCommand>
const& refinementCommands,
bool allowInjection)
const {
1671 if (!refinementPredicatesToInject.empty() && allowInjection) {
1674 for (
auto const& predicate : refinementPredicatesToInject.back()) {
1678 abstractor.get().refine(RefinementCommand(refinementPredicatesToInject.back()));
1679 refinementPredicatesToInject.pop_back();
1681 for (
auto const& command : refinementCommands) {
1682 STORM_LOG_INFO(
"Refining with " << command.getPredicates().size() <<
" predicates.");
1683 for (
auto const& predicate : command.getPredicates()) {
1686 if (!command.getPredicates().empty()) {
1687 abstractor.get().refine(command);
1693 for (
auto const& predicate : abstractor.get().getAbstractionInformation().getPredicates()) {
1698template<storm::dd::DdType Type,
typename ValueType>
1700 return addedAllGuardsFlag;
1707#ifdef STORM_HAVE_CARL
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(uint_fast64_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)
SettingsType const & getModule()
Get module.
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