25template<storm::dd::DdType DdType,
typename ValueType>
27 std::shared_ptr<storm::utility::solver::SmtSolverFactory>
const& smtSolverFactory,
28 bool useDecomposition,
bool addPredicatesForValidBlocks,
bool debug)
29 : smtSolver(smtSolverFactory->create(abstractionInformation.getExpressionManager())),
30 abstractionInformation(abstractionInformation),
32 localExpressionInformation(abstractionInformation),
33 evaluator(abstractionInformation.getExpressionManager()),
34 relevantPredicatesAndVariables(),
35 cachedDd(abstractionInformation.getDdManager().getBddZero(), 0),
37 useDecomposition(useDecomposition),
38 addPredicatesForValidBlocks(addPredicatesForValidBlocks),
39 skipBottomStates(false),
40 forceRecomputation(true),
41 abstractGuard(abstractionInformation.getDdManager().getBddZero()),
42 bottomStateAbstractor(abstractionInformation, {!command.
getGuardExpression()}, smtSolverFactory),
45 relevantPredicatesAndVariables.second.resize(command.getNumberOfUpdates());
48 for (
auto const& constraint : abstractionInformation.getConstraints()) {
49 smtSolver->add(constraint);
50 bottomStateAbstractor.constrain(constraint);
54 smtSolver->add(command.getGuardExpression());
57 for (
auto const& update : command.getUpdates()) {
58 for (
auto const& assignment : update.getAssignments()) {
59 assignedVariables.insert(assignment.getVariable());
64 if (this->addPredicatesForValidBlocks) {
69template<storm::dd::DdType DdType,
typename ValueType>
72 for (
auto predicateIndex : predicates) {
73 localExpressionInformation.addExpression(predicateIndex);
78 std::pair<std::set<uint_fast64_t>, std::vector<std::set<uint_fast64_t>>> newRelevantPredicates = this->computeRelevantPredicates();
81 bool relevantPredicatesChanged = this->relevantPredicatesChanged(newRelevantPredicates);
82 if (relevantPredicatesChanged) {
83 addMissingPredicates(newRelevantPredicates);
85 forceRecomputation |= relevantPredicatesChanged;
88 bottomStateAbstractor.refine(predicates);
91template<storm::dd::DdType DdType,
typename ValueType>
93 return command.get().getGuardExpression();
96template<storm::dd::DdType DdType,
typename ValueType>
98 return command.get().getNumberOfUpdates();
101template<storm::dd::DdType DdType,
typename ValueType>
103 uint64_t auxiliaryChoice)
const {
104 return command.get().getUpdate(auxiliaryChoice).getAsVariableToExpressionMap();
107template<storm::dd::DdType DdType,
typename ValueType>
109 return assignedVariables;
112template<storm::dd::DdType DdType,
typename ValueType>
114 if (useDecomposition) {
115 recomputeCachedBddWithDecomposition();
117 recomputeCachedBddWithoutDecomposition();
121template<storm::dd::DdType DdType,
typename ValueType>
122void CommandAbstractor<DdType, ValueType>::recomputeCachedBddWithDecomposition() {
123 STORM_LOG_TRACE(
"Recomputing BDD for command " << command.get() <<
" [with index " << command.get().getGlobalIndex() <<
"] using the decomposition.");
124 auto start = std::chrono::high_resolution_clock::now();
133 std::set<uint64_t> allRelevantBlocks;
134 std::map<storm::expressions::Variable, uint64_t> variableToBlockIndex;
135 for (
auto const& update : command.get().getUpdates()) {
136 for (
auto const& assignment : update.getAssignments()) {
137 allRelevantBlocks.insert(localExpressionInformation.getBlockIndexOfVariable(assignment.getVariable()));
139 auto rhsVariableBlocks = localExpressionInformation.getBlockIndicesOfVariables(assignment.getExpression().getVariables());
140 allRelevantBlocks.insert(rhsVariableBlocks.begin(), rhsVariableBlocks.end());
143 STORM_LOG_TRACE(
"Found " << allRelevantBlocks.size() <<
" relevant block(s).");
146 std::vector<std::set<uint64_t>> relevantBlockPartition;
147 std::map<storm::expressions::Variable, uint64_t> variableToLocalBlockIndex;
149 for (
auto const& blockIndex : allRelevantBlocks) {
150 relevantBlockPartition.emplace_back(std::set<uint64_t>({blockIndex}));
151 for (
auto const& variable : localExpressionInformation.getVariableBlockWithIndex(blockIndex)) {
152 variableToLocalBlockIndex[variable] = index;
158 for (
auto const& update : command.get().getUpdates()) {
159 for (
auto const& assignment : update.getAssignments()) {
160 std::set<storm::expressions::Variable> rhsVariables = assignment.getExpression().getVariables();
162 if (!rhsVariables.empty()) {
163 uint64_t blockToKeep = variableToLocalBlockIndex.at(*rhsVariables.begin());
164 for (
auto const& variable : rhsVariables) {
165 uint64_t block = variableToLocalBlockIndex.at(variable);
166 if (block != blockToKeep) {
167 for (
auto const& blockIndex : relevantBlockPartition[block]) {
168 for (
auto const& variable : localExpressionInformation.getVariableBlockWithIndex(blockIndex)) {
169 variableToLocalBlockIndex[variable] = blockToKeep;
172 relevantBlockPartition[blockToKeep].insert(relevantBlockPartition[block].begin(), relevantBlockPartition[block].end());
173 relevantBlockPartition[block].clear();
181 bool changed =
false;
184 for (
auto const& update : command.get().getUpdates()) {
185 for (
auto const& assignment : update.getAssignments()) {
186 std::set<storm::expressions::Variable> rhsVariables = assignment.getExpression().getVariables();
188 if (!rhsVariables.empty()) {
190 uint64_t representativeBlock = variableToLocalBlockIndex.at(representativeVariable);
191 uint64_t assignmentVariableBlock = variableToLocalBlockIndex.at(assignment.getVariable());
194 if (assignmentVariableBlock != representativeBlock) {
197 for (
auto const& blockIndex : relevantBlockPartition[assignmentVariableBlock]) {
198 for (
auto const& variable : localExpressionInformation.getVariableBlockWithIndex(blockIndex)) {
199 variableToLocalBlockIndex[variable] = representativeBlock;
202 relevantBlockPartition[representativeBlock].insert(relevantBlockPartition[assignmentVariableBlock].begin(),
203 relevantBlockPartition[assignmentVariableBlock].end());
204 relevantBlockPartition[assignmentVariableBlock].clear();
212 std::vector<std::set<uint64_t>> cleanedRelevantBlockPartition;
213 for (
auto& outerBlock : relevantBlockPartition) {
214 if (!outerBlock.empty()) {
215 cleanedRelevantBlockPartition.emplace_back();
217 for (
auto const& innerBlock : outerBlock) {
218 if (!localExpressionInformation.getExpressionBlock(innerBlock).empty()) {
219 cleanedRelevantBlockPartition.back().insert(innerBlock);
223 if (cleanedRelevantBlockPartition.back().empty()) {
224 cleanedRelevantBlockPartition.pop_back();
228 relevantBlockPartition = std::move(cleanedRelevantBlockPartition);
230 STORM_LOG_TRACE(
"Decomposition into " << relevantBlockPartition.size() <<
" blocks.");
232 uint64_t blockIndex = 0;
233 for (
auto const& block : relevantBlockPartition) {
235 std::set<uint64_t> blockPredicateIndices;
236 for (
auto const& innerBlock : block) {
237 blockPredicateIndices.insert(localExpressionInformation.getExpressionBlock(innerBlock).begin(),
238 localExpressionInformation.getExpressionBlock(innerBlock).end());
241 for (
auto const& predicateIndex : blockPredicateIndices) {
242 STORM_LOG_TRACE(abstractionInformation.get().getPredicateByIndex(predicateIndex));
249 std::set<storm::expressions::Variable> variablesContainedInGuard = command.get().getGuardExpression().getVariables();
253 bool enumerateAbstractGuard =
true;
254 std::set<uint64_t> guardBlocks = localExpressionInformation.getBlockIndicesOfVariables(variablesContainedInGuard);
255 for (
auto const& block : relevantBlockPartition) {
256 bool allContained =
true;
257 for (
auto const& guardBlock : guardBlocks) {
258 if (block.find(guardBlock) == block.end()) {
259 allContained =
false;
264 enumerateAbstractGuard =
false;
268 uint64_t numberOfSolutions = 0;
269 uint64_t numberOfTotalSolutions = 0;
272 if (enumerateAbstractGuard) {
273 std::set<uint64_t> relatedGuardPredicates = localExpressionInformation.getRelatedExpressions(variablesContainedInGuard);
274 std::vector<storm::expressions::Variable> guardDecisionVariables;
275 std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> guardVariablesAndPredicates;
276 for (
auto const& element : relevantPredicatesAndVariables.first) {
277 if (relatedGuardPredicates.find(element.second) != relatedGuardPredicates.end()) {
278 guardDecisionVariables.push_back(element.first);
279 guardVariablesAndPredicates.push_back(element);
282 abstractGuard = this->getAbstractionInformation().getDdManager().getBddZero();
283 smtSolver->allSat(guardDecisionVariables,
285 abstractGuard |= getSourceStateBdd(model, guardVariablesAndPredicates);
289 STORM_LOG_TRACE(
"Enumerated " << numberOfSolutions <<
" solutions for abstract guard.");
298 std::pair<std::vector<storm::expressions::Expression>, std::unordered_map<uint_fast64_t, storm::expressions::Variable>> result =
299 abstractGuard.toExpression(this->getAbstractionInformation().getExpressionManager());
302 for (
auto const& expression : result.first) {
303 smtSolver->add(expression);
307 for (
auto const& indexVariablePair : result.second) {
309 storm::expressions::iff(indexVariablePair.second, this->getAbstractionInformation().getPredicateForDdVariableIndex(indexVariablePair.first)));
314 uint64_t usedNondeterminismVariables = 0;
315 uint64_t blockCounter = 0;
316 std::vector<storm::dd::Bdd<DdType>> blockBdds;
317 for (
auto const& block : relevantBlockPartition) {
318 std::set<uint64_t> relevantPredicates;
319 for (
auto const& innerBlock : block) {
320 relevantPredicates.insert(localExpressionInformation.getExpressionBlock(innerBlock).begin(),
321 localExpressionInformation.getExpressionBlock(innerBlock).end());
324 if (relevantPredicates.empty()) {
325 STORM_LOG_TRACE(
"Block does not contain relevant predicates, skipping it.");
329 std::vector<storm::expressions::Variable> transitionDecisionVariables;
330 std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> sourceVariablesAndPredicates;
331 for (
auto const& element : relevantPredicatesAndVariables.first) {
332 if (relevantPredicates.find(element.second) != relevantPredicates.end()) {
333 transitionDecisionVariables.push_back(element.first);
334 sourceVariablesAndPredicates.push_back(element);
338 std::vector<std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>>> destinationVariablesAndPredicates;
339 for (uint64_t updateIndex = 0; updateIndex < command.get().getNumberOfUpdates(); ++updateIndex) {
340 destinationVariablesAndPredicates.emplace_back();
341 for (
auto const& assignment : command.get().getUpdate(updateIndex).getAssignments()) {
342 uint64_t assignmentVariableBlockIndex = localExpressionInformation.getBlockIndexOfVariable(assignment.getVariable());
344 if (block.find(assignmentVariableBlockIndex) != block.end()) {
345 std::set<uint64_t>
const& assignmentVariableBlock = localExpressionInformation.getExpressionBlock(assignmentVariableBlockIndex);
346 for (
auto const& element : relevantPredicatesAndVariables.second[updateIndex]) {
347 if (assignmentVariableBlock.find(element.second) != assignmentVariableBlock.end()) {
348 destinationVariablesAndPredicates.back().push_back(element);
349 transitionDecisionVariables.push_back(element.first);
356 std::unordered_map<storm::dd::Bdd<DdType>, std::vector<storm::dd::Bdd<DdType>>> sourceToDistributionsMap;
357 numberOfSolutions = 0;
358 smtSolver->allSat(transitionDecisionVariables, [&sourceToDistributionsMap,
this, &numberOfSolutions, &sourceVariablesAndPredicates,
360 sourceToDistributionsMap[getSourceStateBdd(model, sourceVariablesAndPredicates)].push_back(
361 getDistributionBdd(model, destinationVariablesAndPredicates));
365 STORM_LOG_TRACE(
"Enumerated " << numberOfSolutions <<
" solutions for block " << blockCounter <<
".");
366 numberOfTotalSolutions += numberOfSolutions;
370 uint_fast64_t maximalNumberOfChoices = 0;
371 for (
auto const& sourceDistributionsPair : sourceToDistributionsMap) {
372 maximalNumberOfChoices = std::max(maximalNumberOfChoices,
static_cast<uint_fast64_t
>(sourceDistributionsPair.second.size()));
377 uint_fast64_t numberOfVariablesNeeded = (maximalNumberOfChoices > 1)
378 ? (
static_cast<uint_fast64_t
>(std::ceil(std::log2(maximalNumberOfChoices + (blockCounter == 0 ? 1 : 0)))))
379 : (blockCounter == 0 ? 1 : 0);
384 for (
auto const& sourceDistributionsPair : sourceToDistributionsMap) {
385 STORM_LOG_ASSERT(!sourceDistributionsPair.first.isZero(),
"The source BDD must not be empty.");
386 STORM_LOG_ASSERT(!sourceDistributionsPair.second.empty(),
"The distributions must not be empty.");
389 uint_fast64_t distributionIndex = blockCounter == 0 ? 1 : 0;
391 for (
auto const& distribution : sourceDistributionsPair.second) {
392 allDistributions |= distribution && this->getAbstractionInformation().encodePlayer2Choice(
393 distributionIndex, usedNondeterminismVariables, usedNondeterminismVariables + numberOfVariablesNeeded);
397 resultBdd |= sourceDistributionsPair.first && allDistributions;
400 usedNondeterminismVariables += numberOfVariablesNeeded;
402 blockBdds.push_back(resultBdd);
406 if (enumerateAbstractGuard) {
412 for (
auto const& blockBdd : blockBdds) {
413 resultBdd &= blockBdd;
417 if (!enumerateAbstractGuard) {
418 std::set<storm::expressions::Variable> allVariables(getAbstractionInformation().getSuccessorVariables());
419 auto player2Variables = getAbstractionInformation().getPlayer2VariableSet(usedNondeterminismVariables);
420 allVariables.insert(player2Variables.begin(), player2Variables.end());
421 auto auxVariables = getAbstractionInformation().getAuxVariableSet(0, getAbstractionInformation().getAuxVariableCount());
422 allVariables.insert(auxVariables.begin(), auxVariables.end());
424 std::set<storm::expressions::Variable> variablesToAbstract;
431 resultBdd &= abstractGuard;
435 resultBdd &= computeMissingUpdateIdentities();
439 this->getAbstractionInformation().encodePlayer1Choice(command.get().getGlobalIndex(), this->getAbstractionInformation().getPlayer1VariableCount());
442 cachedDd = GameBddResult<DdType>(resultBdd, usedNondeterminismVariables);
444 auto end = std::chrono::high_resolution_clock::now();
446 STORM_LOG_TRACE(
"Enumerated " << numberOfTotalSolutions <<
" solutions in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count()
448 forceRecomputation =
false;
451template<storm::dd::DdType DdType,
typename ValueType>
452void CommandAbstractor<DdType, ValueType>::recomputeCachedBddWithoutDecomposition() {
454 auto start = std::chrono::high_resolution_clock::now();
457 std::unordered_map<storm::dd::Bdd<DdType>, std::vector<storm::dd::Bdd<DdType>>> sourceToDistributionsMap;
458 uint64_t numberOfSolutions = 0;
460 sourceToDistributionsMap[getSourceStateBdd(model, relevantPredicatesAndVariables.first)].push_back(
461 getDistributionBdd(model, relevantPredicatesAndVariables.second));
468 uint_fast64_t maximalNumberOfChoices = 0;
469 for (
auto const& sourceDistributionsPair : sourceToDistributionsMap) {
470 maximalNumberOfChoices = std::max(maximalNumberOfChoices,
static_cast<uint_fast64_t
>(sourceDistributionsPair.second.size()));
475 uint_fast64_t numberOfVariablesNeeded =
static_cast<uint_fast64_t
>(std::ceil(std::log2(maximalNumberOfChoices + 1)));
479 if (!skipBottomStates) {
480 abstractGuard = this->getAbstractionInformation().getDdManager().getBddZero();
482 for (
auto const& sourceDistributionsPair : sourceToDistributionsMap) {
483 if (!skipBottomStates) {
484 abstractGuard |= sourceDistributionsPair.first;
487 STORM_LOG_ASSERT(!sourceDistributionsPair.first.isZero(),
"The source BDD must not be empty.");
488 STORM_LOG_ASSERT(!sourceDistributionsPair.second.empty(),
"The distributions must not be empty.");
490 uint_fast64_t distributionIndex = 1;
492 for (
auto const& distribution : sourceDistributionsPair.second) {
493 allDistributions |= distribution && this->getAbstractionInformation().encodePlayer2Choice(distributionIndex, 0, numberOfVariablesNeeded);
497 resultBdd |= sourceDistributionsPair.first && allDistributions;
501 resultBdd &= computeMissingUpdateIdentities();
503 this->getAbstractionInformation().encodePlayer1Choice(command.get().getGlobalIndex(), this->getAbstractionInformation().getPlayer1VariableCount());
504 STORM_LOG_ASSERT(sourceToDistributionsMap.empty() || !resultBdd.
isZero(),
"The BDD must not be empty, if there were distributions.");
507 cachedDd = GameBddResult<DdType>(resultBdd, numberOfVariablesNeeded);
508 auto end = std::chrono::high_resolution_clock::now();
510 STORM_LOG_TRACE(
"Enumerated " << numberOfSolutions <<
" solutions in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count()
512 forceRecomputation =
false;
515template<storm::dd::DdType DdType,
typename ValueType>
516std::pair<std::set<uint_fast64_t>, std::set<uint_fast64_t>> CommandAbstractor<DdType, ValueType>::computeRelevantPredicates(
517 std::vector<storm::prism::Assignment>
const& assignments)
const {
518 std::pair<std::set<uint_fast64_t>, std::set<uint_fast64_t>> result;
520 std::set<storm::expressions::Variable> assignedVariables;
521 for (
auto const& assignment : assignments) {
523 auto const& rightHandSidePredicates = localExpressionInformation.getExpressionsUsingVariables(assignment.getExpression().getVariables());
524 result.first.insert(rightHandSidePredicates.begin(), rightHandSidePredicates.end());
528 auto const& leftHandSidePredicates = localExpressionInformation.getExpressionsUsingVariable(assignedVariable);
529 result.second.insert(leftHandSidePredicates.begin(), leftHandSidePredicates.end());
532 if (this->addPredicatesForValidBlocks) {
533 auto const& assignedVariableBlock = localExpressionInformation.getRelatedExpressions(assignedVariable);
534 result.first.insert(assignedVariableBlock.begin(), assignedVariableBlock.end());
541template<storm::dd::DdType DdType,
typename ValueType>
542std::pair<std::set<uint_fast64_t>, std::vector<std::set<uint_fast64_t>>> CommandAbstractor<DdType, ValueType>::computeRelevantPredicates()
const {
543 std::pair<std::set<uint_fast64_t>, std::vector<std::set<uint_fast64_t>>> result;
546 result.first = localExpressionInformation.getExpressionsUsingVariables(command.get().getGuardExpression().getVariables());
549 for (
auto const& update : command.get().getUpdates()) {
550 std::pair<std::set<uint_fast64_t>, std::set<uint_fast64_t>> relevantUpdatePredicates = computeRelevantPredicates(update.getAssignments());
551 result.first.insert(relevantUpdatePredicates.first.begin(), relevantUpdatePredicates.first.end());
552 result.second.push_back(relevantUpdatePredicates.second);
570template<storm::dd::DdType DdType,
typename ValueType>
571bool CommandAbstractor<DdType, ValueType>::relevantPredicatesChanged(
572 std::pair<std::set<uint_fast64_t>, std::vector<std::set<uint_fast64_t>>>
const& newRelevantPredicates)
const {
573 if (newRelevantPredicates.first.size() > relevantPredicatesAndVariables.first.size()) {
577 for (uint_fast64_t index = 0; index < command.get().getNumberOfUpdates(); ++index) {
578 if (newRelevantPredicates.second[index].size() > relevantPredicatesAndVariables.second[index].size()) {
586template<storm::dd::DdType DdType,
typename ValueType>
587void CommandAbstractor<DdType, ValueType>::addMissingPredicates(
588 std::pair<std::set<uint_fast64_t>, std::vector<std::set<uint_fast64_t>>>
const& newRelevantPredicates) {
590 std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> newSourceVariables =
591 this->getAbstractionInformation().declareNewVariables(relevantPredicatesAndVariables.first, newRelevantPredicates.first);
592 for (
auto const& element : newSourceVariables) {
593 allRelevantPredicates.insert(element.second);
594 smtSolver->add(
storm::expressions::iff(element.first, this->getAbstractionInformation().getPredicateByIndex(element.second)));
595 decisionVariables.push_back(element.first);
599 relevantPredicatesAndVariables.first.insert(relevantPredicatesAndVariables.first.end(), newSourceVariables.begin(), newSourceVariables.end());
600 std::sort(relevantPredicatesAndVariables.first.begin(), relevantPredicatesAndVariables.first.end(),
601 [](std::pair<storm::expressions::Variable, uint_fast64_t>
const& first, std::pair<storm::expressions::Variable, uint_fast64_t>
const& second) {
602 return first.second < second.second;
606 for (uint_fast64_t index = 0; index < command.get().getNumberOfUpdates(); ++index) {
607 std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> newSuccessorVariables =
608 this->getAbstractionInformation().declareNewVariables(relevantPredicatesAndVariables.second[index], newRelevantPredicates.second[index]);
609 for (
auto const& element : newSuccessorVariables) {
610 allRelevantPredicates.insert(element.second);
612 .getPredicateByIndex(element.second)
613 .substitute(command.get().getUpdate(index).getAsVariableToExpressionMap())));
614 decisionVariables.push_back(element.first);
617 relevantPredicatesAndVariables.second[index].insert(relevantPredicatesAndVariables.second[index].end(), newSuccessorVariables.begin(),
618 newSuccessorVariables.end());
619 std::sort(relevantPredicatesAndVariables.second[index].begin(), relevantPredicatesAndVariables.second[index].end(),
620 [](std::pair<storm::expressions::Variable, uint_fast64_t>
const& first,
621 std::pair<storm::expressions::Variable, uint_fast64_t>
const& second) { return first.second < second.second; });
625template<storm::dd::DdType DdType,
typename ValueType>
628 std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>>
const& variablePredicates)
const {
630 for (
auto variableIndexPairIt = variablePredicates.rbegin(), variableIndexPairIte = variablePredicates.rend(); variableIndexPairIt != variableIndexPairIte;
631 ++variableIndexPairIt) {
632 auto const& variableIndexPair = *variableIndexPairIt;
634 result &= this->getAbstractionInformation().encodePredicateAsSource(variableIndexPair.second);
636 result &= !this->getAbstractionInformation().encodePredicateAsSource(variableIndexPair.second);
644template<storm::dd::DdType DdType,
typename ValueType>
647 std::vector<std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>>>
const& variablePredicates)
const {
650 for (uint_fast64_t updateIndex = 0; updateIndex < command.get().getNumberOfUpdates(); ++updateIndex) {
654 for (
auto variableIndexPairIt = variablePredicates[updateIndex].rbegin(), variableIndexPairIte = variablePredicates[updateIndex].rend();
655 variableIndexPairIt != variableIndexPairIte; ++variableIndexPairIt) {
656 auto const& variableIndexPair = *variableIndexPairIt;
658 updateBdd &= this->getAbstractionInformation().encodePredicateAsSuccessor(variableIndexPair.second);
660 updateBdd &= !this->getAbstractionInformation().encodePredicateAsSuccessor(variableIndexPair.second);
664 updateBdd &= this->getAbstractionInformation().encodeAux(updateIndex, 0, this->getAbstractionInformation().getAuxVariableCount());
672template<storm::dd::DdType DdType,
typename ValueType>
676 for (uint_fast64_t updateIndex = 0; updateIndex < command.get().getNumberOfUpdates(); ++updateIndex) {
678 auto updateRelevantIt = relevantPredicatesAndVariables.second[updateIndex].rbegin();
679 auto updateRelevantIte = relevantPredicatesAndVariables.second[updateIndex].rend();
682 for (uint_fast64_t predicateIndex = this->getAbstractionInformation().getNumberOfPredicates() - 1;; --predicateIndex) {
683 if (updateRelevantIt == updateRelevantIte || updateRelevantIt->second != predicateIndex) {
684 updateIdentity &= this->getAbstractionInformation().getPredicateIdentity(predicateIndex);
689 if (predicateIndex == 0) {
694 result |= updateIdentity && this->getAbstractionInformation().encodeAux(updateIndex, 0, this->getAbstractionInformation().getAuxVariableCount());
699template<storm::dd::DdType DdType,
typename ValueType>
701 if (forceRecomputation) {
702 this->recomputeCachedBdd();
704 cachedDd.bdd &= computeMissingUpdateIdentities();
707 STORM_LOG_TRACE(
"Command produces " << cachedDd.bdd.getNonZeroCount() <<
" transitions.");
712template<storm::dd::DdType DdType,
typename ValueType>
714 uint_fast64_t numberOfPlayer2Variables) {
715 STORM_LOG_TRACE(
"Computing bottom state transitions of command " << command.get());
717 this->getAbstractionInformation().getDdManager().getBddZero());
720 if (skipBottomStates) {
721 STORM_LOG_TRACE(
"Skipping bottom state computation for this command.");
729 bottomStateAbstractor.
constrain(reachableStatesWithCommand);
730 result.
states = bottomStateAbstractor.getAbstractStates() && reachableStatesWithCommand;
734 skipBottomStates =
true;
739 result.
states && this->getAbstractionInformation().getAllPredicateIdentities() && this->getAbstractionInformation().getBottomStateBdd(
false,
false);
742 result.
states &= this->getAbstractionInformation().getBottomStateBdd(
true,
false);
746 this->getAbstractionInformation().encodePlayer1Choice(command.get().getGlobalIndex(), this->getAbstractionInformation().getPlayer1VariableCount()) &&
747 this->getAbstractionInformation().encodePlayer2Choice(0, 0, numberOfPlayer2Variables) &&
748 this->getAbstractionInformation().encodeAux(0, 0, this->getAbstractionInformation().getAuxVariableCount());
753template<storm::dd::DdType DdType,
typename ValueType>
756 for (uint_fast64_t updateIndex = 0; updateIndex < command.get().getNumberOfUpdates(); ++updateIndex) {
758 this->getAbstractionInformation().encodeAux(updateIndex, 0, this->getAbstractionInformation().getAuxVariableCount()).template toAdd<ValueType>() *
759 this->getAbstractionInformation().
getDdManager().getConstant(evaluator.asRational(command.get().getUpdate(updateIndex).getLikelihoodExpression()));
761 result *= this->getAbstractionInformation()
762 .encodePlayer1Choice(command.get().getGlobalIndex(), this->getAbstractionInformation().getPlayer1VariableCount())
763 .template toAdd<ValueType>();
767template<storm::dd::DdType DdType,
typename ValueType>
769 return command.get();
772template<storm::dd::DdType DdType,
typename ValueType>
774 return abstractionInformation.get();
777template<storm::dd::DdType DdType,
typename ValueType>
779 return abstractionInformation.get();
782template<storm::dd::DdType DdType,
typename ValueType>
784 skipBottomStates =
true;
789#ifdef STORM_HAVE_CARL