diff --git a/resources/3rdparty/sylvan/src/sylvan_obj_bdd_storm.hpp b/resources/3rdparty/sylvan/src/sylvan_obj_bdd_storm.hpp index 3a81a05f8..393ce988c 100644 --- a/resources/3rdparty/sylvan/src/sylvan_obj_bdd_storm.hpp +++ b/resources/3rdparty/sylvan/src/sylvan_obj_bdd_storm.hpp @@ -1,2 +1,3 @@ Mtbdd toDoubleMtbdd() const; Mtbdd toInt64Mtbdd() const; + Mtbdd Ite(Mtbdd const& thenDd, Mtbdd const& elseDd) const; diff --git a/resources/3rdparty/sylvan/src/sylvan_obj_storm.cpp b/resources/3rdparty/sylvan/src/sylvan_obj_storm.cpp index 789a385d8..c119f72cd 100644 --- a/resources/3rdparty/sylvan/src/sylvan_obj_storm.cpp +++ b/resources/3rdparty/sylvan/src/sylvan_obj_storm.cpp @@ -10,6 +10,12 @@ Bdd::toInt64Mtbdd() const { return mtbdd_bool_to_int64(bdd); } +Mtbdd +Bdd::Ite(Mtbdd const& thenDd, Mtbdd const& elseDd) const { + LACE_ME; + return mtbdd_ite(bdd, thenDd.GetMTBDD(), elseDd.GetMTBDD()); +} + Mtbdd Mtbdd::Minus(const Mtbdd &other) const { diff --git a/src/adapters/AddExpressionAdapter.cpp b/src/adapters/AddExpressionAdapter.cpp index 0a561a1eb..84e48e8a6 100644 --- a/src/adapters/AddExpressionAdapter.cpp +++ b/src/adapters/AddExpressionAdapter.cpp @@ -41,7 +41,7 @@ namespace storm { } else { storm::dd::Add elseDd = boost::any_cast>(expression.getElseExpression()->accept(*this)); storm::dd::Add thenDd = boost::any_cast>(expression.getThenExpression()->accept(*this)); - storm::dd::Add conditionDd = boost::any_cast>(expression.getCondition()->accept(*this)); + storm::dd::Bdd conditionDd = boost::any_cast>(expression.getCondition()->accept(*this)); return conditionDd.ite(thenDd, elseDd); } } diff --git a/src/builder/DdPrismModelBuilder.cpp b/src/builder/DdPrismModelBuilder.cpp index 1834d178c..59fc4bbd7 100644 --- a/src/builder/DdPrismModelBuilder.cpp +++ b/src/builder/DdPrismModelBuilder.cpp @@ -683,7 +683,7 @@ namespace storm { } // Add a new variable that resolves the nondeterminism between the two choices. - storm::dd::Add combinedTransitions = generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[numberOfUsedNondeterminismVariables], 1).template toAdd().ite(action2Extended, action1Extended); + storm::dd::Add combinedTransitions = generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[numberOfUsedNondeterminismVariables], 1).ite(action2Extended, action1Extended); return ActionDecisionDiagram((action1.guardDd.toBdd() || action2.guardDd.toBdd()).template toAdd(), combinedTransitions, assignedGlobalVariables, numberOfUsedNondeterminismVariables + 1); } else { diff --git a/src/modelchecker/prctl/helper/HybridDtmcPrctlHelper.cpp b/src/modelchecker/prctl/helper/HybridDtmcPrctlHelper.cpp index b93d0dcc3..6ca927aac 100644 --- a/src/modelchecker/prctl/helper/HybridDtmcPrctlHelper.cpp +++ b/src/modelchecker/prctl/helper/HybridDtmcPrctlHelper.cpp @@ -199,7 +199,7 @@ namespace storm { if (qualitative) { // Set the values for all maybe-states to 1 to indicate that their reward values // are neither 0 nor infinity. - return std::unique_ptr(new SymbolicQuantitativeCheckResult(model.getReachableStates(), infinityStates.template toAdd().ite(model.getManager().getConstant(storm::utility::infinity()), model.getManager().template getAddZero()) + maybeStates.template toAdd() * model.getManager().template getAddOne())); + return std::unique_ptr(new SymbolicQuantitativeCheckResult(model.getReachableStates(), infinityStates.ite(model.getManager().getConstant(storm::utility::infinity()), model.getManager().template getAddZero()) + maybeStates.template toAdd() * model.getManager().template getAddOne())); } else { // If there are maybe states, we need to solve an equation system. if (!maybeStates.isZero()) { @@ -233,9 +233,9 @@ namespace storm { solver->solveEquationSystem(x, b); // Return a hybrid check result that stores the numerical values explicitly. - return std::unique_ptr(new storm::modelchecker::HybridQuantitativeCheckResult(model.getReachableStates(), model.getReachableStates() && !maybeStates, infinityStates.template toAdd().ite(model.getManager().getConstant(storm::utility::infinity()), model.getManager().template getAddZero()), maybeStates, odd, x)); + return std::unique_ptr(new storm::modelchecker::HybridQuantitativeCheckResult(model.getReachableStates(), model.getReachableStates() && !maybeStates, infinityStates.ite(model.getManager().getConstant(storm::utility::infinity()), model.getManager().template getAddZero()), maybeStates, odd, x)); } else { - return std::unique_ptr(new storm::modelchecker::SymbolicQuantitativeCheckResult(model.getReachableStates(), infinityStates.template toAdd().ite(model.getManager().getConstant(storm::utility::infinity()), model.getManager().template getAddZero()))); + return std::unique_ptr(new storm::modelchecker::SymbolicQuantitativeCheckResult(model.getReachableStates(), infinityStates.ite(model.getManager().getConstant(storm::utility::infinity()), model.getManager().template getAddZero()))); } } } diff --git a/src/modelchecker/prctl/helper/HybridMdpPrctlHelper.cpp b/src/modelchecker/prctl/helper/HybridMdpPrctlHelper.cpp index 5fd89271a..c980e6dcc 100644 --- a/src/modelchecker/prctl/helper/HybridMdpPrctlHelper.cpp +++ b/src/modelchecker/prctl/helper/HybridMdpPrctlHelper.cpp @@ -218,7 +218,7 @@ namespace storm { if (qualitative) { // Set the values for all maybe-states to 1 to indicate that their reward values // are neither 0 nor infinity. - return std::unique_ptr(new SymbolicQuantitativeCheckResult(model.getReachableStates(), infinityStates.template toAdd().ite(model.getManager().getConstant(storm::utility::infinity()), model.getManager().template getAddZero()) + maybeStates.template toAdd() * model.getManager().getConstant(storm::utility::one()))); + return std::unique_ptr(new SymbolicQuantitativeCheckResult(model.getReachableStates(), infinityStates.ite(model.getManager().getConstant(storm::utility::infinity()), model.getManager().template getAddZero()) + maybeStates.template toAdd() * model.getManager().getConstant(storm::utility::one()))); } else { // If there are maybe states, we need to solve an equation system. if (!maybeStates.isZero()) { @@ -253,9 +253,9 @@ namespace storm { solver->solveEquationSystem(dir, x, explicitRepresentation.second); // Return a hybrid check result that stores the numerical values explicitly. - return std::unique_ptr(new storm::modelchecker::HybridQuantitativeCheckResult(model.getReachableStates(), model.getReachableStates() && !maybeStates, infinityStates.template toAdd().ite(model.getManager().getConstant(storm::utility::infinity()), model.getManager().template getAddZero()), maybeStates, odd, x)); + return std::unique_ptr(new storm::modelchecker::HybridQuantitativeCheckResult(model.getReachableStates(), model.getReachableStates() && !maybeStates, infinityStates.ite(model.getManager().getConstant(storm::utility::infinity()), model.getManager().template getAddZero()), maybeStates, odd, x)); } else { - return std::unique_ptr(new storm::modelchecker::SymbolicQuantitativeCheckResult(model.getReachableStates(), infinityStates.template toAdd().ite(model.getManager().getConstant(storm::utility::infinity()), model.getManager().template getAddZero()))); + return std::unique_ptr(new storm::modelchecker::SymbolicQuantitativeCheckResult(model.getReachableStates(), infinityStates.ite(model.getManager().getConstant(storm::utility::infinity()), model.getManager().template getAddZero()))); } } } diff --git a/src/modelchecker/prctl/helper/SymbolicDtmcPrctlHelper.cpp b/src/modelchecker/prctl/helper/SymbolicDtmcPrctlHelper.cpp index 9d6af2b71..605a5d2e4 100644 --- a/src/modelchecker/prctl/helper/SymbolicDtmcPrctlHelper.cpp +++ b/src/modelchecker/prctl/helper/SymbolicDtmcPrctlHelper.cpp @@ -147,7 +147,7 @@ namespace storm { if (qualitative) { // Set the values for all maybe-states to 1 to indicate that their reward values // are neither 0 nor infinity. - return infinityStates.template toAdd().ite(model.getManager().getConstant(storm::utility::infinity()), model.getManager().template getAddZero()) + maybeStates.template toAdd() * model.getManager().getConstant(storm::utility::one()); + return infinityStates.ite(model.getManager().getConstant(storm::utility::infinity()), model.getManager().template getAddZero()) + maybeStates.template toAdd() * model.getManager().getConstant(storm::utility::one()); } else { // If there are maybe states, we need to solve an equation system. if (!maybeStates.isZero()) { @@ -170,9 +170,9 @@ namespace storm { std::unique_ptr> solver = linearEquationSolverFactory.create(submatrix, maybeStates, model.getRowVariables(), model.getColumnVariables(), model.getRowColumnMetaVariablePairs()); storm::dd::Add result = solver->solveEquationSystem(model.getManager().getConstant(0.5) * maybeStatesAdd, subvector); - return infinityStates.template toAdd().ite(model.getManager().getConstant(storm::utility::infinity()), result); + return infinityStates.ite(model.getManager().getConstant(storm::utility::infinity()), result); } else { - return infinityStates.template toAdd().ite(model.getManager().getConstant(storm::utility::infinity()), model.getManager().getConstant(storm::utility::zero())); + return infinityStates.ite(model.getManager().getConstant(storm::utility::infinity()), model.getManager().getConstant(storm::utility::zero())); } } } diff --git a/src/modelchecker/prctl/helper/SymbolicMdpPrctlHelper.cpp b/src/modelchecker/prctl/helper/SymbolicMdpPrctlHelper.cpp index d2ed0f764..8a51270e9 100644 --- a/src/modelchecker/prctl/helper/SymbolicMdpPrctlHelper.cpp +++ b/src/modelchecker/prctl/helper/SymbolicMdpPrctlHelper.cpp @@ -171,7 +171,7 @@ namespace storm { if (qualitative) { // Set the values for all maybe-states to 1 to indicate that their reward values // are neither 0 nor infinity. - return std::unique_ptr(new SymbolicQuantitativeCheckResult(model.getReachableStates(), infinityStates.template toAdd().ite(model.getManager().getConstant(storm::utility::infinity()), model.getManager().template getAddZero()) + maybeStates.template toAdd() * model.getManager().getConstant(storm::utility::one()))); + return std::unique_ptr(new SymbolicQuantitativeCheckResult(model.getReachableStates(), infinityStates.ite(model.getManager().getConstant(storm::utility::infinity()), model.getManager().template getAddZero()) + maybeStates.template toAdd() * model.getManager().getConstant(storm::utility::one()))); } else { // If there are maybe states, we need to solve an equation system. if (!maybeStates.isZero()) { @@ -192,9 +192,9 @@ namespace storm { std::unique_ptr> solver = linearEquationSolverFactory.create(submatrix, maybeStates, model.getIllegalMask() && maybeStates, model.getRowVariables(), model.getColumnVariables(), model.getNondeterminismVariables(), model.getRowColumnMetaVariablePairs()); storm::dd::Add result = solver->solveEquationSystem(minimize, model.getManager().template getAddZero(), subvector); - return std::unique_ptr(new storm::modelchecker::SymbolicQuantitativeCheckResult(model.getReachableStates(), infinityStates.template toAdd().ite(model.getManager().getConstant(storm::utility::infinity()), result))); + return std::unique_ptr(new storm::modelchecker::SymbolicQuantitativeCheckResult(model.getReachableStates(), infinityStates.ite(model.getManager().getConstant(storm::utility::infinity()), result))); } else { - return std::unique_ptr(new storm::modelchecker::SymbolicQuantitativeCheckResult(model.getReachableStates(), infinityStates.template toAdd().ite(model.getManager().getConstant(storm::utility::infinity()), model.getManager().template getAddZero()))); + return std::unique_ptr(new storm::modelchecker::SymbolicQuantitativeCheckResult(model.getReachableStates(), infinityStates.ite(model.getManager().getConstant(storm::utility::infinity()), model.getManager().template getAddZero()))); } } } diff --git a/src/modelchecker/results/HybridQuantitativeCheckResult.cpp b/src/modelchecker/results/HybridQuantitativeCheckResult.cpp index aee43bd1f..51a254722 100644 --- a/src/modelchecker/results/HybridQuantitativeCheckResult.cpp +++ b/src/modelchecker/results/HybridQuantitativeCheckResult.cpp @@ -143,7 +143,7 @@ namespace storm { ValueType HybridQuantitativeCheckResult::getMin() const { // In order to not get false zeros, we need to set the values of all states whose values is not stored // symbolically to infinity. - storm::dd::Add tmp = symbolicStates.template toAdd().ite(this->symbolicValues, reachableStates.getDdManager().getConstant(storm::utility::infinity())); + storm::dd::Add tmp = symbolicStates.ite(this->symbolicValues, reachableStates.getDdManager().getConstant(storm::utility::infinity())); ValueType min = tmp.getMin(); if (!explicitStates.isZero()) { for (auto const& element : explicitValues) { diff --git a/src/modelchecker/results/SymbolicQuantitativeCheckResult.cpp b/src/modelchecker/results/SymbolicQuantitativeCheckResult.cpp index 5031d9d88..bd4d6b2ba 100644 --- a/src/modelchecker/results/SymbolicQuantitativeCheckResult.cpp +++ b/src/modelchecker/results/SymbolicQuantitativeCheckResult.cpp @@ -81,7 +81,7 @@ namespace storm { ValueType SymbolicQuantitativeCheckResult::getMin() const { // In order to not get false zeros, we need to set the values of all states whose values is not stored // symbolically to infinity. - return states.template toAdd().ite(this->values, states.getDdManager().getConstant(storm::utility::infinity())).getMin(); + return states.ite(this->values, states.getDdManager().getConstant(storm::utility::infinity())).getMin(); } template diff --git a/src/solver/SymbolicLinearEquationSolver.cpp b/src/solver/SymbolicLinearEquationSolver.cpp index 4b795f1ce..01c7d895b 100644 --- a/src/solver/SymbolicLinearEquationSolver.cpp +++ b/src/solver/SymbolicLinearEquationSolver.cpp @@ -28,15 +28,16 @@ namespace storm { template storm::dd::Add SymbolicLinearEquationSolver::solveEquationSystem(storm::dd::Add const& x, storm::dd::Add const& b) const { // Start by computing the Jacobi decomposition of the matrix A. - storm::dd::Add diagonal = x.getDdManager().template getAddOne(); + storm::dd::Bdd diagonal = x.getDdManager().getBddOne(); for (auto const& pair : rowColumnMetaVariablePairs) { - diagonal *= x.getDdManager().template getIdentity(pair.first).equals(x.getDdManager().template getIdentity(pair.second)).template toAdd(); - diagonal *= x.getDdManager().getRange(pair.first).template toAdd() * x.getDdManager().getRange(pair.second).template toAdd(); + diagonal &= x.getDdManager().template getIdentity(pair.first).equals(x.getDdManager().template getIdentity(pair.second)); + diagonal &= x.getDdManager().getRange(pair.first) && x.getDdManager().getRange(pair.second); } - diagonal *= allRows.template toAdd(); + diagonal &= allRows; storm::dd::Add lu = diagonal.ite(this->A.getDdManager().template getAddZero(), this->A); - storm::dd::Add dinv = diagonal / (diagonal * this->A); + storm::dd::Add diagonalAdd = diagonal.template toAdd(); + storm::dd::Add dinv = diagonalAdd / (diagonalAdd * this->A); // Set up additional environment variables. storm::dd::Add xCopy = x; diff --git a/src/solver/SymbolicMinMaxLinearEquationSolver.cpp b/src/solver/SymbolicMinMaxLinearEquationSolver.cpp index c33863ab7..221853a87 100644 --- a/src/solver/SymbolicMinMaxLinearEquationSolver.cpp +++ b/src/solver/SymbolicMinMaxLinearEquationSolver.cpp @@ -14,12 +14,12 @@ namespace storm { namespace solver { template - SymbolicMinMaxLinearEquationSolver::SymbolicMinMaxLinearEquationSolver(storm::dd::Add const& A, storm::dd::Bdd const& allRows, storm::dd::Bdd const& illegalMask, std::set const& rowMetaVariables, std::set const& columnMetaVariables, std::set const& choiceVariables, std::vector> const& rowColumnMetaVariablePairs, double precision, uint_fast64_t maximalNumberOfIterations, bool relative) : A(A), allRows(allRows), illegalMaskAdd(illegalMask.template toAdd().ite(A.getDdManager().getConstant(storm::utility::infinity()), A.getDdManager().template getAddZero())), rowMetaVariables(rowMetaVariables), columnMetaVariables(columnMetaVariables), choiceVariables(choiceVariables), rowColumnMetaVariablePairs(rowColumnMetaVariablePairs), precision(precision), maximalNumberOfIterations(maximalNumberOfIterations), relative(relative) { + SymbolicMinMaxLinearEquationSolver::SymbolicMinMaxLinearEquationSolver(storm::dd::Add const& A, storm::dd::Bdd const& allRows, storm::dd::Bdd const& illegalMask, std::set const& rowMetaVariables, std::set const& columnMetaVariables, std::set const& choiceVariables, std::vector> const& rowColumnMetaVariablePairs, double precision, uint_fast64_t maximalNumberOfIterations, bool relative) : A(A), allRows(allRows), illegalMaskAdd(illegalMask.ite(A.getDdManager().getConstant(storm::utility::infinity()), A.getDdManager().template getAddZero())), rowMetaVariables(rowMetaVariables), columnMetaVariables(columnMetaVariables), choiceVariables(choiceVariables), rowColumnMetaVariablePairs(rowColumnMetaVariablePairs), precision(precision), maximalNumberOfIterations(maximalNumberOfIterations), relative(relative) { // Intentionally left empty. } template - SymbolicMinMaxLinearEquationSolver::SymbolicMinMaxLinearEquationSolver(storm::dd::Add const& A, storm::dd::Bdd const& allRows, storm::dd::Bdd const& illegalMask, std::set const& rowMetaVariables, std::set const& columnMetaVariables, std::set const& choiceVariables, std::vector> const& rowColumnMetaVariablePairs) : A(A), allRows(allRows), illegalMaskAdd(illegalMask.template toAdd().ite(A.getDdManager().getConstant(storm::utility::infinity()), A.getDdManager().template getAddZero())), rowMetaVariables(rowMetaVariables), columnMetaVariables(columnMetaVariables), choiceVariables(choiceVariables), rowColumnMetaVariablePairs(rowColumnMetaVariablePairs) { + SymbolicMinMaxLinearEquationSolver::SymbolicMinMaxLinearEquationSolver(storm::dd::Add const& A, storm::dd::Bdd const& allRows, storm::dd::Bdd const& illegalMask, std::set const& rowMetaVariables, std::set const& columnMetaVariables, std::set const& choiceVariables, std::vector> const& rowColumnMetaVariablePairs) : A(A), allRows(allRows), illegalMaskAdd(illegalMask.ite(A.getDdManager().getConstant(storm::utility::infinity()), A.getDdManager().template getAddZero())), rowMetaVariables(rowMetaVariables), columnMetaVariables(columnMetaVariables), choiceVariables(choiceVariables), rowColumnMetaVariablePairs(rowColumnMetaVariablePairs) { // Get the settings object to customize solving. storm::settings::modules::NativeEquationSolverSettings const& settings = storm::settings::nativeEquationSolverSettings(); diff --git a/src/storage/dd/Add.cpp b/src/storage/dd/Add.cpp index 0ec72e15f..ecd98c2d9 100644 --- a/src/storage/dd/Add.cpp +++ b/src/storage/dd/Add.cpp @@ -29,13 +29,6 @@ namespace storm { return internalAdd != other.internalAdd; } - template - Add Add::ite(Add const& thenAdd, Add const& elseAdd) const { - std::set metaVariables = Dd::joinMetaVariables(thenAdd, elseAdd); - metaVariables.insert(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end()); - return Add(this->getDdManager(), internalAdd.ite(thenAdd.internalAdd, elseAdd.internalAdd), metaVariables); - } - template Add Add::operator+(Add const& other) const { return Add(this->getDdManager(), internalAdd + other.internalAdd, Dd::joinMetaVariables(*this, other)); @@ -320,7 +313,7 @@ namespace storm { this->addMetaVariable(nameValuePair.first); } - internalAdd = valueEncoding.template toAdd().ite(this->getDdManager().getConstant(targetValue), *this); + internalAdd = valueEncoding.ite(this->getDdManager().getConstant(targetValue), *this); } template diff --git a/src/storage/dd/Add.h b/src/storage/dd/Add.h index 2743b548c..e4d2647df 100644 --- a/src/storage/dd/Add.h +++ b/src/storage/dd/Add.h @@ -65,17 +65,6 @@ namespace storm { */ bool operator!=(Add const& other) const; - /*! - * Performs an if-then-else with the given operands, i.e. maps all valuations that are mapped to a non-zero - * function value to the function values specified by the first DD and all others to the function values - * specified by the second DD. - * - * @param thenDd The ADD specifying the 'then' part. - * @param elseDd The ADD specifying the 'else' part. - * @return The ADD corresponding to the if-then-else of the operands. - */ - Add ite(Add const& thenAdd, Add const& elseAdd) const; - /*! * Adds the two ADDs. * diff --git a/src/storage/dd/Bdd.cpp b/src/storage/dd/Bdd.cpp index 407aa9761..8f176048e 100644 --- a/src/storage/dd/Bdd.cpp +++ b/src/storage/dd/Bdd.cpp @@ -58,6 +58,14 @@ namespace storm { return Bdd(this->getDdManager(), internalBdd.ite(thenBdd.internalBdd, elseBdd.internalBdd), metaVariables); } + template + template + Add Bdd::ite(Add const& thenAdd, Add const& elseAdd) const { + std::set metaVariables = Dd::joinMetaVariables(thenAdd, elseAdd); + metaVariables.insert(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end()); + return Add(this->getDdManager(), internalBdd.ite(thenAdd.internalAdd, elseAdd.internalAdd), metaVariables); + } + template Bdd Bdd::operator||(Bdd const& other) const { return Bdd(this->getDdManager(), internalBdd || other.internalBdd, Dd::joinMetaVariables(*this, other)); @@ -334,6 +342,9 @@ namespace storm { template std::vector Bdd::filterExplicitVector(Odd const& odd, std::vector const& values) const; template std::vector Bdd::filterExplicitVector(Odd const& odd, std::vector const& values) const; + template Add Bdd::ite(Add const& thenAdd, Add const& elseAdd) const; + template Add Bdd::ite(Add const& thenAdd, Add const& elseAdd) const; + template class Bdd; @@ -345,5 +356,8 @@ namespace storm { template std::vector Bdd::filterExplicitVector(Odd const& odd, std::vector const& values) const; template std::vector Bdd::filterExplicitVector(Odd const& odd, std::vector const& values) const; + + template Add Bdd::ite(Add const& thenAdd, Add const& elseAdd) const; + template Add Bdd::ite(Add const& thenAdd, Add const& elseAdd) const; } } \ No newline at end of file diff --git a/src/storage/dd/Bdd.h b/src/storage/dd/Bdd.h index dbe1d3a0b..e7e5e3ab7 100644 --- a/src/storage/dd/Bdd.h +++ b/src/storage/dd/Bdd.h @@ -74,6 +74,17 @@ namespace storm { */ Bdd ite(Bdd const& thenBdd, Bdd const& elseBdd) const; + /*! + * Performs an if-then-else with the given operands, i.e. maps all valuations that are mapped to true to the + * function values specified by the first DD and all others to the function values specified by the second DD. + * + * @param thenAdd The ADD defining the 'then' part. + * @param elseAdd The ADD defining the 'else' part. + * @return The resulting ADD. + */ + template + Add ite(Add const& thenAdd, Add const& elseAdd) const; + /*! * Performs a logical or of the current and the given BDD. * diff --git a/src/storage/dd/cudd/InternalCuddAdd.cpp b/src/storage/dd/cudd/InternalCuddAdd.cpp index 0573a9629..10107ff2c 100644 --- a/src/storage/dd/cudd/InternalCuddAdd.cpp +++ b/src/storage/dd/cudd/InternalCuddAdd.cpp @@ -26,12 +26,7 @@ namespace storm { bool InternalAdd::operator!=(InternalAdd const& other) const { return !(*this == other); } - - template - InternalAdd InternalAdd::ite(InternalAdd const& thenDd, InternalAdd const& elseDd) const { - return InternalAdd(ddManager, this->getCuddAdd().Ite(thenDd.getCuddAdd(), elseDd.getCuddAdd())); - } - + template InternalAdd InternalAdd::operator+(InternalAdd const& other) const { return InternalAdd(ddManager, this->getCuddAdd() + other.getCuddAdd()); diff --git a/src/storage/dd/cudd/InternalCuddAdd.h b/src/storage/dd/cudd/InternalCuddAdd.h index e235a4e6d..73512ad38 100644 --- a/src/storage/dd/cudd/InternalCuddAdd.h +++ b/src/storage/dd/cudd/InternalCuddAdd.h @@ -42,6 +42,8 @@ namespace storm { template class InternalAdd { public: + friend class InternalBdd; + /*! * Creates an ADD that encapsulates the given CUDD ADD. * @@ -73,17 +75,6 @@ namespace storm { */ bool operator!=(InternalAdd const& other) const; - /*! - * Performs an if-then-else with the given operands, i.e. maps all valuations that are mapped to a non-zero - * function value to the function values specified by the first DD and all others to the function values - * specified by the second DD. - * - * @param thenDd The ADD specifying the 'then' part. - * @param elseDd The ADD specifying the 'else' part. - * @return The ADD corresponding to the if-then-else of the operands. - */ - InternalAdd ite(InternalAdd const& thenAdd, InternalAdd const& elseAdd) const; - /*! * Adds the two ADDs. * diff --git a/src/storage/dd/cudd/InternalCuddBdd.cpp b/src/storage/dd/cudd/InternalCuddBdd.cpp index e70b97dc2..ce285fc1d 100644 --- a/src/storage/dd/cudd/InternalCuddBdd.cpp +++ b/src/storage/dd/cudd/InternalCuddBdd.cpp @@ -58,6 +58,11 @@ namespace storm { return InternalBdd(ddManager, this->getCuddBdd().Ite(thenDd.getCuddBdd(), elseDd.getCuddBdd())); } + template + InternalAdd InternalBdd::ite(InternalAdd const& thenAdd, InternalAdd const& elseAdd) const { + return InternalAdd(ddManager, this->getCuddBdd().Add().Ite(thenAdd.getCuddAdd(), elseAdd.getCuddAdd())); + } + InternalBdd InternalBdd::operator||(InternalBdd const& other) const { InternalBdd result(*this); result |= other; @@ -413,5 +418,8 @@ namespace storm { template void InternalBdd::filterExplicitVector(Odd const& odd, std::vector const& ddVariableIndices, std::vector const& sourceValues, std::vector& targetValues) const; template void InternalBdd::filterExplicitVector(Odd const& odd, std::vector const& ddVariableIndices, std::vector const& sourceValues, std::vector& targetValues) const; + + template InternalAdd InternalBdd::ite(InternalAdd const& thenAdd, InternalAdd const& elseAdd) const; + template InternalAdd InternalBdd::ite(InternalAdd const& thenAdd, InternalAdd const& elseAdd) const; } } \ No newline at end of file diff --git a/src/storage/dd/cudd/InternalCuddBdd.h b/src/storage/dd/cudd/InternalCuddBdd.h index 2855d71c1..6ab068681 100644 --- a/src/storage/dd/cudd/InternalCuddBdd.h +++ b/src/storage/dd/cudd/InternalCuddBdd.h @@ -120,6 +120,17 @@ namespace storm { */ InternalBdd ite(InternalBdd const& thenBdd, InternalBdd const& elseBdd) const; + /*! + * Performs an if-then-else with the given operands, i.e. maps all valuations that are mapped to true to the + * function values specified by the first DD and all others to the function values specified by the second DD. + * + * @param thenAdd The ADD defining the 'then' part. + * @param elseAdd The ADD defining the 'else' part. + * @return The resulting ADD. + */ + template + InternalAdd ite(InternalAdd const& thenAdd, InternalAdd const& elseAdd) const; + /*! * Performs a logical or of the current and the given BDD. * diff --git a/src/storage/dd/sylvan/InternalSylvanAdd.cpp b/src/storage/dd/sylvan/InternalSylvanAdd.cpp index 30fa65a59..fb9834aaa 100644 --- a/src/storage/dd/sylvan/InternalSylvanAdd.cpp +++ b/src/storage/dd/sylvan/InternalSylvanAdd.cpp @@ -26,12 +26,7 @@ namespace storm { bool InternalAdd::operator!=(InternalAdd const& other) const { return this->sylvanMtbdd != other.sylvanMtbdd; } - - template - InternalAdd InternalAdd::ite(InternalAdd const& thenDd, InternalAdd const& elseDd) const { - return InternalAdd(ddManager, sylvan::Mtbdd(static_cast(this->sylvanMtbdd.NotZero().GetBDD())).Ite(thenDd.sylvanMtbdd, elseDd.sylvanMtbdd)); - } - + template InternalAdd InternalAdd::operator+(InternalAdd const& other) const { return InternalAdd(ddManager, this->sylvanMtbdd.Plus(other.sylvanMtbdd)); diff --git a/src/storage/dd/sylvan/InternalSylvanAdd.h b/src/storage/dd/sylvan/InternalSylvanAdd.h index 9aafc630e..f45fb6aa5 100644 --- a/src/storage/dd/sylvan/InternalSylvanAdd.h +++ b/src/storage/dd/sylvan/InternalSylvanAdd.h @@ -41,6 +41,7 @@ namespace storm { class InternalAdd { public: friend class AddIterator; + friend class InternalBdd; /*! * Creates an ADD that encapsulates the given Sylvan MTBDD. @@ -72,17 +73,6 @@ namespace storm { * @return True if the DDs represent the different functions. */ bool operator!=(InternalAdd const& other) const; - - /*! - * Performs an if-then-else with the given operands, i.e. maps all valuations that are mapped to a non-zero - * function value to the function values specified by the first DD and all others to the function values - * specified by the second DD. - * - * @param thenDd The ADD specifying the 'then' part. - * @param elseDd The ADD specifying the 'else' part. - * @return The ADD corresponding to the if-then-else of the operands. - */ - InternalAdd ite(InternalAdd const& thenAdd, InternalAdd const& elseAdd) const; /*! * Adds the two ADDs. diff --git a/src/storage/dd/sylvan/InternalSylvanBdd.cpp b/src/storage/dd/sylvan/InternalSylvanBdd.cpp index 57e2635fa..4d580cfeb 100644 --- a/src/storage/dd/sylvan/InternalSylvanBdd.cpp +++ b/src/storage/dd/sylvan/InternalSylvanBdd.cpp @@ -107,6 +107,11 @@ namespace storm { return InternalBdd(ddManager, this->sylvanBdd.Ite(thenDd.sylvanBdd, elseDd.sylvanBdd)); } + template + InternalAdd InternalBdd::ite(InternalAdd const& thenAdd, InternalAdd const& elseAdd) const { + return InternalAdd(ddManager, this->sylvanBdd.Ite(thenAdd.getSylvanMtbdd(), elseAdd.getSylvanMtbdd())); + } + InternalBdd InternalBdd::operator||(InternalBdd const& other) const { return InternalBdd(ddManager, this->sylvanBdd | other.sylvanBdd); } @@ -382,5 +387,9 @@ namespace storm { template void InternalBdd::filterExplicitVector(Odd const& odd, std::vector const& ddVariableIndices, std::vector const& sourceValues, std::vector& targetValues) const; template void InternalBdd::filterExplicitVector(Odd const& odd, std::vector const& ddVariableIndices, std::vector const& sourceValues, std::vector& targetValues) const; + + template InternalAdd InternalBdd::ite(InternalAdd const& thenAdd, InternalAdd const& elseAdd) const; + template InternalAdd InternalBdd::ite(InternalAdd const& thenAdd, InternalAdd const& elseAdd) const; + } } \ No newline at end of file diff --git a/src/storage/dd/sylvan/InternalSylvanBdd.h b/src/storage/dd/sylvan/InternalSylvanBdd.h index b1effdf47..fba511223 100644 --- a/src/storage/dd/sylvan/InternalSylvanBdd.h +++ b/src/storage/dd/sylvan/InternalSylvanBdd.h @@ -108,6 +108,17 @@ namespace storm { */ InternalBdd ite(InternalBdd const& thenBdd, InternalBdd const& elseBdd) const; + /*! + * Performs an if-then-else with the given operands, i.e. maps all valuations that are mapped to true to the + * function values specified by the first DD and all others to the function values specified by the second DD. + * + * @param thenAdd The ADD defining the 'then' part. + * @param elseAdd The ADD defining the 'else' part. + * @return The resulting ADD. + */ + template + InternalAdd ite(InternalAdd const& thenAdd, InternalAdd const& elseAdd) const; + /*! * Performs a logical or of the current and the given BDD. * diff --git a/test/functional/storage/CuddDdTest.cpp b/test/functional/storage/CuddDdTest.cpp index 18742b688..279fa4dd0 100644 --- a/test/functional/storage/CuddDdTest.cpp +++ b/test/functional/storage/CuddDdTest.cpp @@ -164,7 +164,7 @@ TEST(CuddDd, OperatorTest) { dd3 = dd1.greaterOrEqual(dd2).template toAdd(); EXPECT_EQ(5ul, dd3.getNonZeroCount()); - dd3 = (manager->getEncoding(x.first, 2).template toAdd()).ite(dd2, dd1); + dd3 = manager->getEncoding(x.first, 2).ite(dd2, dd1); dd4 = dd3.less(dd2).template toAdd(); EXPECT_EQ(10ul, dd4.getNonZeroCount()); @@ -296,7 +296,7 @@ TEST(CuddDd, AddIteratorTest) { EXPECT_EQ(9ul, numberOfValuations); dd = manager->getRange(x.first).template toAdd(); - dd = dd.ite(manager->template getAddOne(), manager->template getAddOne()); + dd = dd.notZero().ite(manager->template getAddOne(), manager->template getAddOne()); ASSERT_NO_THROW(it = dd.begin()); ASSERT_NO_THROW(ite = dd.end()); numberOfValuations = 0; @@ -354,7 +354,7 @@ TEST(CuddDd, AddOddTest) { EXPECT_EQ(9ul, matrix.getColumnCount()); EXPECT_EQ(25ul, matrix.getNonzeroEntryCount()); - dd = manager->getRange(x.first).template toAdd() * manager->getRange(x.second).template toAdd() * manager->getEncoding(a.first, 0).template toAdd().ite(dd, dd + manager->template getConstant(1)); + dd = manager->getRange(x.first).template toAdd() * manager->getRange(x.second).template toAdd() * manager->getEncoding(a.first, 0).ite(dd, dd + manager->template getConstant(1)); ASSERT_NO_THROW(matrix = dd.toMatrix({a.first}, rowOdd, columnOdd)); EXPECT_EQ(18ul, matrix.getRowCount()); EXPECT_EQ(9ul, matrix.getRowGroupCount()); @@ -401,7 +401,7 @@ TEST(CuddDd, BddOddTest) { EXPECT_EQ(9ul, matrix.getColumnCount()); EXPECT_EQ(25ul, matrix.getNonzeroEntryCount()); - dd = manager->getRange(x.first).template toAdd() * manager->getRange(x.second).template toAdd() * manager->getEncoding(a.first, 0).template toAdd().ite(dd, dd + manager->template getConstant(1)); + dd = manager->getRange(x.first).template toAdd() * manager->getRange(x.second).template toAdd() * manager->getEncoding(a.first, 0).ite(dd, dd + manager->template getConstant(1)); ASSERT_NO_THROW(matrix = dd.toMatrix({a.first}, rowOdd, columnOdd)); EXPECT_EQ(18ul, matrix.getRowCount()); EXPECT_EQ(9ul, matrix.getRowGroupCount()); diff --git a/test/functional/storage/SylvanDdTest.cpp b/test/functional/storage/SylvanDdTest.cpp index 85a152cff..fdb60e5c0 100644 --- a/test/functional/storage/SylvanDdTest.cpp +++ b/test/functional/storage/SylvanDdTest.cpp @@ -168,7 +168,7 @@ TEST(SylvanDd, OperatorTest) { bdd = dd1.greaterOrEqual(dd2); EXPECT_EQ(5ul, bdd.getNonZeroCount()); - dd3 = (manager->getEncoding(x.first, 2).template toAdd()).ite(dd2, dd1); + dd3 = manager->getEncoding(x.first, 2).ite(dd2, dd1); bdd = dd3.less(dd2); EXPECT_EQ(10ul, bdd.getNonZeroCount()); @@ -300,7 +300,7 @@ TEST(SylvanDd, AddIteratorTest) { EXPECT_EQ(9ul, numberOfValuations); dd = manager->getRange(x.first).template toAdd(); - dd = dd.ite(manager->template getAddOne(), manager->template getAddOne()); + dd = dd.notZero().ite(manager->template getAddOne(), manager->template getAddOne()); ASSERT_NO_THROW(it = dd.begin()); ASSERT_NO_THROW(ite = dd.end()); numberOfValuations = 0; @@ -358,7 +358,7 @@ TEST(SylvanDd, AddOddTest) { EXPECT_EQ(9ul, matrix.getColumnCount()); EXPECT_EQ(25ul, matrix.getNonzeroEntryCount()); - dd = manager->getRange(x.first).template toAdd() * manager->getRange(x.second).template toAdd() * manager->getEncoding(a.first, 0).template toAdd().ite(dd, dd + manager->template getConstant(1)); + dd = manager->getRange(x.first).template toAdd() * manager->getRange(x.second).template toAdd() * manager->getEncoding(a.first, 0).ite(dd, dd + manager->template getConstant(1)); ASSERT_NO_THROW(matrix = dd.toMatrix({a.first}, rowOdd, columnOdd)); EXPECT_EQ(18ul, matrix.getRowCount()); EXPECT_EQ(9ul, matrix.getRowGroupCount()); @@ -405,7 +405,7 @@ TEST(SylvanDd, BddOddTest) { EXPECT_EQ(9ul, matrix.getColumnCount()); EXPECT_EQ(25ul, matrix.getNonzeroEntryCount()); - dd = manager->getRange(x.first).template toAdd() * manager->getRange(x.second).template toAdd() * manager->getEncoding(a.first, 0).template toAdd().ite(dd, dd + manager->template getConstant(1)); + dd = manager->getRange(x.first).template toAdd() * manager->getRange(x.second).template toAdd() * manager->getEncoding(a.first, 0).ite(dd, dd + manager->template getConstant(1)); ASSERT_NO_THROW(matrix = dd.toMatrix({a.first}, rowOdd, columnOdd)); EXPECT_EQ(18ul, matrix.getRowCount()); EXPECT_EQ(9ul, matrix.getRowGroupCount());