19template<storm::dd::DdType DdType,
typename ValueType>
21 std::shared_ptr<storm::utility::solver::SmtSolverFactory>
const& smtSolverFactory,
22 bool useDecomposition,
bool addPredicatesForValidBlocks,
bool debug)
23 : smtSolver(smtSolverFactory->create(abstractionInformation.getExpressionManager())),
24 abstractionInformation(abstractionInformation),
26 localExpressionInformation(abstractionInformation),
27 evaluator(abstractionInformation.getExpressionManager()),
28 relevantPredicatesAndVariables(),
29 cachedDd(abstractionInformation.getDdManager().getBddZero(), 0),
31 useDecomposition(useDecomposition),
32 addPredicatesForValidBlocks(addPredicatesForValidBlocks),
33 skipBottomStates(false),
34 forceRecomputation(true),
35 abstractGuard(abstractionInformation.getDdManager().getBddZero()),
36 bottomStateAbstractor(abstractionInformation, {!command.
getGuardExpression()}, smtSolverFactory),
39 relevantPredicatesAndVariables.second.resize(command.getNumberOfUpdates());
42 for (
auto const& constraint : abstractionInformation.getConstraints()) {
43 smtSolver->add(constraint);
44 bottomStateAbstractor.constrain(constraint);
48 smtSolver->add(command.getGuardExpression());
51 for (
auto const& update : command.getUpdates()) {
52 for (
auto const& assignment : update.getAssignments()) {
53 assignedVariables.insert(assignment.getVariable());
58 if (this->addPredicatesForValidBlocks) {
63template<storm::dd::DdType DdType,
typename ValueType>
66 for (
auto predicateIndex : predicates) {
67 localExpressionInformation.addExpression(predicateIndex);
72 std::pair<std::set<uint_fast64_t>, std::vector<std::set<uint_fast64_t>>> newRelevantPredicates = this->computeRelevantPredicates();
75 bool relevantPredicatesChanged = this->relevantPredicatesChanged(newRelevantPredicates);
76 if (relevantPredicatesChanged) {
77 addMissingPredicates(newRelevantPredicates);
79 forceRecomputation |= relevantPredicatesChanged;
82 bottomStateAbstractor.refine(predicates);
85template<storm::dd::DdType DdType,
typename ValueType>
87 return command.get().getGuardExpression();
90template<storm::dd::DdType DdType,
typename ValueType>
92 return command.get().getNumberOfUpdates();
95template<storm::dd::DdType DdType,
typename ValueType>
97 uint64_t auxiliaryChoice)
const {
98 return command.get().getUpdate(auxiliaryChoice).getAsVariableToExpressionMap();
101template<storm::dd::DdType DdType,
typename ValueType>
103 return assignedVariables;
106template<storm::dd::DdType DdType,
typename ValueType>
108 if (useDecomposition) {
109 recomputeCachedBddWithDecomposition();
111 recomputeCachedBddWithoutDecomposition();
115template<storm::dd::DdType DdType,
typename ValueType>
116void CommandAbstractor<DdType, ValueType>::recomputeCachedBddWithDecomposition() {
117 STORM_LOG_TRACE(
"Recomputing BDD for command " << command.get() <<
" [with index " << command.get().getGlobalIndex() <<
"] using the decomposition.");
118 auto start = std::chrono::high_resolution_clock::now();
127 std::set<uint64_t> allRelevantBlocks;
128 std::map<storm::expressions::Variable, uint64_t> variableToBlockIndex;
129 for (
auto const& update : command.get().getUpdates()) {
130 for (
auto const& assignment : update.getAssignments()) {
131 allRelevantBlocks.insert(localExpressionInformation.getBlockIndexOfVariable(assignment.getVariable()));
133 auto rhsVariableBlocks = localExpressionInformation.getBlockIndicesOfVariables(assignment.getExpression().getVariables());
134 allRelevantBlocks.insert(rhsVariableBlocks.begin(), rhsVariableBlocks.end());
137 STORM_LOG_TRACE(
"Found " << allRelevantBlocks.size() <<
" relevant block(s).");
140 std::vector<std::set<uint64_t>> relevantBlockPartition;
141 std::map<storm::expressions::Variable, uint64_t> variableToLocalBlockIndex;
143 for (
auto const& blockIndex : allRelevantBlocks) {
144 relevantBlockPartition.emplace_back(std::set<uint64_t>({blockIndex}));
145 for (
auto const& variable : localExpressionInformation.getVariableBlockWithIndex(blockIndex)) {
146 variableToLocalBlockIndex[variable] = index;
152 for (
auto const& update : command.get().getUpdates()) {
153 for (
auto const& assignment : update.getAssignments()) {
154 std::set<storm::expressions::Variable> rhsVariables = assignment.getExpression().getVariables();
156 if (!rhsVariables.empty()) {
157 uint64_t blockToKeep = variableToLocalBlockIndex.at(*rhsVariables.begin());
158 for (
auto const& variable : rhsVariables) {
159 uint64_t block = variableToLocalBlockIndex.at(variable);
160 if (block != blockToKeep) {
161 for (
auto const& blockIndex : relevantBlockPartition[block]) {
162 for (
auto const& variable : localExpressionInformation.getVariableBlockWithIndex(blockIndex)) {
163 variableToLocalBlockIndex[variable] = blockToKeep;
166 relevantBlockPartition[blockToKeep].insert(relevantBlockPartition[block].begin(), relevantBlockPartition[block].end());
167 relevantBlockPartition[block].clear();
175 bool changed =
false;
178 for (
auto const& update : command.get().getUpdates()) {
179 for (
auto const& assignment : update.getAssignments()) {
180 std::set<storm::expressions::Variable> rhsVariables = assignment.getExpression().getVariables();
182 if (!rhsVariables.empty()) {
184 uint64_t representativeBlock = variableToLocalBlockIndex.at(representativeVariable);
185 uint64_t assignmentVariableBlock = variableToLocalBlockIndex.at(assignment.getVariable());
188 if (assignmentVariableBlock != representativeBlock) {
191 for (
auto const& blockIndex : relevantBlockPartition[assignmentVariableBlock]) {
192 for (
auto const& variable : localExpressionInformation.getVariableBlockWithIndex(blockIndex)) {
193 variableToLocalBlockIndex[variable] = representativeBlock;
196 relevantBlockPartition[representativeBlock].insert(relevantBlockPartition[assignmentVariableBlock].begin(),
197 relevantBlockPartition[assignmentVariableBlock].end());
198 relevantBlockPartition[assignmentVariableBlock].clear();
206 std::vector<std::set<uint64_t>> cleanedRelevantBlockPartition;
207 for (
auto& outerBlock : relevantBlockPartition) {
208 if (!outerBlock.empty()) {
209 cleanedRelevantBlockPartition.emplace_back();
211 for (
auto const& innerBlock : outerBlock) {
212 if (!localExpressionInformation.getExpressionBlock(innerBlock).empty()) {
213 cleanedRelevantBlockPartition.back().insert(innerBlock);
217 if (cleanedRelevantBlockPartition.back().empty()) {
218 cleanedRelevantBlockPartition.pop_back();
222 relevantBlockPartition = std::move(cleanedRelevantBlockPartition);
224 STORM_LOG_TRACE(
"Decomposition into " << relevantBlockPartition.size() <<
" blocks.");
226 uint64_t blockIndex = 0;
227 for (
auto const& block : relevantBlockPartition) {
229 std::set<uint64_t> blockPredicateIndices;
230 for (
auto const& innerBlock : block) {
231 blockPredicateIndices.insert(localExpressionInformation.getExpressionBlock(innerBlock).begin(),
232 localExpressionInformation.getExpressionBlock(innerBlock).end());
235 for (
auto const& predicateIndex : blockPredicateIndices) {
236 STORM_LOG_TRACE(abstractionInformation.get().getPredicateByIndex(predicateIndex));
243 std::set<storm::expressions::Variable> variablesContainedInGuard = command.get().getGuardExpression().getVariables();
247 bool enumerateAbstractGuard =
true;
248 std::set<uint64_t> guardBlocks = localExpressionInformation.getBlockIndicesOfVariables(variablesContainedInGuard);
249 for (
auto const& block : relevantBlockPartition) {
250 bool allContained =
true;
251 for (
auto const& guardBlock : guardBlocks) {
252 if (block.find(guardBlock) == block.end()) {
253 allContained =
false;
258 enumerateAbstractGuard =
false;
262 uint64_t numberOfSolutions = 0;
263 uint64_t numberOfTotalSolutions = 0;
266 if (enumerateAbstractGuard) {
267 std::set<uint64_t> relatedGuardPredicates = localExpressionInformation.getRelatedExpressions(variablesContainedInGuard);
268 std::vector<storm::expressions::Variable> guardDecisionVariables;
269 std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> guardVariablesAndPredicates;
270 for (
auto const& element : relevantPredicatesAndVariables.first) {
271 if (relatedGuardPredicates.find(element.second) != relatedGuardPredicates.end()) {
272 guardDecisionVariables.push_back(element.first);
273 guardVariablesAndPredicates.push_back(element);
276 abstractGuard = this->getAbstractionInformation().getDdManager().getBddZero();
277 smtSolver->allSat(guardDecisionVariables,
279 abstractGuard |= getSourceStateBdd(model, guardVariablesAndPredicates);
283 STORM_LOG_TRACE(
"Enumerated " << numberOfSolutions <<
" solutions for abstract guard.");
292 std::pair<std::vector<storm::expressions::Expression>, std::unordered_map<uint_fast64_t, storm::expressions::Variable>> result =
293 abstractGuard.toExpression(this->getAbstractionInformation().getExpressionManager());
296 for (
auto const& expression : result.first) {
297 smtSolver->add(expression);
301 for (
auto const& indexVariablePair : result.second) {
303 storm::expressions::iff(indexVariablePair.second, this->getAbstractionInformation().getPredicateForDdVariableIndex(indexVariablePair.first)));
308 uint64_t usedNondeterminismVariables = 0;
309 uint64_t blockCounter = 0;
310 std::vector<storm::dd::Bdd<DdType>> blockBdds;
311 for (
auto const& block : relevantBlockPartition) {
312 std::set<uint64_t> relevantPredicates;
313 for (
auto const& innerBlock : block) {
314 relevantPredicates.insert(localExpressionInformation.getExpressionBlock(innerBlock).begin(),
315 localExpressionInformation.getExpressionBlock(innerBlock).end());
318 if (relevantPredicates.empty()) {
319 STORM_LOG_TRACE(
"Block does not contain relevant predicates, skipping it.");
323 std::vector<storm::expressions::Variable> transitionDecisionVariables;
324 std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> sourceVariablesAndPredicates;
325 for (
auto const& element : relevantPredicatesAndVariables.first) {
326 if (relevantPredicates.find(element.second) != relevantPredicates.end()) {
327 transitionDecisionVariables.push_back(element.first);
328 sourceVariablesAndPredicates.push_back(element);
332 std::vector<std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>>> destinationVariablesAndPredicates;
333 for (uint64_t updateIndex = 0; updateIndex < command.get().getNumberOfUpdates(); ++updateIndex) {
334 destinationVariablesAndPredicates.emplace_back();
335 for (
auto const& assignment : command.get().getUpdate(updateIndex).getAssignments()) {
336 uint64_t assignmentVariableBlockIndex = localExpressionInformation.getBlockIndexOfVariable(assignment.getVariable());
338 if (block.find(assignmentVariableBlockIndex) != block.end()) {
339 std::set<uint64_t>
const& assignmentVariableBlock = localExpressionInformation.getExpressionBlock(assignmentVariableBlockIndex);
340 for (
auto const& element : relevantPredicatesAndVariables.second[updateIndex]) {
341 if (assignmentVariableBlock.find(element.second) != assignmentVariableBlock.end()) {
342 destinationVariablesAndPredicates.back().push_back(element);
343 transitionDecisionVariables.push_back(element.first);
350 std::unordered_map<storm::dd::Bdd<DdType>, std::vector<storm::dd::Bdd<DdType>>> sourceToDistributionsMap;
351 numberOfSolutions = 0;
352 smtSolver->allSat(transitionDecisionVariables, [&sourceToDistributionsMap,
this, &numberOfSolutions, &sourceVariablesAndPredicates,
354 sourceToDistributionsMap[getSourceStateBdd(model, sourceVariablesAndPredicates)].push_back(
355 getDistributionBdd(model, destinationVariablesAndPredicates));
359 STORM_LOG_TRACE(
"Enumerated " << numberOfSolutions <<
" solutions for block " << blockCounter <<
".");
360 numberOfTotalSolutions += numberOfSolutions;
364 uint_fast64_t maximalNumberOfChoices = 0;
365 for (
auto const& sourceDistributionsPair : sourceToDistributionsMap) {
366 maximalNumberOfChoices = std::max(maximalNumberOfChoices,
static_cast<uint_fast64_t
>(sourceDistributionsPair.second.size()));
371 uint_fast64_t numberOfVariablesNeeded = (maximalNumberOfChoices > 1)
372 ? (
static_cast<uint_fast64_t
>(std::ceil(std::log2(maximalNumberOfChoices + (blockCounter == 0 ? 1 : 0)))))
373 : (blockCounter == 0 ? 1 : 0);
378 for (
auto const& sourceDistributionsPair : sourceToDistributionsMap) {
379 STORM_LOG_ASSERT(!sourceDistributionsPair.first.isZero(),
"The source BDD must not be empty.");
380 STORM_LOG_ASSERT(!sourceDistributionsPair.second.empty(),
"The distributions must not be empty.");
383 uint_fast64_t distributionIndex = blockCounter == 0 ? 1 : 0;
385 for (
auto const& distribution : sourceDistributionsPair.second) {
386 allDistributions |= distribution && this->getAbstractionInformation().encodePlayer2Choice(
387 distributionIndex, usedNondeterminismVariables, usedNondeterminismVariables + numberOfVariablesNeeded);
391 resultBdd |= sourceDistributionsPair.first && allDistributions;
394 usedNondeterminismVariables += numberOfVariablesNeeded;
396 blockBdds.push_back(resultBdd);
400 if (enumerateAbstractGuard) {
406 for (
auto const& blockBdd : blockBdds) {
407 resultBdd &= blockBdd;
411 if (!enumerateAbstractGuard) {
412 std::set<storm::expressions::Variable> allVariables(getAbstractionInformation().getSuccessorVariables());
413 auto player2Variables = getAbstractionInformation().getPlayer2VariableSet(usedNondeterminismVariables);
414 allVariables.insert(player2Variables.begin(), player2Variables.end());
415 auto auxVariables = getAbstractionInformation().getAuxVariableSet(0, getAbstractionInformation().getAuxVariableCount());
416 allVariables.insert(auxVariables.begin(), auxVariables.end());
418 std::set<storm::expressions::Variable> variablesToAbstract;
425 resultBdd &= abstractGuard;
429 resultBdd &= computeMissingUpdateIdentities();
433 this->getAbstractionInformation().encodePlayer1Choice(command.get().getGlobalIndex(), this->getAbstractionInformation().getPlayer1VariableCount());
436 cachedDd = GameBddResult<DdType>(resultBdd, usedNondeterminismVariables);
438 auto end = std::chrono::high_resolution_clock::now();
440 STORM_LOG_TRACE(
"Enumerated " << numberOfTotalSolutions <<
" solutions in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count()
442 forceRecomputation =
false;
445template<storm::dd::DdType DdType,
typename ValueType>
446void CommandAbstractor<DdType, ValueType>::recomputeCachedBddWithoutDecomposition() {
448 auto start = std::chrono::high_resolution_clock::now();
451 std::unordered_map<storm::dd::Bdd<DdType>, std::vector<storm::dd::Bdd<DdType>>> sourceToDistributionsMap;
452 uint64_t numberOfSolutions = 0;
454 sourceToDistributionsMap[getSourceStateBdd(model, relevantPredicatesAndVariables.first)].push_back(
455 getDistributionBdd(model, relevantPredicatesAndVariables.second));
462 uint_fast64_t maximalNumberOfChoices = 0;
463 for (
auto const& sourceDistributionsPair : sourceToDistributionsMap) {
464 maximalNumberOfChoices = std::max(maximalNumberOfChoices,
static_cast<uint_fast64_t
>(sourceDistributionsPair.second.size()));
469 uint_fast64_t numberOfVariablesNeeded =
static_cast<uint_fast64_t
>(std::ceil(std::log2(maximalNumberOfChoices + 1)));
473 if (!skipBottomStates) {
474 abstractGuard = this->getAbstractionInformation().getDdManager().getBddZero();
476 for (
auto const& sourceDistributionsPair : sourceToDistributionsMap) {
477 if (!skipBottomStates) {
478 abstractGuard |= sourceDistributionsPair.first;
481 STORM_LOG_ASSERT(!sourceDistributionsPair.first.isZero(),
"The source BDD must not be empty.");
482 STORM_LOG_ASSERT(!sourceDistributionsPair.second.empty(),
"The distributions must not be empty.");
484 uint_fast64_t distributionIndex = 1;
486 for (
auto const& distribution : sourceDistributionsPair.second) {
487 allDistributions |= distribution && this->getAbstractionInformation().encodePlayer2Choice(distributionIndex, 0, numberOfVariablesNeeded);
491 resultBdd |= sourceDistributionsPair.first && allDistributions;
495 resultBdd &= computeMissingUpdateIdentities();
497 this->getAbstractionInformation().encodePlayer1Choice(command.get().getGlobalIndex(), this->getAbstractionInformation().getPlayer1VariableCount());
498 STORM_LOG_ASSERT(sourceToDistributionsMap.empty() || !resultBdd.
isZero(),
"The BDD must not be empty, if there were distributions.");
501 cachedDd = GameBddResult<DdType>(resultBdd, numberOfVariablesNeeded);
502 auto end = std::chrono::high_resolution_clock::now();
504 STORM_LOG_TRACE(
"Enumerated " << numberOfSolutions <<
" solutions in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count()
506 forceRecomputation =
false;
509template<storm::dd::DdType DdType,
typename ValueType>
510std::pair<std::set<uint_fast64_t>, std::set<uint_fast64_t>> CommandAbstractor<DdType, ValueType>::computeRelevantPredicates(
511 std::vector<storm::prism::Assignment>
const& assignments)
const {
512 std::pair<std::set<uint_fast64_t>, std::set<uint_fast64_t>> result;
514 std::set<storm::expressions::Variable> assignedVariables;
515 for (
auto const& assignment : assignments) {
517 auto const& rightHandSidePredicates = localExpressionInformation.getExpressionsUsingVariables(assignment.getExpression().getVariables());
518 result.first.insert(rightHandSidePredicates.begin(), rightHandSidePredicates.end());
522 auto const& leftHandSidePredicates = localExpressionInformation.getExpressionsUsingVariable(assignedVariable);
523 result.second.insert(leftHandSidePredicates.begin(), leftHandSidePredicates.end());
526 if (this->addPredicatesForValidBlocks) {
527 auto const& assignedVariableBlock = localExpressionInformation.getRelatedExpressions(assignedVariable);
528 result.first.insert(assignedVariableBlock.begin(), assignedVariableBlock.end());
535template<storm::dd::DdType DdType,
typename ValueType>
536std::pair<std::set<uint_fast64_t>, std::vector<std::set<uint_fast64_t>>> CommandAbstractor<DdType, ValueType>::computeRelevantPredicates()
const {
537 std::pair<std::set<uint_fast64_t>, std::vector<std::set<uint_fast64_t>>> result;
540 result.first = localExpressionInformation.getExpressionsUsingVariables(command.get().getGuardExpression().getVariables());
543 for (
auto const& update : command.get().getUpdates()) {
544 std::pair<std::set<uint_fast64_t>, std::set<uint_fast64_t>> relevantUpdatePredicates = computeRelevantPredicates(update.getAssignments());
545 result.first.insert(relevantUpdatePredicates.first.begin(), relevantUpdatePredicates.first.end());
546 result.second.push_back(relevantUpdatePredicates.second);
564template<storm::dd::DdType DdType,
typename ValueType>
565bool CommandAbstractor<DdType, ValueType>::relevantPredicatesChanged(
566 std::pair<std::set<uint_fast64_t>, std::vector<std::set<uint_fast64_t>>>
const& newRelevantPredicates)
const {
567 if (newRelevantPredicates.first.size() > relevantPredicatesAndVariables.first.size()) {
571 for (uint_fast64_t index = 0; index < command.get().getNumberOfUpdates(); ++index) {
572 if (newRelevantPredicates.second[index].size() > relevantPredicatesAndVariables.second[index].size()) {
580template<storm::dd::DdType DdType,
typename ValueType>
581void CommandAbstractor<DdType, ValueType>::addMissingPredicates(
582 std::pair<std::set<uint_fast64_t>, std::vector<std::set<uint_fast64_t>>>
const& newRelevantPredicates) {
584 std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> newSourceVariables =
585 this->getAbstractionInformation().declareNewVariables(relevantPredicatesAndVariables.first, newRelevantPredicates.first);
586 for (
auto const& element : newSourceVariables) {
587 allRelevantPredicates.insert(element.second);
588 smtSolver->add(
storm::expressions::iff(element.first, this->getAbstractionInformation().getPredicateByIndex(element.second)));
589 decisionVariables.push_back(element.first);
593 relevantPredicatesAndVariables.first.insert(relevantPredicatesAndVariables.first.end(), newSourceVariables.begin(), newSourceVariables.end());
594 std::sort(relevantPredicatesAndVariables.first.begin(), relevantPredicatesAndVariables.first.end(),
595 [](std::pair<storm::expressions::Variable, uint_fast64_t>
const& first, std::pair<storm::expressions::Variable, uint_fast64_t>
const& second) {
596 return first.second < second.second;
600 for (uint_fast64_t index = 0; index < command.get().getNumberOfUpdates(); ++index) {
601 std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> newSuccessorVariables =
602 this->getAbstractionInformation().declareNewVariables(relevantPredicatesAndVariables.second[index], newRelevantPredicates.second[index]);
603 for (
auto const& element : newSuccessorVariables) {
604 allRelevantPredicates.insert(element.second);
606 .getPredicateByIndex(element.second)
607 .substitute(command.get().getUpdate(index).getAsVariableToExpressionMap())));
608 decisionVariables.push_back(element.first);
611 relevantPredicatesAndVariables.second[index].insert(relevantPredicatesAndVariables.second[index].end(), newSuccessorVariables.begin(),
612 newSuccessorVariables.end());
613 std::sort(relevantPredicatesAndVariables.second[index].begin(), relevantPredicatesAndVariables.second[index].end(),
614 [](std::pair<storm::expressions::Variable, uint_fast64_t>
const& first,
615 std::pair<storm::expressions::Variable, uint_fast64_t>
const& second) { return first.second < second.second; });
619template<storm::dd::DdType DdType,
typename ValueType>
622 std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>>
const& variablePredicates)
const {
624 for (
auto variableIndexPairIt = variablePredicates.rbegin(), variableIndexPairIte = variablePredicates.rend(); variableIndexPairIt != variableIndexPairIte;
625 ++variableIndexPairIt) {
626 auto const& variableIndexPair = *variableIndexPairIt;
628 result &= this->getAbstractionInformation().encodePredicateAsSource(variableIndexPair.second);
630 result &= !this->getAbstractionInformation().encodePredicateAsSource(variableIndexPair.second);
638template<storm::dd::DdType DdType,
typename ValueType>
641 std::vector<std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>>>
const& variablePredicates)
const {
644 for (uint_fast64_t updateIndex = 0; updateIndex < command.get().getNumberOfUpdates(); ++updateIndex) {
648 for (
auto variableIndexPairIt = variablePredicates[updateIndex].rbegin(), variableIndexPairIte = variablePredicates[updateIndex].rend();
649 variableIndexPairIt != variableIndexPairIte; ++variableIndexPairIt) {
650 auto const& variableIndexPair = *variableIndexPairIt;
652 updateBdd &= this->getAbstractionInformation().encodePredicateAsSuccessor(variableIndexPair.second);
654 updateBdd &= !this->getAbstractionInformation().encodePredicateAsSuccessor(variableIndexPair.second);
658 updateBdd &= this->getAbstractionInformation().encodeAux(updateIndex, 0, this->getAbstractionInformation().getAuxVariableCount());
666template<storm::dd::DdType DdType,
typename ValueType>
670 for (uint_fast64_t updateIndex = 0; updateIndex < command.get().getNumberOfUpdates(); ++updateIndex) {
672 auto updateRelevantIt = relevantPredicatesAndVariables.second[updateIndex].rbegin();
673 auto updateRelevantIte = relevantPredicatesAndVariables.second[updateIndex].rend();
676 for (uint_fast64_t predicateIndex = this->getAbstractionInformation().getNumberOfPredicates() - 1;; --predicateIndex) {
677 if (updateRelevantIt == updateRelevantIte || updateRelevantIt->second != predicateIndex) {
678 updateIdentity &= this->getAbstractionInformation().getPredicateIdentity(predicateIndex);
683 if (predicateIndex == 0) {
688 result |= updateIdentity && this->getAbstractionInformation().encodeAux(updateIndex, 0, this->getAbstractionInformation().getAuxVariableCount());
693template<storm::dd::DdType DdType,
typename ValueType>
695 if (forceRecomputation) {
696 this->recomputeCachedBdd();
698 cachedDd.bdd &= computeMissingUpdateIdentities();
701 STORM_LOG_TRACE(
"Command produces " << cachedDd.bdd.getNonZeroCount() <<
" transitions.");
706template<storm::dd::DdType DdType,
typename ValueType>
708 uint_fast64_t numberOfPlayer2Variables) {
709 STORM_LOG_TRACE(
"Computing bottom state transitions of command " << command.get());
711 this->getAbstractionInformation().getDdManager().getBddZero());
714 if (skipBottomStates) {
715 STORM_LOG_TRACE(
"Skipping bottom state computation for this command.");
723 bottomStateAbstractor.
constrain(reachableStatesWithCommand);
724 result.
states = bottomStateAbstractor.getAbstractStates() && reachableStatesWithCommand;
728 skipBottomStates =
true;
733 result.
states && this->getAbstractionInformation().getAllPredicateIdentities() && this->getAbstractionInformation().getBottomStateBdd(
false,
false);
736 result.
states &= this->getAbstractionInformation().getBottomStateBdd(
true,
false);
740 this->getAbstractionInformation().encodePlayer1Choice(command.get().getGlobalIndex(), this->getAbstractionInformation().getPlayer1VariableCount()) &&
741 this->getAbstractionInformation().encodePlayer2Choice(0, 0, numberOfPlayer2Variables) &&
742 this->getAbstractionInformation().encodeAux(0, 0, this->getAbstractionInformation().getAuxVariableCount());
747template<storm::dd::DdType DdType,
typename ValueType>
750 for (uint_fast64_t updateIndex = 0; updateIndex < command.get().getNumberOfUpdates(); ++updateIndex) {
752 this->getAbstractionInformation().encodeAux(updateIndex, 0, this->getAbstractionInformation().getAuxVariableCount()).template toAdd<ValueType>() *
753 this->getAbstractionInformation().
getDdManager().getConstant(evaluator.asRational(command.get().getUpdate(updateIndex).getLikelihoodExpression()));
755 result *= this->getAbstractionInformation()
756 .encodePlayer1Choice(command.get().getGlobalIndex(), this->getAbstractionInformation().getPlayer1VariableCount())
757 .template toAdd<ValueType>();
761template<storm::dd::DdType DdType,
typename ValueType>
763 return command.get();
766template<storm::dd::DdType DdType,
typename ValueType>
768 return abstractionInformation.get();
771template<storm::dd::DdType DdType,
typename ValueType>
773 return abstractionInformation.get();
776template<storm::dd::DdType DdType,
typename ValueType>
778 skipBottomStates =
true;