46using storm::gbar::abstraction::ExplicitQuantitativeResult;
47using storm::gbar::abstraction::ExplicitQuantitativeResultMinMax;
48using storm::gbar::abstraction::SymbolicQuantitativeGameResult;
49using storm::gbar::abstraction::SymbolicQuantitativeGameResultMinMax;
51template<storm::dd::DdType Type,
typename ModelType>
54 std::shared_ptr<storm::utility::solver::SmtSolverFactory>
const& smtSolverFactory)
56 smtSolverFactory(smtSolverFactory),
59 reuseQualitativeResults(false),
60 reuseQuantitativeResults(false),
64 auto undefinedConstants = model.getUndefinedConstants();
65 std::vector<std::string> undefinedConstantNames;
66 for (auto undefinedConstant : undefinedConstants) {
67 undefinedConstantNames.emplace_back(undefinedConstant.getName());
71 "Model contains undefined constants ("
72 << boost::algorithm::join(undefinedConstantNames,
",")
73 <<
"). Game-based abstraction can treat such models, but you should make sure that you did not simply forget to define these "
74 "constants. In particular, it may be necessary to constrain the values of the undefined constants.");
77 if (model.isPrismProgram()) {
78 storm::prism::Program const& originalProgram = model.asPrismProgram();
80 originalProgram.getModelType() == storm::prism::Program::ModelType::DTMC || originalProgram.getModelType() == storm::prism::Program::ModelType::MDP,
81 storm::exceptions::NotSupportedException,
"Currently only DTMCs/MDPs are supported by the game-based model checker.");
83 auto flattenStart = std::chrono::high_resolution_clock::now();
85 if (originalProgram.getNumberOfModules() > 1) {
86 preprocessedModel = originalProgram.substituteFormulas().flattenModules(this->smtSolverFactory);
88 preprocessedModel = originalProgram;
90 auto flattenEnd = std::chrono::high_resolution_clock::now();
91 STORM_LOG_INFO(
"Flattened model in " << std::chrono::duration_cast<std::chrono::milliseconds>(flattenEnd - flattenStart).count() <<
"ms.");
93 STORM_LOG_TRACE(
"Game-based model checker got program " << preprocessedModel.asPrismProgram());
97 storm::exceptions::NotSupportedException,
"Currently only DTMCs/MDPs are supported by the game-based model checker.");
100 preprocessedModel = model.asJaniModel().flattenComposition();
109 maximalNumberOfAbstractions = abstractionSettings.getMaximalAbstractionCount();
110 fixPlayer1Strategy = abstractionSettings.isFixPlayer1StrategySet();
111 fixPlayer2Strategy = abstractionSettings.isFixPlayer2StrategySet();
114template<storm::dd::DdType Type,
typename ModelType>
121template<storm::dd::DdType Type,
typename ModelType>
125 std::map<std::string, storm::expressions::Expression> labelToExpressionMapping;
126 if (preprocessedModel.isPrismProgram()) {
127 labelToExpressionMapping = preprocessedModel.asPrismProgram().getLabelToExpressionMapping();
131 if (variable.isTransient()) {
132 labelToExpressionMapping[variable.getName()] = janiModel.
getLabelExpression(variable);
142 return performGameBasedAbstractionRefinement(env, checkTask.template substituteFormula<storm::logic::Formula>(pathFormula), constraintExpression,
143 targetStateExpression);
146template<storm::dd::DdType Type,
typename ModelType>
150 std::map<std::string, storm::expressions::Expression> labelToExpressionMapping;
151 if (preprocessedModel.isPrismProgram()) {
152 labelToExpressionMapping = preprocessedModel.asPrismProgram().getLabelToExpressionMapping();
156 if (variable.isTransient()) {
157 labelToExpressionMapping[variable.getName()] = janiModel.
getLabelExpression(variable);
165 return performGameBasedAbstractionRefinement(env, checkTask.template substituteFormula<storm::logic::Formula>(pathFormula), constraintExpression,
166 targetStateExpression);
169template<storm::dd::DdType Type,
typename ValueType>
173 std::unique_ptr<storm::modelchecker::CheckResult> result;
178 if (player2Direction == storm::OptimizationDirection::Minimize) {
180 if ((prob1 && initialStates) == initialStates) {
185 if (!(prob1 && initialStates).isZero()) {
190 }
else if (player2Direction == storm::OptimizationDirection::Maximize) {
192 if ((prob0 && initialStates) == initialStates) {
197 if (!(prob0 && initialStates).isZero()) {
204 if (player2Direction == storm::OptimizationDirection::Minimize && (prob1 && initialStates) == initialStates) {
207 }
else if (player2Direction == storm::OptimizationDirection::Maximize && (prob0 && initialStates) == initialStates) {
216template<storm::dd::DdType Type,
typename ValueType>
221 std::unique_ptr<storm::modelchecker::CheckResult> result =
223 qualitativeResult.
prob0Min.getPlayer1States(), qualitativeResult.
prob1Min.getPlayer1States());
228 qualitativeResult.
prob0Max.getPlayer1States(), qualitativeResult.
prob1Max.getPlayer1States());
235template<
typename ValueType>
239 std::unique_ptr<storm::modelchecker::CheckResult> result;
244 if (player2Direction == storm::OptimizationDirection::Minimize) {
256 }
else if (player2Direction == storm::OptimizationDirection::Maximize) {
270 if (player2Direction == storm::OptimizationDirection::Minimize && initialStates.
isSubsetOf(prob1)) {
273 }
else if (player2Direction == storm::OptimizationDirection::Maximize && initialStates.
isSubsetOf(prob0)) {
282template<
typename ValueType>
287 std::unique_ptr<storm::modelchecker::CheckResult> result =
301template<
typename ValueType>
304 std::pair<ValueType, ValueType>
const& initialValueRange) {
305 std::unique_ptr<storm::modelchecker::CheckResult> result;
315 ValueType
const& lowerValue = initialValueRange.first;
316 ValueType
const& upperValue = initialValueRange.second;
322 if (player2Direction == storm::OptimizationDirection::Minimize) {
332 if (player2Direction == storm::OptimizationDirection::Maximize) {
346template<
typename ValueType>
349 std::unique_ptr<storm::modelchecker::CheckResult> result;
352 if (comparator.
isEqual(minValue, maxValue)) {
354 (minValue + maxValue) / ValueType(2));
360template<storm::dd::DdType Type,
typename ValueType>
365 STORM_LOG_TRACE(
"Performing quantative solution step. Player 1: " << player1Direction <<
", player 2: " << player2Direction <<
".");
380 startVector = startInfo.get().values * maybeStatesAdd;
382 startVector = game.
getManager().template getAddZero<ValueType>();
387 std::unique_ptr<storm::solver::SymbolicGameSolver<Type, ValueType>>
solver =
390 solver->setGeneratePlayersStrategies(
true);
391 auto values =
solver->solveGame(env, player1Direction, player2Direction, startVector, subvector,
392 startInfo ? boost::make_optional(startInfo.get().getPlayer1Strategy()) : boost::none,
393 startInfo ? boost::make_optional(startInfo.get().getPlayer2Strategy()) : boost::none);
395 solver->getPlayer1Strategy(),
solver->getPlayer2Strategy());
398template<storm::dd::DdType Type,
typename ValueType>
404 bool min = player2Direction == storm::OptimizationDirection::Minimize;
412 combinedPlayer1QualitativeStrategies = (qualitativeResult.
prob0Min.getPlayer1Strategy() || qualitativeResult.
prob1Min.getPlayer1Strategy());
413 combinedPlayer2QualitativeStrategies = (qualitativeResult.
prob0Min.getPlayer2Strategy() || qualitativeResult.
prob1Min.getPlayer2Strategy());
415 combinedPlayer1QualitativeStrategies = (qualitativeResult.
prob0Max.getPlayer1Strategy() || qualitativeResult.
prob1Max.getPlayer1Strategy());
416 combinedPlayer2QualitativeStrategies = (qualitativeResult.
prob0Max.getPlayer2Strategy() || qualitativeResult.
prob1Max.getPlayer2Strategy());
423 auto start = std::chrono::high_resolution_clock::now();
424 if (!maybeStates.
isZero()) {
428 result =
solveMaybeStates(env, player1Direction, player2Direction, game, maybeStates,
429 min ? qualitativeResult.
prob1Min.getPlayer1States() : qualitativeResult.
prob1Max.getPlayer1States(), startInfo);
436 result.
values += min ? qualitativeResult.
prob1Min.getPlayer1States().template toAdd<ValueType>()
437 : qualitativeResult.
prob1Max.getPlayer1States().template toAdd<ValueType>();
439 STORM_LOG_TRACE(
"No " << (player2Direction == storm::OptimizationDirection::Minimize ?
"min" :
"max") <<
" maybe states.");
442 result.
values += min ? qualitativeResult.
prob1Min.getPlayer1States().template toAdd<ValueType>()
443 : qualitativeResult.
prob1Max.getPlayer1States().template toAdd<ValueType>();
449 ValueType maxValueOverInitialStates = initialStateValueAdd.
getMax();
450 initialStateValueAdd += (!game.
getInitialStates()).template toAdd<ValueType>();
451 ValueType minValueOverInitialStates = initialStateValueAdd.
getMin();
453 result.
initialStatesRange = std::make_pair(minValueOverInitialStates, maxValueOverInitialStates);
460 auto end = std::chrono::high_resolution_clock::now();
461 STORM_LOG_TRACE(
"Obtained quantitative " << (min ?
"lower" :
"upper") <<
" bound "
463 << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() <<
"ms.");
468template<
typename ValueType>
476 bool player2Min = player2Direction == storm::OptimizationDirection::Minimize;
488 if (maybeStates.
empty()) {
493 if (previousResult) {
494 STORM_LOG_ASSERT(player2Min,
"Can only reuse previous values when minimizing.");
495 previousResult.get().odd.oldToNewIndex(odd, [&previousResult, &result, player2Min, player1Prob1States](uint64_t oldOffset, uint64_t newOffset) {
496 if (!player1Prob1States.get(newOffset)) {
498 player2Min ? previousResult.get().values.getValues()[oldOffset] : previousResult.get().values.getValues()[oldOffset];
508 uint64_t position = 0;
509 uint64_t previousPlayer2States = 0;
511 for (uint64_t state : maybeStates) {
512 subPlayer1Groups[position] = previousPlayer2States;
514 [[maybe_unused]]
bool hasMaybePlayer2Successor =
false;
515 for (uint64_t player2State = player1Groups[state]; player2State < player1Groups[state + 1]; ++player2State) {
516 if (!player2Prob0States.get(player2State) && !player2Prob1States.get(player2State)) {
517 player2MaybeStates.
set(player2State);
518 hasMaybePlayer2Successor =
true;
519 ++previousPlayer2States;
522 STORM_LOG_ASSERT(hasMaybePlayer2Successor,
"Player 1 maybe state has no player2 maybe successor.");
525 subPlayer1Groups.back() = previousPlayer2States;
536 if (startingQuantitativeResult) {
539 if (previousResult) {
540 STORM_LOG_ASSERT(!startingQuantitativeResult,
"Cannot take two different hints.");
545 std::vector<uint64_t> player1Scheduler(subPlayer1Groups.size() - 1);
547 if (startingStrategyPair) {
549 uint64_t maybeStatePosition = 0;
550 previousPlayer2States = 0;
551 for (uint64_t state : maybeStates) {
552 uint64_t chosenPlayer2State = startingStrategyPair->getPlayer1Strategy().getChoice(state);
554 uint64_t previousPlayer2MaybeStatesForState = 0;
555 for (uint64_t player2State = player1Groups[state]; player2State < player1Groups[state + 1]; ++player2State) {
556 if (player2MaybeStates.
get(player2State)) {
557 if (player2State == chosenPlayer2State) {
558 player1Scheduler[maybeStatePosition] = previousPlayer2MaybeStatesForState;
562 if (startingStrategyPair->getPlayer2Strategy().hasDefinedChoice(player2State)) {
563 player2Scheduler[previousPlayer2States] =
564 startingStrategyPair->getPlayer2Strategy().getChoice(player2State) - transitionMatrix.
getRowGroupIndices()[player2State];
566 player2Scheduler[previousPlayer2States] = 0;
569 ++previousPlayer2MaybeStatesForState;
570 ++previousPlayer2States;
574 ++maybeStatePosition;
580 gameSolver->solveGame(env, player1Direction, player2Direction, values, b, &player1Scheduler, &player2Scheduler);
586 uint64_t previousPlayer1MaybeStates = 0;
587 uint64_t previousPlayer2MaybeStates = 0;
588 for (uint64_t state : maybeStates) {
589 uint64_t previousPlayer2MaybeStatesForState = 0;
590 [[maybe_unused]]
bool madePlayer1Choice =
false;
591 for (uint64_t player2State = player1Groups[state]; player2State < player1Groups[state + 1]; ++player2State) {
592 if (player1Scheduler[previousPlayer1MaybeStates] == previousPlayer2MaybeStatesForState) {
594 madePlayer1Choice =
true;
597 if (player2MaybeStates.
get(player2State)) {
599 transitionMatrix.
getRowGroupIndices()[player2State] + player2Scheduler[previousPlayer2MaybeStates]);
601 ++previousPlayer2MaybeStatesForState;
602 ++previousPlayer2MaybeStates;
605 STORM_LOG_ASSERT(madePlayer1Choice,
"[" << player1Direction <<
"]: player 1 state " << state
606 <<
" did not make a choice, scheduler: " << player1Scheduler[previousPlayer1MaybeStates] <<
".");
608 ++previousPlayer1MaybeStates;
614template<storm::dd::DdType Type,
typename ModelType>
615std::unique_ptr<storm::modelchecker::CheckResult> GameBasedMdpModelChecker<Type, ModelType>::performGameBasedAbstractionRefinement(
619 "The game-based abstraction refinement model checker can only compute the result for the initial states.");
626 std::vector<storm::expressions::Expression> initialPredicates = getInitialPredicates(constraintExpression, targetStateExpression);
633 if (preprocessedModel.isPrismProgram()) {
634 abstractor = std::make_shared<storm::gbar::abstraction::prism::PrismMenuGameAbstractor<Type, ValueType>>(env, preprocessedModel.asPrismProgram(),
635 smtSolverFactory, abstractorOptions);
637 abstractor = std::make_shared<storm::gbar::abstraction::jani::JaniMenuGameAbstractor<Type, ValueType>>(env, preprocessedModel.asJaniModel(),
638 smtSolverFactory, abstractorOptions);
640 std::unique_ptr<storm::modelchecker::CheckResult> result;
641 abstractor->getDdManager().execute([&]() {
642 if (!constraintExpression.
isTrue()) {
643 abstractor->addTerminalStates(!constraintExpression);
645 abstractor->addTerminalStates(targetStateExpression);
646 abstractor->setTargetStates(targetStateExpression);
649 storm::gbar::abstraction::MenuGameRefinerOptions refinerOptions(std::move(options.injectedRefinementPredicates));
650 storm::gbar::abstraction::MenuGameRefiner<Type, ValueType> refiner(*abstractor, smtSolverFactory->create(preprocessedModel.getManager()),
652 refiner.refine(initialPredicates,
false);
654 storm::dd::Bdd<Type> globalConstraintStates = abstractor->getStates(constraintExpression);
655 storm::dd::Bdd<Type> globalTargetStates = abstractor->getStates(targetStateExpression);
659 boost::optional<SymbolicQualitativeGameResultMinMax<Type>> previousSymbolicQualitativeResult = boost::none;
660 boost::optional<SymbolicQuantitativeGameResult<Type, ValueType>> previousSymbolicMinQuantitativeResult = boost::none;
661 boost::optional<PreviousExplicitResult<ValueType>> previousExplicitResult = boost::none;
662 uint64_t peakPlayer1States = 0;
663 uint64_t peakTransitions = 0;
664 for (iteration = 0; iteration < maximalNumberOfAbstractions; ++iteration) {
665 auto iterationStart = std::chrono::high_resolution_clock::now();
669 storm::utility::Stopwatch abstractionWatch(
true);
670 storm::gbar::abstraction::MenuGame<Type, ValueType> game = abstractor->abstract();
671 abstractionWatch.stop();
672 totalAbstractionWatch.add(abstractionWatch);
675 peakPlayer1States = std::max(peakPlayer1States, numberOfPlayer1States);
677 peakTransitions = std::max(peakTransitions, numberOfTransitions);
680 <<
" initial), " << game.
getNumberOfPlayer2States() <<
" player 2 states, " << numberOfTransitions <<
" transitions, "
683 << abstractionWatch.getTimeInMilliseconds() <<
"ms).");
690 storm::dd::Bdd<Type> constraintStates = globalConstraintStates && game.
getReachableStates();
692 if (player1Direction == storm::OptimizationDirection::Minimize) {
704 result = performSymbolicAbstractionSolutionStep(env, checkTask, game, player1Direction, initialStates, constraintStates, targetStates, refiner,
705 previousSymbolicQualitativeResult, previousSymbolicMinQuantitativeResult);
707 result = performExplicitAbstractionSolutionStep(env, checkTask, game, player1Direction, initialStates, constraintStates, targetStates, refiner,
708 previousExplicitResult);
713 printStatistics(*abstractor, game, iteration, peakPlayer1States, peakTransitions);
717 auto iterationEnd = std::chrono::high_resolution_clock::now();
718 STORM_LOG_INFO(
"Iteration " << iteration <<
" took " << std::chrono::duration_cast<std::chrono::milliseconds>(iterationEnd - iterationStart).
count()
728 STORM_LOG_WARN(
"Could not derive result, maximal number of abstractions exceeded.");
732template<storm::dd::DdType Type,
typename ModelType>
733std::unique_ptr<storm::modelchecker::CheckResult> GameBasedMdpModelChecker<Type, ModelType>::performSymbolicAbstractionSolutionStep(
734 Environment const& env, storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>
const& checkTask,
735 storm::gbar::abstraction::MenuGame<Type, ValueType>
const& game,
storm::OptimizationDirection player1Direction, storm::dd::Bdd<Type>
const& initialStates,
736 storm::dd::Bdd<Type>
const& constraintStates, storm::dd::Bdd<Type>
const& targetStates,
737 storm::gbar::abstraction::MenuGameRefiner<Type, ValueType>
const& refiner,
738 boost::optional<SymbolicQualitativeGameResultMinMax<Type>>& previousQualitativeResult,
739 boost::optional<SymbolicQuantitativeGameResult<Type, ValueType>>& previousMinQuantitativeResult) {
746 storm::utility::Stopwatch qualitativeWatch(
true);
747 SymbolicQualitativeGameResultMinMax<Type> qualitativeResult =
748 computeProb01States(previousQualitativeResult, game, player1Direction, transitionMatrixBdd, constraintStates, targetStates);
749 std::unique_ptr<storm::modelchecker::CheckResult> result =
750 checkForResultAfterQualitativeCheck<Type, ValueType>(checkTask, initialStates, qualitativeResult);
754 previousQualitativeResult = qualitativeResult;
755 qualitativeWatch.stop();
756 totalSolutionWatch.add(qualitativeWatch);
757 STORM_LOG_INFO(
"Qualitative computation completed in " << qualitativeWatch.getTimeInMilliseconds() <<
"ms.");
760 storm::dd::Bdd<Type> maybeMin =
761 !(qualitativeResult.prob0Min.getPlayer1States() || qualitativeResult.prob1Min.getPlayer1States()) && game.
getReachableStates();
762 storm::dd::Bdd<Type> maybeMax =
763 !(qualitativeResult.prob0Max.getPlayer1States() || qualitativeResult.prob1Max.getPlayer1States()) && game.
getReachableStates();
766 storm::dd::Bdd<Type> initialMaybeStates = (initialStates && maybeMin) || (initialStates && maybeMax);
767 bool qualitativeRefinement =
false;
768 if (initialMaybeStates.
isZero()) {
772 STORM_LOG_INFO(
"Obtained qualitative bounds [0, 1] on the actual value for the initial states (after "
773 << totalWatch.getTimeInMilliseconds() <<
"ms in iteration " << this->iteration <<
"). Refining abstraction based on qualitative check.");
777 storm::utility::Stopwatch refinementWatch(
true);
778 qualitativeRefinement = refiner.
refine(game, transitionMatrixBdd, qualitativeResult);
779 refinementWatch.stop();
780 totalRefinementWatch.add(refinementWatch);
781 STORM_LOG_INFO(
"Qualitative refinement completed in " << refinementWatch.getTimeInMilliseconds() <<
"ms.");
785 if (!qualitativeRefinement) {
789 storm::dd::Add<Type, ValueType> initialStatesAdd = initialStates.template toAdd<ValueType>();
791 SymbolicQuantitativeGameResultMinMax<Type, ValueType> quantitativeResult;
794 storm::utility::Stopwatch quantitativeWatch(
true);
795 quantitativeResult.
min =
computeQuantitativeResult(env, player1Direction, storm::OptimizationDirection::Minimize, game, qualitativeResult,
796 initialStatesAdd, maybeMin, reuseQuantitativeResults ? previousMinQuantitativeResult : boost::none);
797 quantitativeWatch.stop();
798 previousMinQuantitativeResult = quantitativeResult.
min;
800 checkForResultAfterQuantitativeCheck<ValueType>(checkTask, storm::OptimizationDirection::Minimize, quantitativeResult.
min.getInitialStatesRange());
802 totalSolutionWatch.add(quantitativeWatch);
807 quantitativeWatch.start();
808 quantitativeResult.
max =
computeQuantitativeResult(env, player1Direction, storm::OptimizationDirection::Maximize, game, qualitativeResult,
809 initialStatesAdd, maybeMax, boost::make_optional(quantitativeResult.
min));
810 quantitativeWatch.stop();
812 checkForResultAfterQuantitativeCheck<ValueType>(checkTask, storm::OptimizationDirection::Maximize, quantitativeResult.
max.getInitialStatesRange());
813 totalSolutionWatch.add(quantitativeWatch);
818 ValueType minVal = quantitativeResult.
min.getInitialStatesRange().first;
819 ValueType maxVal = quantitativeResult.
max.getInitialStatesRange().second;
821 if (std::is_same<ValueType, double>::value) {
822 std::stringstream differenceStream;
823 differenceStream.setf(std::ios::fixed, std::ios::floatfield);
824 differenceStream.precision(15);
825 differenceStream << difference;
826 STORM_LOG_INFO(
"Obtained quantitative bounds [" << minVal <<
", " << maxVal <<
"] (difference " << differenceStream.str()
827 <<
") on the actual value for the initial states in " << quantitativeWatch.getTimeInMilliseconds()
828 <<
"ms (after " << totalWatch.getTimeInMilliseconds() <<
"ms in iteration " << this->iteration
833 <<
") on the actual value for the initial states in " << quantitativeWatch.getTimeInMilliseconds()
834 <<
"ms (after " << totalWatch.getTimeInMilliseconds() <<
"ms in iteration " << this->iteration
839 result = checkForResultAfterQuantitativeCheck<ValueType>(quantitativeResult.
min.getInitialStatesRange().first,
840 quantitativeResult.
max.getInitialStatesRange().second, comparator);
847 quantitativeResult.
min.getPlayer1Strategy().template toAdd<ValueType>().sumAbstract(game.
getPlayer1Variables()).getMax() <= 1,
848 "Player 1 strategy for min is illegal.");
850 quantitativeResult.
max.getPlayer1Strategy().template toAdd<ValueType>().sumAbstract(game.
getPlayer1Variables()).getMax() <= 1,
851 "Player 1 strategy for max is illegal.");
853 quantitativeResult.
min.getPlayer2Strategy().template toAdd<ValueType>().sumAbstract(game.
getPlayer2Variables()).getMax() <= 1,
854 "Player 2 strategy for min is illegal.");
856 quantitativeResult.
max.getPlayer2Strategy().template toAdd<ValueType>().sumAbstract(game.
getPlayer2Variables()).getMax() <= 1,
857 "Player 2 strategy for max is illegal.");
861 storm::utility::Stopwatch refinementWatch(
true);
862 refiner.
refine(game, transitionMatrixBdd, quantitativeResult);
863 refinementWatch.stop();
864 totalRefinementWatch.add(refinementWatch);
865 STORM_LOG_INFO(
"Quantitative refinement completed in " << refinementWatch.getTimeInMilliseconds() <<
"ms.");
872template<
typename ValueType>
878 if (!redirectPlayer1 && !redirectPlayer2) {
882 for (uint64_t state = 0; state < player1Groups.size() - 1; ++state) {
885 bool hasMinPlayer1Choice =
false;
886 uint64_t lowerPlayer1Choice = 0;
887 bool hasMaxPlayer1Choice =
false;
888 uint64_t upperPlayer1Choice = 0;
891 hasMinPlayer1Choice =
true;
898 if (lowerPlayer2Choice == upperPlayer2Choice) {
902 bool redirect =
true;
904 for (
auto const& entry : transitionMatrix.
getRow(upperPlayer2Choice)) {
912 if (redirectPlayer2 && redirect) {
918 bool lowerChoiceUnderUpperIsProb0 =
false;
923 hasMaxPlayer1Choice =
true;
928 if (lowerPlayer2Choice == upperPlayer2Choice) {
932 lowerChoiceUnderUpperIsProb0 =
true;
933 for (
auto const& entry : transitionMatrix.
getRow(lowerPlayer2Choice)) {
935 lowerChoiceUnderUpperIsProb0 =
false;
940 bool redirect =
true;
941 if (lowerChoiceUnderUpperIsProb0) {
942 for (
auto const& entry : transitionMatrix.
getRow(upperPlayer2Choice)) {
950 if (redirectPlayer2 && redirect) {
956 if (redirectPlayer1 && player1Direction == storm::OptimizationDirection::Minimize) {
957 if (hasMinPlayer1Choice && hasMaxPlayer1Choice && lowerPlayer1Choice != upperPlayer1Choice) {
958 if (!isProb0Min || lowerChoiceUnderUpperIsProb0) {
966template<
typename ValueType>
973 void exportToJson(std::string
const& filename, std::vector<uint64_t>
const& player1Groups, std::vector<uint64_t>
const& player2Groups,
979 std::ofstream outfile;
981 exportGame(outfile, player1Groups, player2Groups, transitionMatrix, initialStates, constraintStates, targetStates, quantitativeResult, minStrategyPair,
987 showNonStrategyAlternatives = value;
992 NodeData(uint64_t
id, uint64_t player,
bool initial,
bool target) : id(id), player(player), initial(initial), target(target) {
1003 EdgeData(uint64_t
id, uint64_t source, uint64_t target, ValueType probability, uint64_t label,
bool min,
bool max)
1004 : id(id), source(source), target(target), probability(probability), label(label), min(min), max(max) {
1011 ValueType probability;
1017 void exportEdge(std::ofstream& out, EdgeData
const& data,
bool& first) {
1024 out <<
"\t\t\t\"data\": {\n";
1025 out <<
"\t\t\t\t\"id\": \"" << data.id <<
"\",\n";
1027 out <<
"\t\t\t\t\"name\": \"" << data.probability <<
"\",\n";
1029 out <<
"\t\t\t\t\"name\": \"" << data.label <<
"\",\n";
1031 out <<
"\t\t\t\t\"source\": \"" << data.source <<
"\",\n";
1032 out <<
"\t\t\t\t\"target\": \"" << data.target <<
"\"\n";
1033 out <<
"\t\t\t},\n";
1034 out <<
"\t\t\t\"classes\": \"";
1035 if (data.min && data.max) {
1036 out <<
"minMaxEdge";
1037 }
else if (data.min) {
1039 }
else if (data.max) {
1048 void exportNode(std::ofstream& out, NodeData
const& data, ExplicitQuantitativeResultMinMax<ValueType>
const* quantitativeResult,
bool& first) {
1055 out <<
"\t\t\t\"data\": {\n";
1056 out <<
"\t\t\t\t\"id\": \"" << data.id <<
"\",\n";
1057 out <<
"\t\t\t\t\"name\": \"" << data.id;
1058 if (quantitativeResult && data.player == 1) {
1059 out <<
" [" << quantitativeResult->
getMin().getValues()[data.id] <<
", " << quantitativeResult->
getMax().getValues()[data.id] <<
"]";
1062 out <<
"\t\t\t},\n";
1063 out <<
"\t\t\t\"group\": \"nodes\",\n";
1064 out <<
"\t\t\t\"classes\": \"";
1065 if (data.player == 1) {
1067 out <<
"initialNode";
1068 }
else if (data.target) {
1069 out <<
"targetNode";
1073 }
else if (data.player == 2) {
1075 }
else if (data.player == 0) {
1082 void exportGame(std::ofstream& out, std::vector<uint64_t>
const& player1Groups, std::vector<uint64_t>
const& player2Groups,
1083 storm::storage::SparseMatrix<ValueType>
const& transitionMatrix, storm::storage::BitVector
const& initialStates,
1084 storm::storage::BitVector
const& constraintStates, storm::storage::BitVector
const& targetStates,
1085 ExplicitQuantitativeResultMinMax<ValueType>
const& quantitativeResult, storage::ExplicitGameStrategyPair
const* minStrategyPair,
1086 storage::ExplicitGameStrategyPair
const* maxStrategyPair) {
1088 std::vector<NodeData> nodes;
1089 std::vector<EdgeData> edges;
1091 std::vector<uint64_t> stack;
1092 for (uint64_t state : initialStates) {
1093 stack.push_back(state);
1095 storm::storage::BitVector reachablePlayer1(player1Groups.size() - 1);
1097 uint64_t edgeId = 0;
1098 while (!stack.empty()) {
1099 uint64_t currentState = stack.back();
1102 nodes.emplace_back(currentState, 1, initialStates.get(currentState), targetStates.
get(currentState));
1104 for (uint64_t player2State = player1Groups[currentState]; player2State < player1Groups[currentState + 1]; ++player2State) {
1105 bool emit = (minStrategyPair || maxStrategyPair) ? this->showNonStrategyAlternatives : true;
1109 if (minStrategyPair && minStrategyPair->getPlayer1Strategy().hasDefinedChoice(currentState) &&
1110 minStrategyPair->getPlayer1Strategy().getChoice(currentState) == player2State) {
1114 if (maxStrategyPair && maxStrategyPair->getPlayer1Strategy().hasDefinedChoice(currentState) &&
1115 maxStrategyPair->getPlayer1Strategy().getChoice(currentState) == player2State) {
1121 nodes.emplace_back(player2State, 2,
false,
false);
1125 for (uint64_t playerPState = player2Groups[player2State]; playerPState < player2Groups[player2State + 1]; ++playerPState) {
1126 emit = (minStrategyPair || maxStrategyPair) ? this->showNonStrategyAlternatives : true;
1130 if (minStrategyPair && minStrategyPair->getPlayer2Strategy().hasDefinedChoice(player2State) &&
1131 minStrategyPair->getPlayer2Strategy().getChoice(player2State) == playerPState) {
1135 if (maxStrategyPair && maxStrategyPair->getPlayer2Strategy().hasDefinedChoice(player2State) &&
1136 maxStrategyPair->getPlayer2Strategy().getChoice(player2State) == playerPState) {
1142 nodes.emplace_back(playerPState, 0,
false,
false);
1144 playerPState - player2Groups[player2State], min, max);
1146 for (
auto const& entry : transitionMatrix.
getRow(playerPState)) {
1147 auto player1Successor = entry.getColumn();
1148 if (!reachablePlayer1.get(player1Successor)) {
1149 reachablePlayer1.set(player1Successor);
1150 stack.push_back(player1Successor);
1153 edges.emplace_back(edgeId++, playerPState, player1Successor, entry.getValue(), 0,
false,
false);
1164 out <<
"{\n\t\"nodes\": [\n";
1166 for (
auto const& node : nodes) {
1167 exportNode(out, node, &quantitativeResult, first);
1173 out <<
"\t\"edges\": [\n";
1174 for (
auto const& edge : edges) {
1175 exportEdge(out, edge, first);
1177 out <<
"\n\t]\n}\n";
1180 bool showNonStrategyAlternatives;
1183template<
typename ValueType>
1189 bool redirectPlayer1,
bool redirectPlayer2,
bool sanityCheck) {
1190 if (redirectPlayer1 || redirectPlayer2) {
1191 for (uint64_t state = 0; state < player1Groups.size() - 1; ++state) {
1193 "Expected lower player 1 choice in state " << state <<
".");
1195 "Expected upper player 1 choice in state " << state <<
".");
1197 bool hasMinPlayer1Choice =
false;
1198 uint64_t lowerPlayer1Choice = 0;
1200 bool hasMaxPlayer1Choice =
false;
1201 uint64_t upperPlayer1Choice = 0;
1205 hasMinPlayer1Choice =
true;
1209 "Expected lower player 2 choice for state " << state <<
" (lower player 1 choice " << lowerPlayer1Choice <<
").");
1212 ValueType lowerValueUnderLowerChoicePlayer2 =
1214 lowerValueUnderMinChoicePlayer1 = lowerValueUnderLowerChoicePlayer2;
1219 if (lowerPlayer2Choice != upperPlayer2Choice) {
1220 ValueType lowerValueUnderUpperChoicePlayer2 =
1223 if (redirectPlayer2 && lowerValueUnderUpperChoicePlayer2 <= lowerValueUnderLowerChoicePlayer2) {
1224 lowerValueUnderMinChoicePlayer1 = lowerValueUnderUpperChoicePlayer2;
1235 hasMaxPlayer1Choice =
true;
1239 ValueType lowerValueUnderLowerChoicePlayer2 =
1241 lowerValueUnderMaxChoicePlayer1 = lowerValueUnderLowerChoicePlayer2;
1244 "Expected upper player 2 choice for state " << state <<
" (upper player 1 choice " << upperPlayer1Choice <<
").");
1247 if (lowerPlayer2Choice != upperPlayer2Choice) {
1248 ValueType lowerValueUnderUpperChoicePlayer2 =
1251 if (redirectPlayer2 && lowerValueUnderUpperChoicePlayer2 <= lowerValueUnderLowerChoicePlayer2) {
1258 if (redirectPlayer1 && player1Direction == storm::OptimizationDirection::Minimize) {
1259 if (hasMinPlayer1Choice && hasMaxPlayer1Choice && lowerPlayer1Choice != upperPlayer1Choice) {
1260 if (lowerValueUnderMaxChoicePlayer1 <= lowerValueUnderMinChoicePlayer1) {
1274 for (uint64_t state = 0; state < player1Groups.size() - 1; ++state) {
1275 if (targetStates.
get(state)) {
1280 "Expected max player 2 choice in state " << state <<
" with player 2 choice "
1283 for (
auto const& entry : transitionMatrix.
getRow(player2Choice)) {
1284 dtmcMatrixBuilder.
addNextValue(state, entry.getColumn(), entry.getValue());
1288 auto dtmcMatrix = dtmcMatrixBuilder.
build();
1293 uint64_t maxState = 0;
1294 for (uint64_t state = 0; state < player1Groups.size() - 1; ++state) {
1296 if (diff > maxDiff) {
1303 "Deviation " << maxDiff <<
" between computed value (" << quantitativeResult.
getMin().getValues()[maxState]
1304 <<
") and sanity check value (" << sanityValues[maxState] <<
") in state " << maxState
1305 <<
" appears to be too high. (Obtained bounds were [" << quantitativeResult.
getMin().getValues()[maxState] <<
", "
1306 << quantitativeResult.
getMax().getValues()[maxState] <<
"].)");
1311 for (uint64_t state = 0; state < player1Groups.size() - 1; ++state) {
1312 if (targetStates.
get(state)) {
1317 "Expected max player 2 choice in state " << state <<
" with player 2 choice "
1321 for (
auto const& entry : transitionMatrix.
getRow(player2Choice)) {
1322 dtmcMatrixBuilder.
addNextValue(state, entry.getColumn(), entry.getValue());
1326 dtmcMatrix = dtmcMatrixBuilder.
build();
1332 for (uint64_t state = 0; state < player1Groups.size() - 1; ++state) {
1334 if (diff > maxDiff) {
1341 "Deviation " << maxDiff <<
" between computed value (" << quantitativeResult.
getMax().getValues()[maxState]
1342 <<
") and sanity check value (" << sanityValues[maxState] <<
") in state " << maxState
1343 <<
" appears to be too high. (Obtained bounds were [" << quantitativeResult.
getMin().getValues()[maxState] <<
", "
1344 << quantitativeResult.
getMax().getValues()[maxState] <<
"].)");
1348template<storm::dd::DdType Type,
typename ModelType>
1349std::unique_ptr<storm::modelchecker::CheckResult> GameBasedMdpModelChecker<Type, ModelType>::performExplicitAbstractionSolutionStep(
1363 auto& transitionMatrix = matrixAndLabeling.
matrix;
1364 auto& player1Labeling = matrixAndLabeling.
labelings.front();
1365 auto& player2Labeling = matrixAndLabeling.
labelings.back();
1368 std::vector<uint64_t> tmpPlayer2RowGrouping;
1369 for (uint64_t player1State = 0; player1State < transitionMatrix.
getRowGroupCount(); ++player1State) {
1370 uint64_t lastLabel = std::numeric_limits<uint64_t>::max();
1372 if (player1Labeling[row] != lastLabel) {
1373 tmpPlayer2RowGrouping.emplace_back(row);
1374 lastLabel = player1Labeling[row];
1378 tmpPlayer2RowGrouping.emplace_back(player1Labeling.size());
1380 std::vector<uint64_t> player1RowGrouping = transitionMatrix.
swapRowGroupIndices(std::move(tmpPlayer2RowGrouping));
1384 std::vector<uint64_t> player1Groups(player1RowGrouping.size());
1385 storm::storage::SparseMatrix<ValueType> player1BackwardTransitions = transitionMatrix.
transpose(
true);
1386 std::vector<uint64_t> player2BackwardTransitions(transitionMatrix.
getRowGroupCount());
1388 uint64_t player2State = 0;
1389 for (uint64_t player1State = 0; player1State < player1RowGrouping.size() - 1; ++player1State) {
1390 while (player1RowGrouping[player1State + 1] > player2RowGrouping[player2State]) {
1391 player2BackwardTransitions[player2State] = player1State;
1395 player1Groups[player1State + 1] = player2State;
1399 for (uint64_t player1State = 0; player1State < player1Groups.size() - 1; ++player1State) {
1400 for (uint64_t player2State = player1Groups[player1State]; player2State < player1Groups[player1State + 1]; ++player2State) {
1401 player1Labeling[player2State] = player1Labeling[player2RowGrouping[player2State]];
1404 player1Labeling.resize(player2RowGrouping.size() - 1);
1407 storm::storage::BitVector initialStates = initialStatesBdd.
toVector(odd);
1408 storm::storage::BitVector constraintStates = constraintStatesBdd.
toVector(odd);
1409 storm::storage::BitVector targetStates = targetStatesBdd.
toVector(odd);
1410 translationWatch.stop();
1411 totalTranslationWatch.add(translationWatch);
1412 STORM_LOG_INFO(
"Translation to explicit representation completed in " << translationWatch.getTimeInMilliseconds() <<
"ms.");
1419 storm::utility::Stopwatch qualitativeWatch(
true);
1420 ExplicitQualitativeGameResultMinMax qualitativeResult =
1421 computeProb01States(previousResult, odd, player1Direction, transitionMatrix, player1Groups, player1BackwardTransitions, player2BackwardTransitions,
1422 constraintStates, targetStates, minStrategyPair, maxStrategyPair);
1423 qualitativeWatch.stop();
1424 totalSolutionWatch.add(qualitativeWatch);
1425 STORM_LOG_INFO(
"Qualitative computation completed in " << qualitativeWatch.getTimeInMilliseconds() <<
"ms.");
1427 std::unique_ptr<storm::modelchecker::CheckResult> result = checkForResultAfterQualitativeCheck<ValueType>(checkTask, initialStates, qualitativeResult);
1433 storm::storage::BitVector maybeMin = ~(qualitativeResult.getProb0Min().
getStates() | qualitativeResult.getProb1Min().getStates());
1434 storm::storage::BitVector maybeMax = ~(qualitativeResult.getProb0Max().
getStates() | qualitativeResult.getProb1Max().getStates());
1437 storm::storage::BitVector initialMaybeStates = initialStates & (maybeMin | maybeMax);
1438 bool qualitativeRefinement =
false;
1439 if (initialMaybeStates.
empty()) {
1443 STORM_LOG_INFO(
"Obtained qualitative bounds [0, 1] on the actual value for the initial states (after "
1444 << totalWatch.getTimeInMilliseconds() <<
"ms in iteration " << this->iteration <<
"). Refining abstraction based on qualitative check.");
1447 storm::utility::Stopwatch strategyProcessingWatch(
true);
1448 postProcessStrategies(player1Direction, minStrategyPair, maxStrategyPair, player1Groups, player2RowGrouping, transitionMatrix, constraintStates,
1449 targetStates, qualitativeResult, this->fixPlayer1Strategy, this->fixPlayer2Strategy, this->debug);
1450 strategyProcessingWatch.stop();
1451 totalStrategyProcessingWatch.add(strategyProcessingWatch);
1452 STORM_LOG_DEBUG(
"Postprocessed strategies in " << strategyProcessingWatch.getTimeInMilliseconds() <<
"ms.");
1456 storm::utility::Stopwatch refinementWatch(
true);
1457 qualitativeRefinement = refiner.
refine(game, odd, transitionMatrix, player1Groups, player1Labeling, player2Labeling, initialStates, constraintStates,
1458 targetStates, qualitativeResult, minStrategyPair, maxStrategyPair);
1459 refinementWatch.stop();
1460 totalRefinementWatch.add(refinementWatch);
1461 STORM_LOG_INFO(
"Qualitative refinement completed in " << refinementWatch.getTimeInMilliseconds() <<
"ms.");
1464 ExplicitQuantitativeResultMinMax<ValueType> quantitativeResult;
1467 if (!qualitativeRefinement) {
1472 storm::utility::Stopwatch quantitativeWatch(
true);
1473 quantitativeResult.
setMin(computeQuantitativeResult<ValueType>(env, player1Direction, storm::OptimizationDirection::Minimize, transitionMatrix,
1474 player1Groups, qualitativeResult, maybeMin, minStrategyPair, odd,
nullptr,
nullptr,
1475 this->reuseQuantitativeResults ? previousResult : boost::none));
1478 if (previousResult) {
1479 previousResult.get().clear();
1481 quantitativeWatch.stop();
1482 result = checkForResultAfterQuantitativeCheck<ValueType>(checkTask, storm::OptimizationDirection::Minimize,
1483 quantitativeResult.
getMin().getRange(initialStates));
1485 totalSolutionWatch.add(quantitativeWatch);
1490 quantitativeWatch.start();
1492 qualitativeResult, maybeMax, maxStrategyPair, odd, &quantitativeResult.
getMin(), &minStrategyPair));
1493 quantitativeWatch.stop();
1494 result = checkForResultAfterQuantitativeCheck<ValueType>(checkTask, storm::OptimizationDirection::Maximize,
1495 quantitativeResult.
getMax().getRange(initialStates));
1496 totalSolutionWatch.add(quantitativeWatch);
1501 ValueType minVal = quantitativeResult.
getMin().getRange(initialStates).first;
1502 ValueType maxVal = quantitativeResult.
getMax().getRange(initialStates).second;
1504 if (std::is_same<ValueType, double>::value) {
1505 std::stringstream differenceStream;
1506 differenceStream.setf(std::ios::fixed, std::ios::floatfield);
1507 differenceStream.precision(15);
1508 differenceStream << difference;
1509 STORM_LOG_INFO(
"Obtained quantitative bounds [" << minVal <<
", " << maxVal <<
"] (difference " << differenceStream.str()
1510 <<
") on the actual value for the initial states in " << quantitativeWatch.getTimeInMilliseconds()
1511 <<
"ms (after " << totalWatch.getTimeInMilliseconds() <<
"ms in iteration " << this->iteration
1516 <<
") on the actual value for the initial states in " << quantitativeWatch.getTimeInMilliseconds()
1517 <<
"ms (after " << totalWatch.getTimeInMilliseconds() <<
"ms in iteration " << this->iteration
1522 result = checkForResultAfterQuantitativeCheck<ValueType>(quantitativeResult.
getMin().getRange(initialStates).first,
1523 quantitativeResult.
getMax().getRange(initialStates).second, comparator);
1529 storm::utility::Stopwatch strategyProcessingWatch(
true);
1530 postProcessStrategies(this->iteration, player1Direction, minStrategyPair, maxStrategyPair, player1Groups, player2RowGrouping, transitionMatrix,
1531 initialStates, constraintStates, targetStates, quantitativeResult, this->fixPlayer1Strategy, this->fixPlayer2Strategy,
1533 strategyProcessingWatch.stop();
1534 totalStrategyProcessingWatch.add(strategyProcessingWatch);
1535 STORM_LOG_DEBUG(
"Postprocessed strategies in " << strategyProcessingWatch.getTimeInMilliseconds() <<
"ms.");
1539 "Expected at most " << targetStates.
getNumberOfSetBits() <<
" (number of target states) player 1 states with undefined choice but got "
1540 << minStrategyPair.getNumberOfUndefinedPlayer1States() <<
".");
1542 "Expected at most " << targetStates.
getNumberOfSetBits() <<
" (number of target states) player 1 states with undefined choice but got "
1543 << maxStrategyPair.getNumberOfUndefinedPlayer1States() <<
".");
1547 storm::utility::Stopwatch refinementWatch(
true);
1548 refiner.
refine(game, odd, transitionMatrix, player1Groups, player1Labeling, player2Labeling, initialStates, constraintStates, targetStates,
1549 quantitativeResult, minStrategyPair, maxStrategyPair);
1550 refinementWatch.stop();
1551 totalRefinementWatch.add(refinementWatch);
1552 STORM_LOG_INFO(
"Quantitative refinement completed in " << refinementWatch.getTimeInMilliseconds() <<
"ms.");
1554 if (this->reuseQuantitativeResults) {
1555 PreviousExplicitResult<ValueType> nextPreviousResult;
1556 nextPreviousResult.
values = std::move(quantitativeResult.
getMin());
1557 nextPreviousResult.
odd = odd;
1558 previousResult = std::move(nextPreviousResult);
1566template<storm::dd::DdType Type,
typename ModelType>
1567std::vector<storm::expressions::Expression> GameBasedMdpModelChecker<Type, ModelType>::getInitialPredicates(
1568 storm::expressions::Expression
const& constraintExpression, storm::expressions::Expression
const& targetStateExpression) {
1569 std::vector<storm::expressions::Expression> initialPredicates;
1570 if (preprocessedModel.isJaniModel()) {
1571 storm::expressions::VariableSetPredicateSplitter splitter(preprocessedModel.asJaniModel().getAllLocationExpressionVariables());
1573 std::vector<storm::expressions::Expression> splitExpressions = splitter.split(targetStateExpression);
1574 initialPredicates.insert(initialPredicates.end(), splitExpressions.begin(), splitExpressions.end());
1576 splitExpressions = splitter.split(constraintExpression);
1577 initialPredicates.insert(initialPredicates.end(), splitExpressions.begin(), splitExpressions.end());
1579 if (!targetStateExpression.
isTrue() && !targetStateExpression.
isFalse()) {
1580 initialPredicates.push_back(targetStateExpression);
1582 if (!constraintExpression.
isTrue() && !constraintExpression.
isFalse()) {
1583 initialPredicates.push_back(constraintExpression);
1586 return initialPredicates;
1589template<storm::dd::DdType Type,
typename ModelType>
1591 storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>
const& checkTask) {
1593 return storm::OptimizationDirection::Maximize;
1599 STORM_LOG_THROW(
false, storm::exceptions::InvalidPropertyException,
"Could not derive player 1 optimization direction.");
1600 return storm::OptimizationDirection::Maximize;
1603template<storm::dd::DdType Type>
1607 "Unable to proceed without strategy.");
1610 "Unable to proceed without strategy.");
1614 "Unable to proceed without strategy.");
1619template<storm::dd::DdType Type>
1629template<storm::dd::DdType Type,
typename ModelType>
1630ExplicitQualitativeGameResultMinMax GameBasedMdpModelChecker<Type, ModelType>::computeProb01States(
1636 ExplicitQualitativeGameResultMinMax result;
1644 targetStates, player1Direction, storm::OptimizationDirection::Minimize, &minStrategyPair);
1647 targetStates, player1Direction, storm::OptimizationDirection::Minimize, &minStrategyPair);
1650 targetStates, player1Direction, storm::OptimizationDirection::Maximize, &maxStrategyPair);
1653 targetStates, player1Direction, storm::OptimizationDirection::Maximize, &maxStrategyPair);
1655 STORM_LOG_INFO(
"[" << player1Direction <<
", " << storm::OptimizationDirection::Minimize <<
"]: " << result.prob0Min.player1States.getNumberOfSetBits()
1656 <<
" 'no', " << result.prob1Min.player1States.getNumberOfSetBits() <<
" 'yes'.");
1657 STORM_LOG_INFO(
"[" << player1Direction <<
", " << storm::OptimizationDirection::Maximize <<
"]: " << result.prob0Max.player1States.getNumberOfSetBits()
1658 <<
" 'no', " << result.prob1Max.player1States.getNumberOfSetBits() <<
" 'yes'.");
1663template<storm::dd::DdType Type,
typename ModelType>
1664SymbolicQualitativeGameResultMinMax<Type> GameBasedMdpModelChecker<Type, ModelType>::computeProb01States(
1665 boost::optional<SymbolicQualitativeGameResultMinMax<Type>>
const& previousQualitativeResult,
1668 SymbolicQualitativeGameResultMinMax<Type> result;
1670 if (reuseQualitativeResults) {
1672 if (player1Direction == storm::OptimizationDirection::Minimize) {
1675 storm::OptimizationDirection::Minimize,
true,
true);
1680 game, transitionMatrixBdd, previousQualitativeResult ? previousQualitativeResult.get().prob1Min.player1States : targetStates, candidates);
1684 storm::OptimizationDirection::Minimize,
true,
true, boost::make_optional(prob1MinMinMdp));
1688 storm::OptimizationDirection::Maximize,
true,
true);
1693 boost::optional<storm::dd::Bdd<Type>> prob1Candidates;
1694 if (previousQualitativeResult) {
1695 prob1Candidates = previousQualitativeResult.get().prob1Max.player1States;
1698 storm::OptimizationDirection::Maximize,
true,
true, prob1Candidates);
1702 storm::OptimizationDirection::Maximize,
true,
true);
1705 storm::dd::Bdd<Type> candidates = game.
getReachableStates() && !result.prob0Max.player1States;
1706 if (previousQualitativeResult) {
1707 candidates &= previousQualitativeResult.get().prob1Max.player1States;
1713 storm::OptimizationDirection::Maximize,
true,
true, boost::make_optional(prob1MaxMaxMdp));
1717 storm::OptimizationDirection::Minimize,
true,
true);
1721 storm::OptimizationDirection::Minimize,
true,
true, boost::make_optional(prob1MaxMaxMdp));
1725 storm::OptimizationDirection::Minimize,
true,
true);
1727 storm::OptimizationDirection::Minimize,
true,
true);
1729 storm::OptimizationDirection::Maximize,
true,
true);
1731 storm::OptimizationDirection::Maximize,
true,
true);
1734 STORM_LOG_INFO(
"[" << player1Direction <<
", " << storm::OptimizationDirection::Minimize <<
"]: " << result.prob0Min.player1States.getNonZeroCount()
1735 <<
" 'no', " << result.prob1Min.player1States.getNonZeroCount() <<
" 'yes'.");
1736 STORM_LOG_INFO(
"[" << player1Direction <<
", " << storm::OptimizationDirection::Maximize <<
"]: " << result.prob0Max.player1States.getNonZeroCount()
1737 <<
" 'no', " << result.prob1Max.player1States.getNonZeroCount() <<
" 'yes'.");
1743template<storm::dd::DdType Type,
typename ModelType>
1744void GameBasedMdpModelChecker<Type, ModelType>::printStatistics(storm::gbar::abstraction::MenuGameAbstractor<Type, ValueType>
const& abstractor,
1745 storm::gbar::abstraction::MenuGame<Type, ValueType>
const& game, uint64_t refinements,
1746 uint64_t peakPlayer1States, uint64_t peakTransitions)
const {
1747 storm::gbar::abstraction::AbstractionInformation<Type>
const& abstractionInformation = abstractor.
getAbstractionInformation();
1749 std::ostringstream oss;
1750 oss << std::fixed << std::setprecision(2);
1753 oss <<
"Statistics:\n";
1755 <<
" transitions\n";
1756 oss <<
" * peak size of game: " << peakPlayer1States <<
" player 1 states, " << peakTransitions <<
" transitions\n";
1757 oss <<
" * refinements: " << refinements <<
'\n';
1760 uint64_t totalAbstractionTimeMillis = totalAbstractionWatch.getTimeInMilliseconds();
1761 uint64_t totalTranslationTimeMillis = totalTranslationWatch.getTimeInMilliseconds();
1762 uint64_t totalStrategyProcessingTimeMillis = totalStrategyProcessingWatch.getTimeInMilliseconds();
1763 uint64_t totalSolutionTimeMillis = totalSolutionWatch.getTimeInMilliseconds();
1764 uint64_t totalRefinementTimeMillis = totalRefinementWatch.getTimeInMilliseconds();
1765 uint64_t setupTime = setupWatch.getTimeInMilliseconds();
1766 uint64_t totalTimeMillis = totalWatch.getTimeInMilliseconds();
1768 oss <<
"Time breakdown:\n";
1769 oss <<
" * setup: " << setupTime <<
"ms (" << 100 *
static_cast<double>(setupTime) / totalTimeMillis <<
"%)\n";
1770 oss <<
" * abstraction: " << totalAbstractionTimeMillis <<
"ms (" << 100 *
static_cast<double>(totalAbstractionTimeMillis) / totalTimeMillis <<
"%)\n";
1772 oss <<
" * translation: " << totalTranslationTimeMillis <<
"ms (" << 100 *
static_cast<double>(totalTranslationTimeMillis) / totalTimeMillis
1774 if (fixPlayer1Strategy || fixPlayer2Strategy) {
1775 oss <<
" * strategy processing: " << totalStrategyProcessingTimeMillis <<
"ms ("
1776 << 100 *
static_cast<double>(totalStrategyProcessingTimeMillis) / totalTimeMillis <<
"%)\n";
1779 oss <<
" * solution: " << totalSolutionTimeMillis <<
"ms (" << 100 *
static_cast<double>(totalSolutionTimeMillis) / totalTimeMillis <<
"%)\n";
1780 oss <<
" * refinement: " << totalRefinementTimeMillis <<
"ms (" << 100 *
static_cast<double>(totalRefinementTimeMillis) / totalTimeMillis <<
"%)\n";
1781 oss <<
" ---------------------------------------------\n";
1782 oss <<
" * total: " << totalTimeMillis <<
"ms\n\n";
1787template<storm::dd::DdType Type,
typename ModelType>
1788storm::expressions::Expression GameBasedMdpModelChecker<Type, ModelType>::getExpression(storm::logic::Formula
const& formula) {
1790 storm::exceptions::InvalidPropertyException,
"The target states have to be given as label or an expression.");
1791 storm::expressions::Expression result;
1803template class GameBasedMdpModelChecker<storm::dd::DdType::CUDD, storm::models::symbolic::Dtmc<storm::dd::DdType::CUDD, double>>;
1804template class GameBasedMdpModelChecker<storm::dd::DdType::CUDD, storm::models::symbolic::Mdp<storm::dd::DdType::CUDD, double>>;
1805template class GameBasedMdpModelChecker<storm::dd::DdType::Sylvan, storm::models::symbolic::Dtmc<storm::dd::DdType::Sylvan, double>>;
1806template class GameBasedMdpModelChecker<storm::dd::DdType::Sylvan, storm::models::symbolic::Mdp<storm::dd::DdType::Sylvan, double>>;
1808template class GameBasedMdpModelChecker<storm::dd::DdType::Sylvan, storm::models::symbolic::Dtmc<storm::dd::DdType::Sylvan, storm::RationalNumber>>;
1809template class GameBasedMdpModelChecker<storm::dd::DdType::Sylvan, storm::models::symbolic::Mdp<storm::dd::DdType::Sylvan, storm::RationalNumber>>;
Add< LibraryType, ValueType > swapVariables(std::vector< std::pair< storm::expressions::Variable, storm::expressions::Variable > > const &metaVariablePairs) const
Swaps the given pairs of meta variables in the ADD.
MatrixAndLabeling toLabeledMatrix(std::set< storm::expressions::Variable > const &rowMetaVariables, std::set< storm::expressions::Variable > const &columnMetaVariables, std::set< storm::expressions::Variable > const &groupMetaVariables, storm::dd::Odd const &rowOdd, storm::dd::Odd const &columnOdd, std::vector< std::set< storm::expressions::Variable > > const &labelMetaVariables=std::vector< std::set< storm::expressions::Variable > >()) const
ValueType getMax() const
Retrieves the highest function value of any encoding.
ValueType getMin() const
Retrieves the lowest function value of any encoding.
virtual uint_fast64_t getNonZeroCount() const override
Retrieves the number of encodings that are mapped to a non-zero value.
Add< LibraryType, ValueType > sumAbstract(std::set< storm::expressions::Variable > const &metaVariables) const
Sum-abstracts from the given meta variables.
virtual uint_fast64_t getNodeCount() const override
Retrieves the number of nodes necessary to represent the DD.
Bdd< LibraryType > toBdd() const
Converts the ADD to a BDD by mapping all values unequal to zero to 1.
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.
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.
Odd createOdd() const
Creates an ODD based on the current BDD.
storm::storage::BitVector toVector(storm::dd::Odd const &rowOdd) const
Converts the BDD to a bit vector.
bool isFalse() const
Checks if the expression is equal to the boolean literal false.
ExpressionManager const & getManager() const
Retrieves the manager responsible for this expression.
bool isTrue() const
Checks if the expression is equal to the boolean literal true.
Expression boolean(bool value) const
Creates an expression that characterizes the given boolean literal.
ExplicitQualitativeGameResult prob0Min
ExplicitQualitativeGameResult prob1Min
ExplicitQualitativeGameResult prob0Max
ExplicitQualitativeGameResult prob1Max
ExplicitQualitativeGameResult & asExplicitQualitativeGameResult()
virtual storm::storage::BitVector const & getStates() const =0
ExplicitQualitativeResult const & getProb0Max() const
ExplicitQualitativeResult const & getProb1Min() const
ExplicitQualitativeResult const & getProb1Max() const
ExplicitQualitativeResult const & getProb0Min() const
std::vector< ValueType > const & getValues() const
ExplicitQuantitativeResult< ValueType > const & getMin() const
ExplicitQuantitativeResult< ValueType > const & getMax() const
SymbolicQualitativeGameResult< Type > prob0Min
SymbolicQualitativeGameResult< Type > prob1Max
SymbolicQualitativeGameResult< Type > prob0Max
SymbolicQualitativeGameResult< Type > prob1Min
boost::optional< storm::dd::Bdd< Type > > player2Strategy
boost::optional< std::pair< ValueType, ValueType > > initialStatesRange
boost::optional< storm::dd::Bdd< Type > > player1Strategy
std::pair< ValueType, ValueType > const & getInitialStatesRange() const
storm::dd::Bdd< Type > const & getPlayer2Strategy() const
storm::dd::Add< Type, ValueType > values
storm::dd::Bdd< Type > const & getPlayer1Strategy() const
void setShowNonStrategyAlternatives(bool value)
void exportToJson(std::string const &filename, std::vector< uint64_t > const &player1Groups, std::vector< uint64_t > const &player2Groups, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::BitVector const &initialStates, storm::storage::BitVector const &constraintStates, storm::storage::BitVector const &targetStates, ExplicitQuantitativeResultMinMax< ValueType > const &quantitativeResult, storage::ExplicitGameStrategyPair const *minStrategyPair, storage::ExplicitGameStrategyPair const *maxStrategyPair)
void setMin(ExplicitQuantitativeResult< ValueType > &&newMin)
ExplicitQuantitativeResult< ValueType > const & getMin() const
void setMax(ExplicitQuantitativeResult< ValueType > &&newMax)
ExplicitQuantitativeResult< ValueType > const & getMax() const
virtual std::unique_ptr< storm::modelchecker::CheckResult > computeReachabilityProbabilities(Environment const &env, storm::modelchecker::CheckTask< storm::logic::EventuallyFormula, ValueType > const &checkTask) override
virtual std::unique_ptr< storm::modelchecker::CheckResult > computeUntilProbabilities(Environment const &env, storm::modelchecker::CheckTask< storm::logic::UntilFormula, ValueType > const &checkTask) override
ModelType::ValueType ValueType
GameBasedMdpModelChecker(storm::storage::SymbolicModelDescription const &model, GameBasedMdpModelCheckerOptions const &options=GameBasedMdpModelCheckerOptions(), std::shared_ptr< storm::utility::solver::SmtSolverFactory > const &smtSolverFactory=std::make_shared< storm::utility::solver::MathsatSmtSolverFactory >())
Constructs a model checker whose underlying model is implicitly given by the provided program.
virtual bool canHandle(storm::modelchecker::CheckTask< storm::logic::Formula, ValueType > const &checkTask) const override
Overridden methods from super class.
SymbolicQuantitativeGameResult< Type, ValueType > max
SymbolicQuantitativeGameResult< Type, ValueType > min
VariableSet & getGlobalVariables()
Retrieves the variables of this automaton.
ModelType const & getModelType() const
Retrieves the type of the model.
storm::expressions::Expression getLabelExpression(Variable const &transientVariable, std::vector< std::reference_wrapper< Automaton const > > const &automata) const
Creates the expression that characterizes all states in which the provided transient boolean variable...
detail::Variables< Variable > getBooleanVariables()
Retrieves the boolean variables in this set.
bool isBoundSet() const
Retrieves whether there is a bound with which the values for the states will be compared.
ValueType getBoundThreshold() const
Retrieves the value of the bound (if set).
storm::logic::ComparisonType const & getBoundComparisonType() const
Retrieves the comparison type of the bound (if set).
bool isOptimizationDirectionSet() const
Retrieves whether an optimization direction was set.
FormulaType const & getFormula() const
Retrieves the formula from this task.
storm::OptimizationDirection const & getOptimizationDirection() const
Retrieves the optimization direction (if set).
bool isOnlyInitialStatesRelevantSet() const
Retrieves whether only the initial states are relevant in the computation.
static std::vector< SolutionType > computeUntilProbabilities(Environment const &env, storm::solver::SolveGoal< ValueType, SolutionType > &&goal, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, bool qualitative, ModelCheckerHint const &hint=ModelCheckerHint())
storm::dd::DdManager< Type > & getManager() const
Retrieves the manager responsible for the DDs that represent this model.
storm::dd::Add< Type, ValueType > const & getTransitionMatrix() const
Retrieves the matrix representing the transitions of the 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 uint_fast64_t getNumberOfTransitions() const override
Returns the number of (non-zero) transitions of the model.
storm::dd::Bdd< Type > const & getReachableStates() const
Retrieves the reachable states of the model.
virtual uint_fast64_t getNumberOfStates() const override
Returns the number of states of the model.
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.
storm::dd::Bdd< Type > getIllegalPlayer1Mask() const
Retrieves a BDD characterizing all illegal player 1 choice encodings in the model.
uint64_t getNumberOfPlayer2States() const
Retrieves the number of player 2 states in the game.
storm::dd::Bdd< Type > getIllegalPlayer2Mask() const
Retrieves a BDD characterizing all illegal player 2 choice encodings in the model.
virtual std::unique_ptr< GameSolver< ValueType > > create(Environment const &env, storm::storage::SparseMatrix< storm::storage::sparse::state_type > const &player1Matrix, storm::storage::SparseMatrix< ValueType > const &player2Matrix) const
virtual std::unique_ptr< storm::solver::SymbolicGameSolver< Type, ValueType > > create(storm::dd::Add< Type, ValueType > const &A, storm::dd::Bdd< Type > const &allRows, storm::dd::Bdd< Type > const &illegalPlayer1Mask, storm::dd::Bdd< Type > const &illegalPlayer2Mask, std::set< storm::expressions::Variable > const &rowMetaVariables, std::set< storm::expressions::Variable > const &columnMetaVariables, std::vector< std::pair< storm::expressions::Variable, storm::expressions::Variable > > const &rowColumnMetaVariablePairs, std::set< storm::expressions::Variable > const &player1Variables, std::set< storm::expressions::Variable > const &player2Variables) const
A bit vector that is internally represented as a vector of 64-bit values.
bool isDisjointFrom(BitVector const &other) const
Checks whether none of the bits that are set in the current bit vector are also set in the given bit ...
bool empty() const
Retrieves whether no bits are set to true in this bit vector.
bool isSubsetOf(BitVector const &other) const
Checks whether all bits that are set in the current bit vector are also set in the given bit vector.
uint64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
size_t size() const
Retrieves the number of bits this bit vector can store.
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
void setChoice(uint64_t state, uint64_t choice)
uint64_t getChoice(uint64_t state) const
ExplicitGameStrategy & getPlayer1Strategy()
ExplicitGameStrategy & getPlayer2Strategy()
A class that can be used to build a sparse matrix by adding value by value.
void addNextValue(index_type row, index_type column, value_type const &value)
Sets the matrix entry at the given row and column to the given value.
SparseMatrix< value_type > build(index_type overriddenRowCount=0, index_type overriddenColumnCount=0, index_type overriddenRowGroupCount=0)
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.
SparseMatrix getSubmatrix(bool useGroups, storm::storage::BitVector const &rowConstraint, storm::storage::BitVector const &columnConstraint, bool insertDiagonalEntries=false, storm::storage::BitVector const &makeZeroColumns=storm::storage::BitVector()) const
Creates a submatrix of the current matrix by dropping all rows and columns whose bits are not set to ...
std::vector< index_type > swapRowGroupIndices(std::vector< index_type > &&newRowGrouping)
Swaps the grouping of rows of this matrix.
value_type multiplyRowWithVector(index_type row, std::vector< value_type > const &vector) const
Multiplies a single row of the matrix with the given vector and returns the result.
index_type getRowGroupCount() const
Returns the number of row groups in the matrix.
std::vector< index_type > const & getRowGroupIndices() const
Returns the grouping of rows of this matrix.
std::vector< value_type > getConstrainedRowGroupSumVector(storm::storage::BitVector const &rowGroupConstraint, storm::storage::BitVector const &columnConstraint) const
Computes a vector whose entries represent the sums of selected columns for all rows in selected row g...
storm::storage::SparseMatrix< value_type > transpose(bool joinGroups=false, bool keepZeros=false) const
Transposes the matrix.
bool hasUndefinedConstants() const
bool isZero(ValueType const &value) const
bool isEqual(ValueType const &value1, ValueType const &value2) const
A class that provides convenience operations to display run times.
#define STORM_LOG_INFO(message)
#define STORM_LOG_WARN(message)
#define STORM_LOG_DEBUG(message)
#define STORM_LOG_STATISTICS(message)
#define STORM_LOG_TRACE(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_WARN_COND(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
SFTBDDChecker::ValueType ValueType
std::unique_ptr< storm::modelchecker::CheckResult > checkForResultAfterQuantitativeCheck(storm::modelchecker::CheckTask< storm::logic::Formula, ValueType > const &checkTask, storm::OptimizationDirection const &player2Direction, std::pair< ValueType, ValueType > const &initialValueRange)
void postProcessStrategies(storm::OptimizationDirection const &player1Direction, storage::ExplicitGameStrategyPair &minStrategyPair, storage::ExplicitGameStrategyPair &maxStrategyPair, std::vector< uint64_t > const &player1Groups, std::vector< uint64_t > const &player2Groups, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::BitVector const &constraintStates, storm::storage::BitVector const &targetStates, ExplicitQualitativeGameResultMinMax const &qualitativeResult, bool redirectPlayer1, bool redirectPlayer2, bool sanityCheck)
std::unique_ptr< storm::modelchecker::CheckResult > checkForResultAfterQualitativeCheck(storm::modelchecker::CheckTask< storm::logic::Formula, ValueType > const &checkTask, storm::OptimizationDirection player2Direction, storm::dd::Bdd< Type > const &initialStates, storm::dd::Bdd< Type > const &prob0, storm::dd::Bdd< Type > const &prob1)
SymbolicQuantitativeGameResult< Type, ValueType > computeQuantitativeResult(Environment const &env, storm::OptimizationDirection player1Direction, storm::OptimizationDirection player2Direction, storm::gbar::abstraction::MenuGame< Type, ValueType > const &game, SymbolicQualitativeGameResultMinMax< Type > const &qualitativeResult, storm::dd::Add< Type, ValueType > const &initialStatesAdd, storm::dd::Bdd< Type > const &maybeStates, boost::optional< SymbolicQuantitativeGameResult< Type, ValueType > > const &startInfo=boost::none)
bool checkQualitativeStrategies(bool prob0, SymbolicQualitativeGameResult< Type > const &result, storm::dd::Bdd< Type > const &targetStates)
SymbolicQuantitativeGameResult< Type, ValueType > solveMaybeStates(Environment const &env, storm::OptimizationDirection const &player1Direction, storm::OptimizationDirection const &player2Direction, storm::gbar::abstraction::MenuGame< Type, ValueType > const &game, storm::dd::Bdd< Type > const &maybeStates, storm::dd::Bdd< Type > const &prob1States, boost::optional< SymbolicQuantitativeGameResult< Type, ValueType > > const &startInfo=boost::none)
void closeFile(std::ofstream &stream)
Close the given file after writing.
void openFile(std::string const &filepath, std::ofstream &filestream, bool append=false, bool silent=false)
Open the given file for writing.
bool isLowerBound(ComparisonType t)
bool isStrict(ComparisonType t)
FragmentSpecification reachability()
storm::storage::BitVector getStates(storm::logic::Formula const &propositionalFormula, bool formulaInverted, PomdpType const &pomdp)
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.
ExplicitGameProb01Result performProb0(storm::storage::SparseMatrix< ValueType > const &transitionMatrix, std::vector< uint64_t > const &player1Groups, storm::storage::SparseMatrix< ValueType > const &player1BackwardTransitions, std::vector< uint64_t > const &player2BackwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, storm::OptimizationDirection const &player1Direction, storm::OptimizationDirection const &player2Direction, storm::storage::ExplicitGameStrategyPair *strategyPair)
Computes the set of states that have probability 0 given the strategies of the two players.
storm::storage::BitVector performProb1A(storm::models::sparse::NondeterministicModel< T, RM > const &model, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Computes the sets of states that have probability 1 of satisfying phi until psi under all possible re...
storm::storage::BitVector performProb1(storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &, storm::storage::BitVector const &psiStates, storm::storage::BitVector const &statesWithProbabilityGreater0)
Computes the set of states of the given model for which all paths lead to the given set of target sta...
storm::storage::BitVector performProb1E(storm::storage::SparseMatrix< T > const &transitionMatrix, std::vector< uint_fast64_t > const &nondeterministicChoiceIndices, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, boost::optional< storm::storage::BitVector > const &choiceConstraint)
Computes the sets of states that have probability 1 of satisfying phi until psi under at least one po...
void setVectorValues(std::vector< T > &vector, storm::storage::BitVector const &positions, std::vector< T > const &values)
Sets the provided values at the provided positions in the given vector.
void selectVectorValues(std::vector< T > &vector, storm::storage::BitVector const &positions, std::vector< T > const &values)
Selects the elements from a vector at the specified positions and writes them consecutively into anot...
ValueType max(ValueType const &first, ValueType const &second)
ValueType min(ValueType const &first, ValueType const &second)
ValueType abs(ValueType const &number)
TargetType convertNumber(SourceType const &number)
solver::OptimizationDirection OptimizationDirection
Converts the ADD to a row-grouped (sparse) matrix.
std::vector< std::vector< uint64_t > > labelings
storm::storage::SparseMatrix< ValueType > matrix
ExplicitQuantitativeResult< ValueType > values
storm::storage::BitVector const & getPlayer1States() const
storm::storage::BitVector const & getPlayer2States() const
bool hasPlayer1Strategy() const
storm::dd::Bdd< Type > const & getPlayer2States() const
bool hasPlayer2Strategy() const
storm::dd::Bdd< Type > const & getPlayer1Strategy() const
storm::dd::Bdd< Type > const & getPlayer2Strategy() const
storm::dd::Bdd< Type > const & getPlayer1States() const