5#include <boost/iterator/transform_iterator.hpp>
19#include "storm-config.h"
23namespace abstraction {
25template<storm::dd::DdType DdType,
typename ValueType>
27 std::shared_ptr<storm::utility::solver::SmtSolverFactory>
const& smtSolverFactory,
bool useDecomposition,
28 bool addPredicatesForValidBlocks,
bool debug)
29 : smtSolver(smtSolverFactory->create(abstractionInformation.getExpressionManager())),
30 abstractionInformation(abstractionInformation),
33 localExpressionInformation(abstractionInformation),
34 evaluator(abstractionInformation.getExpressionManager()),
35 relevantPredicatesAndVariables(),
36 cachedDd(abstractionInformation.getDdManager().getBddZero(), 0),
38 useDecomposition(useDecomposition),
39 addPredicatesForValidBlocks(addPredicatesForValidBlocks),
40 skipBottomStates(false),
41 forceRecomputation(true),
42 abstractGuard(abstractionInformation.getDdManager().getBddZero()),
43 bottomStateAbstractor(abstractionInformation, {!edge.
getGuard()}, smtSolverFactory),
46 relevantPredicatesAndVariables.second.resize(edge.getNumberOfDestinations());
49 for (
auto const& constraint : abstractionInformation.getConstraints()) {
50 smtSolver->add(constraint);
51 bottomStateAbstractor.constrain(constraint);
55 smtSolver->add(edge.getGuard());
58 for (
auto const& destination : edge.getDestinations()) {
59 for (
auto const& assignment : destination.getOrderedAssignments()) {
60 assignedVariables.insert(assignment.getExpressionVariable());
65 if (this->addPredicatesForValidBlocks) {
70template<storm::dd::DdType DdType,
typename ValueType>
73 for (
auto predicateIndex : predicates) {
74 localExpressionInformation.addExpression(predicateIndex);
79 std::pair<std::set<uint_fast64_t>, std::vector<std::set<uint_fast64_t>>> newRelevantPredicates = this->computeRelevantPredicates();
82 bool relevantPredicatesChanged = this->relevantPredicatesChanged(newRelevantPredicates);
83 if (relevantPredicatesChanged) {
84 addMissingPredicates(newRelevantPredicates);
86 forceRecomputation |= relevantPredicatesChanged;
89 bottomStateAbstractor.refine(predicates);
92template<storm::dd::DdType DdType,
typename ValueType>
94 return edge.get().getGuard();
97template<storm::dd::DdType DdType,
typename ValueType>
99 return edge.get().getNumberOfDestinations();
102template<storm::dd::DdType DdType,
typename ValueType>
104 return edge.get().getDestination(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 EdgeAbstractor<DdType, ValueType>::recomputeCachedBddWithDecomposition() {
123 STORM_LOG_TRACE(
"Recomputing BDD for edge with id " << edgeId <<
" and guard " << edge.get().getGuard() <<
" 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& destination : edge.get().getDestinations()) {
136 for (
auto const& assignment : destination.getOrderedAssignments().getAllAssignments()) {
137 allRelevantBlocks.insert(localExpressionInformation.getBlockIndexOfVariable(assignment.getExpressionVariable()));
139 auto rhsVariableBlocks = localExpressionInformation.getBlockIndicesOfVariables(assignment.getAssignedExpression().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& destination : edge.get().getDestinations()) {
159 for (
auto const& assignment : destination.getOrderedAssignments().getAllAssignments()) {
160 std::set<storm::expressions::Variable> rhsVariables = assignment.getAssignedExpression().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& destination : edge.get().getDestinations()) {
185 for (
auto const& assignment : destination.getOrderedAssignments().getAllAssignments()) {
186 std::set<storm::expressions::Variable> rhsVariables = assignment.getAssignedExpression().getVariables();
188 if (!rhsVariables.empty()) {
190 uint64_t representativeBlock = variableToLocalBlockIndex.at(representativeVariable);
191 uint64_t assignmentVariableBlock = variableToLocalBlockIndex.at(assignment.getExpressionVariable());
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 = edge.get().getGuard().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 destinationIndex = 0; destinationIndex < edge.get().getNumberOfDestinations(); ++destinationIndex) {
340 destinationVariablesAndPredicates.emplace_back();
341 for (
auto const& assignment : edge.get().getDestination(destinationIndex).getOrderedAssignments().getAllAssignments()) {
342 uint64_t assignmentVariableBlockIndex = localExpressionInformation.getBlockIndexOfVariable(assignment.getVariable().getExpressionVariable());
344 if (block.find(assignmentVariableBlockIndex) != block.end()) {
345 std::set<uint64_t>
const& assignmentVariableBlock = localExpressionInformation.getExpressionBlock(assignmentVariableBlockIndex);
346 for (
auto const& element : relevantPredicatesAndVariables.second[destinationIndex]) {
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 &= computeMissingDestinationIdentities();
438 resultBdd &= this->getAbstractionInformation().encodePlayer1Choice(edgeId, this->getAbstractionInformation().getPlayer1VariableCount());
441 cachedDd = GameBddResult<DdType>(resultBdd, usedNondeterminismVariables);
443 auto end = std::chrono::high_resolution_clock::now();
445 STORM_LOG_TRACE(
"Enumerated " << numberOfTotalSolutions <<
" solutions in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count()
447 forceRecomputation =
false;
450template<storm::dd::DdType DdType,
typename ValueType>
451void EdgeAbstractor<DdType, ValueType>::recomputeCachedBddWithoutDecomposition() {
452 STORM_LOG_TRACE(
"Recomputing BDD for edge with id " << edgeId <<
" and guard " << edge.get().getGuard());
453 auto start = std::chrono::high_resolution_clock::now();
456 std::unordered_map<storm::dd::Bdd<DdType>, std::vector<storm::dd::Bdd<DdType>>> sourceToDistributionsMap;
457 uint64_t numberOfSolutions = 0;
459 sourceToDistributionsMap[getSourceStateBdd(model, relevantPredicatesAndVariables.first)].push_back(
460 getDistributionBdd(model, relevantPredicatesAndVariables.second));
467 uint_fast64_t maximalNumberOfChoices = 0;
468 for (
auto const& sourceDistributionsPair : sourceToDistributionsMap) {
469 maximalNumberOfChoices = std::max(maximalNumberOfChoices,
static_cast<uint_fast64_t
>(sourceDistributionsPair.second.size()));
474 uint_fast64_t numberOfVariablesNeeded =
static_cast<uint_fast64_t
>(std::ceil(std::log2(maximalNumberOfChoices + 1)));
478 if (!skipBottomStates) {
479 abstractGuard = this->getAbstractionInformation().getDdManager().getBddZero();
481 for (
auto const& sourceDistributionsPair : sourceToDistributionsMap) {
482 if (!skipBottomStates) {
483 abstractGuard |= sourceDistributionsPair.first;
486 STORM_LOG_ASSERT(!sourceDistributionsPair.first.isZero(),
"The source BDD must not be empty.");
487 STORM_LOG_ASSERT(!sourceDistributionsPair.second.empty(),
"The distributions must not be empty.");
489 uint_fast64_t distributionIndex = 1;
491 for (
auto const& distribution : sourceDistributionsPair.second) {
492 allDistributions |= distribution && this->getAbstractionInformation().encodePlayer2Choice(distributionIndex, 0, numberOfVariablesNeeded);
496 resultBdd |= sourceDistributionsPair.first && allDistributions;
500 resultBdd &= computeMissingDestinationIdentities();
501 resultBdd &= this->getAbstractionInformation().encodePlayer1Choice(edgeId, this->getAbstractionInformation().getPlayer1VariableCount());
502 STORM_LOG_ASSERT(sourceToDistributionsMap.empty() || !resultBdd.
isZero(),
"The BDD must not be empty, if there were distributions.");
505 cachedDd = GameBddResult<DdType>(resultBdd, numberOfVariablesNeeded);
506 auto end = std::chrono::high_resolution_clock::now();
508 STORM_LOG_TRACE(
"Enumerated " << numberOfSolutions <<
" solutions in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count()
510 forceRecomputation =
false;
513template<storm::dd::DdType DdType,
typename ValueType>
514std::pair<std::set<uint_fast64_t>, std::set<uint_fast64_t>> EdgeAbstractor<DdType, ValueType>::computeRelevantPredicates(
516 std::pair<std::set<uint_fast64_t>, std::set<uint_fast64_t>> result;
518 std::set<storm::expressions::Variable> assignedVariables;
519 for (
auto const& assignment : assignments.getAllAssignments()) {
521 auto const& rightHandSidePredicates = localExpressionInformation.getExpressionsUsingVariables(assignment.getAssignedExpression().getVariables());
522 result.first.insert(rightHandSidePredicates.begin(), rightHandSidePredicates.end());
526 auto const& leftHandSidePredicates = localExpressionInformation.getExpressionsUsingVariable(assignedVariable);
527 result.second.insert(leftHandSidePredicates.begin(), leftHandSidePredicates.end());
530 if (this->addPredicatesForValidBlocks) {
531 auto const& assignedVariableBlock = localExpressionInformation.getRelatedExpressions(assignedVariable);
532 result.first.insert(assignedVariableBlock.begin(), assignedVariableBlock.end());
539template<storm::dd::DdType DdType,
typename ValueType>
540std::pair<std::set<uint_fast64_t>, std::vector<std::set<uint_fast64_t>>> EdgeAbstractor<DdType, ValueType>::computeRelevantPredicates()
const {
541 std::pair<std::set<uint_fast64_t>, std::vector<std::set<uint_fast64_t>>> result;
544 result.first = localExpressionInformation.getExpressionsUsingVariables(edge.get().getGuard().getVariables());
547 for (
auto const& destination : edge.get().getDestinations()) {
548 std::pair<std::set<uint_fast64_t>, std::set<uint_fast64_t>> relevantUpdatePredicates = computeRelevantPredicates(destination.getOrderedAssignments());
549 result.first.insert(relevantUpdatePredicates.first.begin(), relevantUpdatePredicates.first.end());
550 result.second.push_back(relevantUpdatePredicates.second);
556template<storm::dd::DdType DdType,
typename ValueType>
557bool EdgeAbstractor<DdType, ValueType>::relevantPredicatesChanged(
558 std::pair<std::set<uint_fast64_t>, std::vector<std::set<uint_fast64_t>>>
const& newRelevantPredicates)
const {
559 if (newRelevantPredicates.first.size() > relevantPredicatesAndVariables.first.size()) {
563 for (uint_fast64_t index = 0; index < edge.get().getNumberOfDestinations(); ++index) {
564 if (newRelevantPredicates.second[index].size() > relevantPredicatesAndVariables.second[index].size()) {
572template<storm::dd::DdType DdType,
typename ValueType>
573void EdgeAbstractor<DdType, ValueType>::addMissingPredicates(
574 std::pair<std::set<uint_fast64_t>, std::vector<std::set<uint_fast64_t>>>
const& newRelevantPredicates) {
576 std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> newSourceVariables =
577 this->getAbstractionInformation().declareNewVariables(relevantPredicatesAndVariables.first, newRelevantPredicates.first);
578 for (
auto const& element : newSourceVariables) {
579 allRelevantPredicates.insert(element.second);
580 smtSolver->add(
storm::expressions::iff(element.first, this->getAbstractionInformation().getPredicateByIndex(element.second)));
581 decisionVariables.push_back(element.first);
585 relevantPredicatesAndVariables.first.insert(relevantPredicatesAndVariables.first.end(), newSourceVariables.begin(), newSourceVariables.end());
586 std::sort(relevantPredicatesAndVariables.first.begin(), relevantPredicatesAndVariables.first.end(),
587 [](std::pair<storm::expressions::Variable, uint_fast64_t>
const& first, std::pair<storm::expressions::Variable, uint_fast64_t>
const& second) {
588 return first.second < second.second;
592 for (uint_fast64_t index = 0; index < edge.get().getNumberOfDestinations(); ++index) {
593 std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> newSuccessorVariables =
594 this->getAbstractionInformation().declareNewVariables(relevantPredicatesAndVariables.second[index], newRelevantPredicates.second[index]);
595 for (
auto const& element : newSuccessorVariables) {
596 allRelevantPredicates.insert(element.second);
598 .getPredicateByIndex(element.second)
599 .substitute(edge.get().getDestination(index).getAsVariableToExpressionMap())));
600 decisionVariables.push_back(element.first);
603 relevantPredicatesAndVariables.second[index].insert(relevantPredicatesAndVariables.second[index].end(), newSuccessorVariables.begin(),
604 newSuccessorVariables.end());
605 std::sort(relevantPredicatesAndVariables.second[index].begin(), relevantPredicatesAndVariables.second[index].end(),
606 [](std::pair<storm::expressions::Variable, uint_fast64_t>
const& first,
607 std::pair<storm::expressions::Variable, uint_fast64_t>
const& second) { return first.second < second.second; });
611template<storm::dd::DdType DdType,
typename ValueType>
614 std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>>
const& variablePredicates)
const {
616 for (
auto variableIndexPairIt = variablePredicates.rbegin(), variableIndexPairIte = variablePredicates.rend(); variableIndexPairIt != variableIndexPairIte;
617 ++variableIndexPairIt) {
618 auto const& variableIndexPair = *variableIndexPairIt;
620 result &= this->getAbstractionInformation().encodePredicateAsSource(variableIndexPair.second);
622 result &= !this->getAbstractionInformation().encodePredicateAsSource(variableIndexPair.second);
630template<storm::dd::DdType DdType,
typename ValueType>
633 std::vector<std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>>>
const& variablePredicates)
const {
636 for (uint_fast64_t destinationIndex = 0; destinationIndex < edge.get().getNumberOfDestinations(); ++destinationIndex) {
640 for (
auto variableIndexPairIt = variablePredicates[destinationIndex].rbegin(), variableIndexPairIte = variablePredicates[destinationIndex].rend();
641 variableIndexPairIt != variableIndexPairIte; ++variableIndexPairIt) {
642 auto const& variableIndexPair = *variableIndexPairIt;
644 updateBdd &= this->getAbstractionInformation().encodePredicateAsSuccessor(variableIndexPair.second);
646 updateBdd &= !this->getAbstractionInformation().encodePredicateAsSuccessor(variableIndexPair.second);
650 updateBdd &= this->getAbstractionInformation().encodeAux(destinationIndex, 0, this->getAbstractionInformation().getAuxVariableCount());
658template<storm::dd::DdType DdType,
typename ValueType>
662 for (uint_fast64_t destinationIndex = 0; destinationIndex < edge.get().getNumberOfDestinations(); ++destinationIndex) {
664 auto updateRelevantIt = relevantPredicatesAndVariables.second[destinationIndex].rbegin();
665 auto updateRelevantIte = relevantPredicatesAndVariables.second[destinationIndex].rend();
668 for (uint_fast64_t predicateIndex = this->getAbstractionInformation().getNumberOfPredicates() - 1;; --predicateIndex) {
669 if (updateRelevantIt == updateRelevantIte || updateRelevantIt->second != predicateIndex) {
670 updateIdentity &= this->getAbstractionInformation().getPredicateIdentity(predicateIndex);
675 if (predicateIndex == 0) {
680 result |= updateIdentity && this->getAbstractionInformation().encodeAux(destinationIndex, 0, this->getAbstractionInformation().getAuxVariableCount());
685template<storm::dd::DdType DdType,
typename ValueType>
687 if (forceRecomputation) {
688 this->recomputeCachedBdd();
690 cachedDd.bdd &= computeMissingDestinationIdentities();
693 STORM_LOG_TRACE(
"Edge produces " << cachedDd.bdd.getNonZeroCount() <<
" transitions.");
698template<storm::dd::DdType DdType,
typename ValueType>
701 boost::optional<std::pair<storm::expressions::Variable, storm::expressions::Variable>>
const& locationVariables) {
702 STORM_LOG_TRACE(
"Computing bottom state transitions of edge with index " << edgeId <<
".");
704 this->getAbstractionInformation().getDdManager().getBddZero());
707 if (skipBottomStates) {
725 bottomStateAbstractor.
constrain(reachableStatesWithEdge);
726 if (locationVariables) {
727 result.
states = bottomStateAbstractor.getAbstractStates() && reachableStatesWithEdge &&
728 this->getAbstractionInformation().encodeLocation(locationVariables.get().first, edge.get().getSourceLocationIndex());
730 result.
states = bottomStateAbstractor.getAbstractStates() && reachableStatesWithEdge;
735 skipBottomStates =
true;
740 result.
states && this->getAbstractionInformation().getAllPredicateIdentities() && this->getAbstractionInformation().getBottomStateBdd(
false,
false);
743 result.
states &= this->getAbstractionInformation().getBottomStateBdd(
true,
false);
746 result.
transitions &= this->getAbstractionInformation().encodePlayer1Choice(edgeId, 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>
755 boost::optional<std::pair<storm::expressions::Variable, storm::expressions::Variable>>
const& locationVariables)
const {
757 for (uint_fast64_t destinationIndex = 0; destinationIndex < edge.get().getNumberOfDestinations(); ++destinationIndex) {
759 this->getAbstractionInformation()
760 .encodeAux(destinationIndex, 0, this->getAbstractionInformation().getAuxVariableCount())
761 .template toAdd<ValueType>() *
762 this->getAbstractionInformation().
getDdManager().getConstant(evaluator.asRational(edge.get().getDestination(destinationIndex).getProbability()));
763 if (locationVariables) {
764 tmp *= this->getAbstractionInformation()
765 .encodeLocation(locationVariables.get().second, edge.get().getDestination(destinationIndex).getLocationIndex())
766 .template toAdd<ValueType>();
772 if (locationVariables) {
773 tmp *= this->getAbstractionInformation().encodeLocation(locationVariables.get().first, edge.get().getSourceLocationIndex()).template toAdd<ValueType>();
776 this->getAbstractionInformation().encodePlayer1Choice(edgeId, this->getAbstractionInformation().getPlayer1VariableCount()).template toAdd<ValueType>();
783template<storm::dd::DdType DdType,
typename ValueType>
788template<storm::dd::DdType DdType,
typename ValueType>
790 return abstractionInformation.get();
793template<storm::dd::DdType DdType,
typename ValueType>
795 return abstractionInformation.get();
798template<storm::dd::DdType DdType,
typename ValueType>
800 skipBottomStates =
true;
805#ifdef STORM_HAVE_CARL
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