3#include <boost/iterator/transform_iterator.hpp>
17namespace abstraction {
19template<storm::dd::DdType DdType,
typename ValueType>
21 std::shared_ptr<storm::utility::solver::SmtSolverFactory>
const& smtSolverFactory,
bool useDecomposition,
22 bool addPredicatesForValidBlocks,
bool debug)
23 : smtSolver(smtSolverFactory->create(abstractionInformation.getExpressionManager())),
24 abstractionInformation(abstractionInformation),
27 localExpressionInformation(abstractionInformation),
28 evaluator(abstractionInformation.getExpressionManager()),
29 relevantPredicatesAndVariables(),
30 cachedDd(abstractionInformation.getDdManager().getBddZero(), 0),
32 useDecomposition(useDecomposition),
33 addPredicatesForValidBlocks(addPredicatesForValidBlocks),
34 skipBottomStates(false),
35 forceRecomputation(true),
36 abstractGuard(abstractionInformation.getDdManager().getBddZero()),
37 bottomStateAbstractor(abstractionInformation, {!edge.
getGuard()}, smtSolverFactory),
40 relevantPredicatesAndVariables.second.resize(edge.getNumberOfDestinations());
43 for (
auto const& constraint : abstractionInformation.getConstraints()) {
44 smtSolver->add(constraint);
45 bottomStateAbstractor.constrain(constraint);
49 smtSolver->add(edge.getGuard());
52 for (
auto const& destination : edge.getDestinations()) {
53 for (
auto const& assignment : destination.getOrderedAssignments()) {
54 assignedVariables.insert(assignment.getExpressionVariable());
59 if (this->addPredicatesForValidBlocks) {
64template<storm::dd::DdType DdType,
typename ValueType>
67 for (
auto predicateIndex : predicates) {
68 localExpressionInformation.addExpression(predicateIndex);
73 std::pair<std::set<uint_fast64_t>, std::vector<std::set<uint_fast64_t>>> newRelevantPredicates = this->computeRelevantPredicates();
76 bool relevantPredicatesChanged = this->relevantPredicatesChanged(newRelevantPredicates);
77 if (relevantPredicatesChanged) {
78 addMissingPredicates(newRelevantPredicates);
80 forceRecomputation |= relevantPredicatesChanged;
83 bottomStateAbstractor.refine(predicates);
86template<storm::dd::DdType DdType,
typename ValueType>
88 return edge.get().getGuard();
91template<storm::dd::DdType DdType,
typename ValueType>
93 return edge.get().getNumberOfDestinations();
96template<storm::dd::DdType DdType,
typename ValueType>
98 return edge.get().getDestination(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 EdgeAbstractor<DdType, ValueType>::recomputeCachedBddWithDecomposition() {
117 STORM_LOG_TRACE(
"Recomputing BDD for edge with id " << edgeId <<
" and guard " << edge.get().getGuard() <<
" 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& destination : edge.get().getDestinations()) {
130 for (
auto const& assignment : destination.getOrderedAssignments().getAllAssignments()) {
131 allRelevantBlocks.insert(localExpressionInformation.getBlockIndexOfVariable(assignment.getExpressionVariable()));
133 auto rhsVariableBlocks = localExpressionInformation.getBlockIndicesOfVariables(assignment.getAssignedExpression().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& destination : edge.get().getDestinations()) {
153 for (
auto const& assignment : destination.getOrderedAssignments().getAllAssignments()) {
154 std::set<storm::expressions::Variable> rhsVariables = assignment.getAssignedExpression().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& destination : edge.get().getDestinations()) {
179 for (
auto const& assignment : destination.getOrderedAssignments().getAllAssignments()) {
180 std::set<storm::expressions::Variable> rhsVariables = assignment.getAssignedExpression().getVariables();
182 if (!rhsVariables.empty()) {
184 uint64_t representativeBlock = variableToLocalBlockIndex.at(representativeVariable);
185 uint64_t assignmentVariableBlock = variableToLocalBlockIndex.at(assignment.getExpressionVariable());
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 = edge.get().getGuard().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 destinationIndex = 0; destinationIndex < edge.get().getNumberOfDestinations(); ++destinationIndex) {
334 destinationVariablesAndPredicates.emplace_back();
335 for (
auto const& assignment : edge.get().getDestination(destinationIndex).getOrderedAssignments().getAllAssignments()) {
336 uint64_t assignmentVariableBlockIndex = localExpressionInformation.getBlockIndexOfVariable(assignment.getVariable().getExpressionVariable());
338 if (block.find(assignmentVariableBlockIndex) != block.end()) {
339 std::set<uint64_t>
const& assignmentVariableBlock = localExpressionInformation.getExpressionBlock(assignmentVariableBlockIndex);
340 for (
auto const& element : relevantPredicatesAndVariables.second[destinationIndex]) {
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 &= computeMissingDestinationIdentities();
432 resultBdd &= this->getAbstractionInformation().encodePlayer1Choice(edgeId, this->getAbstractionInformation().getPlayer1VariableCount());
435 cachedDd = GameBddResult<DdType>(resultBdd, usedNondeterminismVariables);
437 auto end = std::chrono::high_resolution_clock::now();
439 STORM_LOG_TRACE(
"Enumerated " << numberOfTotalSolutions <<
" solutions in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count()
441 forceRecomputation =
false;
444template<storm::dd::DdType DdType,
typename ValueType>
445void EdgeAbstractor<DdType, ValueType>::recomputeCachedBddWithoutDecomposition() {
446 STORM_LOG_TRACE(
"Recomputing BDD for edge with id " << edgeId <<
" and guard " << edge.get().getGuard());
447 auto start = std::chrono::high_resolution_clock::now();
450 std::unordered_map<storm::dd::Bdd<DdType>, std::vector<storm::dd::Bdd<DdType>>> sourceToDistributionsMap;
451 uint64_t numberOfSolutions = 0;
453 sourceToDistributionsMap[getSourceStateBdd(model, relevantPredicatesAndVariables.first)].push_back(
454 getDistributionBdd(model, relevantPredicatesAndVariables.second));
461 uint_fast64_t maximalNumberOfChoices = 0;
462 for (
auto const& sourceDistributionsPair : sourceToDistributionsMap) {
463 maximalNumberOfChoices = std::max(maximalNumberOfChoices,
static_cast<uint_fast64_t
>(sourceDistributionsPair.second.size()));
468 uint_fast64_t numberOfVariablesNeeded =
static_cast<uint_fast64_t
>(std::ceil(std::log2(maximalNumberOfChoices + 1)));
472 if (!skipBottomStates) {
473 abstractGuard = this->getAbstractionInformation().getDdManager().getBddZero();
475 for (
auto const& sourceDistributionsPair : sourceToDistributionsMap) {
476 if (!skipBottomStates) {
477 abstractGuard |= sourceDistributionsPair.first;
480 STORM_LOG_ASSERT(!sourceDistributionsPair.first.isZero(),
"The source BDD must not be empty.");
481 STORM_LOG_ASSERT(!sourceDistributionsPair.second.empty(),
"The distributions must not be empty.");
483 uint_fast64_t distributionIndex = 1;
485 for (
auto const& distribution : sourceDistributionsPair.second) {
486 allDistributions |= distribution && this->getAbstractionInformation().encodePlayer2Choice(distributionIndex, 0, numberOfVariablesNeeded);
490 resultBdd |= sourceDistributionsPair.first && allDistributions;
494 resultBdd &= computeMissingDestinationIdentities();
495 resultBdd &= this->getAbstractionInformation().encodePlayer1Choice(edgeId, this->getAbstractionInformation().getPlayer1VariableCount());
496 STORM_LOG_ASSERT(sourceToDistributionsMap.empty() || !resultBdd.
isZero(),
"The BDD must not be empty, if there were distributions.");
499 cachedDd = GameBddResult<DdType>(resultBdd, numberOfVariablesNeeded);
500 auto end = std::chrono::high_resolution_clock::now();
502 STORM_LOG_TRACE(
"Enumerated " << numberOfSolutions <<
" solutions in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count()
504 forceRecomputation =
false;
507template<storm::dd::DdType DdType,
typename ValueType>
508std::pair<std::set<uint_fast64_t>, std::set<uint_fast64_t>> EdgeAbstractor<DdType, ValueType>::computeRelevantPredicates(
510 std::pair<std::set<uint_fast64_t>, std::set<uint_fast64_t>> result;
512 std::set<storm::expressions::Variable> assignedVariables;
513 for (
auto const& assignment : assignments.getAllAssignments()) {
515 auto const& rightHandSidePredicates = localExpressionInformation.getExpressionsUsingVariables(assignment.getAssignedExpression().getVariables());
516 result.first.insert(rightHandSidePredicates.begin(), rightHandSidePredicates.end());
520 auto const& leftHandSidePredicates = localExpressionInformation.getExpressionsUsingVariable(assignedVariable);
521 result.second.insert(leftHandSidePredicates.begin(), leftHandSidePredicates.end());
524 if (this->addPredicatesForValidBlocks) {
525 auto const& assignedVariableBlock = localExpressionInformation.getRelatedExpressions(assignedVariable);
526 result.first.insert(assignedVariableBlock.begin(), assignedVariableBlock.end());
533template<storm::dd::DdType DdType,
typename ValueType>
534std::pair<std::set<uint_fast64_t>, std::vector<std::set<uint_fast64_t>>> EdgeAbstractor<DdType, ValueType>::computeRelevantPredicates()
const {
535 std::pair<std::set<uint_fast64_t>, std::vector<std::set<uint_fast64_t>>> result;
538 result.first = localExpressionInformation.getExpressionsUsingVariables(edge.get().getGuard().getVariables());
541 for (
auto const& destination : edge.get().getDestinations()) {
542 std::pair<std::set<uint_fast64_t>, std::set<uint_fast64_t>> relevantUpdatePredicates = computeRelevantPredicates(destination.getOrderedAssignments());
543 result.first.insert(relevantUpdatePredicates.first.begin(), relevantUpdatePredicates.first.end());
544 result.second.push_back(relevantUpdatePredicates.second);
550template<storm::dd::DdType DdType,
typename ValueType>
551bool EdgeAbstractor<DdType, ValueType>::relevantPredicatesChanged(
552 std::pair<std::set<uint_fast64_t>, std::vector<std::set<uint_fast64_t>>>
const& newRelevantPredicates)
const {
553 if (newRelevantPredicates.first.size() > relevantPredicatesAndVariables.first.size()) {
557 for (uint_fast64_t index = 0; index < edge.get().getNumberOfDestinations(); ++index) {
558 if (newRelevantPredicates.second[index].size() > relevantPredicatesAndVariables.second[index].size()) {
566template<storm::dd::DdType DdType,
typename ValueType>
567void EdgeAbstractor<DdType, ValueType>::addMissingPredicates(
568 std::pair<std::set<uint_fast64_t>, std::vector<std::set<uint_fast64_t>>>
const& newRelevantPredicates) {
570 std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> newSourceVariables =
571 this->getAbstractionInformation().declareNewVariables(relevantPredicatesAndVariables.first, newRelevantPredicates.first);
572 for (
auto const& element : newSourceVariables) {
573 allRelevantPredicates.insert(element.second);
574 smtSolver->add(
storm::expressions::iff(element.first, this->getAbstractionInformation().getPredicateByIndex(element.second)));
575 decisionVariables.push_back(element.first);
579 relevantPredicatesAndVariables.first.insert(relevantPredicatesAndVariables.first.end(), newSourceVariables.begin(), newSourceVariables.end());
580 std::sort(relevantPredicatesAndVariables.first.begin(), relevantPredicatesAndVariables.first.end(),
581 [](std::pair<storm::expressions::Variable, uint_fast64_t>
const& first, std::pair<storm::expressions::Variable, uint_fast64_t>
const& second) {
582 return first.second < second.second;
586 for (uint_fast64_t index = 0; index < edge.get().getNumberOfDestinations(); ++index) {
587 std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> newSuccessorVariables =
588 this->getAbstractionInformation().declareNewVariables(relevantPredicatesAndVariables.second[index], newRelevantPredicates.second[index]);
589 for (
auto const& element : newSuccessorVariables) {
590 allRelevantPredicates.insert(element.second);
592 .getPredicateByIndex(element.second)
593 .substitute(edge.get().getDestination(index).getAsVariableToExpressionMap())));
594 decisionVariables.push_back(element.first);
597 relevantPredicatesAndVariables.second[index].insert(relevantPredicatesAndVariables.second[index].end(), newSuccessorVariables.begin(),
598 newSuccessorVariables.end());
599 std::sort(relevantPredicatesAndVariables.second[index].begin(), relevantPredicatesAndVariables.second[index].end(),
600 [](std::pair<storm::expressions::Variable, uint_fast64_t>
const& first,
601 std::pair<storm::expressions::Variable, uint_fast64_t>
const& second) { return first.second < second.second; });
605template<storm::dd::DdType DdType,
typename ValueType>
608 std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>>
const& variablePredicates)
const {
610 for (
auto variableIndexPairIt = variablePredicates.rbegin(), variableIndexPairIte = variablePredicates.rend(); variableIndexPairIt != variableIndexPairIte;
611 ++variableIndexPairIt) {
612 auto const& variableIndexPair = *variableIndexPairIt;
614 result &= this->getAbstractionInformation().encodePredicateAsSource(variableIndexPair.second);
616 result &= !this->getAbstractionInformation().encodePredicateAsSource(variableIndexPair.second);
624template<storm::dd::DdType DdType,
typename ValueType>
627 std::vector<std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>>>
const& variablePredicates)
const {
630 for (uint_fast64_t destinationIndex = 0; destinationIndex < edge.get().getNumberOfDestinations(); ++destinationIndex) {
634 for (
auto variableIndexPairIt = variablePredicates[destinationIndex].rbegin(), variableIndexPairIte = variablePredicates[destinationIndex].rend();
635 variableIndexPairIt != variableIndexPairIte; ++variableIndexPairIt) {
636 auto const& variableIndexPair = *variableIndexPairIt;
638 updateBdd &= this->getAbstractionInformation().encodePredicateAsSuccessor(variableIndexPair.second);
640 updateBdd &= !this->getAbstractionInformation().encodePredicateAsSuccessor(variableIndexPair.second);
644 updateBdd &= this->getAbstractionInformation().encodeAux(destinationIndex, 0, this->getAbstractionInformation().getAuxVariableCount());
652template<storm::dd::DdType DdType,
typename ValueType>
656 for (uint_fast64_t destinationIndex = 0; destinationIndex < edge.get().getNumberOfDestinations(); ++destinationIndex) {
658 auto updateRelevantIt = relevantPredicatesAndVariables.second[destinationIndex].rbegin();
659 auto updateRelevantIte = relevantPredicatesAndVariables.second[destinationIndex].rend();
662 for (uint_fast64_t predicateIndex = this->getAbstractionInformation().getNumberOfPredicates() - 1;; --predicateIndex) {
663 if (updateRelevantIt == updateRelevantIte || updateRelevantIt->second != predicateIndex) {
664 updateIdentity &= this->getAbstractionInformation().getPredicateIdentity(predicateIndex);
669 if (predicateIndex == 0) {
674 result |= updateIdentity && this->getAbstractionInformation().encodeAux(destinationIndex, 0, this->getAbstractionInformation().getAuxVariableCount());
679template<storm::dd::DdType DdType,
typename ValueType>
681 if (forceRecomputation) {
682 this->recomputeCachedBdd();
684 cachedDd.bdd &= computeMissingDestinationIdentities();
687 STORM_LOG_TRACE(
"Edge produces " << cachedDd.bdd.getNonZeroCount() <<
" transitions.");
692template<storm::dd::DdType DdType,
typename ValueType>
695 boost::optional<std::pair<storm::expressions::Variable, storm::expressions::Variable>>
const& locationVariables) {
696 STORM_LOG_TRACE(
"Computing bottom state transitions of edge with index " << edgeId <<
".");
698 this->getAbstractionInformation().getDdManager().getBddZero());
701 if (skipBottomStates) {
719 bottomStateAbstractor.
constrain(reachableStatesWithEdge);
720 if (locationVariables) {
721 result.
states = bottomStateAbstractor.getAbstractStates() && reachableStatesWithEdge &&
722 this->getAbstractionInformation().encodeLocation(locationVariables.get().first, edge.get().getSourceLocationIndex());
724 result.
states = bottomStateAbstractor.getAbstractStates() && reachableStatesWithEdge;
729 skipBottomStates =
true;
734 result.
states && this->getAbstractionInformation().getAllPredicateIdentities() && this->getAbstractionInformation().getBottomStateBdd(
false,
false);
737 result.
states &= this->getAbstractionInformation().getBottomStateBdd(
true,
false);
740 result.
transitions &= this->getAbstractionInformation().encodePlayer1Choice(edgeId, 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>
749 boost::optional<std::pair<storm::expressions::Variable, storm::expressions::Variable>>
const& locationVariables)
const {
751 for (uint_fast64_t destinationIndex = 0; destinationIndex < edge.get().getNumberOfDestinations(); ++destinationIndex) {
753 this->getAbstractionInformation()
754 .encodeAux(destinationIndex, 0, this->getAbstractionInformation().getAuxVariableCount())
755 .template toAdd<ValueType>() *
756 this->getAbstractionInformation().
getDdManager().getConstant(evaluator.asRational(edge.get().getDestination(destinationIndex).getProbability()));
757 if (locationVariables) {
758 tmp *= this->getAbstractionInformation()
759 .encodeLocation(locationVariables.get().second, edge.get().getDestination(destinationIndex).getLocationIndex())
760 .template toAdd<ValueType>();
766 if (locationVariables) {
767 tmp *= this->getAbstractionInformation().encodeLocation(locationVariables.get().first, edge.get().getSourceLocationIndex()).template toAdd<ValueType>();
770 this->getAbstractionInformation().encodePlayer1Choice(edgeId, this->getAbstractionInformation().getPlayer1VariableCount()).template toAdd<ValueType>();
777template<storm::dd::DdType DdType,
typename ValueType>
782template<storm::dd::DdType DdType,
typename ValueType>
784 return abstractionInformation.get();
787template<storm::dd::DdType DdType,
typename ValueType>
789 return abstractionInformation.get();
792template<storm::dd::DdType DdType,
typename ValueType>
794 skipBottomStates =
true;
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.
Bdd< LibraryType > constrain(Bdd< LibraryType > const &constraint) const
Computes the constraint of the current BDD with the given constraint.
std::set< storm::expressions::Variable > const & getContainedMetaVariables() const
Retrieves the set of all meta variables contained in the DD.
DdManager< LibraryType > & getDdManager() const
Retrieves the manager that is responsible for this DD.
void refine(std::vector< uint_fast64_t > const &predicates)
Refines the abstract edge with the given predicates.
BottomStateResult< DdType > getBottomStateTransitions(storm::dd::Bdd< DdType > const &reachableStates, uint_fast64_t numberOfPlayer2Variables, boost::optional< std::pair< storm::expressions::Variable, storm::expressions::Variable > > const &locationVariables)
Retrieves the transitions to bottom states of this edge.
EdgeAbstractor(uint64_t edgeId, storm::jani::Edge const &edge, AbstractionInformation< DdType > &abstractionInformation, std::shared_ptr< storm::utility::solver::SmtSolverFactory > const &smtSolverFactory, bool useDecomposition, bool addPredicatesForValidBlocks, bool debug)
Constructs an abstract edge from the given command and the initial predicates.
std::map< storm::expressions::Variable, storm::expressions::Expression > getVariableUpdates(uint64_t auxiliaryChoice) const
Retrieves a mapping from variables to expressions that define their updates wrt.
storm::jani::Edge const & getConcreteEdge() const
Retrieves the concrete edge that is abstracted by this abstract edge.
std::set< storm::expressions::Variable > const & getAssignedVariables() const
Retrieves the assigned variables.
storm::expressions::Expression const & getGuard() const
Retrieves the guard of this edge.
uint64_t getNumberOfUpdates(uint64_t player1Choice) const
Retrieves the number of updates of this edge.
GameBddResult< DdType > abstract()
Computes the abstraction of the edge wrt.
storm::dd::Add< DdType, ValueType > getEdgeDecoratorAdd(boost::optional< std::pair< storm::expressions::Variable, storm::expressions::Variable > > const &locationVariables) const
Retrieves an ADD that maps the encoding of the edge, source/target locations and its updates to their...
void notifyGuardIsPredicate()
storm::expressions::Expression const & getGuard() const
Retrieves the guard of this edge.
The base class for all model references.
virtual bool getBooleanValue(storm::expressions::Variable const &variable) const =0
#define STORM_LOG_DEBUG(message)
#define STORM_LOG_TRACE(message)
#define STORM_LOG_ASSERT(cond, message)
Expression iff(Expression const &first, Expression const &second)
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)
storm::dd::Bdd< DdType > states
storm::dd::Bdd< DdType > transitions