44using storm::gbar::abstraction::ExplicitQuantitativeResult;
45using storm::gbar::abstraction::ExplicitQuantitativeResultMinMax;
46using storm::gbar::abstraction::SymbolicQuantitativeGameResult;
47using storm::gbar::abstraction::SymbolicQuantitativeGameResultMinMax;
49template<storm::dd::DdType Type,
typename ModelType>
52 std::shared_ptr<storm::utility::solver::SmtSolverFactory>
const& smtSolverFactory)
54 smtSolverFactory(smtSolverFactory),
55 comparator(
storm::
utility::convertNumber<
ValueType>(options.precision), options.relativeTerminationCriterion),
56 reuseQualitativeResults(false),
57 reuseQuantitativeResults(false),
58 solveMode(options.solveMode),
59 debug(options.debug) {
61 auto undefinedConstants = model.getUndefinedConstants();
62 std::vector<std::string> undefinedConstantNames;
63 for (auto undefinedConstant : undefinedConstants) {
64 undefinedConstantNames.emplace_back(undefinedConstant.getName());
68 "Model contains undefined constants ("
69 << boost::algorithm::join(undefinedConstantNames,
",")
70 <<
"). Game-based abstraction can treat such models, but you should make sure that you did not simply forget to define these "
71 "constants. In particular, it may be necessary to constrain the values of the undefined constants.");
74 if (model.isPrismProgram()) {
75 storm::prism::Program const& originalProgram = model.asPrismProgram();
77 originalProgram.getModelType() == storm::prism::Program::ModelType::DTMC || originalProgram.getModelType() == storm::prism::Program::ModelType::MDP,
78 storm::exceptions::NotSupportedException,
"Currently only DTMCs/MDPs are supported by the game-based model checker.");
80 auto flattenStart = std::chrono::high_resolution_clock::now();
82 if (originalProgram.getNumberOfModules() > 1) {
83 preprocessedModel = originalProgram.substituteFormulas().flattenModules(this->smtSolverFactory);
85 preprocessedModel = originalProgram;
87 auto flattenEnd = std::chrono::high_resolution_clock::now();
88 STORM_LOG_INFO(
"Flattened model in " << std::chrono::duration_cast<std::chrono::milliseconds>(flattenEnd - flattenStart).count() <<
"ms.");
90 STORM_LOG_TRACE(
"Game-based model checker got program " << preprocessedModel.asPrismProgram());
94 storm::exceptions::NotSupportedException,
"Currently only DTMCs/MDPs are supported by the game-based model checker.");
97 preprocessedModel = model.asJaniModel().flattenComposition();
102 maximalNumberOfAbstractions = options.maximalNumberOfAbstractions;
103 fixPlayer1Strategy = options.fixPlayer1Strategy;
104 fixPlayer2Strategy = options.fixPlayer2Strategy;
107template<storm::dd::DdType Type,
typename ModelType>
114template<storm::dd::DdType Type,
typename ModelType>
118 std::map<std::string, storm::expressions::Expression> labelToExpressionMapping;
119 if (preprocessedModel.isPrismProgram()) {
120 labelToExpressionMapping = preprocessedModel.asPrismProgram().getLabelToExpressionMapping();
124 if (variable.isTransient()) {
125 labelToExpressionMapping[variable.getName()] = janiModel.
getLabelExpression(variable);
135 return performGameBasedAbstractionRefinement(env, checkTask.template substituteFormula<storm::logic::Formula>(pathFormula), constraintExpression,
136 targetStateExpression);
139template<storm::dd::DdType Type,
typename ModelType>
143 std::map<std::string, storm::expressions::Expression> labelToExpressionMapping;
144 if (preprocessedModel.isPrismProgram()) {
145 labelToExpressionMapping = preprocessedModel.asPrismProgram().getLabelToExpressionMapping();
149 if (variable.isTransient()) {
150 labelToExpressionMapping[variable.getName()] = janiModel.
getLabelExpression(variable);
158 return performGameBasedAbstractionRefinement(env, checkTask.template substituteFormula<storm::logic::Formula>(pathFormula), constraintExpression,
159 targetStateExpression);
162template<storm::dd::DdType Type,
typename ValueType>
166 std::unique_ptr<storm::modelchecker::CheckResult> result;
171 if (player2Direction == storm::OptimizationDirection::Minimize) {
173 if ((prob1 && initialStates) == initialStates) {
178 if (!(prob1 && initialStates).isZero()) {
183 }
else if (player2Direction == storm::OptimizationDirection::Maximize) {
185 if ((prob0 && initialStates) == initialStates) {
190 if (!(prob0 && initialStates).isZero()) {
197 if (player2Direction == storm::OptimizationDirection::Minimize && (prob1 && initialStates) == initialStates) {
200 }
else if (player2Direction == storm::OptimizationDirection::Maximize && (prob0 && initialStates) == initialStates) {
209template<storm::dd::DdType Type,
typename ValueType>
214 std::unique_ptr<storm::modelchecker::CheckResult> result =
216 qualitativeResult.
prob0Min.getPlayer1States(), qualitativeResult.
prob1Min.getPlayer1States());
221 qualitativeResult.
prob0Max.getPlayer1States(), qualitativeResult.
prob1Max.getPlayer1States());
228template<
typename ValueType>
232 std::unique_ptr<storm::modelchecker::CheckResult> result;
237 if (player2Direction == storm::OptimizationDirection::Minimize) {
249 }
else if (player2Direction == storm::OptimizationDirection::Maximize) {
263 if (player2Direction == storm::OptimizationDirection::Minimize && initialStates.
isSubsetOf(prob1)) {
266 }
else if (player2Direction == storm::OptimizationDirection::Maximize && initialStates.
isSubsetOf(prob0)) {
275template<
typename ValueType>
280 std::unique_ptr<storm::modelchecker::CheckResult> result =
294template<
typename ValueType>
297 std::pair<ValueType, ValueType>
const& initialValueRange) {
298 std::unique_ptr<storm::modelchecker::CheckResult> result;
308 ValueType
const& lowerValue = initialValueRange.first;
309 ValueType
const& upperValue = initialValueRange.second;
315 if (player2Direction == storm::OptimizationDirection::Minimize) {
325 if (player2Direction == storm::OptimizationDirection::Maximize) {
339template<
typename ValueType>
342 std::unique_ptr<storm::modelchecker::CheckResult> result;
345 if (comparator.
isEqual(minValue, maxValue)) {
347 ValueType((minValue + maxValue) / ValueType(2)));
353template<storm::dd::DdType Type,
typename ValueType>
358 STORM_LOG_TRACE(
"Performing quantative solution step. Player 1: " << player1Direction <<
", player 2: " << player2Direction <<
".");
373 startVector = startInfo.get().values * maybeStatesAdd;
375 startVector = game.
getManager().template getAddZero<ValueType>();
380 std::unique_ptr<storm::solver::SymbolicGameSolver<Type, ValueType>>
solver =
383 solver->setGeneratePlayersStrategies(
true);
384 auto values =
solver->solveGame(env, player1Direction, player2Direction, startVector, subvector,
385 startInfo ? boost::make_optional(startInfo.get().getPlayer1Strategy()) : boost::none,
386 startInfo ? boost::make_optional(startInfo.get().getPlayer2Strategy()) : boost::none);
388 solver->getPlayer1Strategy(),
solver->getPlayer2Strategy());
391template<storm::dd::DdType Type,
typename ValueType>
397 bool min = player2Direction == storm::OptimizationDirection::Minimize;
405 combinedPlayer1QualitativeStrategies = (qualitativeResult.
prob0Min.getPlayer1Strategy() || qualitativeResult.
prob1Min.getPlayer1Strategy());
406 combinedPlayer2QualitativeStrategies = (qualitativeResult.
prob0Min.getPlayer2Strategy() || qualitativeResult.
prob1Min.getPlayer2Strategy());
408 combinedPlayer1QualitativeStrategies = (qualitativeResult.
prob0Max.getPlayer1Strategy() || qualitativeResult.
prob1Max.getPlayer1Strategy());
409 combinedPlayer2QualitativeStrategies = (qualitativeResult.
prob0Max.getPlayer2Strategy() || qualitativeResult.
prob1Max.getPlayer2Strategy());
416 auto start = std::chrono::high_resolution_clock::now();
417 if (!maybeStates.
isZero()) {
421 result =
solveMaybeStates(env, player1Direction, player2Direction, game, maybeStates,
422 min ? qualitativeResult.
prob1Min.getPlayer1States() : qualitativeResult.
prob1Max.getPlayer1States(), startInfo);
429 result.
values += min ? qualitativeResult.
prob1Min.getPlayer1States().template toAdd<ValueType>()
430 : qualitativeResult.
prob1Max.getPlayer1States().template toAdd<ValueType>();
432 STORM_LOG_TRACE(
"No " << (player2Direction == storm::OptimizationDirection::Minimize ?
"min" :
"max") <<
" maybe states.");
435 result.
values += min ? qualitativeResult.
prob1Min.getPlayer1States().template toAdd<ValueType>()
436 : qualitativeResult.
prob1Max.getPlayer1States().template toAdd<ValueType>();
442 ValueType maxValueOverInitialStates = initialStateValueAdd.
getMax();
443 initialStateValueAdd += (!game.
getInitialStates()).template toAdd<ValueType>();
444 ValueType minValueOverInitialStates = initialStateValueAdd.
getMin();
446 result.
initialStatesRange = std::make_pair(minValueOverInitialStates, maxValueOverInitialStates);
453 auto end = std::chrono::high_resolution_clock::now();
454 STORM_LOG_TRACE(
"Obtained quantitative " << (min ?
"lower" :
"upper") <<
" bound "
456 << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() <<
"ms.");
461template<
typename ValueType>
469 bool player2Min = player2Direction == storm::OptimizationDirection::Minimize;
481 if (maybeStates.
empty()) {
486 if (previousResult) {
487 STORM_LOG_ASSERT(player2Min,
"Can only reuse previous values when minimizing.");
488 previousResult.get().odd.oldToNewIndex(odd, [&previousResult, &result, player2Min, player1Prob1States](uint64_t oldOffset, uint64_t newOffset) {
489 if (!player1Prob1States.get(newOffset)) {
491 player2Min ? previousResult.get().values.getValues()[oldOffset] : previousResult.get().values.getValues()[oldOffset];
501 uint64_t position = 0;
502 uint64_t previousPlayer2States = 0;
504 for (uint64_t state : maybeStates) {
505 subPlayer1Groups[position] = previousPlayer2States;
507 [[maybe_unused]]
bool hasMaybePlayer2Successor =
false;
508 for (uint64_t player2State = player1Groups[state]; player2State < player1Groups[state + 1]; ++player2State) {
509 if (!player2Prob0States.get(player2State) && !player2Prob1States.get(player2State)) {
510 player2MaybeStates.
set(player2State);
511 hasMaybePlayer2Successor =
true;
512 ++previousPlayer2States;
515 STORM_LOG_ASSERT(hasMaybePlayer2Successor,
"Player 1 maybe state has no player2 maybe successor.");
518 subPlayer1Groups.back() = previousPlayer2States;
529 if (startingQuantitativeResult) {
532 if (previousResult) {
533 STORM_LOG_ASSERT(!startingQuantitativeResult,
"Cannot take two different hints.");
538 std::vector<uint64_t> player1Scheduler(subPlayer1Groups.size() - 1);
540 if (startingStrategyPair) {
542 uint64_t maybeStatePosition = 0;
543 previousPlayer2States = 0;
544 for (uint64_t state : maybeStates) {
545 uint64_t chosenPlayer2State = startingStrategyPair->getPlayer1Strategy().getChoice(state);
547 uint64_t previousPlayer2MaybeStatesForState = 0;
548 for (uint64_t player2State = player1Groups[state]; player2State < player1Groups[state + 1]; ++player2State) {
549 if (player2MaybeStates.
get(player2State)) {
550 if (player2State == chosenPlayer2State) {
551 player1Scheduler[maybeStatePosition] = previousPlayer2MaybeStatesForState;
555 if (startingStrategyPair->getPlayer2Strategy().hasDefinedChoice(player2State)) {
556 player2Scheduler[previousPlayer2States] =
557 startingStrategyPair->getPlayer2Strategy().getChoice(player2State) - transitionMatrix.
getRowGroupIndices()[player2State];
559 player2Scheduler[previousPlayer2States] = 0;
562 ++previousPlayer2MaybeStatesForState;
563 ++previousPlayer2States;
567 ++maybeStatePosition;
573 gameSolver->solveGame(env, player1Direction, player2Direction, values, b, &player1Scheduler, &player2Scheduler);
579 uint64_t previousPlayer1MaybeStates = 0;
580 uint64_t previousPlayer2MaybeStates = 0;
581 for (uint64_t state : maybeStates) {
582 uint64_t previousPlayer2MaybeStatesForState = 0;
583 [[maybe_unused]]
bool madePlayer1Choice =
false;
584 for (uint64_t player2State = player1Groups[state]; player2State < player1Groups[state + 1]; ++player2State) {
585 if (player1Scheduler[previousPlayer1MaybeStates] == previousPlayer2MaybeStatesForState) {
587 madePlayer1Choice =
true;
590 if (player2MaybeStates.
get(player2State)) {
592 transitionMatrix.
getRowGroupIndices()[player2State] + player2Scheduler[previousPlayer2MaybeStates]);
594 ++previousPlayer2MaybeStatesForState;
595 ++previousPlayer2MaybeStates;
598 STORM_LOG_ASSERT(madePlayer1Choice,
"[" << player1Direction <<
"]: player 1 state " << state
599 <<
" did not make a choice, scheduler: " << player1Scheduler[previousPlayer1MaybeStates] <<
".");
601 ++previousPlayer1MaybeStates;
607template<storm::dd::DdType Type,
typename ModelType>
608std::unique_ptr<storm::modelchecker::CheckResult> GameBasedMdpModelChecker<Type, ModelType>::performGameBasedAbstractionRefinement(
612 "The game-based abstraction refinement model checker can only compute the result for the initial states.");
619 std::vector<storm::expressions::Expression> initialPredicates = getInitialPredicates(constraintExpression, targetStateExpression);
625 if (preprocessedModel.isPrismProgram()) {
626 abstractor = std::make_shared<storm::gbar::abstraction::prism::PrismMenuGameAbstractor<Type, ValueType>>(env, preprocessedModel.asPrismProgram(),
627 smtSolverFactory, options);
629 abstractor = std::make_shared<storm::gbar::abstraction::jani::JaniMenuGameAbstractor<Type, ValueType>>(env, preprocessedModel.asJaniModel(),
630 smtSolverFactory, options);
632 std::unique_ptr<storm::modelchecker::CheckResult> result;
633 abstractor->getDdManager().execute([&]() {
634 if (!constraintExpression.
isTrue()) {
635 abstractor->addTerminalStates(!constraintExpression);
637 abstractor->addTerminalStates(targetStateExpression);
638 abstractor->setTargetStates(targetStateExpression);
641 storm::gbar::abstraction::MenuGameRefiner<Type, ValueType> refiner(*abstractor, smtSolverFactory->create(preprocessedModel.getManager()), options);
642 refiner.refine(initialPredicates,
false);
644 storm::dd::Bdd<Type> globalConstraintStates = abstractor->getStates(constraintExpression);
645 storm::dd::Bdd<Type> globalTargetStates = abstractor->getStates(targetStateExpression);
649 boost::optional<SymbolicQualitativeGameResultMinMax<Type>> previousSymbolicQualitativeResult = boost::none;
650 boost::optional<SymbolicQuantitativeGameResult<Type, ValueType>> previousSymbolicMinQuantitativeResult = boost::none;
651 boost::optional<PreviousExplicitResult<ValueType>> previousExplicitResult = boost::none;
652 uint64_t peakPlayer1States = 0;
653 uint64_t peakTransitions = 0;
654 for (iteration = 0; iteration < maximalNumberOfAbstractions; ++iteration) {
655 auto iterationStart = std::chrono::high_resolution_clock::now();
659 storm::utility::Stopwatch abstractionWatch(
true);
660 storm::gbar::abstraction::MenuGame<Type, ValueType> game = abstractor->abstract();
661 abstractionWatch.stop();
662 totalAbstractionWatch.add(abstractionWatch);
665 peakPlayer1States = std::max(peakPlayer1States, numberOfPlayer1States);
667 peakTransitions = std::max(peakTransitions, numberOfTransitions);
670 <<
" initial), " << game.
getNumberOfPlayer2States() <<
" player 2 states, " << numberOfTransitions <<
" transitions, "
673 << abstractionWatch.getTimeInMilliseconds() <<
"ms).");
680 storm::dd::Bdd<Type> constraintStates = globalConstraintStates && game.
getReachableStates();
682 if (player1Direction == storm::OptimizationDirection::Minimize) {
693 if (solveMode == abstraction::SolveMode::Dd) {
694 result = performSymbolicAbstractionSolutionStep(env, checkTask, game, player1Direction, initialStates, constraintStates, targetStates, refiner,
695 previousSymbolicQualitativeResult, previousSymbolicMinQuantitativeResult);
697 result = performExplicitAbstractionSolutionStep(env, checkTask, game, player1Direction, initialStates, constraintStates, targetStates, refiner,
698 previousExplicitResult);
703 printStatistics(*abstractor, game, iteration, peakPlayer1States, peakTransitions);
707 auto iterationEnd = std::chrono::high_resolution_clock::now();
708 STORM_LOG_INFO(
"Iteration " << iteration <<
" took " << std::chrono::duration_cast<std::chrono::milliseconds>(iterationEnd - iterationStart).
count()
718 STORM_LOG_WARN(
"Could not derive result, maximal number of abstractions exceeded.");
722template<storm::dd::DdType Type,
typename ModelType>
723std::unique_ptr<storm::modelchecker::CheckResult> GameBasedMdpModelChecker<Type, ModelType>::performSymbolicAbstractionSolutionStep(
724 Environment const& env, storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>
const& checkTask,
725 storm::gbar::abstraction::MenuGame<Type, ValueType>
const& game,
storm::OptimizationDirection player1Direction, storm::dd::Bdd<Type>
const& initialStates,
726 storm::dd::Bdd<Type>
const& constraintStates, storm::dd::Bdd<Type>
const& targetStates,
727 storm::gbar::abstraction::MenuGameRefiner<Type, ValueType>
const& refiner,
728 boost::optional<SymbolicQualitativeGameResultMinMax<Type>>& previousQualitativeResult,
729 boost::optional<SymbolicQuantitativeGameResult<Type, ValueType>>& previousMinQuantitativeResult) {
736 storm::utility::Stopwatch qualitativeWatch(
true);
737 SymbolicQualitativeGameResultMinMax<Type> qualitativeResult =
738 computeProb01States(previousQualitativeResult, game, player1Direction, transitionMatrixBdd, constraintStates, targetStates);
739 std::unique_ptr<storm::modelchecker::CheckResult> result =
740 checkForResultAfterQualitativeCheck<Type, ValueType>(checkTask, initialStates, qualitativeResult);
744 previousQualitativeResult = qualitativeResult;
745 qualitativeWatch.stop();
746 totalSolutionWatch.add(qualitativeWatch);
747 STORM_LOG_INFO(
"Qualitative computation completed in " << qualitativeWatch.getTimeInMilliseconds() <<
"ms.");
750 storm::dd::Bdd<Type> maybeMin =
751 !(qualitativeResult.prob0Min.getPlayer1States() || qualitativeResult.prob1Min.getPlayer1States()) && game.
getReachableStates();
752 storm::dd::Bdd<Type> maybeMax =
753 !(qualitativeResult.prob0Max.getPlayer1States() || qualitativeResult.prob1Max.getPlayer1States()) && game.
getReachableStates();
756 storm::dd::Bdd<Type> initialMaybeStates = (initialStates && maybeMin) || (initialStates && maybeMax);
757 bool qualitativeRefinement =
false;
758 if (initialMaybeStates.
isZero()) {
762 STORM_LOG_INFO(
"Obtained qualitative bounds [0, 1] on the actual value for the initial states (after "
763 << totalWatch.getTimeInMilliseconds() <<
"ms in iteration " << this->iteration <<
"). Refining abstraction based on qualitative check.");
767 storm::utility::Stopwatch refinementWatch(
true);
768 qualitativeRefinement = refiner.
refine(game, transitionMatrixBdd, qualitativeResult);
769 refinementWatch.stop();
770 totalRefinementWatch.add(refinementWatch);
771 STORM_LOG_INFO(
"Qualitative refinement completed in " << refinementWatch.getTimeInMilliseconds() <<
"ms.");
775 if (!qualitativeRefinement) {
779 storm::dd::Add<Type, ValueType> initialStatesAdd = initialStates.template toAdd<ValueType>();
781 SymbolicQuantitativeGameResultMinMax<Type, ValueType> quantitativeResult;
784 storm::utility::Stopwatch quantitativeWatch(
true);
785 quantitativeResult.
min =
computeQuantitativeResult(env, player1Direction, storm::OptimizationDirection::Minimize, game, qualitativeResult,
786 initialStatesAdd, maybeMin, reuseQuantitativeResults ? previousMinQuantitativeResult : boost::none);
787 quantitativeWatch.stop();
788 previousMinQuantitativeResult = quantitativeResult.
min;
790 checkForResultAfterQuantitativeCheck<ValueType>(checkTask, storm::OptimizationDirection::Minimize, quantitativeResult.
min.getInitialStatesRange());
792 totalSolutionWatch.add(quantitativeWatch);
797 quantitativeWatch.start();
798 quantitativeResult.
max =
computeQuantitativeResult(env, player1Direction, storm::OptimizationDirection::Maximize, game, qualitativeResult,
799 initialStatesAdd, maybeMax, boost::make_optional(quantitativeResult.
min));
800 quantitativeWatch.stop();
802 checkForResultAfterQuantitativeCheck<ValueType>(checkTask, storm::OptimizationDirection::Maximize, quantitativeResult.
max.getInitialStatesRange());
803 totalSolutionWatch.add(quantitativeWatch);
808 ValueType minVal = quantitativeResult.
min.getInitialStatesRange().first;
809 ValueType maxVal = quantitativeResult.
max.getInitialStatesRange().second;
811 if (std::is_same<ValueType, double>::value) {
812 std::stringstream differenceStream;
813 differenceStream.setf(std::ios::fixed, std::ios::floatfield);
814 differenceStream.precision(15);
815 differenceStream << difference;
816 STORM_LOG_INFO(
"Obtained quantitative bounds [" << minVal <<
", " << maxVal <<
"] (difference " << differenceStream.str()
817 <<
") on the actual value for the initial states in " << quantitativeWatch.getTimeInMilliseconds()
818 <<
"ms (after " << totalWatch.getTimeInMilliseconds() <<
"ms in iteration " << this->iteration
823 <<
") on the actual value for the initial states in " << quantitativeWatch.getTimeInMilliseconds()
824 <<
"ms (after " << totalWatch.getTimeInMilliseconds() <<
"ms in iteration " << this->iteration
829 result = checkForResultAfterQuantitativeCheck<ValueType>(quantitativeResult.
min.getInitialStatesRange().first,
830 quantitativeResult.
max.getInitialStatesRange().second, comparator);
837 quantitativeResult.
min.getPlayer1Strategy().template toAdd<ValueType>().sumAbstract(game.
getPlayer1Variables()).getMax() <= 1,
838 "Player 1 strategy for min is illegal.");
840 quantitativeResult.
max.getPlayer1Strategy().template toAdd<ValueType>().sumAbstract(game.
getPlayer1Variables()).getMax() <= 1,
841 "Player 1 strategy for max is illegal.");
843 quantitativeResult.
min.getPlayer2Strategy().template toAdd<ValueType>().sumAbstract(game.
getPlayer2Variables()).getMax() <= 1,
844 "Player 2 strategy for min is illegal.");
846 quantitativeResult.
max.getPlayer2Strategy().template toAdd<ValueType>().sumAbstract(game.
getPlayer2Variables()).getMax() <= 1,
847 "Player 2 strategy for max is illegal.");
851 storm::utility::Stopwatch refinementWatch(
true);
852 refiner.
refine(game, transitionMatrixBdd, quantitativeResult);
853 refinementWatch.stop();
854 totalRefinementWatch.add(refinementWatch);
855 STORM_LOG_INFO(
"Quantitative refinement completed in " << refinementWatch.getTimeInMilliseconds() <<
"ms.");
862template<
typename ValueType>
868 if (!redirectPlayer1 && !redirectPlayer2) {
872 for (uint64_t state = 0; state < player1Groups.size() - 1; ++state) {
875 bool hasMinPlayer1Choice =
false;
876 uint64_t lowerPlayer1Choice = 0;
877 bool hasMaxPlayer1Choice =
false;
878 uint64_t upperPlayer1Choice = 0;
881 hasMinPlayer1Choice =
true;
888 if (lowerPlayer2Choice == upperPlayer2Choice) {
892 bool redirect =
true;
894 for (
auto const& entry : transitionMatrix.
getRow(upperPlayer2Choice)) {
902 if (redirectPlayer2 && redirect) {
908 bool lowerChoiceUnderUpperIsProb0 =
false;
913 hasMaxPlayer1Choice =
true;
918 if (lowerPlayer2Choice == upperPlayer2Choice) {
922 lowerChoiceUnderUpperIsProb0 =
true;
923 for (
auto const& entry : transitionMatrix.
getRow(lowerPlayer2Choice)) {
925 lowerChoiceUnderUpperIsProb0 =
false;
930 bool redirect =
true;
931 if (lowerChoiceUnderUpperIsProb0) {
932 for (
auto const& entry : transitionMatrix.
getRow(upperPlayer2Choice)) {
940 if (redirectPlayer2 && redirect) {
946 if (redirectPlayer1 && player1Direction == storm::OptimizationDirection::Minimize) {
947 if (hasMinPlayer1Choice && hasMaxPlayer1Choice && lowerPlayer1Choice != upperPlayer1Choice) {
948 if (!isProb0Min || lowerChoiceUnderUpperIsProb0) {
956template<
typename ValueType>
963 void exportToJson(std::string
const& filename, std::vector<uint64_t>
const& player1Groups, std::vector<uint64_t>
const& player2Groups,
969 std::ofstream outfile;
971 exportGame(outfile, player1Groups, player2Groups, transitionMatrix, initialStates, constraintStates, targetStates, quantitativeResult, minStrategyPair,
977 showNonStrategyAlternatives = value;
982 NodeData(uint64_t
id, uint64_t player,
bool initial,
bool target) : id(id), player(player), initial(initial), target(target) {
993 EdgeData(uint64_t
id, uint64_t source, uint64_t target, ValueType probability, uint64_t label,
bool min,
bool max)
994 : id(id), source(source), target(target), probability(probability), label(label), min(min), max(max) {
1001 ValueType probability;
1007 void exportEdge(std::ofstream& out, EdgeData
const& data,
bool& first) {
1014 out <<
"\t\t\t\"data\": {\n";
1015 out <<
"\t\t\t\t\"id\": \"" << data.id <<
"\",\n";
1017 out <<
"\t\t\t\t\"name\": \"" << data.probability <<
"\",\n";
1019 out <<
"\t\t\t\t\"name\": \"" << data.label <<
"\",\n";
1021 out <<
"\t\t\t\t\"source\": \"" << data.source <<
"\",\n";
1022 out <<
"\t\t\t\t\"target\": \"" << data.target <<
"\"\n";
1023 out <<
"\t\t\t},\n";
1024 out <<
"\t\t\t\"classes\": \"";
1025 if (data.min && data.max) {
1026 out <<
"minMaxEdge";
1027 }
else if (data.min) {
1029 }
else if (data.max) {
1038 void exportNode(std::ofstream& out, NodeData
const& data, ExplicitQuantitativeResultMinMax<ValueType>
const* quantitativeResult,
bool& first) {
1045 out <<
"\t\t\t\"data\": {\n";
1046 out <<
"\t\t\t\t\"id\": \"" << data.id <<
"\",\n";
1047 out <<
"\t\t\t\t\"name\": \"" << data.id;
1048 if (quantitativeResult && data.player == 1) {
1049 out <<
" [" << quantitativeResult->
getMin().getValues()[data.id] <<
", " << quantitativeResult->
getMax().getValues()[data.id] <<
"]";
1052 out <<
"\t\t\t},\n";
1053 out <<
"\t\t\t\"group\": \"nodes\",\n";
1054 out <<
"\t\t\t\"classes\": \"";
1055 if (data.player == 1) {
1057 out <<
"initialNode";
1058 }
else if (data.target) {
1059 out <<
"targetNode";
1063 }
else if (data.player == 2) {
1065 }
else if (data.player == 0) {
1072 void exportGame(std::ofstream& out, std::vector<uint64_t>
const& player1Groups, std::vector<uint64_t>
const& player2Groups,
1073 storm::storage::SparseMatrix<ValueType>
const& transitionMatrix, storm::storage::BitVector
const& initialStates,
1074 storm::storage::BitVector
const& constraintStates, storm::storage::BitVector
const& targetStates,
1075 ExplicitQuantitativeResultMinMax<ValueType>
const& quantitativeResult, storage::ExplicitGameStrategyPair
const* minStrategyPair,
1076 storage::ExplicitGameStrategyPair
const* maxStrategyPair) {
1078 std::vector<NodeData> nodes;
1079 std::vector<EdgeData> edges;
1081 std::vector<uint64_t> stack;
1082 for (uint64_t state : initialStates) {
1083 stack.push_back(state);
1085 storm::storage::BitVector reachablePlayer1(player1Groups.size() - 1);
1087 uint64_t edgeId = 0;
1088 while (!stack.empty()) {
1089 uint64_t currentState = stack.back();
1092 nodes.emplace_back(currentState, 1, initialStates.get(currentState), targetStates.
get(currentState));
1094 for (uint64_t player2State = player1Groups[currentState]; player2State < player1Groups[currentState + 1]; ++player2State) {
1095 bool emit = (minStrategyPair || maxStrategyPair) ? this->showNonStrategyAlternatives : true;
1099 if (minStrategyPair && minStrategyPair->getPlayer1Strategy().hasDefinedChoice(currentState) &&
1100 minStrategyPair->getPlayer1Strategy().getChoice(currentState) == player2State) {
1104 if (maxStrategyPair && maxStrategyPair->getPlayer1Strategy().hasDefinedChoice(currentState) &&
1105 maxStrategyPair->getPlayer1Strategy().getChoice(currentState) == player2State) {
1111 nodes.emplace_back(player2State, 2,
false,
false);
1115 for (uint64_t playerPState = player2Groups[player2State]; playerPState < player2Groups[player2State + 1]; ++playerPState) {
1116 emit = (minStrategyPair || maxStrategyPair) ? this->showNonStrategyAlternatives : true;
1120 if (minStrategyPair && minStrategyPair->getPlayer2Strategy().hasDefinedChoice(player2State) &&
1121 minStrategyPair->getPlayer2Strategy().getChoice(player2State) == playerPState) {
1125 if (maxStrategyPair && maxStrategyPair->getPlayer2Strategy().hasDefinedChoice(player2State) &&
1126 maxStrategyPair->getPlayer2Strategy().getChoice(player2State) == playerPState) {
1132 nodes.emplace_back(playerPState, 0,
false,
false);
1134 playerPState - player2Groups[player2State], min, max);
1136 for (
auto const& entry : transitionMatrix.
getRow(playerPState)) {
1137 auto player1Successor = entry.getColumn();
1138 if (!reachablePlayer1.get(player1Successor)) {
1139 reachablePlayer1.set(player1Successor);
1140 stack.push_back(player1Successor);
1143 edges.emplace_back(edgeId++, playerPState, player1Successor, entry.getValue(), 0,
false,
false);
1154 out <<
"{\n\t\"nodes\": [\n";
1156 for (
auto const& node : nodes) {
1157 exportNode(out, node, &quantitativeResult, first);
1163 out <<
"\t\"edges\": [\n";
1164 for (
auto const& edge : edges) {
1165 exportEdge(out, edge, first);
1167 out <<
"\n\t]\n}\n";
1170 bool showNonStrategyAlternatives;
1173template<
typename ValueType>
1176 std::vector<uint64_t>
const& player1Groups, std::vector<uint64_t>
const& player2Groups,
1181 if (redirectPlayer1 || redirectPlayer2) {
1182 for (uint64_t state = 0; state < player1Groups.size() - 1; ++state) {
1184 "Expected lower player 1 choice in state " << state <<
".");
1186 "Expected upper player 1 choice in state " << state <<
".");
1188 bool hasMinPlayer1Choice =
false;
1189 uint64_t lowerPlayer1Choice = 0;
1191 bool hasMaxPlayer1Choice =
false;
1192 uint64_t upperPlayer1Choice = 0;
1196 hasMinPlayer1Choice =
true;
1200 "Expected lower player 2 choice for state " << state <<
" (lower player 1 choice " << lowerPlayer1Choice <<
").");
1203 ValueType lowerValueUnderLowerChoicePlayer2 =
1205 lowerValueUnderMinChoicePlayer1 = lowerValueUnderLowerChoicePlayer2;
1210 if (lowerPlayer2Choice != upperPlayer2Choice) {
1211 ValueType lowerValueUnderUpperChoicePlayer2 =
1214 if (redirectPlayer2 && lowerValueUnderUpperChoicePlayer2 <= lowerValueUnderLowerChoicePlayer2) {
1215 lowerValueUnderMinChoicePlayer1 = lowerValueUnderUpperChoicePlayer2;
1226 hasMaxPlayer1Choice =
true;
1230 ValueType lowerValueUnderLowerChoicePlayer2 =
1232 lowerValueUnderMaxChoicePlayer1 = lowerValueUnderLowerChoicePlayer2;
1235 "Expected upper player 2 choice for state " << state <<
" (upper player 1 choice " << upperPlayer1Choice <<
").");
1238 if (lowerPlayer2Choice != upperPlayer2Choice) {
1239 ValueType lowerValueUnderUpperChoicePlayer2 =
1242 if (redirectPlayer2 && lowerValueUnderUpperChoicePlayer2 <= lowerValueUnderLowerChoicePlayer2) {
1249 if (redirectPlayer1 && player1Direction == storm::OptimizationDirection::Minimize) {
1250 if (hasMinPlayer1Choice && hasMaxPlayer1Choice && lowerPlayer1Choice != upperPlayer1Choice) {
1251 if (lowerValueUnderMaxChoicePlayer1 <= lowerValueUnderMinChoicePlayer1) {
1265 for (uint64_t state = 0; state < player1Groups.size() - 1; ++state) {
1266 if (targetStates.
get(state)) {
1271 "Expected max player 2 choice in state " << state <<
" with player 2 choice "
1274 for (
auto const& entry : transitionMatrix.
getRow(player2Choice)) {
1275 dtmcMatrixBuilder.
addNextValue(state, entry.getColumn(), entry.getValue());
1279 auto dtmcMatrix = dtmcMatrixBuilder.
build();
1280 std::vector<ValueType> sanityValues =
1286 uint64_t maxState = 0;
1287 for (uint64_t state = 0; state < player1Groups.size() - 1; ++state) {
1289 if (diff > maxDiff) {
1296 "Deviation " << maxDiff <<
" between computed value (" << quantitativeResult.
getMin().getValues()[maxState]
1297 <<
") and sanity check value (" << sanityValues[maxState] <<
") in state " << maxState
1298 <<
" appears to be too high. (Obtained bounds were [" << quantitativeResult.
getMin().getValues()[maxState] <<
", "
1299 << quantitativeResult.
getMax().getValues()[maxState] <<
"].)");
1304 for (uint64_t state = 0; state < player1Groups.size() - 1; ++state) {
1305 if (targetStates.
get(state)) {
1310 "Expected max player 2 choice in state " << state <<
" with player 2 choice "
1314 for (
auto const& entry : transitionMatrix.
getRow(player2Choice)) {
1315 dtmcMatrixBuilder.
addNextValue(state, entry.getColumn(), entry.getValue());
1319 dtmcMatrix = dtmcMatrixBuilder.
build();
1326 for (uint64_t state = 0; state < player1Groups.size() - 1; ++state) {
1328 if (diff > maxDiff) {
1335 "Deviation " << maxDiff <<
" between computed value (" << quantitativeResult.
getMax().getValues()[maxState]
1336 <<
") and sanity check value (" << sanityValues[maxState] <<
") in state " << maxState
1337 <<
" appears to be too high. (Obtained bounds were [" << quantitativeResult.
getMin().getValues()[maxState] <<
", "
1338 << quantitativeResult.
getMax().getValues()[maxState] <<
"].)");
1342template<storm::dd::DdType Type,
typename ModelType>
1343std::unique_ptr<storm::modelchecker::CheckResult> GameBasedMdpModelChecker<Type, ModelType>::performExplicitAbstractionSolutionStep(
1357 auto& transitionMatrix = matrixAndLabeling.
matrix;
1358 auto& player1Labeling = matrixAndLabeling.
labelings.front();
1359 auto& player2Labeling = matrixAndLabeling.
labelings.back();
1362 std::vector<uint64_t> tmpPlayer2RowGrouping;
1363 for (uint64_t player1State = 0; player1State < transitionMatrix.
getRowGroupCount(); ++player1State) {
1364 uint64_t lastLabel = std::numeric_limits<uint64_t>::max();
1366 if (player1Labeling[row] != lastLabel) {
1367 tmpPlayer2RowGrouping.emplace_back(row);
1368 lastLabel = player1Labeling[row];
1372 tmpPlayer2RowGrouping.emplace_back(player1Labeling.size());
1374 std::vector<uint64_t> player1RowGrouping = transitionMatrix.
swapRowGroupIndices(std::move(tmpPlayer2RowGrouping));
1378 std::vector<uint64_t> player1Groups(player1RowGrouping.size());
1379 storm::storage::SparseMatrix<ValueType> player1BackwardTransitions = transitionMatrix.
transpose(
true);
1380 std::vector<uint64_t> player2BackwardTransitions(transitionMatrix.
getRowGroupCount());
1382 uint64_t player2State = 0;
1383 for (uint64_t player1State = 0; player1State < player1RowGrouping.size() - 1; ++player1State) {
1384 while (player1RowGrouping[player1State + 1] > player2RowGrouping[player2State]) {
1385 player2BackwardTransitions[player2State] = player1State;
1389 player1Groups[player1State + 1] = player2State;
1393 for (uint64_t player1State = 0; player1State < player1Groups.size() - 1; ++player1State) {
1394 for (uint64_t player2State = player1Groups[player1State]; player2State < player1Groups[player1State + 1]; ++player2State) {
1395 player1Labeling[player2State] = player1Labeling[player2RowGrouping[player2State]];
1398 player1Labeling.resize(player2RowGrouping.size() - 1);
1401 storm::storage::BitVector initialStates = initialStatesBdd.
toVector(odd);
1402 storm::storage::BitVector constraintStates = constraintStatesBdd.
toVector(odd);
1403 storm::storage::BitVector targetStates = targetStatesBdd.
toVector(odd);
1404 translationWatch.stop();
1405 totalTranslationWatch.add(translationWatch);
1406 STORM_LOG_INFO(
"Translation to explicit representation completed in " << translationWatch.getTimeInMilliseconds() <<
"ms.");
1413 storm::utility::Stopwatch qualitativeWatch(
true);
1414 ExplicitQualitativeGameResultMinMax qualitativeResult =
1415 computeProb01States(previousResult, odd, player1Direction, transitionMatrix, player1Groups, player1BackwardTransitions, player2BackwardTransitions,
1416 constraintStates, targetStates, minStrategyPair, maxStrategyPair);
1417 qualitativeWatch.stop();
1418 totalSolutionWatch.add(qualitativeWatch);
1419 STORM_LOG_INFO(
"Qualitative computation completed in " << qualitativeWatch.getTimeInMilliseconds() <<
"ms.");
1421 std::unique_ptr<storm::modelchecker::CheckResult> result = checkForResultAfterQualitativeCheck<ValueType>(checkTask, initialStates, qualitativeResult);
1427 storm::storage::BitVector maybeMin = ~(qualitativeResult.getProb0Min().
getStates() | qualitativeResult.getProb1Min().getStates());
1428 storm::storage::BitVector maybeMax = ~(qualitativeResult.getProb0Max().
getStates() | qualitativeResult.getProb1Max().getStates());
1431 storm::storage::BitVector initialMaybeStates = initialStates & (maybeMin | maybeMax);
1432 bool qualitativeRefinement =
false;
1433 if (initialMaybeStates.
empty()) {
1437 STORM_LOG_INFO(
"Obtained qualitative bounds [0, 1] on the actual value for the initial states (after "
1438 << totalWatch.getTimeInMilliseconds() <<
"ms in iteration " << this->iteration <<
"). Refining abstraction based on qualitative check.");
1441 storm::utility::Stopwatch strategyProcessingWatch(
true);
1442 postProcessStrategies(player1Direction, minStrategyPair, maxStrategyPair, player1Groups, player2RowGrouping, transitionMatrix, constraintStates,
1443 targetStates, qualitativeResult, this->fixPlayer1Strategy, this->fixPlayer2Strategy, this->debug);
1444 strategyProcessingWatch.stop();
1445 totalStrategyProcessingWatch.add(strategyProcessingWatch);
1446 STORM_LOG_DEBUG(
"Postprocessed strategies in " << strategyProcessingWatch.getTimeInMilliseconds() <<
"ms.");
1450 storm::utility::Stopwatch refinementWatch(
true);
1451 qualitativeRefinement = refiner.
refine(game, odd, transitionMatrix, player1Groups, player1Labeling, player2Labeling, initialStates, constraintStates,
1452 targetStates, qualitativeResult, minStrategyPair, maxStrategyPair);
1453 refinementWatch.stop();
1454 totalRefinementWatch.add(refinementWatch);
1455 STORM_LOG_INFO(
"Qualitative refinement completed in " << refinementWatch.getTimeInMilliseconds() <<
"ms.");
1458 ExplicitQuantitativeResultMinMax<ValueType> quantitativeResult;
1461 if (!qualitativeRefinement) {
1466 storm::utility::Stopwatch quantitativeWatch(
true);
1467 quantitativeResult.
setMin(computeQuantitativeResult<ValueType>(env, player1Direction, storm::OptimizationDirection::Minimize, transitionMatrix,
1468 player1Groups, qualitativeResult, maybeMin, minStrategyPair, odd,
nullptr,
nullptr,
1469 this->reuseQuantitativeResults ? previousResult : boost::none));
1472 if (previousResult) {
1473 previousResult.get().clear();
1475 quantitativeWatch.stop();
1476 result = checkForResultAfterQuantitativeCheck<ValueType>(checkTask, storm::OptimizationDirection::Minimize,
1477 quantitativeResult.
getMin().getRange(initialStates));
1479 totalSolutionWatch.add(quantitativeWatch);
1484 quantitativeWatch.start();
1486 qualitativeResult, maybeMax, maxStrategyPair, odd, &quantitativeResult.
getMin(), &minStrategyPair));
1487 quantitativeWatch.stop();
1488 result = checkForResultAfterQuantitativeCheck<ValueType>(checkTask, storm::OptimizationDirection::Maximize,
1489 quantitativeResult.
getMax().getRange(initialStates));
1490 totalSolutionWatch.add(quantitativeWatch);
1495 ValueType minVal = quantitativeResult.
getMin().getRange(initialStates).first;
1496 ValueType maxVal = quantitativeResult.
getMax().getRange(initialStates).second;
1498 if (std::is_same<ValueType, double>::value) {
1499 std::stringstream differenceStream;
1500 differenceStream.setf(std::ios::fixed, std::ios::floatfield);
1501 differenceStream.precision(15);
1502 differenceStream << difference;
1503 STORM_LOG_INFO(
"Obtained quantitative bounds [" << minVal <<
", " << maxVal <<
"] (difference " << differenceStream.str()
1504 <<
") on the actual value for the initial states in " << quantitativeWatch.getTimeInMilliseconds()
1505 <<
"ms (after " << totalWatch.getTimeInMilliseconds() <<
"ms in iteration " << this->iteration
1510 <<
") on the actual value for the initial states in " << quantitativeWatch.getTimeInMilliseconds()
1511 <<
"ms (after " << totalWatch.getTimeInMilliseconds() <<
"ms in iteration " << this->iteration
1516 result = checkForResultAfterQuantitativeCheck<ValueType>(quantitativeResult.
getMin().getRange(initialStates).first,
1517 quantitativeResult.
getMax().getRange(initialStates).second, comparator);
1523 storm::utility::Stopwatch strategyProcessingWatch(
true);
1524 postProcessStrategies(env, this->iteration, player1Direction, minStrategyPair, maxStrategyPair, player1Groups, player2RowGrouping, transitionMatrix,
1525 initialStates, constraintStates, targetStates, quantitativeResult, this->fixPlayer1Strategy, this->fixPlayer2Strategy,
1527 strategyProcessingWatch.stop();
1528 totalStrategyProcessingWatch.add(strategyProcessingWatch);
1529 STORM_LOG_DEBUG(
"Postprocessed strategies in " << strategyProcessingWatch.getTimeInMilliseconds() <<
"ms.");
1533 "Expected at most " << targetStates.
getNumberOfSetBits() <<
" (number of target states) player 1 states with undefined choice but got "
1534 << minStrategyPair.getNumberOfUndefinedPlayer1States() <<
".");
1536 "Expected at most " << targetStates.
getNumberOfSetBits() <<
" (number of target states) player 1 states with undefined choice but got "
1537 << maxStrategyPair.getNumberOfUndefinedPlayer1States() <<
".");
1541 storm::utility::Stopwatch refinementWatch(
true);
1542 refiner.
refine(game, odd, transitionMatrix, player1Groups, player1Labeling, player2Labeling, initialStates, constraintStates, targetStates,
1543 quantitativeResult, minStrategyPair, maxStrategyPair);
1544 refinementWatch.stop();
1545 totalRefinementWatch.add(refinementWatch);
1546 STORM_LOG_INFO(
"Quantitative refinement completed in " << refinementWatch.getTimeInMilliseconds() <<
"ms.");
1548 if (this->reuseQuantitativeResults) {
1549 PreviousExplicitResult<ValueType> nextPreviousResult;
1550 nextPreviousResult.
values = std::move(quantitativeResult.
getMin());
1551 nextPreviousResult.
odd = odd;
1552 previousResult = std::move(nextPreviousResult);
1560template<storm::dd::DdType Type,
typename ModelType>
1561std::vector<storm::expressions::Expression> GameBasedMdpModelChecker<Type, ModelType>::getInitialPredicates(
1562 storm::expressions::Expression
const& constraintExpression, storm::expressions::Expression
const& targetStateExpression) {
1563 std::vector<storm::expressions::Expression> initialPredicates;
1564 if (preprocessedModel.isJaniModel()) {
1565 storm::expressions::VariableSetPredicateSplitter splitter(preprocessedModel.asJaniModel().getAllLocationExpressionVariables());
1567 std::vector<storm::expressions::Expression> splitExpressions = splitter.split(targetStateExpression);
1568 initialPredicates.insert(initialPredicates.end(), splitExpressions.begin(), splitExpressions.end());
1570 splitExpressions = splitter.split(constraintExpression);
1571 initialPredicates.insert(initialPredicates.end(), splitExpressions.begin(), splitExpressions.end());
1573 if (!targetStateExpression.
isTrue() && !targetStateExpression.
isFalse()) {
1574 initialPredicates.push_back(targetStateExpression);
1576 if (!constraintExpression.
isTrue() && !constraintExpression.
isFalse()) {
1577 initialPredicates.push_back(constraintExpression);
1580 return initialPredicates;
1583template<storm::dd::DdType Type,
typename ModelType>
1585 storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>
const& checkTask) {
1587 return storm::OptimizationDirection::Maximize;
1593 STORM_LOG_THROW(
false, storm::exceptions::InvalidPropertyException,
"Could not derive player 1 optimization direction.");
1594 return storm::OptimizationDirection::Maximize;
1597template<storm::dd::DdType Type>
1601 "Unable to proceed without strategy.");
1604 "Unable to proceed without strategy.");
1608 "Unable to proceed without strategy.");
1613template<storm::dd::DdType Type>
1623template<storm::dd::DdType Type,
typename ModelType>
1624ExplicitQualitativeGameResultMinMax GameBasedMdpModelChecker<Type, ModelType>::computeProb01States(
1630 ExplicitQualitativeGameResultMinMax result;
1638 targetStates, player1Direction, storm::OptimizationDirection::Minimize, &minStrategyPair);
1641 targetStates, player1Direction, storm::OptimizationDirection::Minimize, &minStrategyPair);
1644 targetStates, player1Direction, storm::OptimizationDirection::Maximize, &maxStrategyPair);
1647 targetStates, player1Direction, storm::OptimizationDirection::Maximize, &maxStrategyPair);
1649 STORM_LOG_INFO(
"[" << player1Direction <<
", " << storm::OptimizationDirection::Minimize <<
"]: " << result.prob0Min.player1States.getNumberOfSetBits()
1650 <<
" 'no', " << result.prob1Min.player1States.getNumberOfSetBits() <<
" 'yes'.");
1651 STORM_LOG_INFO(
"[" << player1Direction <<
", " << storm::OptimizationDirection::Maximize <<
"]: " << result.prob0Max.player1States.getNumberOfSetBits()
1652 <<
" 'no', " << result.prob1Max.player1States.getNumberOfSetBits() <<
" 'yes'.");
1657template<storm::dd::DdType Type,
typename ModelType>
1658SymbolicQualitativeGameResultMinMax<Type> GameBasedMdpModelChecker<Type, ModelType>::computeProb01States(
1659 boost::optional<SymbolicQualitativeGameResultMinMax<Type>>
const& previousQualitativeResult,
1662 SymbolicQualitativeGameResultMinMax<Type> result;
1664 if (reuseQualitativeResults) {
1666 if (player1Direction == storm::OptimizationDirection::Minimize) {
1669 storm::OptimizationDirection::Minimize,
true,
true);
1674 game, transitionMatrixBdd, previousQualitativeResult ? previousQualitativeResult.get().prob1Min.player1States : targetStates, candidates);
1678 storm::OptimizationDirection::Minimize,
true,
true, boost::make_optional(prob1MinMinMdp));
1682 storm::OptimizationDirection::Maximize,
true,
true);
1687 boost::optional<storm::dd::Bdd<Type>> prob1Candidates;
1688 if (previousQualitativeResult) {
1689 prob1Candidates = previousQualitativeResult.get().prob1Max.player1States;
1692 storm::OptimizationDirection::Maximize,
true,
true, prob1Candidates);
1696 storm::OptimizationDirection::Maximize,
true,
true);
1699 storm::dd::Bdd<Type> candidates = game.
getReachableStates() && !result.prob0Max.player1States;
1700 if (previousQualitativeResult) {
1701 candidates &= previousQualitativeResult.get().prob1Max.player1States;
1707 storm::OptimizationDirection::Maximize,
true,
true, boost::make_optional(prob1MaxMaxMdp));
1711 storm::OptimizationDirection::Minimize,
true,
true);
1715 storm::OptimizationDirection::Minimize,
true,
true, boost::make_optional(prob1MaxMaxMdp));
1719 storm::OptimizationDirection::Minimize,
true,
true);
1721 storm::OptimizationDirection::Minimize,
true,
true);
1723 storm::OptimizationDirection::Maximize,
true,
true);
1725 storm::OptimizationDirection::Maximize,
true,
true);
1728 STORM_LOG_INFO(
"[" << player1Direction <<
", " << storm::OptimizationDirection::Minimize <<
"]: " << result.prob0Min.player1States.getNonZeroCount()
1729 <<
" 'no', " << result.prob1Min.player1States.getNonZeroCount() <<
" 'yes'.");
1730 STORM_LOG_INFO(
"[" << player1Direction <<
", " << storm::OptimizationDirection::Maximize <<
"]: " << result.prob0Max.player1States.getNonZeroCount()
1731 <<
" 'no', " << result.prob1Max.player1States.getNonZeroCount() <<
" 'yes'.");
1737template<storm::dd::DdType Type,
typename ModelType>
1738void GameBasedMdpModelChecker<Type, ModelType>::printStatistics(storm::gbar::abstraction::MenuGameAbstractor<Type, ValueType>
const& abstractor,
1739 storm::gbar::abstraction::MenuGame<Type, ValueType>
const& game, uint64_t refinements,
1740 uint64_t peakPlayer1States, uint64_t peakTransitions)
const {
1741 storm::gbar::abstraction::AbstractionInformation<Type>
const& abstractionInformation = abstractor.
getAbstractionInformation();
1743 std::ostringstream oss;
1744 oss << std::fixed << std::setprecision(2);
1747 oss <<
"Statistics:\n";
1749 <<
" transitions\n";
1750 oss <<
" * peak size of game: " << peakPlayer1States <<
" player 1 states, " << peakTransitions <<
" transitions\n";
1751 oss <<
" * refinements: " << refinements <<
'\n';
1754 uint64_t totalAbstractionTimeMillis = totalAbstractionWatch.getTimeInMilliseconds();
1755 uint64_t totalTranslationTimeMillis = totalTranslationWatch.getTimeInMilliseconds();
1756 uint64_t totalStrategyProcessingTimeMillis = totalStrategyProcessingWatch.getTimeInMilliseconds();
1757 uint64_t totalSolutionTimeMillis = totalSolutionWatch.getTimeInMilliseconds();
1758 uint64_t totalRefinementTimeMillis = totalRefinementWatch.getTimeInMilliseconds();
1759 uint64_t setupTime = setupWatch.getTimeInMilliseconds();
1760 uint64_t totalTimeMillis = totalWatch.getTimeInMilliseconds();
1762 oss <<
"Time breakdown:\n";
1763 oss <<
" * setup: " << setupTime <<
"ms (" << 100 *
static_cast<double>(setupTime) / totalTimeMillis <<
"%)\n";
1764 oss <<
" * abstraction: " << totalAbstractionTimeMillis <<
"ms (" << 100 *
static_cast<double>(totalAbstractionTimeMillis) / totalTimeMillis <<
"%)\n";
1765 if (this->solveMode == abstraction::SolveMode::Sparse) {
1766 oss <<
" * translation: " << totalTranslationTimeMillis <<
"ms (" << 100 *
static_cast<double>(totalTranslationTimeMillis) / totalTimeMillis
1768 if (fixPlayer1Strategy || fixPlayer2Strategy) {
1769 oss <<
" * strategy processing: " << totalStrategyProcessingTimeMillis <<
"ms ("
1770 << 100 *
static_cast<double>(totalStrategyProcessingTimeMillis) / totalTimeMillis <<
"%)\n";
1773 oss <<
" * solution: " << totalSolutionTimeMillis <<
"ms (" << 100 *
static_cast<double>(totalSolutionTimeMillis) / totalTimeMillis <<
"%)\n";
1774 oss <<
" * refinement: " << totalRefinementTimeMillis <<
"ms (" << 100 *
static_cast<double>(totalRefinementTimeMillis) / totalTimeMillis <<
"%)\n";
1775 oss <<
" ---------------------------------------------\n";
1776 oss <<
" * total: " << totalTimeMillis <<
"ms\n\n";
1781template<storm::dd::DdType Type,
typename ModelType>
1782storm::expressions::Expression GameBasedMdpModelChecker<Type, ModelType>::getExpression(storm::logic::Formula
const& formula) {
1784 storm::exceptions::InvalidPropertyException,
"The target states have to be given as label or an expression.");
1785 storm::expressions::Expression result;
1797template class GameBasedMdpModelChecker<storm::dd::DdType::CUDD, storm::models::symbolic::Dtmc<storm::dd::DdType::CUDD, double>>;
1798template class GameBasedMdpModelChecker<storm::dd::DdType::CUDD, storm::models::symbolic::Mdp<storm::dd::DdType::CUDD, double>>;
1799template class GameBasedMdpModelChecker<storm::dd::DdType::Sylvan, storm::models::symbolic::Dtmc<storm::dd::DdType::Sylvan, double>>;
1800template class GameBasedMdpModelChecker<storm::dd::DdType::Sylvan, storm::models::symbolic::Mdp<storm::dd::DdType::Sylvan, double>>;
1802template class GameBasedMdpModelChecker<storm::dd::DdType::Sylvan, storm::models::symbolic::Dtmc<storm::dd::DdType::Sylvan, storm::RationalNumber>>;
1803template 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, abstraction::AbstractionOptions const &options=abstraction::AbstractionOptions(), 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 DTMCSparseModelCheckingHelperReturnType< 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)
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< S > 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
Options that configure the game-based abstraction-refinement procedure.
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