diff --git a/src/adapters/DdExpressionAdapter.cpp b/src/adapters/AddExpressionAdapter.cpp
similarity index 60%
rename from src/adapters/DdExpressionAdapter.cpp
rename to src/adapters/AddExpressionAdapter.cpp
index e33fb40b9..12677b85e 100644
--- a/src/adapters/DdExpressionAdapter.cpp
+++ b/src/adapters/AddExpressionAdapter.cpp
@@ -1,4 +1,4 @@
-#include "src/adapters/DdExpressionAdapter.h"
+#include "src/adapters/AddExpressionAdapter.h"
 
 #include "src/utility/macros.h"
 #include "src/exceptions/ExpressionEvaluationException.h"
@@ -9,44 +9,44 @@ namespace storm {
     namespace adapters {
         
         template<storm::dd::DdType Type>
-        DdExpressionAdapter<Type>::DdExpressionAdapter(std::shared_ptr<storm::dd::DdManager<Type>> ddManager, std::map<storm::expressions::Variable, storm::expressions::Variable> const& variableMapping) : ddManager(ddManager), variableMapping(variableMapping) {
+        AddExpressionAdapter<Type>::AddExpressionAdapter(std::shared_ptr<storm::dd::DdManager<Type>> ddManager, std::map<storm::expressions::Variable, storm::expressions::Variable> const& variableMapping) : ddManager(ddManager), variableMapping(variableMapping) {
             // Intentionally left empty.
         }
         
         template<storm::dd::DdType Type>
-        storm::dd::Dd<Type> DdExpressionAdapter<Type>::translateExpression(storm::expressions::Expression const& expression) {
-            return boost::any_cast<storm::dd::Dd<Type>>(expression.accept(*this));
+        storm::dd::Add<Type> AddExpressionAdapter<Type>::translateExpression(storm::expressions::Expression const& expression) {
+            return boost::any_cast<storm::dd::Add<Type>>(expression.accept(*this));
         }
         
         template<storm::dd::DdType Type>
-        boost::any DdExpressionAdapter<Type>::visit(storm::expressions::IfThenElseExpression const& expression) {
-            storm::dd::Dd<Type> elseDd = boost::any_cast<storm::dd::Dd<Type>>(expression.getElseExpression()->accept(*this));
-            storm::dd::Dd<Type> thenDd = boost::any_cast<storm::dd::Dd<Type>>(expression.getThenExpression()->accept(*this));
-            storm::dd::Dd<Type> conditionDd = boost::any_cast<storm::dd::Dd<Type>>(expression.getCondition()->accept(*this));
+        boost::any AddExpressionAdapter<Type>::visit(storm::expressions::IfThenElseExpression const& expression) {
+            storm::dd::Add<Type> elseDd = boost::any_cast<storm::dd::Add<Type>>(expression.getElseExpression()->accept(*this));
+            storm::dd::Add<Type> thenDd = boost::any_cast<storm::dd::Add<Type>>(expression.getThenExpression()->accept(*this));
+            storm::dd::Add<Type> conditionDd = boost::any_cast<storm::dd::Add<Type>>(expression.getCondition()->accept(*this));
             return conditionDd.ite(thenDd, elseDd);
         }
         
         template<storm::dd::DdType Type>
-        boost::any DdExpressionAdapter<Type>::visit(storm::expressions::BinaryBooleanFunctionExpression const& expression) {
-            storm::dd::Dd<Type> leftResult = boost::any_cast<storm::dd::Dd<Type>>(expression.getFirstOperand()->accept(*this));
-            storm::dd::Dd<Type> rightResult = boost::any_cast<storm::dd::Dd<Type>>(expression.getSecondOperand()->accept(*this));
+        boost::any AddExpressionAdapter<Type>::visit(storm::expressions::BinaryBooleanFunctionExpression const& expression) {
+            storm::dd::Bdd<Type> leftResult = boost::any_cast<storm::dd::Add<Type>>(expression.getFirstOperand()->accept(*this)).toBdd();
+            storm::dd::Bdd<Type> rightResult = boost::any_cast<storm::dd::Add<Type>>(expression.getSecondOperand()->accept(*this)).toBdd();
             
-            storm::dd::Dd<Type> result;
+            storm::dd::Add<Type> result;
             switch (expression.getOperatorType()) {
                 case storm::expressions::BinaryBooleanFunctionExpression::OperatorType::And:
-                    result = leftResult && rightResult;
+                    result = (leftResult && rightResult).toAdd();
                     break;
                 case storm::expressions::BinaryBooleanFunctionExpression::OperatorType::Or:
-                    result = leftResult || rightResult;
+                    result = (leftResult || rightResult).toAdd();
                     break;
                 case storm::expressions::BinaryBooleanFunctionExpression::OperatorType::Iff:
-                    result = leftResult.iff(rightResult);
+                    result = (leftResult.iff(rightResult)).toAdd();
                     break;
                 case storm::expressions::BinaryBooleanFunctionExpression::OperatorType::Implies:
-                    result = !leftResult || rightResult;
+                    result = (!leftResult || rightResult).toAdd();
                     break;
                 case storm::expressions::BinaryBooleanFunctionExpression::OperatorType::Xor:
-                    result = leftResult.exclusiveOr(rightResult);
+                    result = (leftResult.exclusiveOr(rightResult)).toAdd();
                     break;
             }
             
@@ -54,11 +54,11 @@ namespace storm {
         }
         
         template<storm::dd::DdType Type>
-        boost::any DdExpressionAdapter<Type>::visit(storm::expressions::BinaryNumericalFunctionExpression const& expression) {
-            storm::dd::Dd<Type> leftResult = boost::any_cast<storm::dd::Dd<Type>>(expression.getFirstOperand()->accept(*this));
-            storm::dd::Dd<Type> rightResult = boost::any_cast<storm::dd::Dd<Type>>(expression.getSecondOperand()->accept(*this));
+        boost::any AddExpressionAdapter<Type>::visit(storm::expressions::BinaryNumericalFunctionExpression const& expression) {
+            storm::dd::Add<Type> leftResult = boost::any_cast<storm::dd::Add<Type>>(expression.getFirstOperand()->accept(*this));
+            storm::dd::Add<Type> rightResult = boost::any_cast<storm::dd::Add<Type>>(expression.getSecondOperand()->accept(*this));
             
-            storm::dd::Dd<Type> result;
+            storm::dd::Add<Type> result;
             switch (expression.getOperatorType()) {
                 case storm::expressions::BinaryNumericalFunctionExpression::OperatorType::Plus:
                     result = leftResult + rightResult;
@@ -86,11 +86,11 @@ namespace storm {
         }
         
         template<storm::dd::DdType Type>
-        boost::any DdExpressionAdapter<Type>::visit(storm::expressions::BinaryRelationExpression const& expression) {
-            storm::dd::Dd<Type> leftResult = boost::any_cast<storm::dd::Dd<Type>>(expression.getFirstOperand()->accept(*this));
-            storm::dd::Dd<Type> rightResult = boost::any_cast<storm::dd::Dd<Type>>(expression.getSecondOperand()->accept(*this));
+        boost::any AddExpressionAdapter<Type>::visit(storm::expressions::BinaryRelationExpression const& expression) {
+            storm::dd::Add<Type> leftResult = boost::any_cast<storm::dd::Add<Type>>(expression.getFirstOperand()->accept(*this));
+            storm::dd::Add<Type> rightResult = boost::any_cast<storm::dd::Add<Type>>(expression.getSecondOperand()->accept(*this));
 
-            storm::dd::Dd<Type> result;
+            storm::dd::Add<Type> result;
             switch (expression.getRelationType()) {
                 case storm::expressions::BinaryRelationExpression::RelationType::Equal:
                     result = leftResult.equals(rightResult);
@@ -116,15 +116,15 @@ namespace storm {
         }
         
         template<storm::dd::DdType Type>
-        boost::any DdExpressionAdapter<Type>::visit(storm::expressions::VariableExpression const& expression) {
+        boost::any AddExpressionAdapter<Type>::visit(storm::expressions::VariableExpression const& expression) {
             auto const& variablePair = variableMapping.find(expression.getVariable());
             STORM_LOG_THROW(variablePair != variableMapping.end(), storm::exceptions::InvalidArgumentException, "Cannot translate the given expression, because it contains the variable '" << expression.getVariableName() << "' for which no DD counterpart is known.");
             return ddManager->getIdentity(variablePair->second);
         }
         
         template<storm::dd::DdType Type>
-        boost::any DdExpressionAdapter<Type>::visit(storm::expressions::UnaryBooleanFunctionExpression const& expression) {
-            storm::dd::Dd<Type> result = boost::any_cast<storm::dd::Dd<Type>>(expression.getOperand()->accept(*this));
+        boost::any AddExpressionAdapter<Type>::visit(storm::expressions::UnaryBooleanFunctionExpression const& expression) {
+            storm::dd::Bdd<Type> result = boost::any_cast<storm::dd::Add<Type>>(expression.getOperand()->accept(*this)).toBdd();
             
             switch (expression.getOperatorType()) {
                 case storm::expressions::UnaryBooleanFunctionExpression::OperatorType::Not:
@@ -132,12 +132,12 @@ namespace storm {
                     break;
             }
             
-            return result;
+            return result.toAdd();
         }
         
         template<storm::dd::DdType Type>
-        boost::any DdExpressionAdapter<Type>::visit(storm::expressions::UnaryNumericalFunctionExpression const& expression) {
-            storm::dd::Dd<Type> result = boost::any_cast<storm::dd::Dd<Type>>(expression.getOperand()->accept(*this));
+        boost::any AddExpressionAdapter<Type>::visit(storm::expressions::UnaryNumericalFunctionExpression const& expression) {
+            storm::dd::Add<Type> result = boost::any_cast<storm::dd::Add<Type>>(expression.getOperand()->accept(*this));
             
             switch (expression.getOperatorType()) {
                 case storm::expressions::UnaryNumericalFunctionExpression::OperatorType::Minus:
@@ -151,22 +151,22 @@ namespace storm {
         }
         
         template<storm::dd::DdType Type>
-        boost::any DdExpressionAdapter<Type>::visit(storm::expressions::BooleanLiteralExpression const& expression) {
+        boost::any AddExpressionAdapter<Type>::visit(storm::expressions::BooleanLiteralExpression const& expression) {
             return ddManager->getConstant(expression.getValue());
         }
         
         template<storm::dd::DdType Type>
-        boost::any DdExpressionAdapter<Type>::visit(storm::expressions::IntegerLiteralExpression const& expression) {
+        boost::any AddExpressionAdapter<Type>::visit(storm::expressions::IntegerLiteralExpression const& expression) {
             return ddManager->getConstant(expression.getValue());
         }
         
         template<storm::dd::DdType Type>
-        boost::any DdExpressionAdapter<Type>::visit(storm::expressions::DoubleLiteralExpression const& expression) {
+        boost::any AddExpressionAdapter<Type>::visit(storm::expressions::DoubleLiteralExpression const& expression) {
             return ddManager->getConstant(expression.getValue());
         }
         
         // Explicitly instantiate the symbolic expression adapter
-        template class DdExpressionAdapter<storm::dd::DdType::CUDD>;
+        template class AddExpressionAdapter<storm::dd::DdType::CUDD>;
         
     } // namespace adapters
 } // namespace storm
diff --git a/src/adapters/DdExpressionAdapter.h b/src/adapters/AddExpressionAdapter.h
similarity index 83%
rename from src/adapters/DdExpressionAdapter.h
rename to src/adapters/AddExpressionAdapter.h
index cba1c422b..8225556f1 100644
--- a/src/adapters/DdExpressionAdapter.h
+++ b/src/adapters/AddExpressionAdapter.h
@@ -5,18 +5,18 @@
 #include "src/storage/expressions/Expressions.h"
 #include "storage/expressions/ExpressionVisitor.h"
 
-#include "src/storage/dd/Dd.h"
+#include "src/storage/dd/Add.h"
 #include "src/storage/dd/DdManager.h"
 
 namespace storm {
     namespace adapters {
         
         template<storm::dd::DdType Type>
-        class DdExpressionAdapter : public storm::expressions::ExpressionVisitor {
+        class AddExpressionAdapter : public storm::expressions::ExpressionVisitor {
         public:
-            DdExpressionAdapter(std::shared_ptr<storm::dd::DdManager<Type>> ddManager, std::map<storm::expressions::Variable, storm::expressions::Variable> const& variableMapping);
+            AddExpressionAdapter(std::shared_ptr<storm::dd::DdManager<Type>> ddManager, std::map<storm::expressions::Variable, storm::expressions::Variable> const& variableMapping);
             
-            storm::dd::Dd<Type> translateExpression(storm::expressions::Expression const& expression);
+            storm::dd::Add<Type> translateExpression(storm::expressions::Expression const& expression);
             
             virtual boost::any visit(storm::expressions::IfThenElseExpression const& expression) override;
             virtual boost::any visit(storm::expressions::BinaryBooleanFunctionExpression const& expression) override;
diff --git a/src/builder/DdPrismModelBuilder.cpp b/src/builder/DdPrismModelBuilder.cpp
index 74508e763..ec80e6dd6 100644
--- a/src/builder/DdPrismModelBuilder.cpp
+++ b/src/builder/DdPrismModelBuilder.cpp
@@ -52,8 +52,8 @@ namespace storm {
         }
         
         template <storm::dd::DdType Type>
-        storm::dd::Dd<Type> DdPrismModelBuilder<Type>::createUpdateDecisionDiagram(GenerationInformation& generationInfo, storm::prism::Module const& module, storm::dd::Dd<Type> const& guard, storm::prism::Update const& update) {
-            storm::dd::Dd<Type> updateDd = generationInfo.manager->getOne(true);
+        storm::dd::Add<Type> DdPrismModelBuilder<Type>::createUpdateDecisionDiagram(GenerationInformation& generationInfo, storm::prism::Module const& module, storm::dd::Add<Type> const& guard, storm::prism::Update const& update) {
+            storm::dd::Add<Type> updateDd = generationInfo.manager->getAddOne();
             
             STORM_LOG_TRACE("Translating update " << update);
             
@@ -67,20 +67,20 @@ namespace storm {
                 
                 // Translate the written variable.
                 auto const& primedMetaVariable = generationInfo.variableToColumnMetaVariableMap.at(assignment.getVariable());
-                storm::dd::Dd<Type> writtenVariable = generationInfo.manager->getIdentity(primedMetaVariable);
+                storm::dd::Add<Type> writtenVariable = generationInfo.manager->getIdentity(primedMetaVariable);
                 
                 // Translate the expression that is being assigned.
-                storm::dd::Dd<Type> updateExpression = generationInfo.rowExpressionAdapter->translateExpression(assignment.getExpression());
+                storm::dd::Add<Type> updateExpression = generationInfo.rowExpressionAdapter->translateExpression(assignment.getExpression());
                 
                 // Combine the update expression with the guard.
-                storm::dd::Dd<Type> result = updateExpression * guard;
+                storm::dd::Add<Type> result = updateExpression * guard;
                 
                 // Combine the variable and the assigned expression.
                 result = result.equals(writtenVariable);
                 result *= guard;
                 
                 // Restrict the transitions to the range of the written variable.
-                result = result * generationInfo.manager->getRange(primedMetaVariable, true);
+                result = result * generationInfo.manager->getRange(primedMetaVariable).toAdd();
                 
                 updateDd *= result;
             }
@@ -129,17 +129,17 @@ namespace storm {
         template <storm::dd::DdType Type>
         typename DdPrismModelBuilder<Type>::ActionDecisionDiagram DdPrismModelBuilder<Type>::createCommandDecisionDiagram(GenerationInformation& generationInfo, storm::prism::Module const& module, storm::prism::Command const& command) {
             STORM_LOG_TRACE("Translating guard " << command.getGuardExpression());
-            storm::dd::Dd<Type> guardDd = generationInfo.rowExpressionAdapter->translateExpression(command.getGuardExpression()) * generationInfo.moduleToRangeMap[module.getName()];
+            storm::dd::Add<Type> guardDd = generationInfo.rowExpressionAdapter->translateExpression(command.getGuardExpression()) * generationInfo.moduleToRangeMap[module.getName()];
             STORM_LOG_WARN_COND(!guardDd.isZero(), "The guard '" << command.getGuardExpression() << "' is unsatisfiable.");
             
             if (!guardDd.isZero()) {
-                storm::dd::Dd<Type> commandDd = generationInfo.manager->getZero(true);
+                storm::dd::Add<Type> commandDd = generationInfo.manager->getAddZero();
                 for (storm::prism::Update const& update : command.getUpdates()) {
-                    storm::dd::Dd<Type> updateDd = createUpdateDecisionDiagram(generationInfo, module, guardDd, update);
+                    storm::dd::Add<Type> updateDd = createUpdateDecisionDiagram(generationInfo, module, guardDd, update);
                     
                     STORM_LOG_WARN_COND(!updateDd.isZero(), "Update '" << update << "' does not have any effect.");
                     
-                    storm::dd::Dd<Type> probabilityDd = generationInfo.rowExpressionAdapter->translateExpression(update.getLikelihoodExpression());
+                    storm::dd::Add<Type> probabilityDd = generationInfo.rowExpressionAdapter->translateExpression(update.getLikelihoodExpression());
                     updateDd *= probabilityDd;
                     
                     commandDd += updateDd;
@@ -186,9 +186,9 @@ namespace storm {
         
         template <storm::dd::DdType Type>
         typename DdPrismModelBuilder<Type>::ActionDecisionDiagram DdPrismModelBuilder<Type>::combineCommandsToActionDTMC(GenerationInformation& generationInfo, std::vector<ActionDecisionDiagram> const& commandDds) {
-            storm::dd::Dd<Type> allGuards = generationInfo.manager->getZero(true);
-            storm::dd::Dd<Type> allCommands = generationInfo.manager->getZero(true);
-            storm::dd::Dd<Type> temporary;
+            storm::dd::Add<Type> allGuards = generationInfo.manager->getAddZero();
+            storm::dd::Add<Type> allCommands = generationInfo.manager->getAddZero();
+            storm::dd::Add<Type> temporary;
             
             for (auto const& commandDd : commandDds) {
                 // Check for overlapping guards.
@@ -203,8 +203,8 @@ namespace storm {
         }
         
         template <storm::dd::DdType Type>
-        storm::dd::Dd<Type> DdPrismModelBuilder<Type>::encodeChoice(GenerationInformation& generationInfo, uint_fast64_t nondeterminismVariableOffset, uint_fast64_t numberOfBinaryVariables, int_fast64_t value) {
-            storm::dd::Dd<Type> result = generationInfo.manager->getZero(true);
+        storm::dd::Add<Type> DdPrismModelBuilder<Type>::encodeChoice(GenerationInformation& generationInfo, uint_fast64_t nondeterminismVariableOffset, uint_fast64_t numberOfBinaryVariables, int_fast64_t value) {
+            storm::dd::Add<Type> result = generationInfo.manager->getAddZero();
             
             STORM_LOG_TRACE("Encoding " << value << " with " << numberOfBinaryVariables << " binary variable(s) starting from offset " << nondeterminismVariableOffset << ".");
             
@@ -223,11 +223,11 @@ namespace storm {
         
         template <storm::dd::DdType Type>
         typename DdPrismModelBuilder<Type>::ActionDecisionDiagram DdPrismModelBuilder<Type>::combineCommandsToActionMDP(GenerationInformation& generationInfo, std::vector<ActionDecisionDiagram> const& commandDds, uint_fast64_t nondeterminismVariableOffset) {
-            storm::dd::Dd<Type> allGuards = generationInfo.manager->getZero(true);
-            storm::dd::Dd<Type> allCommands = generationInfo.manager->getZero(true);
+            storm::dd::Add<Type> allGuards = generationInfo.manager->getAddZero();
+            storm::dd::Add<Type> allCommands = generationInfo.manager->getAddZero();
             
             // Sum all guards, so we can read off the maximal number of nondeterministic choices in any given state.
-            storm::dd::Dd<Type> sumOfGuards = generationInfo.manager->getZero(true);
+            storm::dd::Add<Type> sumOfGuards = generationInfo.manager->getAddZero();
             for (auto const& commandDd : commandDds) {
                 sumOfGuards += commandDd.guardDd;
                 allGuards = allGuards || commandDd.guardDd;
@@ -242,17 +242,16 @@ namespace storm {
             } else if (maxChoices == 1) {
                 // Sum up all commands.
                 for (auto const& commandDd : commandDds) {
-                    // FIXME: necessary to multiply with guard again?
-                    allCommands += commandDd.guardDd * commandDd.transitionsDd;
+                    allCommands += commandDd.transitionsDd;
                 }
                 return ActionDecisionDiagram(sumOfGuards, allCommands);
             } else {
                 // Calculate number of required variables to encode the nondeterminism.
                 uint_fast64_t numberOfBinaryVariables = static_cast<uint_fast64_t>(std::ceil(storm::utility::math::log2(maxChoices)));
                 
-                storm::dd::Dd<Type> equalsNumberOfChoicesDd = generationInfo.manager->getZero(true);
-                std::vector<storm::dd::Dd<Type>> choiceDds(maxChoices, generationInfo.manager->getZero(true));
-                std::vector<storm::dd::Dd<Type>> remainingDds(maxChoices, generationInfo.manager->getZero(true));
+                storm::dd::Add<Type> equalsNumberOfChoicesDd = generationInfo.manager->getAddZero();
+                std::vector<storm::dd::Add<Type>> choiceDds(maxChoices, generationInfo.manager->getAddZero());
+                std::vector<storm::dd::Add<Type>> remainingDds(maxChoices, generationInfo.manager->getAddZero());
                 
                 for (uint_fast64_t currentChoices = 1; currentChoices <= maxChoices; ++currentChoices) {
                     // Determine the set of states with exactly currentChoices choices.
@@ -265,14 +264,14 @@ namespace storm {
                     
                     // Reset the previously used intermediate storage.
                     for (uint_fast64_t j = 0; j < currentChoices; ++j) {
-                        choiceDds[j] = generationInfo.manager->getZero(true);
+                        choiceDds[j] = generationInfo.manager->getAddZero();
                         remainingDds[j] = equalsNumberOfChoicesDd;
                     }
                     
                     for (std::size_t j = 0; j < commandDds.size(); ++j) {
                         // Check if command guard overlaps with equalsNumberOfChoicesDd. That is, there are states with exactly currentChoices
                         // choices such that one outgoing choice is given by the j-th command.
-                        storm::dd::Dd<Type> guardChoicesIntersection = commandDds[j].guardDd && equalsNumberOfChoicesDd;
+                        storm::dd::Add<Type> guardChoicesIntersection = commandDds[j].guardDd * equalsNumberOfChoicesDd;
                         
                         // If there is no such state, continue with the next command.
                         if (guardChoicesIntersection.isZero()) {
@@ -282,19 +281,19 @@ namespace storm {
                         // Split the currentChoices nondeterministic choices.
                         for (uint_fast64_t k = 0; k < currentChoices; ++k) {
                             // Calculate the overlapping part of command guard and the remaining DD.
-                            storm::dd::Dd<Type> remainingGuardChoicesIntersection = guardChoicesIntersection && remainingDds[k];
+                            storm::dd::Add<Type> remainingGuardChoicesIntersection = guardChoicesIntersection * remainingDds[k];
                             
                             // Check if we can add some overlapping parts to the current index.
                             if (!remainingGuardChoicesIntersection.isZero()) {
                                 // Remove overlapping parts from the remaining DD.
-                                remainingDds[k] = remainingDds[k] && !remainingGuardChoicesIntersection;
+                                remainingDds[k] = remainingDds[k] * !remainingGuardChoicesIntersection;
                                 
                                 // Combine the overlapping part of the guard with command updates and add it to the resulting DD.
                                 choiceDds[k] += remainingGuardChoicesIntersection * commandDds[j].transitionsDd;
                             }
                             
                             // Remove overlapping parts from the command guard DD
-                            guardChoicesIntersection = guardChoicesIntersection && !remainingGuardChoicesIntersection;
+                            guardChoicesIntersection = guardChoicesIntersection * !remainingGuardChoicesIntersection;
                             
                             // If the guard DD has become equivalent to false, we can stop here.
                             if (guardChoicesIntersection.isZero()) {
@@ -309,7 +308,7 @@ namespace storm {
                     }
                     
                     // Delete currentChoices out of overlapping DD
-                    sumOfGuards = sumOfGuards * (!equalsNumberOfChoicesDd);
+                    sumOfGuards = sumOfGuards * !equalsNumberOfChoicesDd;
                 }
                 
                 return ActionDecisionDiagram(allGuards, allCommands, nondeterminismVariableOffset + numberOfBinaryVariables);
@@ -322,9 +321,9 @@ namespace storm {
         }
         
         template <storm::dd::DdType Type>
-        typename DdPrismModelBuilder<Type>::ActionDecisionDiagram DdPrismModelBuilder<Type>::combineUnsynchronizedActions(GenerationInformation const& generationInfo, ActionDecisionDiagram const& action1, ActionDecisionDiagram const& action2, storm::dd::Dd<Type> const& identityDd1, storm::dd::Dd<Type> const& identityDd2) {
-            storm::dd::Dd<Type> action1Extended = action1.transitionsDd * identityDd2;
-            storm::dd::Dd<Type> action2Extended = action2.transitionsDd * identityDd1;
+        typename DdPrismModelBuilder<Type>::ActionDecisionDiagram DdPrismModelBuilder<Type>::combineUnsynchronizedActions(GenerationInformation const& generationInfo, ActionDecisionDiagram const& action1, ActionDecisionDiagram const& action2, storm::dd::Add<Type> const& identityDd1, storm::dd::Add<Type> const& identityDd2) {
+            storm::dd::Add<Type> action1Extended = action1.transitionsDd * identityDd2;
+            storm::dd::Add<Type> action2Extended = action2.transitionsDd * identityDd1;
 
             if (generationInfo.program.getModelType() == storm::prism::Program::ModelType::DTMC) {
                 return ActionDecisionDiagram(action1.guardDd + action2.guardDd, action1Extended + action2Extended, 0);
@@ -338,23 +337,23 @@ namespace storm {
                 // Bring both choices to the same number of variables that encode the nondeterminism.
                 uint_fast64_t numberOfUsedNondeterminismVariables = std::max(action1.numberOfUsedNondeterminismVariables, action2.numberOfUsedNondeterminismVariables);
                 if (action1.numberOfUsedNondeterminismVariables > action2.numberOfUsedNondeterminismVariables) {
-                    storm::dd::Dd<Type> nondeterminisimEncoding = generationInfo.manager->getOne(true);
+                    storm::dd::Add<Type> nondeterminismEncoding = generationInfo.manager->getAddOne();
                     
                     for (uint_fast64_t i = action2.numberOfUsedNondeterminismVariables; i < action1.numberOfUsedNondeterminismVariables; ++i) {
-                        nondeterminisimEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0, true);
+                        nondeterminismEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0).toAdd();
                     }
-                    action2Extended *= nondeterminisimEncoding;
+                    action2Extended *= nondeterminismEncoding;
                 } else if (action2.numberOfUsedNondeterminismVariables > action1.numberOfUsedNondeterminismVariables) {
-                    storm::dd::Dd<Type> nondeterminisimEncoding = generationInfo.manager->getOne(true);
+                    storm::dd::Add<Type> nondeterminismEncoding = generationInfo.manager->getAddOne();
                     
                     for (uint_fast64_t i = action1.numberOfUsedNondeterminismVariables; i < action2.numberOfUsedNondeterminismVariables; ++i) {
-                        nondeterminisimEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0, true);
+                        nondeterminismEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0).toAdd();
                     }
-                    action1Extended *= nondeterminisimEncoding;
+                    action1Extended *= nondeterminismEncoding;
                 }
                 
                 // Add a new variable that resolves the nondeterminism between the two choices.
-                storm::dd::Dd<Type> combinedTransitions = generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[numberOfUsedNondeterminismVariables], 1, true).ite(action2Extended, action1Extended);
+                storm::dd::Add<Type> combinedTransitions = generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[numberOfUsedNondeterminismVariables], 1).toAdd().ite(action2Extended, action1Extended);
                 
                 return ActionDecisionDiagram(action1.guardDd || action2.guardDd, combinedTransitions, numberOfUsedNondeterminismVariables + 1);
             } else {
@@ -381,41 +380,41 @@ namespace storm {
         }
         
         template <storm::dd::DdType Type>
-        storm::dd::Dd<Type> DdPrismModelBuilder<Type>::getSynchronizationDecisionDiagram(GenerationInformation& generationInfo, boost::optional<uint_fast64_t> const& synchronizationAction) {
-            storm::dd::Dd<Type> synchronization = generationInfo.manager->getOne(true);
+        storm::dd::Add<Type> DdPrismModelBuilder<Type>::getSynchronizationDecisionDiagram(GenerationInformation& generationInfo, boost::optional<uint_fast64_t> const& synchronizationAction) {
+            storm::dd::Add<Type> synchronization = generationInfo.manager->getAddOne();
             for (uint_fast64_t i = 0; i < generationInfo.synchronizationMetaVariables.size(); ++i) {
                 if (synchronizationAction && synchronizationAction.get() == i) {
-                    synchronization *= generationInfo.manager->getEncoding(generationInfo.synchronizationMetaVariables[i], 1, true);
+                    synchronization *= generationInfo.manager->getEncoding(generationInfo.synchronizationMetaVariables[i], 1).toAdd();
                 } else {
-                    synchronization *= generationInfo.manager->getEncoding(generationInfo.synchronizationMetaVariables[i], 0, true);
+                    synchronization *= generationInfo.manager->getEncoding(generationInfo.synchronizationMetaVariables[i], 0).toAdd();
                 }
             }
             return synchronization;
         }
         
         template <storm::dd::DdType Type>
-        storm::dd::Dd<Type> DdPrismModelBuilder<Type>::createSystemFromModule(GenerationInformation& generationInfo, ModuleDecisionDiagram const& module) {
+        storm::dd::Add<Type> DdPrismModelBuilder<Type>::createSystemFromModule(GenerationInformation& generationInfo, ModuleDecisionDiagram const& module) {
             // If the model is an MDP, we need to encode the nondeterminism using additional variables.
             if (generationInfo.program.getModelType() == storm::prism::Program::ModelType::MDP) {
-                storm::dd::Dd<Type> result = generationInfo.manager->getZero(true);
+                storm::dd::Add<Type> result = generationInfo.manager->getAddZero();
                 
                 // First, determine the highest number of nondeterminism variables that is used in any action and make
                 // all actions use the same amout of nondeterminism variables.
                 uint_fast64_t numberOfUsedNondeterminismVariables = module.numberOfUsedNondeterminismVariables;
 
                 // Add variables to independent action DD.
-                storm::dd::Dd<Type> nondeterminismEncoding = generationInfo.manager->getOne(true);
+                storm::dd::Add<Type> nondeterminismEncoding = generationInfo.manager->getAddOne();
                 for (uint_fast64_t i = module.independentAction.numberOfUsedNondeterminismVariables; i < numberOfUsedNondeterminismVariables; ++i) {
-                    nondeterminismEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0, true);
+                    nondeterminismEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0).toAdd();
                 }
                 result = module.independentAction.transitionsDd * nondeterminismEncoding;
 
                 // Add variables to synchronized action DDs.
-                std::map<uint_fast64_t, storm::dd::Dd<Type>> synchronizingActionToDdMap;
+                std::map<uint_fast64_t, storm::dd::Add<Type>> synchronizingActionToDdMap;
                 for (auto const& synchronizingAction : module.synchronizingActionToDecisionDiagramMap) {
-                    nondeterminismEncoding = generationInfo.manager->getOne(true);
+                    nondeterminismEncoding = generationInfo.manager->getAddOne();
                     for (uint_fast64_t i = synchronizingAction.second.numberOfUsedNondeterminismVariables; i < numberOfUsedNondeterminismVariables; ++i) {
-                        nondeterminismEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0, true);
+                        nondeterminismEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0).toAdd();
                     }
                     synchronizingActionToDdMap.emplace(synchronizingAction.first, synchronizingAction.second.transitionsDd * nondeterminismEncoding);
                 }
@@ -435,7 +434,7 @@ namespace storm {
                 return result;
             } else if (generationInfo.program.getModelType() == storm::prism::Program::ModelType::DTMC) {
                 // Simply add all actions.
-                storm::dd::Dd<Type> result = module.independentAction.transitionsDd;
+                storm::dd::Add<Type> result = module.independentAction.transitionsDd;
                 for (auto const& synchronizingAction : module.synchronizingActionToDecisionDiagramMap) {
                     result += synchronizingAction.second.transitionsDd;
                 }
@@ -446,7 +445,7 @@ namespace storm {
         }
         
         template <storm::dd::DdType Type>
-        std::pair<storm::dd::Dd<Type>, typename DdPrismModelBuilder<Type>::ModuleDecisionDiagram> DdPrismModelBuilder<Type>::createSystemDecisionDiagram(GenerationInformation& generationInfo) {
+        std::pair<storm::dd::Add<Type>, typename DdPrismModelBuilder<Type>::ModuleDecisionDiagram> DdPrismModelBuilder<Type>::createSystemDecisionDiagram(GenerationInformation& generationInfo) {
             // Create the initial offset mapping.
             std::map<uint_fast64_t, uint_fast64_t> synchronizingActionToOffsetMap;
             for (auto const& actionIndex : generationInfo.program.getActionIndices()) {
@@ -501,7 +500,7 @@ namespace storm {
                 system.numberOfUsedNondeterminismVariables = std::max(system.numberOfUsedNondeterminismVariables, numberOfUsedNondeterminismVariables);
             }
             
-            storm::dd::Dd<Type> result = createSystemFromModule(generationInfo, system);
+            storm::dd::Add<Type> result = createSystemFromModule(generationInfo, system);
             
             // For DTMCs, we normalize each row to 1 (to account for non-determinism).
             if (generationInfo.program.getModelType() == storm::prism::Program::ModelType::DTMC) {
@@ -519,12 +518,12 @@ namespace storm {
         }
         
         template <storm::dd::DdType Type>
-        std::pair<storm::dd::Dd<Type>, storm::dd::Dd<Type>> DdPrismModelBuilder<Type>::createRewardDecisionDiagrams(GenerationInformation& generationInfo, storm::prism::RewardModel const& rewardModel, ModuleDecisionDiagram const& globalModule, storm::dd::Dd<Type> const& fullTransitionMatrix) {
+        std::pair<storm::dd::Add<Type>, storm::dd::Add<Type>> DdPrismModelBuilder<Type>::createRewardDecisionDiagrams(GenerationInformation& generationInfo, storm::prism::RewardModel const& rewardModel, ModuleDecisionDiagram const& globalModule, storm::dd::Add<Type> const& fullTransitionMatrix) {
             // Start by creating the state reward vector.
-            storm::dd::Dd<Type> stateRewards = generationInfo.manager->getZero();
+            storm::dd::Add<Type> stateRewards = generationInfo.manager->getAddZero();
             for (auto const& stateReward : rewardModel.getStateRewards()) {
-                storm::dd::Dd<Type> states = generationInfo.rowExpressionAdapter->translateExpression(stateReward.getStatePredicateExpression());
-                storm::dd::Dd<Type> rewards = generationInfo.rowExpressionAdapter->translateExpression(stateReward.getRewardValueExpression());
+                storm::dd::Add<Type> states = generationInfo.rowExpressionAdapter->translateExpression(stateReward.getStatePredicateExpression());
+                storm::dd::Add<Type> rewards = generationInfo.rowExpressionAdapter->translateExpression(stateReward.getRewardValueExpression());
                 
                 // Restrict the rewards to those states that satisfy the condition.
                 rewards = states * rewards;
@@ -538,13 +537,13 @@ namespace storm {
             }
             
             // Then build the transition reward matrix.
-            storm::dd::Dd<Type> transitionRewards = generationInfo.manager->getZero();
+            storm::dd::Add<Type> transitionRewards = generationInfo.manager->getAddZero();
             for (auto const& transitionReward : rewardModel.getTransitionRewards()) {
-                storm::dd::Dd<Type> states = generationInfo.rowExpressionAdapter->translateExpression(transitionReward.getStatePredicateExpression());
-                storm::dd::Dd<Type> rewards = generationInfo.rowExpressionAdapter->translateExpression(transitionReward.getRewardValueExpression());
+                storm::dd::Add<Type> states = generationInfo.rowExpressionAdapter->translateExpression(transitionReward.getStatePredicateExpression());
+                storm::dd::Add<Type> rewards = generationInfo.rowExpressionAdapter->translateExpression(transitionReward.getRewardValueExpression());
                 
-                storm::dd::Dd<Type> synchronization;
-                storm::dd::Dd<Type> transitions;
+                storm::dd::Add<Type> synchronization;
+                storm::dd::Add<Type> transitions;
                 if (transitionReward.isLabeled()) {
                     synchronization = getSynchronizationDecisionDiagram(generationInfo, transitionReward.getActionIndex());
                     transitions = globalModule.synchronizingActionToDecisionDiagramMap.at(transitionReward.getActionIndex()).transitionsDd;
@@ -553,9 +552,9 @@ namespace storm {
                     transitions = globalModule.independentAction.transitionsDd;
                 }
                 
-                storm::dd::Dd<Type> transitionRewardDd = synchronization * states * rewards;
+                storm::dd::Add<Type> transitionRewardDd = synchronization * states * rewards;
                 if (generationInfo.program.getModelType() == storm::prism::Program::ModelType::MDP) {
-                    transitionRewardDd += transitions.notZero() * transitionRewardDd;
+                    transitionRewardDd += transitions.notZero().toAdd() * transitionRewardDd;
                 } else {
                     transitionRewardDd += transitions * transitionRewardDd;
                 }
@@ -608,15 +607,15 @@ namespace storm {
             // In particular, this creates the meta variables used to encode the model.
             GenerationInformation generationInfo(preparedProgram);
 
-            std::pair<storm::dd::Dd<Type>, ModuleDecisionDiagram> transitionMatrixModulePair = createSystemDecisionDiagram(generationInfo);
-            storm::dd::Dd<Type> transitionMatrix = transitionMatrixModulePair.first;
+            std::pair<storm::dd::Add<Type>, ModuleDecisionDiagram> transitionMatrixModulePair = createSystemDecisionDiagram(generationInfo);
+            storm::dd::Add<Type> transitionMatrix = transitionMatrixModulePair.first;
             ModuleDecisionDiagram const& globalModule = transitionMatrixModulePair.second;
             
             // Finally, we build the DDs for a reward structure, if requested. It is important to do this now, because
             // we still have the uncut transition matrix, which is needed for the reward computation. This is because
             // the reward computation might divide by the transition probabilities, which must therefore never be 0.
             // However, cutting it to the reachable fragment, there might be zero probability transitions.
-            boost::optional<std::pair<storm::dd::Dd<Type>, storm::dd::Dd<Type>>> stateAndTransitionRewards;
+            boost::optional<std::pair<storm::dd::Add<Type>, storm::dd::Add<Type>>> stateAndTransitionRewards;
             if (options.buildRewards) {
                 // If a specific reward model was selected or one with the empty name exists, select it.
                 storm::prism::RewardModel rewardModel = storm::prism::RewardModel();
@@ -634,17 +633,17 @@ namespace storm {
             }
             
             // Cut the transition matrix to the reachable fragment of the state space.
-            storm::dd::Dd<Type> initialStates = createInitialStatesDecisionDiagram(generationInfo);
-            storm::dd::Dd<Type> reachableStates = computeReachableStates(generationInfo, initialStates, transitionMatrix);
-            transitionMatrix *= reachableStates.toMtbdd();
-
-            // Detect deadlocks and 1) fix them if requested 2) throw an error otherwise.
-            storm::dd::Dd<Type> statesWithTransition = transitionMatrix.notZero();
+            storm::dd::Bdd<Type> initialStates = createInitialStatesDecisionDiagram(generationInfo);
+            storm::dd::Bdd<Type> transitionMatrixBdd = transitionMatrix.notZero();
             if (program.getModelType() == storm::prism::Program::ModelType::MDP) {
-                statesWithTransition = statesWithTransition.existsAbstract(generationInfo.allNondeterminismVariables);
+                transitionMatrixBdd = transitionMatrixBdd.existsAbstract(generationInfo.allNondeterminismVariables);
             }
-            statesWithTransition = statesWithTransition.existsAbstract(generationInfo.columnMetaVariables);
-            storm::dd::Dd<Type> deadlockStates = (reachableStates && !statesWithTransition).toMtbdd();
+            storm::dd::Bdd<Type> reachableStates = computeReachableStates(generationInfo, initialStates, transitionMatrixBdd);
+            transitionMatrix *= reachableStates.toAdd();
+
+            // Detect deadlocks and 1) fix them if requested 2) throw an error otherwise.
+            storm::dd::Bdd<Type> statesWithTransition = transitionMatrixBdd.existsAbstract(generationInfo.columnMetaVariables);
+            storm::dd::Add<Type> deadlockStates = (reachableStates && !statesWithTransition).toAdd();
 
             if (!deadlockStates.isZero()) {
                 // If we need to fix deadlocks, we do so now.
@@ -657,7 +656,7 @@ namespace storm {
                     } else if (program.getModelType() == storm::prism::Program::ModelType::MDP) {
                         // For MDPs, however, we need to select an action associated with the self-loop, if we do not
                         // want to attach a lot of self-loops to the deadlock states.
-                        storm::dd::Dd<Type> action = generationInfo.manager->getOne(true);
+                        storm::dd::Add<Type> action = generationInfo.manager->getAddOne();
                         std::for_each(generationInfo.allNondeterminismVariables.begin(), generationInfo.allNondeterminismVariables.end(), [&action,&generationInfo] (storm::expressions::Variable const& metaVariable) { action *= !generationInfo.manager->getIdentity(metaVariable); } );
                         transitionMatrix += deadlockStates * globalModule.identity * action;
                     }
@@ -673,17 +672,17 @@ namespace storm {
             }
             
             if (program.getModelType() == storm::prism::Program::ModelType::DTMC) {
-                return std::shared_ptr<storm::models::symbolic::Model<Type>>(new storm::models::symbolic::Dtmc<Type>(generationInfo.manager, reachableStates, initialStates, transitionMatrix, generationInfo.rowMetaVariables, generationInfo.rowExpressionAdapter, generationInfo.columnMetaVariables, generationInfo.columnExpressionAdapter, generationInfo.rowColumnMetaVariablePairs, labelToExpressionMapping, stateAndTransitionRewards ? stateAndTransitionRewards.get().first : boost::optional<storm::dd::Dd<Type>>(), stateAndTransitionRewards ? stateAndTransitionRewards.get().second : boost::optional<storm::dd::Dd<Type>>()));
+                return std::shared_ptr<storm::models::symbolic::Model<Type>>(new storm::models::symbolic::Dtmc<Type>(generationInfo.manager, reachableStates, initialStates, transitionMatrix, generationInfo.rowMetaVariables, generationInfo.rowExpressionAdapter, generationInfo.columnMetaVariables, generationInfo.columnExpressionAdapter, generationInfo.rowColumnMetaVariablePairs, labelToExpressionMapping, stateAndTransitionRewards ? stateAndTransitionRewards.get().first : boost::optional<storm::dd::Add<Type>>(), stateAndTransitionRewards ? stateAndTransitionRewards.get().second : boost::optional<storm::dd::Add<Type>>()));
             } else if (program.getModelType() == storm::prism::Program::ModelType::MDP) {
-                return std::shared_ptr<storm::models::symbolic::Model<Type>>(new storm::models::symbolic::Mdp<Type>(generationInfo.manager, reachableStates, initialStates, transitionMatrix, generationInfo.rowMetaVariables, generationInfo.rowExpressionAdapter, generationInfo.columnMetaVariables, generationInfo.columnExpressionAdapter, generationInfo.rowColumnMetaVariablePairs, generationInfo.allNondeterminismVariables, labelToExpressionMapping, stateAndTransitionRewards ? stateAndTransitionRewards.get().first : boost::optional<storm::dd::Dd<Type>>(), stateAndTransitionRewards ? stateAndTransitionRewards.get().second : boost::optional<storm::dd::Dd<Type>>()));
+                return std::shared_ptr<storm::models::symbolic::Model<Type>>(new storm::models::symbolic::Mdp<Type>(generationInfo.manager, reachableStates, initialStates, transitionMatrix, generationInfo.rowMetaVariables, generationInfo.rowExpressionAdapter, generationInfo.columnMetaVariables, generationInfo.columnExpressionAdapter, generationInfo.rowColumnMetaVariablePairs, generationInfo.allNondeterminismVariables, labelToExpressionMapping, stateAndTransitionRewards ? stateAndTransitionRewards.get().first : boost::optional<storm::dd::Add<Type>>(), stateAndTransitionRewards ? stateAndTransitionRewards.get().second : boost::optional<storm::dd::Add<Type>>()));
             } else {
                 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Invalid model type.");
             }
         }
         
         template <storm::dd::DdType Type>
-        storm::dd::Dd<Type> DdPrismModelBuilder<Type>::createInitialStatesDecisionDiagram(GenerationInformation& generationInfo) {
-            storm::dd::Dd<Type> initialStates = generationInfo.rowExpressionAdapter->translateExpression(generationInfo.program.getInitialConstruct().getInitialStatesExpression()).toBdd();
+        storm::dd::Bdd<Type> DdPrismModelBuilder<Type>::createInitialStatesDecisionDiagram(GenerationInformation& generationInfo) {
+            storm::dd::Bdd<Type> initialStates = generationInfo.rowExpressionAdapter->translateExpression(generationInfo.program.getInitialConstruct().getInitialStatesExpression()).toBdd();
             
             for (auto const& metaVariable : generationInfo.rowMetaVariables) {
                 initialStates &= generationInfo.manager->getRange(metaVariable);
@@ -693,14 +692,8 @@ namespace storm {
         }
         
         template <storm::dd::DdType Type>
-        storm::dd::Dd<Type> DdPrismModelBuilder<Type>::computeReachableStates(GenerationInformation& generationInfo, storm::dd::Dd<Type> const& initialStates, storm::dd::Dd<Type> const& transitions) {
-            storm::dd::Dd<Type> reachableStatesBdd = initialStates.toBdd();
-            
-            // If the model is an MDP, we can abstract from the variables encoding the nondeterminism in the model.
-            storm::dd::Dd<Type> transitionBdd = transitions.notZero();
-            if (generationInfo.program.getModelType() == storm::prism::Program::ModelType::MDP) {
-                transitionBdd = transitionBdd.existsAbstract(generationInfo.allNondeterminismVariables);
-            }
+        storm::dd::Bdd<Type> DdPrismModelBuilder<Type>::computeReachableStates(GenerationInformation& generationInfo, storm::dd::Bdd<Type> const& initialStates, storm::dd::Bdd<Type> const& transitionBdd) {
+            storm::dd::Bdd<Type> reachableStates = initialStates;
             
             // Perform the BFS to discover all reachable states.
             bool changed = true;
@@ -708,21 +701,21 @@ namespace storm {
             do {
                 STORM_LOG_TRACE("Iteration " << iteration << " of computing reachable states.");
                 changed = false;
-                storm::dd::Dd<Type> tmp = reachableStatesBdd.andExists(transitionBdd, generationInfo.rowMetaVariables);
+                storm::dd::Bdd<Type> tmp = reachableStates.andExists(transitionBdd, generationInfo.rowMetaVariables);
                 tmp = tmp.swapVariables(generationInfo.rowColumnMetaVariablePairs);
 
-                storm::dd::Dd<Type> newReachableStates = tmp && (!reachableStatesBdd);
+                storm::dd::Bdd<Type> newReachableStates = tmp && (!reachableStates);
                 
                 // Check whether new states were indeed discovered.
                 if (!newReachableStates.isZero()) {
                     changed = true;
                 }
                 
-                reachableStatesBdd |= newReachableStates;
+                reachableStates |= newReachableStates;
                 ++iteration;
             } while (changed);
             
-            return reachableStatesBdd;
+            return reachableStates;
         }
         
         // Explicitly instantiate the symbolic expression adapter
diff --git a/src/builder/DdPrismModelBuilder.h b/src/builder/DdPrismModelBuilder.h
index fb6e8c7ff..4f6d8f580 100644
--- a/src/builder/DdPrismModelBuilder.h
+++ b/src/builder/DdPrismModelBuilder.h
@@ -7,7 +7,7 @@
 #include "src/models/symbolic/Model.h"
 #include "src/logic/Formulas.h"
 #include "src/storage/prism/Program.h"
-#include "src/adapters/DdExpressionAdapter.h"
+#include "src/adapters/AddExpressionAdapter.h"
 #include "src/utility/macros.h"
 
 namespace storm {
@@ -71,11 +71,11 @@ namespace storm {
                     // Intentionally left empty.
                 }
                 
-                ActionDecisionDiagram(storm::dd::DdManager<Type> const& manager, uint_fast64_t numberOfUsedNondeterminismVariables = 0) : guardDd(manager.getZero(true)), transitionsDd(manager.getZero(true)), numberOfUsedNondeterminismVariables(numberOfUsedNondeterminismVariables) {
+                ActionDecisionDiagram(storm::dd::DdManager<Type> const& manager, uint_fast64_t numberOfUsedNondeterminismVariables = 0) : guardDd(manager.getAddZero()), transitionsDd(manager.getAddZero()), numberOfUsedNondeterminismVariables(numberOfUsedNondeterminismVariables) {
                     // Intentionally left empty.
                 }
                 
-                ActionDecisionDiagram(storm::dd::Dd<Type> guardDd, storm::dd::Dd<Type> transitionsDd, uint_fast64_t numberOfUsedNondeterminismVariables = 0) : guardDd(guardDd), transitionsDd(transitionsDd), numberOfUsedNondeterminismVariables(numberOfUsedNondeterminismVariables) {
+                ActionDecisionDiagram(storm::dd::Add<Type> guardDd, storm::dd::Add<Type> transitionsDd, uint_fast64_t numberOfUsedNondeterminismVariables = 0) : guardDd(guardDd), transitionsDd(transitionsDd), numberOfUsedNondeterminismVariables(numberOfUsedNondeterminismVariables) {
                     // Intentionally left empty.
                 }
                 
@@ -83,10 +83,10 @@ namespace storm {
                 ActionDecisionDiagram& operator=(ActionDecisionDiagram const& other) = default;
                 
                 // The guard of the action.
-                storm::dd::Dd<Type> guardDd;
+                storm::dd::Add<Type> guardDd;
                 
                 // The actual transitions (source and target states).
-                storm::dd::Dd<Type> transitionsDd;
+                storm::dd::Add<Type> transitionsDd;
                 
                 // The number of variables that are used to encode the nondeterminism.
                 uint_fast64_t numberOfUsedNondeterminismVariables;
@@ -98,11 +98,11 @@ namespace storm {
                     // Intentionally left empty.
                 }
                 
-                ModuleDecisionDiagram(storm::dd::DdManager<Type> const& manager) : independentAction(manager), synchronizingActionToDecisionDiagramMap(), identity(manager.getZero(true)), numberOfUsedNondeterminismVariables(0) {
+                ModuleDecisionDiagram(storm::dd::DdManager<Type> const& manager) : independentAction(manager), synchronizingActionToDecisionDiagramMap(), identity(manager.getAddZero()), numberOfUsedNondeterminismVariables(0) {
                     // Intentionally left empty.
                 }
 
-                ModuleDecisionDiagram(ActionDecisionDiagram const& independentAction, std::map<uint_fast64_t, ActionDecisionDiagram> const& synchronizingActionToDecisionDiagramMap, storm::dd::Dd<Type> const& identity, uint_fast64_t numberOfUsedNondeterminismVariables = 0) : independentAction(independentAction), synchronizingActionToDecisionDiagramMap(synchronizingActionToDecisionDiagramMap), identity(identity), numberOfUsedNondeterminismVariables(numberOfUsedNondeterminismVariables) {
+                ModuleDecisionDiagram(ActionDecisionDiagram const& independentAction, std::map<uint_fast64_t, ActionDecisionDiagram> const& synchronizingActionToDecisionDiagramMap, storm::dd::Add<Type> const& identity, uint_fast64_t numberOfUsedNondeterminismVariables = 0) : independentAction(independentAction), synchronizingActionToDecisionDiagramMap(synchronizingActionToDecisionDiagramMap), identity(identity), numberOfUsedNondeterminismVariables(numberOfUsedNondeterminismVariables) {
                     // Intentionally left empty.
                 }
                 
@@ -120,7 +120,7 @@ namespace storm {
                 std::map<uint_fast64_t, ActionDecisionDiagram> synchronizingActionToDecisionDiagramMap;
                 
                 // A decision diagram that represents the identity of this module.
-                storm::dd::Dd<Type> identity;
+                storm::dd::Add<Type> identity;
                 
                 // The number of variables encoding the nondeterminism that were actually used.
                 uint_fast64_t numberOfUsedNondeterminismVariables;
@@ -135,8 +135,8 @@ namespace storm {
                     // Initializes variables and identity DDs.
                     createMetaVariablesAndIdentities();
                     
-                    rowExpressionAdapter = std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>>(new storm::adapters::DdExpressionAdapter<Type>(manager, variableToRowMetaVariableMap));
-                    columnExpressionAdapter = std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>>(new storm::adapters::DdExpressionAdapter<Type>(manager, variableToColumnMetaVariableMap));
+                    rowExpressionAdapter = std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>>(new storm::adapters::AddExpressionAdapter<Type>(manager, variableToRowMetaVariableMap));
+                    columnExpressionAdapter = std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>>(new storm::adapters::AddExpressionAdapter<Type>(manager, variableToColumnMetaVariableMap));
                 }
                 
                 // The program that is currently translated.
@@ -148,12 +148,12 @@ namespace storm {
                 // The meta variables for the row encoding.
                 std::set<storm::expressions::Variable> rowMetaVariables;
                 std::map<storm::expressions::Variable, storm::expressions::Variable> variableToRowMetaVariableMap;
-                std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> rowExpressionAdapter;
+                std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> rowExpressionAdapter;
                 
                 // The meta variables for the column encoding.
                 std::set<storm::expressions::Variable> columnMetaVariables;
                 std::map<storm::expressions::Variable, storm::expressions::Variable> variableToColumnMetaVariableMap;
-                std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> columnExpressionAdapter;
+                std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> columnExpressionAdapter;
                 
                 // All pairs of row/column meta variables.
                 std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> rowColumnMetaVariablePairs;
@@ -169,13 +169,13 @@ namespace storm {
                 std::set<storm::expressions::Variable> allNondeterminismVariables;
                 
                 // DDs representing the identity for each variable.
-                std::map<storm::expressions::Variable, storm::dd::Dd<Type>> variableToIdentityMap;
+                std::map<storm::expressions::Variable, storm::dd::Add<Type>> variableToIdentityMap;
                 
                 // DDs representing the identity for each module.
-                std::map<std::string, storm::dd::Dd<Type>> moduleToIdentityMap;
+                std::map<std::string, storm::dd::Add<Type>> moduleToIdentityMap;
                 
                 // DDs representing the valid ranges of the variables of each module.
-                std::map<std::string, storm::dd::Dd<Type>> moduleToRangeMap;
+                std::map<std::string, storm::dd::Add<Type>> moduleToRangeMap;
                 
             private:
                 /*!
@@ -212,7 +212,7 @@ namespace storm {
                         columnMetaVariables.insert(variablePair.second);
                         variableToColumnMetaVariableMap.emplace(integerVariable.getExpressionVariable(), variablePair.second);
                         
-                        storm::dd::Dd<Type> variableIdentity = manager->getIdentity(variablePair.first).equals(manager->getIdentity(variablePair.second)) * manager->getRange(variablePair.first, true);
+                        storm::dd::Add<Type> variableIdentity = manager->getIdentity(variablePair.first).equals(manager->getIdentity(variablePair.second)) * manager->getRange(variablePair.first).toAdd();
                         variableToIdentityMap.emplace(integerVariable.getExpressionVariable(), variableIdentity);
                         rowColumnMetaVariablePairs.push_back(variablePair);
                     }
@@ -225,7 +225,7 @@ namespace storm {
                         columnMetaVariables.insert(variablePair.second);
                         variableToColumnMetaVariableMap.emplace(booleanVariable.getExpressionVariable(), variablePair.second);
                         
-                        storm::dd::Dd<Type> variableIdentity = manager->getIdentity(variablePair.first).equals(manager->getIdentity(variablePair.second));
+                        storm::dd::Add<Type> variableIdentity = manager->getIdentity(variablePair.first).equals(manager->getIdentity(variablePair.second));
                         variableToIdentityMap.emplace(booleanVariable.getExpressionVariable(), variableIdentity);
                         
                         rowColumnMetaVariablePairs.push_back(variablePair);
@@ -233,8 +233,8 @@ namespace storm {
 
                     // Create meta variables for each of the modules' variables.
                     for (storm::prism::Module const& module : program.getModules()) {
-                        storm::dd::Dd<Type> moduleIdentity = manager->getOne(true);
-                        storm::dd::Dd<Type> moduleRange = manager->getOne(true);
+                        storm::dd::Add<Type> moduleIdentity = manager->getAddOne();
+                        storm::dd::Add<Type> moduleRange = manager->getAddOne();
                         
                         for (storm::prism::IntegerVariable const& integerVariable : module.getIntegerVariables()) {
                             int_fast64_t low = integerVariable.getLowerBoundExpression().evaluateAsInt();
@@ -248,10 +248,10 @@ namespace storm {
                             columnMetaVariables.insert(variablePair.second);
                             variableToColumnMetaVariableMap.emplace(integerVariable.getExpressionVariable(), variablePair.second);
                             
-                            storm::dd::Dd<Type> variableIdentity = manager->getIdentity(variablePair.first).equals(manager->getIdentity(variablePair.second)) * manager->getRange(variablePair.first, true) * manager->getRange(variablePair.second, true);
+                            storm::dd::Add<Type> variableIdentity = manager->getIdentity(variablePair.first).equals(manager->getIdentity(variablePair.second)) * manager->getRange(variablePair.first).toAdd() * manager->getRange(variablePair.second).toAdd();
                             variableToIdentityMap.emplace(integerVariable.getExpressionVariable(), variableIdentity);
                             moduleIdentity *= variableIdentity;
-                            moduleRange *= manager->getRange(variablePair.first, true);
+                            moduleRange *= manager->getRange(variablePair.first).toAdd();
                             
                             rowColumnMetaVariablePairs.push_back(variablePair);
                         }
@@ -265,10 +265,10 @@ namespace storm {
                             columnMetaVariables.insert(variablePair.second);
                             variableToColumnMetaVariableMap.emplace(booleanVariable.getExpressionVariable(), variablePair.second);
                             
-                            storm::dd::Dd<Type> variableIdentity = manager->getIdentity(variablePair.first).equals(manager->getIdentity(variablePair.second)) * manager->getRange(variablePair.first, true) * manager->getRange(variablePair.second, true);
+                            storm::dd::Add<Type> variableIdentity = manager->getIdentity(variablePair.first).equals(manager->getIdentity(variablePair.second)) * manager->getRange(variablePair.first).toAdd() * manager->getRange(variablePair.second).toAdd();
                             variableToIdentityMap.emplace(booleanVariable.getExpressionVariable(), variableIdentity);
                             moduleIdentity *= variableIdentity;
-                            moduleRange *= manager->getRange(variablePair.first, true);
+                            moduleRange *= manager->getRange(variablePair.first).toAdd();
 
                             rowColumnMetaVariablePairs.push_back(variablePair);
                         }
@@ -280,9 +280,9 @@ namespace storm {
             
         private:
             
-            static storm::dd::Dd<Type> encodeChoice(GenerationInformation& generationInfo, uint_fast64_t nondeterminismVariableOffset, uint_fast64_t numberOfBinaryVariables, int_fast64_t value);
+            static storm::dd::Add<Type> encodeChoice(GenerationInformation& generationInfo, uint_fast64_t nondeterminismVariableOffset, uint_fast64_t numberOfBinaryVariables, int_fast64_t value);
             
-            static storm::dd::Dd<Type> createUpdateDecisionDiagram(GenerationInformation& generationInfo, storm::prism::Module const& module, storm::dd::Dd<Type> const& guard, storm::prism::Update const& update);
+            static storm::dd::Add<Type> createUpdateDecisionDiagram(GenerationInformation& generationInfo, storm::prism::Module const& module, storm::dd::Add<Type> const& guard, storm::prism::Update const& update);
 
             static ActionDecisionDiagram createCommandDecisionDiagram(GenerationInformation& generationInfo, storm::prism::Module const& module, storm::prism::Command const& command);
 
@@ -294,21 +294,21 @@ namespace storm {
 
             static ActionDecisionDiagram combineSynchronizingActions(GenerationInformation const& generationInfo, ActionDecisionDiagram const& action1, ActionDecisionDiagram const& action2);
 
-            static ActionDecisionDiagram combineUnsynchronizedActions(GenerationInformation const& generationInfo, ActionDecisionDiagram const& action1, ActionDecisionDiagram const& action2, storm::dd::Dd<Type> const& identityDd1, storm::dd::Dd<Type> const& identityDd2);
+            static ActionDecisionDiagram combineUnsynchronizedActions(GenerationInformation const& generationInfo, ActionDecisionDiagram const& action1, ActionDecisionDiagram const& action2, storm::dd::Add<Type> const& identityDd1, storm::dd::Add<Type> const& identityDd2);
 
             static ModuleDecisionDiagram createModuleDecisionDiagram(GenerationInformation& generationInfo, storm::prism::Module const& module, std::map<uint_fast64_t, uint_fast64_t> const& synchronizingActionToOffsetMap);
 
-            static storm::dd::Dd<Type> getSynchronizationDecisionDiagram(GenerationInformation& generationInfo, boost::optional<uint_fast64_t> const& synchronizationAction = boost::optional<uint_fast64_t>());
+            static storm::dd::Add<Type> getSynchronizationDecisionDiagram(GenerationInformation& generationInfo, boost::optional<uint_fast64_t> const& synchronizationAction = boost::optional<uint_fast64_t>());
             
-            static storm::dd::Dd<Type> createSystemFromModule(GenerationInformation& generationInfo, ModuleDecisionDiagram const& module);
+            static storm::dd::Add<Type> createSystemFromModule(GenerationInformation& generationInfo, ModuleDecisionDiagram const& module);
             
-            static std::pair<storm::dd::Dd<Type>, storm::dd::Dd<Type>> createRewardDecisionDiagrams(GenerationInformation& generationInfo, storm::prism::RewardModel const& rewardModel, ModuleDecisionDiagram const& globalModule, storm::dd::Dd<Type> const& fullTransitionMatrix);
+            static std::pair<storm::dd::Add<Type>, storm::dd::Add<Type>> createRewardDecisionDiagrams(GenerationInformation& generationInfo, storm::prism::RewardModel const& rewardModel, ModuleDecisionDiagram const& globalModule, storm::dd::Add<Type> const& fullTransitionMatrix);
             
-            static std::pair<storm::dd::Dd<Type>, ModuleDecisionDiagram> createSystemDecisionDiagram(GenerationInformation& generationInfo);
+            static std::pair<storm::dd::Add<Type>, ModuleDecisionDiagram> createSystemDecisionDiagram(GenerationInformation& generationInfo);
             
-            static storm::dd::Dd<Type> createInitialStatesDecisionDiagram(GenerationInformation& generationInfo);
+            static storm::dd::Bdd<Type> createInitialStatesDecisionDiagram(GenerationInformation& generationInfo);
 
-            static storm::dd::Dd<Type> computeReachableStates(GenerationInformation& generationInfo, storm::dd::Dd<Type> const& initialStates, storm::dd::Dd<Type> const& transitions);
+            static storm::dd::Bdd<Type> computeReachableStates(GenerationInformation& generationInfo, storm::dd::Bdd<Type> const& initialStates, storm::dd::Bdd<Type> const& transitions);
             
         };
         
diff --git a/src/modelchecker/propositional/SymbolicPropositionalModelChecker.cpp b/src/modelchecker/propositional/SymbolicPropositionalModelChecker.cpp
index 137c292b5..1552235d9 100644
--- a/src/modelchecker/propositional/SymbolicPropositionalModelChecker.cpp
+++ b/src/modelchecker/propositional/SymbolicPropositionalModelChecker.cpp
@@ -25,7 +25,7 @@ namespace storm {
             if (stateFormula.isTrueFormula()) {
                 return std::unique_ptr<CheckResult>(new SymbolicQualitativeCheckResult<Type>(model.getReachableStates(), model.getReachableStates()));
             } else {
-                return std::unique_ptr<CheckResult>(new SymbolicQualitativeCheckResult<Type>(model.getReachableStates(), model.getManager().getZero()));
+                return std::unique_ptr<CheckResult>(new SymbolicQualitativeCheckResult<Type>(model.getReachableStates(), model.getManager().getBddZero()));
             }
         }
         
diff --git a/src/modelchecker/results/SymbolicQualitativeCheckResult.cpp b/src/modelchecker/results/SymbolicQualitativeCheckResult.cpp
index 290da6884..766e2674f 100644
--- a/src/modelchecker/results/SymbolicQualitativeCheckResult.cpp
+++ b/src/modelchecker/results/SymbolicQualitativeCheckResult.cpp
@@ -6,7 +6,7 @@
 namespace storm {
     namespace modelchecker {
         template <storm::dd::DdType Type>
-        SymbolicQualitativeCheckResult<Type>::SymbolicQualitativeCheckResult(storm::dd::Dd<Type> const& allStates, storm::dd::Dd<Type> const& truthValues) : allStates(allStates), truthValues(truthValues) {
+        SymbolicQualitativeCheckResult<Type>::SymbolicQualitativeCheckResult(storm::dd::Bdd<Type> const& allStates, storm::dd::Bdd<Type> const& truthValues) : allStates(allStates), truthValues(truthValues) {
             // Intentionally left empty.
         }
         
diff --git a/src/modelchecker/results/SymbolicQualitativeCheckResult.h b/src/modelchecker/results/SymbolicQualitativeCheckResult.h
index 83c49ab98..e0c70ead3 100644
--- a/src/modelchecker/results/SymbolicQualitativeCheckResult.h
+++ b/src/modelchecker/results/SymbolicQualitativeCheckResult.h
@@ -2,7 +2,7 @@
 #define STORM_MODELCHECKER_SYMBOLICQUALITATIVECHECKRESULT_H_
 
 #include "src/storage/dd/DdType.h"
-#include "src/storage/dd/Dd.h"
+#include "src/storage/dd/CuddBdd.h"
 #include "src/modelchecker/results/QualitativeCheckResult.h"
 #include "src/utility/OsDetection.h"
 
@@ -12,7 +12,7 @@ namespace storm {
         class SymbolicQualitativeCheckResult : public QualitativeCheckResult {
         public:
             SymbolicQualitativeCheckResult() = default;
-            SymbolicQualitativeCheckResult(storm::dd::Dd<Type> const& allStates, storm::dd::Dd<Type> const& truthValues);
+            SymbolicQualitativeCheckResult(storm::dd::Bdd<Type> const& allStates, storm::dd::Bdd<Type> const& truthValues);
             
             SymbolicQualitativeCheckResult(SymbolicQualitativeCheckResult const& other) = default;
             SymbolicQualitativeCheckResult& operator=(SymbolicQualitativeCheckResult const& other) = default;
@@ -38,10 +38,10 @@ namespace storm {
             
         private:
             // The set of all states.
-            storm::dd::Dd<Type> allStates;
+            storm::dd::Bdd<Type> allStates;
             
             // The values of the qualitative check result.
-            storm::dd::Dd<Type> truthValues;
+            storm::dd::Bdd<Type> truthValues;
         };
     }
 }
diff --git a/src/modelchecker/results/SymbolicQuantitativeCheckResult.cpp b/src/modelchecker/results/SymbolicQuantitativeCheckResult.cpp
index b78df481d..50d7d0ac7 100644
--- a/src/modelchecker/results/SymbolicQuantitativeCheckResult.cpp
+++ b/src/modelchecker/results/SymbolicQuantitativeCheckResult.cpp
@@ -7,7 +7,7 @@
 namespace storm {
     namespace modelchecker {
         template<storm::dd::DdType Type>
-        SymbolicQuantitativeCheckResult<Type>::SymbolicQuantitativeCheckResult(storm::dd::Dd<Type> const& allStates, storm::dd::Dd<Type> const& values) : allStates(allStates), values(values) {
+        SymbolicQuantitativeCheckResult<Type>::SymbolicQuantitativeCheckResult(storm::dd::Add<Type> const& allStates, storm::dd::Add<Type> const& values) : allStates(allStates), values(values) {
             // Intentionally left empty.
         }
         
diff --git a/src/modelchecker/results/SymbolicQuantitativeCheckResult.h b/src/modelchecker/results/SymbolicQuantitativeCheckResult.h
index 0b1e331f4..28490aed2 100644
--- a/src/modelchecker/results/SymbolicQuantitativeCheckResult.h
+++ b/src/modelchecker/results/SymbolicQuantitativeCheckResult.h
@@ -2,7 +2,7 @@
 #define STORM_MODELCHECKER_SYMBOLICQUANTITATIVECHECKRESULT_H_
 
 #include "src/storage/dd/DdType.h"
-#include "src/storage/dd/Dd.h"
+#include "src/storage/dd/CuddAdd.h"
 #include "src/modelchecker/results/QuantitativeCheckResult.h"
 #include "src/utility/OsDetection.h"
 
@@ -12,7 +12,7 @@ namespace storm {
         class SymbolicQuantitativeCheckResult : public QuantitativeCheckResult {
         public:
             SymbolicQuantitativeCheckResult() = default;
-            SymbolicQuantitativeCheckResult(storm::dd::Dd<Type> const& allStates, storm::dd::Dd<Type> const& values);
+            SymbolicQuantitativeCheckResult(storm::dd::Add<Type> const& allStates, storm::dd::Add<Type> const& values);
             
             SymbolicQuantitativeCheckResult(SymbolicQuantitativeCheckResult const& other) = default;
             SymbolicQuantitativeCheckResult& operator=(SymbolicQuantitativeCheckResult const& other) = default;
@@ -36,10 +36,10 @@ namespace storm {
             
         private:
             // The set of all states.
-            storm::dd::Dd<Type> allStates;
+            storm::dd::Add<Type> allStates;
             
             // The values of the quantitative check result.
-            storm::dd::Dd<Type> values;
+            storm::dd::Add<Type> values;
         };
     }
 }
diff --git a/src/models/symbolic/DeterministicModel.cpp b/src/models/symbolic/DeterministicModel.cpp
index 64aca24ab..57cf7af60 100644
--- a/src/models/symbolic/DeterministicModel.cpp
+++ b/src/models/symbolic/DeterministicModel.cpp
@@ -7,17 +7,17 @@ namespace storm {
             template<storm::dd::DdType Type>
             DeterministicModel<Type>::DeterministicModel(storm::models::ModelType const& modelType,
                                                          std::shared_ptr<storm::dd::DdManager<Type>> manager,
-                                                         storm::dd::Dd<Type> reachableStates,
-                                                         storm::dd::Dd<Type> initialStates,
-                                                         storm::dd::Dd<Type> transitionMatrix,
+                                                         storm::dd::Bdd<Type> reachableStates,
+                                                         storm::dd::Bdd<Type> initialStates,
+                                                         storm::dd::Add<Type> transitionMatrix,
                                                          std::set<storm::expressions::Variable> const& rowVariables,
-                                                         std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> rowExpressionAdapter,
+                                                         std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> rowExpressionAdapter,
                                                          std::set<storm::expressions::Variable> const& columnVariables,
-                                                         std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> columnExpressionAdapter,
+                                                         std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> columnExpressionAdapter,
                                                          std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs,
                                                          std::map<std::string, storm::expressions::Expression> labelToExpressionMap,
-                                                         boost::optional<storm::dd::Dd<Type>> const& optionalStateRewardVector,
-                                                         boost::optional<storm::dd::Dd<Type>> const& optionalTransitionRewardMatrix)
+                                                         boost::optional<storm::dd::Add<Type>> const& optionalStateRewardVector,
+                                                         boost::optional<storm::dd::Add<Type>> const& optionalTransitionRewardMatrix)
             : Model<Type>(modelType, manager, reachableStates, initialStates, transitionMatrix, rowVariables, rowExpressionAdapter, columnVariables, columnExpressionAdapter, rowColumnMetaVariablePairs, labelToExpressionMap, optionalStateRewardVector, optionalTransitionRewardMatrix) {
                 // Intentionally left empty.
             }
diff --git a/src/models/symbolic/DeterministicModel.h b/src/models/symbolic/DeterministicModel.h
index 274d2818a..84d6116c8 100644
--- a/src/models/symbolic/DeterministicModel.h
+++ b/src/models/symbolic/DeterministicModel.h
@@ -43,17 +43,17 @@ namespace storm {
                  */
                 DeterministicModel(storm::models::ModelType const& modelType,
                                    std::shared_ptr<storm::dd::DdManager<Type>> manager,
-                                   storm::dd::Dd<Type> reachableStates,
-                                   storm::dd::Dd<Type> initialStates,
-                                   storm::dd::Dd<Type> transitionMatrix,
+                                   storm::dd::Bdd<Type> reachableStates,
+                                   storm::dd::Bdd<Type> initialStates,
+                                   storm::dd::Add<Type> transitionMatrix,
                                    std::set<storm::expressions::Variable> const& rowVariables,
-                                   std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> rowExpressionAdapter,
+                                   std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> rowExpressionAdapter,
                                    std::set<storm::expressions::Variable> const& columnVariables,
-                                   std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> columnExpressionAdapter,
+                                   std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> columnExpressionAdapter,
                                    std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs,
                                    std::map<std::string, storm::expressions::Expression> labelToExpressionMap = std::map<std::string, storm::expressions::Expression>(),
-                                   boost::optional<storm::dd::Dd<Type>> const& optionalStateRewardVector = boost::optional<storm::dd::Dd<Type>>(),
-                                   boost::optional<storm::dd::Dd<Type>> const& optionalTransitionRewardMatrix = boost::optional<storm::dd::Dd<Type>>());
+                                   boost::optional<storm::dd::Add<Type>> const& optionalStateRewardVector = boost::optional<storm::dd::Dd<Type>>(),
+                                   boost::optional<storm::dd::Add<Type>> const& optionalTransitionRewardMatrix = boost::optional<storm::dd::Dd<Type>>());
             };
             
         } // namespace symbolic
diff --git a/src/models/symbolic/Dtmc.cpp b/src/models/symbolic/Dtmc.cpp
index 5c28f063f..c11b94850 100644
--- a/src/models/symbolic/Dtmc.cpp
+++ b/src/models/symbolic/Dtmc.cpp
@@ -6,17 +6,17 @@ namespace storm {
             
             template<storm::dd::DdType Type>
             Dtmc<Type>::Dtmc(std::shared_ptr<storm::dd::DdManager<Type>> manager,
-                             storm::dd::Dd<Type> reachableStates,
-                             storm::dd::Dd<Type> initialStates,
-                             storm::dd::Dd<Type> transitionMatrix,
+                             storm::dd::Bdd<Type> reachableStates,
+                             storm::dd::Bdd<Type> initialStates,
+                             storm::dd::Add<Type> transitionMatrix,
                              std::set<storm::expressions::Variable> const& rowVariables,
-                             std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> rowExpressionAdapter,
+                             std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> rowExpressionAdapter,
                              std::set<storm::expressions::Variable> const& columnVariables,
-                             std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> columnExpressionAdapter,
+                             std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> columnExpressionAdapter,
                              std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs,
                              std::map<std::string, storm::expressions::Expression> labelToExpressionMap,
-                             boost::optional<storm::dd::Dd<Type>> const& optionalStateRewardVector,
-                             boost::optional<storm::dd::Dd<Type>> const& optionalTransitionRewardMatrix)
+                             boost::optional<storm::dd::Add<Type>> const& optionalStateRewardVector,
+                             boost::optional<storm::dd::Add<Type>> const& optionalTransitionRewardMatrix)
             : DeterministicModel<Type>(storm::models::ModelType::Dtmc, manager, reachableStates, initialStates, transitionMatrix, rowVariables, rowExpressionAdapter, columnVariables, columnExpressionAdapter, rowColumnMetaVariablePairs, labelToExpressionMap, optionalStateRewardVector, optionalTransitionRewardMatrix) {
                 // Intentionally left empty.
             }
diff --git a/src/models/symbolic/Dtmc.h b/src/models/symbolic/Dtmc.h
index b9c12e86e..47f7a9db4 100644
--- a/src/models/symbolic/Dtmc.h
+++ b/src/models/symbolic/Dtmc.h
@@ -41,17 +41,17 @@ namespace storm {
                  * @param optionalTransitionRewardMatrix The reward values associated with the transitions of the model.
                  */
                 Dtmc(std::shared_ptr<storm::dd::DdManager<Type>> manager,
-                     storm::dd::Dd<Type> reachableStates,
-                     storm::dd::Dd<Type> initialStates,
-                     storm::dd::Dd<Type> transitionMatrix,
+                     storm::dd::Bdd<Type> reachableStates,
+                     storm::dd::Bdd<Type> initialStates,
+                     storm::dd::Add<Type> transitionMatrix,
                      std::set<storm::expressions::Variable> const& rowVariables,
-                     std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> rowExpressionAdapter,
+                     std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> rowExpressionAdapter,
                      std::set<storm::expressions::Variable> const& columnVariables,
-                     std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> columnExpressionAdapter,
+                     std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> columnExpressionAdapter,
                      std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs,
                      std::map<std::string, storm::expressions::Expression> labelToExpressionMap = std::map<std::string, storm::expressions::Expression>(),
-                     boost::optional<storm::dd::Dd<Type>> const& optionalStateRewardVector = boost::optional<storm::dd::Dd<Type>>(),
-                     boost::optional<storm::dd::Dd<Type>> const& optionalTransitionRewardMatrix = boost::optional<storm::dd::Dd<Type>>());
+                     boost::optional<storm::dd::Add<Type>> const& optionalStateRewardVector = boost::optional<storm::dd::Dd<Type>>(),
+                     boost::optional<storm::dd::Add<Type>> const& optionalTransitionRewardMatrix = boost::optional<storm::dd::Dd<Type>>());
             };
             
         } // namespace symbolic
diff --git a/src/models/symbolic/Mdp.cpp b/src/models/symbolic/Mdp.cpp
index 36462c072..6084e2965 100644
--- a/src/models/symbolic/Mdp.cpp
+++ b/src/models/symbolic/Mdp.cpp
@@ -6,18 +6,18 @@ namespace storm {
             
             template<storm::dd::DdType Type>
             Mdp<Type>::Mdp(std::shared_ptr<storm::dd::DdManager<Type>> manager,
-                           storm::dd::Dd<Type> reachableStates,
-                           storm::dd::Dd<Type> initialStates,
-                           storm::dd::Dd<Type> transitionMatrix,
+                           storm::dd::Bdd<Type> reachableStates,
+                           storm::dd::Bdd<Type> initialStates,
+                           storm::dd::Add<Type> transitionMatrix,
                            std::set<storm::expressions::Variable> const& rowVariables,
-                           std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> rowExpressionAdapter,
+                           std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> rowExpressionAdapter,
                            std::set<storm::expressions::Variable> const& columnVariables,
-                           std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> columnExpressionAdapter,
+                           std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> columnExpressionAdapter,
                            std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs,
                            std::set<storm::expressions::Variable> const& nondeterminismVariables,
                            std::map<std::string, storm::expressions::Expression> labelToExpressionMap,
-                           boost::optional<storm::dd::Dd<Type>> const& optionalStateRewardVector,
-                           boost::optional<storm::dd::Dd<Type>> const& optionalTransitionRewardMatrix)
+                           boost::optional<storm::dd::Add<Type>> const& optionalStateRewardVector,
+                           boost::optional<storm::dd::Add<Type>> const& optionalTransitionRewardMatrix)
             : NondeterministicModel<Type>(storm::models::ModelType::Mdp, manager, reachableStates, initialStates, transitionMatrix, rowVariables, rowExpressionAdapter, columnVariables, columnExpressionAdapter, rowColumnMetaVariablePairs, nondeterminismVariables, labelToExpressionMap, optionalStateRewardVector, optionalTransitionRewardMatrix) {
                 // Intentionally left empty.
             }
diff --git a/src/models/symbolic/Mdp.h b/src/models/symbolic/Mdp.h
index 587bdfac7..e8c0aead2 100644
--- a/src/models/symbolic/Mdp.h
+++ b/src/models/symbolic/Mdp.h
@@ -43,18 +43,18 @@ namespace storm {
                  * @param optionalTransitionRewardMatrix The reward values associated with the transitions of the model.
                  */
                 Mdp(std::shared_ptr<storm::dd::DdManager<Type>> manager,
-                    storm::dd::Dd<Type> reachableStates,
-                    storm::dd::Dd<Type> initialStates,
-                    storm::dd::Dd<Type> transitionMatrix,
+                    storm::dd::Bdd<Type> reachableStates,
+                    storm::dd::Bdd<Type> initialStates,
+                    storm::dd::Add<Type> transitionMatrix,
                     std::set<storm::expressions::Variable> const& rowVariables,
-                    std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> rowExpressionAdapter,
+                    std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> rowExpressionAdapter,
                     std::set<storm::expressions::Variable> const& columnVariables,
-                    std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> columnExpressionAdapter,
+                    std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> columnExpressionAdapter,
                     std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs,
                     std::set<storm::expressions::Variable> const& nondeterminismVariables,
                     std::map<std::string, storm::expressions::Expression> labelToExpressionMap = std::map<std::string, storm::expressions::Expression>(),
-                    boost::optional<storm::dd::Dd<Type>> const& optionalStateRewardVector = boost::optional<storm::dd::Dd<Type>>(),
-                    boost::optional<storm::dd::Dd<Type>> const& optionalTransitionRewardMatrix = boost::optional<storm::dd::Dd<Type>>());
+                    boost::optional<storm::dd::Add<Type>> const& optionalStateRewardVector = boost::optional<storm::dd::Dd<Type>>(),
+                    boost::optional<storm::dd::Add<Type>> const& optionalTransitionRewardMatrix = boost::optional<storm::dd::Dd<Type>>());
                 
             };
             
diff --git a/src/models/symbolic/Model.cpp b/src/models/symbolic/Model.cpp
index 6778d8eb0..fc7f1aad6 100644
--- a/src/models/symbolic/Model.cpp
+++ b/src/models/symbolic/Model.cpp
@@ -6,17 +6,17 @@ namespace storm {
             template<storm::dd::DdType Type>
             Model<Type>::Model(storm::models::ModelType const& modelType,
                                std::shared_ptr<storm::dd::DdManager<Type>> manager,
-                               storm::dd::Dd<Type> reachableStates,
-                               storm::dd::Dd<Type> initialStates,
-                               storm::dd::Dd<Type> transitionMatrix,
+                               storm::dd::Bdd<Type> reachableStates,
+                               storm::dd::Bdd<Type> initialStates,
+                               storm::dd::Add<Type> transitionMatrix,
                                std::set<storm::expressions::Variable> const& rowVariables,
-                               std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> rowExpressionAdapter,
+                               std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> rowExpressionAdapter,
                                std::set<storm::expressions::Variable> const& columnVariables,
-                               std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> columnExpressionAdapter,
+                               std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> columnExpressionAdapter,
                                std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs,
                                std::map<std::string, storm::expressions::Expression> labelToExpressionMap,
-                               boost::optional<storm::dd::Dd<Type>> const& optionalStateRewardVector,
-                               boost::optional<storm::dd::Dd<Type>> const& optionalTransitionRewardMatrix)
+                               boost::optional<storm::dd::Add<Type>> const& optionalStateRewardVector,
+                               boost::optional<storm::dd::Add<Type>> const& optionalTransitionRewardMatrix)
             : ModelBase(modelType), manager(manager), reachableStates(reachableStates), initialStates(initialStates), transitionMatrix(transitionMatrix), rowVariables(rowVariables), rowExpressionAdapter(rowExpressionAdapter), columnVariables(columnVariables), columnExpressionAdapter(columnExpressionAdapter), rowColumnMetaVariablePairs(rowColumnMetaVariablePairs), labelToExpressionMap(labelToExpressionMap), stateRewardVector(optionalStateRewardVector), transitionRewardMatrix(optionalTransitionRewardMatrix) {
                 // Intentionally left empty.
             }
@@ -42,23 +42,23 @@ namespace storm {
             }
             
             template<storm::dd::DdType Type>
-            storm::dd::Dd<Type> const& Model<Type>::getReachableStates() const {
+            storm::dd::Bdd<Type> const& Model<Type>::getReachableStates() const {
                 return reachableStates;
             }
             
             template<storm::dd::DdType Type>
-            storm::dd::Dd<Type> const& Model<Type>::getInitialStates() const {
+            storm::dd::Bdd<Type> const& Model<Type>::getInitialStates() const {
                 return initialStates;
             }
             
             template<storm::dd::DdType Type>
-            storm::dd::Dd<Type> Model<Type>::getStates(std::string const& label) const {
+            storm::dd::Bdd<Type> Model<Type>::getStates(std::string const& label) const {
                 STORM_LOG_THROW(labelToExpressionMap.find(label) != labelToExpressionMap.end(), storm::exceptions::InvalidArgumentException, "The label " << label << " is invalid for the labeling of the model.");
                 return rowExpressionAdapter->translateExpression(labelToExpressionMap.at(label)).toBdd() && this->reachableStates;
             }
             
             template<storm::dd::DdType Type>
-            storm::dd::Dd<Type> Model<Type>::getStates(storm::expressions::Expression const& expression) const {
+            storm::dd::Bdd<Type> Model<Type>::getStates(storm::expressions::Expression const& expression) const {
                 return rowExpressionAdapter->translateExpression(expression).toBdd() && this->reachableStates;
             }
             
@@ -68,27 +68,27 @@ namespace storm {
             }
             
             template<storm::dd::DdType Type>
-            storm::dd::Dd<Type> const& Model<Type>::getTransitionMatrix() const {
+            storm::dd::Add<Type> const& Model<Type>::getTransitionMatrix() const {
                 return transitionMatrix;
             }
             
             template<storm::dd::DdType Type>
-            storm::dd::Dd<Type>& Model<Type>::getTransitionMatrix() {
+            storm::dd::Add<Type>& Model<Type>::getTransitionMatrix() {
                 return transitionMatrix;
             }
             
             template<storm::dd::DdType Type>
-            storm::dd::Dd<Type> const& Model<Type>::getTransitionRewardMatrix() const {
+            storm::dd::Add<Type> const& Model<Type>::getTransitionRewardMatrix() const {
                 return transitionRewardMatrix.get();
             }
             
             template<storm::dd::DdType Type>
-            storm::dd::Dd<Type>& Model<Type>::getTransitionRewardMatrix() {
+            storm::dd::Add<Type>& Model<Type>::getTransitionRewardMatrix() {
                 return transitionRewardMatrix.get();
             }
             
             template<storm::dd::DdType Type>
-            storm::dd::Dd<Type> const& Model<Type>::getStateRewardVector() const {
+            storm::dd::Add<Type> const& Model<Type>::getStateRewardVector() const {
                 return stateRewardVector.get();
             }
             
@@ -123,7 +123,7 @@ namespace storm {
             }
             
             template<storm::dd::DdType Type>
-            void Model<Type>::setTransitionMatrix(storm::dd::Dd<Type> const& transitionMatrix) {
+            void Model<Type>::setTransitionMatrix(storm::dd::Add<Type> const& transitionMatrix) {
                 this->transitionMatrix = transitionMatrix;
             }
             
diff --git a/src/models/symbolic/Model.h b/src/models/symbolic/Model.h
index 52dee50cb..d9bf5eb02 100644
--- a/src/models/symbolic/Model.h
+++ b/src/models/symbolic/Model.h
@@ -7,7 +7,7 @@
 
 #include "src/storage/expressions/Expression.h"
 #include "src/storage/expressions/Variable.h"
-#include "src/adapters/DdExpressionAdapter.h"
+#include "src/adapters/AddExpressionAdapter.h"
 #include "src/storage/dd/CuddDd.h"
 #include "src/storage/dd/CuddDdManager.h"
 #include "src/models/ModelBase.h"
@@ -52,17 +52,17 @@ namespace storm {
                  */
                 Model(storm::models::ModelType const& modelType,
                       std::shared_ptr<storm::dd::DdManager<Type>> manager,
-                      storm::dd::Dd<Type> reachableStates,
-                      storm::dd::Dd<Type> initialStates,
-                      storm::dd::Dd<Type> transitionMatrix,
+                      storm::dd::Bdd<Type> reachableStates,
+                      storm::dd::Bdd<Type> initialStates,
+                      storm::dd::Add<Type> transitionMatrix,
                       std::set<storm::expressions::Variable> const& rowVariables,
-                      std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> rowExpressionAdapter,
+                      std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> rowExpressionAdapter,
                       std::set<storm::expressions::Variable> const& columnVariables,
-                      std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> columnExpressionAdapter,
+                      std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> columnExpressionAdapter,
                       std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs,
                       std::map<std::string, storm::expressions::Expression> labelToExpressionMap = std::map<std::string, storm::expressions::Expression>(),
-                      boost::optional<storm::dd::Dd<Type>> const& optionalStateRewardVector = boost::optional<storm::dd::Dd<Type>>(),
-                      boost::optional<storm::dd::Dd<Type>> const& optionalTransitionRewardMatrix = boost::optional<storm::dd::Dd<Type>>());
+                      boost::optional<storm::dd::Add<Type>> const& optionalStateRewardVector = boost::optional<storm::dd::Dd<Type>>(),
+                      boost::optional<storm::dd::Add<Type>> const& optionalTransitionRewardMatrix = boost::optional<storm::dd::Dd<Type>>());
                 
                 virtual uint_fast64_t getNumberOfStates() const override;
                 
@@ -87,14 +87,14 @@ namespace storm {
                  *
                  * @return The reachble states of the model.
                  */
-                storm::dd::Dd<Type> const& getReachableStates() const;
+                storm::dd::Bdd<Type> const& getReachableStates() const;
                 
                 /*!
                  * Retrieves the initial states of the model.
                  *
                  * @return The initial states of the model.
                  */
-                storm::dd::Dd<Type> const& getInitialStates() const;
+                storm::dd::Bdd<Type> const& getInitialStates() const;
                 
                 /*!
                  * Returns the sets of states labeled with the given label.
@@ -102,7 +102,7 @@ namespace storm {
                  * @param label The label for which to get the labeled states.
                  * @return The set of states labeled with the requested label in the form of a bit vector.
                  */
-                storm::dd::Dd<Type> getStates(std::string const& label) const;
+                storm::dd::Bdd<Type> getStates(std::string const& label) const;
                 
                 /*!
                  * Returns the set of states labeled satisfying the given expression (that must be of boolean type).
@@ -110,7 +110,7 @@ namespace storm {
                  * @param expression The expression that needs to hold in the states.
                  * @return The set of states labeled satisfying the given expression.
                  */
-                storm::dd::Dd<Type> getStates(storm::expressions::Expression const& expression) const;
+                storm::dd::Bdd<Type> getStates(storm::expressions::Expression const& expression) const;
                 
                 /*!
                  * Retrieves whether the given label is a valid label in this model.
@@ -125,14 +125,14 @@ namespace storm {
                  *
                  * @return A matrix representing the transitions of the model.
                  */
-                storm::dd::Dd<Type> const& getTransitionMatrix() const;
+                storm::dd::Add<Type> const& getTransitionMatrix() const;
                 
                 /*!
                  * Retrieves the matrix representing the transitions of the model.
                  *
                  * @return A matrix representing the transitions of the model.
                  */
-                storm::dd::Dd<Type>& getTransitionMatrix();
+                storm::dd::Add<Type>& getTransitionMatrix();
                 
                 /*!
                  * Retrieves the matrix representing the transition rewards of the model. Note that calling this method
@@ -140,7 +140,7 @@ namespace storm {
                  *
                  * @return The matrix representing the transition rewards of the model.
                  */
-                storm::dd::Dd<Type> const& getTransitionRewardMatrix() const;
+                storm::dd::Add<Type> const& getTransitionRewardMatrix() const;
                 
                 /*!
                  * Retrieves the matrix representing the transition rewards of the model. Note that calling this method
@@ -148,7 +148,7 @@ namespace storm {
                  *
                  * @return The matrix representing the transition rewards of the model.
                  */
-                storm::dd::Dd<Type>& getTransitionRewardMatrix();
+                storm::dd::Add<Type>& getTransitionRewardMatrix();
                 
                 /*!
                  * Retrieves a vector representing the state rewards of the model. Note that calling this method is only
@@ -156,7 +156,7 @@ namespace storm {
                  *
                  * @return A vector representing the state rewards of the model.
                  */
-                storm::dd::Dd<Type> const& getStateRewardVector() const;
+                storm::dd::Add<Type> const& getStateRewardVector() const;
                 
                 /*!
                  * Retrieves whether this model has state rewards.
@@ -206,7 +206,7 @@ namespace storm {
                  *
                  * @param transitionMatrix The new transition matrix of the model.
                  */
-                void setTransitionMatrix(storm::dd::Dd<Type> const& transitionMatrix);
+                void setTransitionMatrix(storm::dd::Add<Type> const& transitionMatrix);
                 
                 /*!
                  * Retrieves the mapping of labels to their defining expressions.
@@ -220,25 +220,25 @@ namespace storm {
                 std::shared_ptr<storm::dd::DdManager<Type>> manager;
                 
                 // A vector representing the reachable states of the model.
-                storm::dd::Dd<Type> reachableStates;
+                storm::dd::Bdd<Type> reachableStates;
                 
                 // A vector representing the initial states of the model.
-                storm::dd::Dd<Type> initialStates;
+                storm::dd::Bdd<Type> initialStates;
                 
                 // A matrix representing transition relation.
-                storm::dd::Dd<Type> transitionMatrix;
+                storm::dd::Add<Type> transitionMatrix;
                 
                 // The meta variables used to encode the rows of the transition matrix.
                 std::set<storm::expressions::Variable> rowVariables;
                 
                 // An adapter that can translate expressions to DDs over the row meta variables.
-                std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> rowExpressionAdapter;
+                std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> rowExpressionAdapter;
                 
                 // The meta variables used to encode the columns of the transition matrix.
                 std::set<storm::expressions::Variable> columnVariables;
                 
                 // An adapter that can translate expressions to DDs over the column meta variables.
-                std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> columnExpressionAdapter;
+                std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> columnExpressionAdapter;
                 
                 // A vector holding all pairs of row and column meta variable pairs. This is used to swap the variables
                 // in the DDs from row to column variables and vice versa.
@@ -248,10 +248,10 @@ namespace storm {
                 std::map<std::string, storm::expressions::Expression> labelToExpressionMap;
                 
                 // If set, a vector representing the rewards of the states.
-                boost::optional<storm::dd::Dd<Type>> stateRewardVector;
+                boost::optional<storm::dd::Add<Type>> stateRewardVector;
                 
                 // If set, a matrix representing the rewards of transitions.
-                boost::optional<storm::dd::Dd<Type>> transitionRewardMatrix;
+                boost::optional<storm::dd::Add<Type>> transitionRewardMatrix;
             };
             
         } // namespace symbolic
diff --git a/src/models/symbolic/NondeterministicModel.cpp b/src/models/symbolic/NondeterministicModel.cpp
index 59a8381e5..5572c3fe2 100644
--- a/src/models/symbolic/NondeterministicModel.cpp
+++ b/src/models/symbolic/NondeterministicModel.cpp
@@ -7,18 +7,18 @@ namespace storm {
             template<storm::dd::DdType Type>
             NondeterministicModel<Type>::NondeterministicModel(storm::models::ModelType const& modelType,
                                                                std::shared_ptr<storm::dd::DdManager<Type>> manager,
-                                                               storm::dd::Dd<Type> reachableStates,
-                                                               storm::dd::Dd<Type> initialStates,
-                                                               storm::dd::Dd<Type> transitionMatrix,
+                                                               storm::dd::Bdd<Type> reachableStates,
+                                                               storm::dd::Bdd<Type> initialStates,
+                                                               storm::dd::Add<Type> transitionMatrix,
                                                                std::set<storm::expressions::Variable> const& rowVariables,
-                                                               std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> rowExpressionAdapter,
+                                                               std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> rowExpressionAdapter,
                                                                std::set<storm::expressions::Variable> const& columnVariables,
-                                                               std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> columnExpressionAdapter,
+                                                               std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> columnExpressionAdapter,
                                                                std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs,
                                                                std::set<storm::expressions::Variable> const& nondeterminismVariables,
                                                                std::map<std::string, storm::expressions::Expression> labelToExpressionMap,
-                                                               boost::optional<storm::dd::Dd<Type>> const& optionalStateRewardVector,
-                                                               boost::optional<storm::dd::Dd<Type>> const& optionalTransitionRewardMatrix)
+                                                               boost::optional<storm::dd::Add<Type>> const& optionalStateRewardVector,
+                                                               boost::optional<storm::dd::Add<Type>> const& optionalTransitionRewardMatrix)
             : Model<Type>(modelType, manager, reachableStates, initialStates, transitionMatrix, rowVariables, rowExpressionAdapter, columnVariables, columnExpressionAdapter, rowColumnMetaVariablePairs, labelToExpressionMap, optionalStateRewardVector, optionalTransitionRewardMatrix), nondeterminismVariables(nondeterminismVariables) {
                 
                 // Prepare the mask of illegal nondeterministic choices.
@@ -31,7 +31,7 @@ namespace storm {
                 std::set<storm::expressions::Variable> rowAndNondeterminsmVariables;
                 std::set_union(this->getNondeterminismVariables().begin(), this->getNondeterminismVariables().end(), this->getRowVariables().begin(), this->getRowVariables().end(), std::inserter(rowAndNondeterminsmVariables, rowAndNondeterminsmVariables.begin()));
                 
-                storm::dd::Dd<Type> tmp = this->getTransitionMatrix().notZero().existsAbstract(this->getColumnVariables()).toMtbdd().sumAbstract(rowAndNondeterminsmVariables);
+                storm::dd::Add<Type> tmp = this->getTransitionMatrix().notZero().existsAbstract(this->getColumnVariables()).toAdd().sumAbstract(rowAndNondeterminsmVariables);
                 return static_cast<uint_fast64_t>(tmp.getValue());
             }
             
@@ -41,7 +41,7 @@ namespace storm {
             }
             
             template<storm::dd::DdType Type>
-            storm::dd::Dd<Type> const& NondeterministicModel<Type>::getIllegalMask() const {
+            storm::dd::Bdd<Type> const& NondeterministicModel<Type>::getIllegalMask() const {
                 return illegalMask;
             }
             
diff --git a/src/models/symbolic/NondeterministicModel.h b/src/models/symbolic/NondeterministicModel.h
index 1e6d36cd6..16be5ce99 100644
--- a/src/models/symbolic/NondeterministicModel.h
+++ b/src/models/symbolic/NondeterministicModel.h
@@ -44,18 +44,18 @@ namespace storm {
                  */
                 NondeterministicModel(storm::models::ModelType const& modelType,
                                       std::shared_ptr<storm::dd::DdManager<Type>> manager,
-                                      storm::dd::Dd<Type> reachableStates,
-                                      storm::dd::Dd<Type> initialStates,
-                                      storm::dd::Dd<Type> transitionMatrix,
+                                      storm::dd::Bdd<Type> reachableStates,
+                                      storm::dd::Bdd<Type> initialStates,
+                                      storm::dd::Add<Type> transitionMatrix,
                                       std::set<storm::expressions::Variable> const& rowVariables,
-                                      std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> rowExpressionAdapter,
+                                      std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> rowExpressionAdapter,
                                       std::set<storm::expressions::Variable> const& columnVariables,
-                                      std::shared_ptr<storm::adapters::DdExpressionAdapter<Type>> columnExpressionAdapter,
+                                      std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> columnExpressionAdapter,
                                       std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs,
                                       std::set<storm::expressions::Variable> const& nondeterminismVariables,
                                       std::map<std::string, storm::expressions::Expression> labelToExpressionMap = std::map<std::string, storm::expressions::Expression>(),
-                                      boost::optional<storm::dd::Dd<Type>> const& optionalStateRewardVector = boost::optional<storm::dd::Dd<Type>>(),
-                                      boost::optional<storm::dd::Dd<Type>> const& optionalTransitionRewardMatrix = boost::optional<storm::dd::Dd<Type>>());
+                                      boost::optional<storm::dd::Add<Type>> const& optionalStateRewardVector = boost::optional<storm::dd::Dd<Type>>(),
+                                      boost::optional<storm::dd::Add<Type>> const& optionalTransitionRewardMatrix = boost::optional<storm::dd::Dd<Type>>());
                 
                 /*!
                  * Retrieves the number of nondeterministic choices in the model.
@@ -76,7 +76,7 @@ namespace storm {
                  *
                  * @return A BDD characterizing all illegal nondeterminism encodings in the model.
                  */
-                storm::dd::Dd<Type> const& getIllegalMask() const;
+                storm::dd::Bdd<Type> const& getIllegalMask() const;
                 
                 virtual void printModelInformationToStream(std::ostream& out) const override;
                 
@@ -86,7 +86,7 @@ namespace storm {
                 std::set<storm::expressions::Variable> nondeterminismVariables;
                 
                 // A mask that characterizes all legal nondeterministic choices.
-                storm::dd::Dd<Type> illegalMask;
+                storm::dd::Bdd<Type> illegalMask;
             };
             
         } // namespace symbolic
diff --git a/src/storage/dd/CuddAdd.cpp b/src/storage/dd/CuddAdd.cpp
index 31476bc8e..cc04c5f76 100644
--- a/src/storage/dd/CuddAdd.cpp
+++ b/src/storage/dd/CuddAdd.cpp
@@ -1,7 +1,8 @@
 #include <cstring>
 #include <algorithm>
 
-#include "src/storage/dd/CuddDd.h"
+#include "src/storage/dd/CuddAdd.h"
+#include "src/storage/dd/CuddBdd.h"
 #include "src/storage/dd/CuddOdd.h"
 #include "src/storage/dd/CuddDdManager.h"
 #include "src/utility/vector.h"
@@ -13,329 +14,156 @@
 
 namespace storm {
     namespace dd {
-        Dd<DdType::CUDD>::Dd(std::shared_ptr<DdManager<DdType::CUDD> const> ddManager, BDD cuddDd, std::set<storm::expressions::Variable> const& containedMetaVariables) : ddManager(ddManager), cuddDd(cuddDd), containedMetaVariables(containedMetaVariables) {
+        Add<DdType::CUDD>::Add(std::shared_ptr<DdManager<DdType::CUDD> const> ddManager, ADD cuddAdd, std::set<storm::expressions::Variable> const& containedMetaVariables) : Dd<DdType::CUDD>(ddManager, containedMetaVariables), cuddAdd(cuddAdd) {
             // Intentionally left empty.
         }
         
-        Dd<DdType::CUDD>::Dd(std::shared_ptr<DdManager<DdType::CUDD> const> ddManager, ADD cuddDd, std::set<storm::expressions::Variable> const& containedMetaVariables) : ddManager(ddManager), cuddDd(cuddDd), containedMetaVariables(containedMetaVariables) {
-            // Intentionally left empty.
-        }
-        
-        bool Dd<DdType::CUDD>::isBdd() const {
-            return this->cuddDd.which() == 0;
+        Bdd<DdType::CUDD> Add<DdType::CUDD>::toBdd() const {
+            return Bdd<DdType::CUDD>(this->getDdManager(), this->getCuddAdd().BddPattern(), this->getContainedMetaVariables());
         }
         
-        bool Dd<DdType::CUDD>::isMtbdd() const {
-            return this->cuddDd.which() == 1;
-        }
-        
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::toBdd() const {
-            if (this->isBdd()) {
-                return *this;
-            } else {
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().BddPattern(), this->containedMetaVariables);
-            }
+        ADD Add<DdType::CUDD>::getCuddAdd() const {
+            return this->cuddAdd;
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::toMtbdd() const {
-            if (this->isMtbdd()) {
-                return *this;
-            } else {
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().Add(), this->containedMetaVariables);
-            }
+        DdNode* Add<DdType::CUDD>::getCuddDdNode() const {
+            return this->getCuddAdd().getNode();
         }
         
-        BDD Dd<DdType::CUDD>::getCuddBdd() const {
-            if (this->isBdd()) {
-                return boost::get<BDD>(this->cuddDd);
-            } else {
-                STORM_LOG_WARN_COND(false, "Implicitly converting MTBDD to BDD.");
-                return this->getCuddMtbdd().BddPattern();
-            }
+        bool Add<DdType::CUDD>::operator==(Add<DdType::CUDD> const& other) const {
+            return this->getCuddAdd() == other.getCuddAdd();
         }
         
-        ADD Dd<DdType::CUDD>::getCuddMtbdd() const {
-            if (this->isMtbdd()) {
-                return boost::get<ADD>(this->cuddDd);
-            } else {
-                STORM_LOG_WARN_COND(false, "Implicitly converting BDD to MTBDD.");
-                return this->getCuddBdd().Add();
-            }
-        }
-        
-        ABDD const& Dd<DdType::CUDD>::getCuddDd() const {
-            if (this->isBdd()) {
-                return static_cast<ABDD const&>(boost::get<BDD>(this->cuddDd));
-            } else {
-                return static_cast<ABDD const&>(boost::get<ADD>(this->cuddDd));
-            }
-        }
-        
-        DdNode* Dd<DdType::CUDD>::getCuddDdNode() const {
-            if (this->isBdd()) {
-                return this->getCuddBdd().getNode();
-            } else {
-                return this->getCuddMtbdd().getNode();
-            }
-        }
-        
-        bool Dd<DdType::CUDD>::operator==(Dd<DdType::CUDD> const& other) const {
-            if (this->isBdd()) {
-                if (other.isBdd()) {
-                    return this->getCuddBdd() == other.getCuddBdd();
-                } else {
-                    return false;
-                }
-            } else {
-                if (other.isMtbdd()) {
-                    return this->getCuddMtbdd() == other.getCuddMtbdd();
-                } else {
-                    return false;
-                }
-            }
-        }
-        
-        bool Dd<DdType::CUDD>::operator!=(Dd<DdType::CUDD> const& other) const {
+        bool Add<DdType::CUDD>::operator!=(Add<DdType::CUDD> const& other) const {
             return !(*this == other);
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::ite(Dd<DdType::CUDD> const& thenDd, Dd<DdType::CUDD> const& elseDd) const {
-            std::set<storm::expressions::Variable> metaVariableNames(this->getContainedMetaVariables());
-            metaVariableNames.insert(thenDd.getContainedMetaVariables().begin(), thenDd.getContainedMetaVariables().end());
-            metaVariableNames.insert(elseDd.getContainedMetaVariables().begin(), elseDd.getContainedMetaVariables().end());
+        Add<DdType::CUDD> Add<DdType::CUDD>::ite(Add<DdType::CUDD> const& thenDd, Add<DdType::CUDD> const& elseDd) const {
+            std::set<storm::expressions::Variable> metaVariableNames;
+            std::set_union(thenDd.getContainedMetaVariables().begin(), thenDd.getContainedMetaVariables().end(), elseDd.getContainedMetaVariables().begin(), elseDd.getContainedMetaVariables().end(), std::inserter(metaVariableNames, metaVariableNames.begin()));
+            metaVariableNames.insert(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end());
             
-            // If all involved DDs are BDDs, the result is also going to be a BDD.
-            if (this->isBdd() && thenDd.isBdd() && elseDd.isBdd()) {
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().Ite(thenDd.getCuddBdd(), elseDd.getCuddBdd()), metaVariableNames);
-            } else {
-                return Dd<DdType::CUDD>(this->getDdManager(), this->toMtbdd().getCuddMtbdd().Ite(thenDd.toMtbdd().getCuddMtbdd(), elseDd.toMtbdd().getCuddMtbdd()), metaVariableNames);
-            }
+            return Add<DdType::CUDD>(this->getDdManager(), this->getCuddAdd().Ite(thenDd.getCuddAdd(), elseDd.getCuddAdd()), metaVariableNames);
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::operator+(Dd<DdType::CUDD> const& other) const {
-            Dd<DdType::CUDD> result(*this);
-            result += other;
-            return result;
-        }
-        
-        Dd<DdType::CUDD>& Dd<DdType::CUDD>::operator+=(Dd<DdType::CUDD> const& other) {
-            STORM_LOG_WARN_COND(this->isMtbdd() && other.isMtbdd(), "Performing addition on BDDs.");
-            this->getContainedMetaVariables().insert(other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end());
-            this->cuddDd = this->getCuddMtbdd() + other.getCuddMtbdd();
-            return *this;
+        Add<DdType::CUDD> Add<DdType::CUDD>::operator!() const {
+            return Add<DdType::CUDD>(this->getDdManager(), ~this->getCuddAdd(), this->getContainedMetaVariables());
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::operator*(Dd<DdType::CUDD> const& other) const {
-            Dd<DdType::CUDD> result(*this);
-            result *= other;
+        Add<DdType::CUDD> Add<DdType::CUDD>::operator||(Add<DdType::CUDD> const& other) const {
+            Add<DdType::CUDD> result(*this);
+            result |= other;
             return result;
         }
         
-        Dd<DdType::CUDD>& Dd<DdType::CUDD>::operator*=(Dd<DdType::CUDD> const& other) {
-            this->getContainedMetaVariables().insert(other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end());
-            if (this->isMtbdd() && other.isMtbdd()) {
-                this->cuddDd = this->getCuddMtbdd() * other.getCuddMtbdd();
-            } else if (this->isBdd() && other.isBdd()) {
-                this->cuddDd = this->getCuddBdd() & other.getCuddBdd();
-            } else {
-                STORM_LOG_WARN_COND(false, "Performing multiplication on two DDs of different type.");
-                this->cuddDd = this->getCuddMtbdd() * other.getCuddMtbdd();
-            }
+        Add<DdType::CUDD>& Add<DdType::CUDD>::operator|=(Add<DdType::CUDD> const& other) {
+            this->addMetaVariables(other.getContainedMetaVariables());
+            this->cuddAdd = this->getCuddAdd() | other.getCuddAdd();
             return *this;
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::operator-(Dd<DdType::CUDD> const& other) const {
-            STORM_LOG_WARN_COND(this->isMtbdd() && other.isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            Dd<DdType::CUDD> result(*this);
-            result -= other;
+        Add<DdType::CUDD> Add<DdType::CUDD>::operator+(Add<DdType::CUDD> const& other) const {
+            Add<DdType::CUDD> result(*this);
+            result += other;
             return result;
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::operator-() const {
-            STORM_LOG_WARN_COND(this->isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            return this->getDdManager()->getZero(true) - *this;
-        }
-        
-        Dd<DdType::CUDD>& Dd<DdType::CUDD>::operator-=(Dd<DdType::CUDD> const& other) {
-            STORM_LOG_WARN_COND(this->isMtbdd() && other.isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            this->cuddDd = this->getCuddMtbdd() - other.getCuddMtbdd();
-            this->getContainedMetaVariables().insert(other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end());
+        Add<DdType::CUDD>& Add<DdType::CUDD>::operator+=(Add<DdType::CUDD> const& other) {
+            this->addMetaVariables(other.getContainedMetaVariables());
+            this->cuddAdd = this->getCuddAdd() + other.getCuddAdd();
             return *this;
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::operator/(Dd<DdType::CUDD> const& other) const {
-            STORM_LOG_WARN_COND(this->isMtbdd() && other.isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            Dd<DdType::CUDD> result(*this);
-            result /= other;
+        Add<DdType::CUDD> Add<DdType::CUDD>::operator*(Add<DdType::CUDD> const& other) const {
+            Add<DdType::CUDD> result(*this);
+            result *= other;
             return result;
         }
         
-        Dd<DdType::CUDD>& Dd<DdType::CUDD>::operator/=(Dd<DdType::CUDD> const& other) {
-            STORM_LOG_WARN_COND(this->isMtbdd() && other.isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            this->cuddDd = this->getCuddMtbdd().Divide(other.getCuddMtbdd());
-            this->getContainedMetaVariables().insert(other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end());
+        Add<DdType::CUDD>& Add<DdType::CUDD>::operator*=(Add<DdType::CUDD> const& other) {
+            this->addMetaVariables(other.getContainedMetaVariables());
+            this->cuddAdd = this->getCuddAdd() * other.getCuddAdd();
             return *this;
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::operator!() const {
-            Dd<DdType::CUDD> result(*this);
-            result.complement();
+        Add<DdType::CUDD> Add<DdType::CUDD>::operator-(Add<DdType::CUDD> const& other) const {
+            Add<DdType::CUDD> result(*this);
+            result -= other;
             return result;
         }
         
-        Dd<DdType::CUDD>& Dd<DdType::CUDD>::complement() {
-            if (this->isBdd()) {
-                this->cuddDd = ~this->getCuddBdd();
-            } else {
-                this->cuddDd = ~this->getCuddMtbdd();
-            }
-            return *this;
+        Add<DdType::CUDD> Add<DdType::CUDD>::operator-() const {
+            return this->getDdManager()->getAddZero() - *this;
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::operator&&(Dd<DdType::CUDD> const& other) const {
-            Dd<DdType::CUDD> result(*this);
-            result &= other;
-            return result;
-        }
-        
-        Dd<DdType::CUDD>& Dd<DdType::CUDD>::operator&=(Dd<DdType::CUDD> const& other) {
-            this->getContainedMetaVariables().insert(other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end());
-            if (this->isBdd() && other.isBdd()) {
-                this->cuddDd = this->getCuddBdd() & other.getCuddBdd();
-            } else if (this->isMtbdd() && other.isMtbdd()) {
-                // We also tolerate (without a warning) if the two arguments are MTBDDs. The caller has to make sure that
-                // the two given DDs are 0-1-MTBDDs, because the operation may produce wrong results otherwise.
-                this->cuddDd = this->getCuddMtbdd() & other.getCuddMtbdd();
-            } else {
-                STORM_LOG_WARN_COND(false, "Performing logical and on two DDs of different type.");
-                this->cuddDd = this->getCuddBdd() & other.getCuddBdd();
-            }
+        Add<DdType::CUDD>& Add<DdType::CUDD>::operator-=(Add<DdType::CUDD> const& other) {
+            this->addMetaVariables(other.getContainedMetaVariables());
+            this->cuddAdd = this->getCuddAdd() - other.getCuddAdd();
             return *this;
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::operator||(Dd<DdType::CUDD> const& other) const {
-            Dd<DdType::CUDD> result(*this);
-            result |= other;
+        Add<DdType::CUDD> Add<DdType::CUDD>::operator/(Add<DdType::CUDD> const& other) const {
+            Add<DdType::CUDD> result(*this);
+            result /= other;
             return result;
         }
         
-        Dd<DdType::CUDD>& Dd<DdType::CUDD>::operator|=(Dd<DdType::CUDD> const& other) {
-            this->getContainedMetaVariables().insert(other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end());
-            if (this->isBdd() && other.isBdd()) {
-                this->cuddDd = this->getCuddBdd() | other.getCuddBdd();
-            } else if (this->isMtbdd() && other.isMtbdd()) {
-                // We also tolerate (without a warning) if the two arguments are MTBDDs. The caller has to make sure that
-                // the two given DDs are 0-1-MTBDDs, because the operation may produce wrong results otherwise.
-                this->cuddDd = this->getCuddMtbdd() | other.getCuddMtbdd();
-            } else {
-                STORM_LOG_WARN_COND(false, "Performing logical and on two DDs of different type.");
-                this->cuddDd = this->getCuddBdd() & other.getCuddBdd();
-            }
-            return *this;
-            
-            STORM_LOG_WARN_COND(this->isBdd() && other.isBdd(), "Performing logical operation on MTBDD(s).");
-            this->cuddDd = this->getCuddBdd() | other.getCuddBdd();
-            this->getContainedMetaVariables().insert(other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end());
+        Add<DdType::CUDD>& Add<DdType::CUDD>::operator/=(Add<DdType::CUDD> const& other) {
+            this->addMetaVariables(other.getContainedMetaVariables());
+            this->cuddAdd = this->getCuddAdd().Divide(other.getCuddAdd());
             return *this;
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::iff(Dd<DdType::CUDD> const& other) const {
-            std::set<storm::expressions::Variable> metaVariables(this->getContainedMetaVariables());
-            metaVariables.insert(other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end());
-            if (this->isBdd() && other.isBdd()) {
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().Xnor(other.getCuddBdd()), metaVariables);
-            } else if (this->isMtbdd() && other.isMtbdd()) {
-                // We also tolerate (without a warning) if the two arguments are MTBDDs. The caller has to make sure that
-                // the two given DDs are 0-1-MTBDDs, because the operation may produce wrong results otherwise.
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().Xnor(other.getCuddMtbdd()), metaVariables);
-            } else {
-                STORM_LOG_WARN_COND(false, "Performing logical iff on two DDs of different type.");
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().Xnor(other.getCuddBdd()), metaVariables);
-            }
-        }
-        
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::exclusiveOr(Dd<DdType::CUDD> const& other) const {
-            std::set<storm::expressions::Variable> metaVariables(this->getContainedMetaVariables());
-            metaVariables.insert(other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end());
-            if (this->isBdd() && other.isBdd()) {
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().Xor(other.getCuddBdd()), metaVariables);
-            } else if (this->isMtbdd() && other.isMtbdd()) {
-                // We also tolerate (without a warning) if the two arguments are MTBDDs. The caller has to make sure that
-                // the two given DDs are 0-1-MTBDDs, because the operation may produce wrong results otherwise.
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().Xor(other.getCuddMtbdd()), metaVariables);
-            } else {
-                STORM_LOG_WARN_COND(false, "Performing logical iff on two DDs of different type.");
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().Xor(other.getCuddBdd()), metaVariables);
-            }
-        }
-        
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::implies(Dd<DdType::CUDD> const& other) const {
-            std::set<storm::expressions::Variable> metaVariables(this->getContainedMetaVariables());
-            metaVariables.insert(other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end());
-            STORM_LOG_WARN_COND(this->isBdd() && other.isBdd(), "Performing logical operatiorn on MTBDDs.");
-            return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().Ite(other.getCuddBdd(), this->getDdManager()->getOne().getCuddBdd()), metaVariables);
-        }
-        
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::equals(Dd<DdType::CUDD> const& other) const {
-            STORM_LOG_WARN_COND(this->isMtbdd() && other.isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            std::set<storm::expressions::Variable> metaVariables(this->getContainedMetaVariables());
-            metaVariables.insert(other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end());
-            return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().Equals(other.getCuddMtbdd()), metaVariables);
+        Add<DdType::CUDD> Add<DdType::CUDD>::equals(Add<DdType::CUDD> const& other) const {
+            std::set<storm::expressions::Variable> metaVariables;
+            std::set_union(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end(), other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end(), std::inserter(metaVariables, metaVariables.begin()));
+            return Add<DdType::CUDD>(this->getDdManager(), this->getCuddAdd().Equals(other.getCuddAdd()), metaVariables);
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::notEquals(Dd<DdType::CUDD> const& other) const {
-            STORM_LOG_WARN_COND(this->isMtbdd() && other.isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            std::set<storm::expressions::Variable> metaVariables(this->getContainedMetaVariables());
-            metaVariables.insert(other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end());
-            return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().NotEquals(other.getCuddMtbdd()), metaVariables);
+        Add<DdType::CUDD> Add<DdType::CUDD>::notEquals(Add<DdType::CUDD> const& other) const {
+            std::set<storm::expressions::Variable> metaVariables;
+            std::set_union(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end(), other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end(), std::inserter(metaVariables, metaVariables.begin()));
+            return Add<DdType::CUDD>(this->getDdManager(), this->getCuddAdd().NotEquals(other.getCuddAdd()), metaVariables);
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::less(Dd<DdType::CUDD> const& other) const {
-            STORM_LOG_WARN_COND(this->isMtbdd() && other.isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            std::set<storm::expressions::Variable> metaVariables(this->getContainedMetaVariables());
-            metaVariables.insert(other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end());
-            return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().LessThan(other.getCuddMtbdd()), metaVariables);
+        Add<DdType::CUDD> Add<DdType::CUDD>::less(Add<DdType::CUDD> const& other) const {
+            std::set<storm::expressions::Variable> metaVariables;
+            std::set_union(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end(), other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end(), std::inserter(metaVariables, metaVariables.begin()));
+            return Add<DdType::CUDD>(this->getDdManager(), this->getCuddAdd().LessThan(other.getCuddAdd()), metaVariables);
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::lessOrEqual(Dd<DdType::CUDD> const& other) const {
-            STORM_LOG_WARN_COND(this->isMtbdd() && other.isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            std::set<storm::expressions::Variable> metaVariables(this->getContainedMetaVariables());
-            metaVariables.insert(other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end());
-            return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().LessThanOrEqual(other.getCuddMtbdd()), metaVariables);
+        Add<DdType::CUDD> Add<DdType::CUDD>::lessOrEqual(Add<DdType::CUDD> const& other) const {
+            std::set<storm::expressions::Variable> metaVariables;
+            std::set_union(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end(), other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end(), std::inserter(metaVariables, metaVariables.begin()));
+            return Add<DdType::CUDD>(this->getDdManager(), this->getCuddAdd().LessThanOrEqual(other.getCuddAdd()), metaVariables);
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::greater(Dd<DdType::CUDD> const& other) const {
-            STORM_LOG_WARN_COND(this->isMtbdd() && other.isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            std::set<storm::expressions::Variable> metaVariables(this->getContainedMetaVariables());
-            metaVariables.insert(other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end());
-            return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().GreaterThan(other.getCuddMtbdd()), metaVariables);
+        Add<DdType::CUDD> Add<DdType::CUDD>::greater(Add<DdType::CUDD> const& other) const {
+            std::set<storm::expressions::Variable> metaVariables;
+            std::set_union(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end(), other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end(), std::inserter(metaVariables, metaVariables.begin()));
+            return Add<DdType::CUDD>(this->getDdManager(), this->getCuddAdd().GreaterThan(other.getCuddAdd()), metaVariables);
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::greaterOrEqual(Dd<DdType::CUDD> const& other) const {
-            STORM_LOG_WARN_COND(this->isMtbdd() && other.isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            std::set<storm::expressions::Variable> metaVariables(this->getContainedMetaVariables());
-            metaVariables.insert(other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end());
-            return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().GreaterThanOrEqual(other.getCuddMtbdd()), metaVariables);
+        Add<DdType::CUDD> Add<DdType::CUDD>::greaterOrEqual(Add<DdType::CUDD> const& other) const {
+            std::set<storm::expressions::Variable> metaVariables;
+            std::set_union(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end(), other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end(), std::inserter(metaVariables, metaVariables.begin()));
+            return Add<DdType::CUDD>(this->getDdManager(), this->getCuddAdd().GreaterThanOrEqual(other.getCuddAdd()), metaVariables);
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::minimum(Dd<DdType::CUDD> const& other) const {
-            STORM_LOG_WARN_COND(this->isMtbdd() && other.isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            std::set<storm::expressions::Variable> metaVariables(this->getContainedMetaVariables());
-            metaVariables.insert(other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end());
-            return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().Minimum(other.getCuddMtbdd()), metaVariables);
+        Add<DdType::CUDD> Add<DdType::CUDD>::minimum(Add<DdType::CUDD> const& other) const {
+            std::set<storm::expressions::Variable> metaVariables;
+            std::set_union(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end(), other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end(), std::inserter(metaVariables, metaVariables.begin()));
+            return Add<DdType::CUDD>(this->getDdManager(), this->getCuddAdd().Minimum(other.getCuddAdd()), metaVariables);
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::maximum(Dd<DdType::CUDD> const& other) const {
-            STORM_LOG_WARN_COND(this->isMtbdd() && other.isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            std::set<storm::expressions::Variable> metaVariables(this->getContainedMetaVariables());
-            metaVariables.insert(other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end());
-            return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().Maximum(other.getCuddMtbdd()), metaVariables);
+        Add<DdType::CUDD> Add<DdType::CUDD>::maximum(Add<DdType::CUDD> const& other) const {
+            std::set<storm::expressions::Variable> metaVariables;
+            std::set_union(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end(), other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end(), std::inserter(metaVariables, metaVariables.begin()));
+            return Add<DdType::CUDD>(this->getDdManager(), this->getCuddAdd().Maximum(other.getCuddAdd()), metaVariables);
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::existsAbstract(std::set<storm::expressions::Variable> const& metaVariables) const {
-            STORM_LOG_WARN_COND(this->isBdd(), "Performing logical operation on MTBDD(s).");
-            
-            Dd<DdType::CUDD> cubeDd(this->getDdManager()->getOne(false));
+        Add<DdType::CUDD> Add<DdType::CUDD>::sumAbstract(std::set<storm::expressions::Variable> const& metaVariables) const {
+            Bdd<DdType::CUDD> cubeDd = this->getDdManager()->getBddOne();
             std::set<storm::expressions::Variable> newMetaVariables = this->getContainedMetaVariables();
             for (auto const& metaVariable : metaVariables) {
                 // First check whether the DD contains the meta variable and erase it, if this is the case.
@@ -346,13 +174,11 @@ namespace storm {
                 cubeDd &= ddMetaVariable.getCube();
             }
             
-            return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().ExistAbstract(cubeDd.getCuddBdd()), newMetaVariables);
+            return Add<DdType::CUDD>(this->getDdManager(), this->getCuddAdd().ExistAbstract(cubeDd.toAdd().getCuddAdd()), newMetaVariables);
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::universalAbstract(std::set<storm::expressions::Variable> const& metaVariables) const {
-            STORM_LOG_WARN_COND(this->isBdd(), "Performing logical operation on MTBDD(s).");
-            
-            Dd<DdType::CUDD> cubeDd(this->getDdManager()->getOne());
+        Add<DdType::CUDD> Add<DdType::CUDD>::minAbstract(std::set<storm::expressions::Variable> const& metaVariables) const {
+            Bdd<DdType::CUDD> cubeDd = this->getDdManager()->getBddOne();
             std::set<storm::expressions::Variable> newMetaVariables = this->getContainedMetaVariables();
             for (auto const& metaVariable : metaVariables) {
                 // First check whether the DD contains the meta variable and erase it, if this is the case.
@@ -363,47 +189,11 @@ namespace storm {
                 cubeDd &= ddMetaVariable.getCube();
             }
             
-            return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().UnivAbstract(cubeDd.getCuddBdd()), newMetaVariables);
-        }
-        
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::sumAbstract(std::set<storm::expressions::Variable> const& metaVariables) const {
-            STORM_LOG_WARN_COND(this->isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            
-            Dd<DdType::CUDD> cubeDd(this->getDdManager()->getOne(true));
-            std::set<storm::expressions::Variable> newMetaVariables = this->getContainedMetaVariables();
-            for (auto const& metaVariable : metaVariables) {
-                // First check whether the DD contains the meta variable and erase it, if this is the case.
-                STORM_LOG_THROW(this->containsMetaVariable(metaVariable), storm::exceptions::InvalidArgumentException, "Cannot abstract from meta variable '" << metaVariable.getName() << "' that is not present in the DD.");
-                newMetaVariables.erase(metaVariable);
-                
-                DdMetaVariable<DdType::CUDD> const& ddMetaVariable = this->getDdManager()->getMetaVariable(metaVariable);
-                cubeDd *= ddMetaVariable.getCubeAsMtbdd();
-            }
-            
-            return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().ExistAbstract(cubeDd.getCuddMtbdd()), newMetaVariables);
-        }
-        
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::minAbstract(std::set<storm::expressions::Variable> const& metaVariables) const {
-            STORM_LOG_WARN_COND(this->isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            
-            Dd<DdType::CUDD> cubeDd(this->getDdManager()->getOne(true));
-            std::set<storm::expressions::Variable> newMetaVariables = this->getContainedMetaVariables();
-            for (auto const& metaVariable : metaVariables) {
-                // First check whether the DD contains the meta variable and erase it, if this is the case.
-                STORM_LOG_THROW(this->containsMetaVariable(metaVariable), storm::exceptions::InvalidArgumentException, "Cannot abstract from meta variable '" << metaVariable.getName() << "' that is not present in the DD.");
-                newMetaVariables.erase(metaVariable);
-                
-                DdMetaVariable<DdType::CUDD> const& ddMetaVariable = this->getDdManager()->getMetaVariable(metaVariable);
-                cubeDd *= ddMetaVariable.getCubeAsMtbdd();
-            }
-            
-            return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().MinAbstract(cubeDd.getCuddMtbdd()), newMetaVariables);
+            return Add<DdType::CUDD>(this->getDdManager(), this->getCuddAdd().MinAbstract(cubeDd.toAdd().getCuddAdd()), newMetaVariables);
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::maxAbstract(std::set<storm::expressions::Variable> const& metaVariables) const {
-            STORM_LOG_WARN_COND(this->isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            
-            Dd<DdType::CUDD> cubeDd(this->getDdManager()->getOne(true));
+        Add<DdType::CUDD> Add<DdType::CUDD>::maxAbstract(std::set<storm::expressions::Variable> const& metaVariables) const {
+            Bdd<DdType::CUDD> cubeDd = this->getDdManager()->getBddOne();
             std::set<storm::expressions::Variable> newMetaVariables = this->getContainedMetaVariables();
             for (auto const& metaVariable : metaVariables) {
                 // First check whether the DD contains the meta variable and erase it, if this is the case.
@@ -411,95 +201,60 @@ namespace storm {
                 newMetaVariables.erase(metaVariable);
                 
                 DdMetaVariable<DdType::CUDD> const& ddMetaVariable = this->getDdManager()->getMetaVariable(metaVariable);
-                cubeDd *= ddMetaVariable.getCubeAsMtbdd();
+                cubeDd &= ddMetaVariable.getCube();
             }
             
-            return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().MaxAbstract(cubeDd.getCuddMtbdd()), newMetaVariables);
+            return Add<DdType::CUDD>(this->getDdManager(), this->getCuddAdd().MaxAbstract(cubeDd.toAdd().getCuddAdd()), newMetaVariables);
         }
         
-        bool Dd<DdType::CUDD>::equalModuloPrecision(Dd<DdType::CUDD> const& other, double precision, bool relative) const {
-            STORM_LOG_WARN_COND(this->isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            
+        bool Add<DdType::CUDD>::equalModuloPrecision(Add<DdType::CUDD> const& other, double precision, bool relative) const {
             if (relative) {
-                return this->getCuddMtbdd().EqualSupNormRel(other.getCuddMtbdd(), precision);
+                return this->getCuddAdd().EqualSupNormRel(other.getCuddAdd(), precision);
             } else {
-                return this->getCuddMtbdd().EqualSupNorm(other.getCuddMtbdd(), precision);
+                return this->getCuddAdd().EqualSupNorm(other.getCuddAdd(), precision);
             }
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::swapVariables(std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& metaVariablePairs) {
+        Add<DdType::CUDD> Add<DdType::CUDD>::swapVariables(std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& metaVariablePairs) {
             std::set<storm::expressions::Variable> newContainedMetaVariables;
-            if (this->isBdd()) {
-                std::vector<BDD> from;
-                std::vector<BDD> to;
-                for (auto const& metaVariablePair : metaVariablePairs) {
-                    DdMetaVariable<DdType::CUDD> const& variable1 = this->getDdManager()->getMetaVariable(metaVariablePair.first);
-                    DdMetaVariable<DdType::CUDD> const& variable2 = this->getDdManager()->getMetaVariable(metaVariablePair.second);
-                    
-                    // Check if it's legal so swap the meta variables.
-                    STORM_LOG_THROW(variable1.getNumberOfDdVariables() == variable2.getNumberOfDdVariables(), storm::exceptions::InvalidArgumentException, "Unable to swap meta variables with different size.");
-                    
-                    // Keep track of the contained meta variables in the DD.
-                    if (this->containsMetaVariable(metaVariablePair.first)) {
-                        newContainedMetaVariables.insert(metaVariablePair.second);
-                    }
-                    if (this->containsMetaVariable(metaVariablePair.second)) {
-                        newContainedMetaVariables.insert(metaVariablePair.first);
-                    }
-                    
-                    // Add the variables to swap to the corresponding vectors.
-                    for (auto const& ddVariable : variable1.getDdVariables()) {
-                        from.push_back(ddVariable.getCuddBdd());
-                    }
-                    for (auto const& ddVariable : variable2.getDdVariables()) {
-                        to.push_back(ddVariable.getCuddBdd());
-                    }
+            std::vector<ADD> from;
+            std::vector<ADD> to;
+            for (auto const& metaVariablePair : metaVariablePairs) {
+                DdMetaVariable<DdType::CUDD> const& variable1 = this->getDdManager()->getMetaVariable(metaVariablePair.first);
+                DdMetaVariable<DdType::CUDD> const& variable2 = this->getDdManager()->getMetaVariable(metaVariablePair.second);
+                
+                // Check if it's legal so swap the meta variables.
+                if (variable1.getNumberOfDdVariables() != variable2.getNumberOfDdVariables()) {
+                    throw storm::exceptions::InvalidArgumentException() << "Unable to swap meta variables with different size.";
                 }
                 
-                // Finally, call CUDD to swap the variables.
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().SwapVariables(from, to), newContainedMetaVariables);
-            } else {
-                std::vector<ADD> from;
-                std::vector<ADD> to;
-                for (auto const& metaVariablePair : metaVariablePairs) {
-                    DdMetaVariable<DdType::CUDD> const& variable1 = this->getDdManager()->getMetaVariable(metaVariablePair.first);
-                    DdMetaVariable<DdType::CUDD> const& variable2 = this->getDdManager()->getMetaVariable(metaVariablePair.second);
-                    
-                    // Check if it's legal so swap the meta variables.
-                    if (variable1.getNumberOfDdVariables() != variable2.getNumberOfDdVariables()) {
-                        throw storm::exceptions::InvalidArgumentException() << "Unable to swap meta variables with different size.";
-                    }
-                    
-                    // Keep track of the contained meta variables in the DD.
-                    if (this->containsMetaVariable(metaVariablePair.first)) {
-                        newContainedMetaVariables.insert(metaVariablePair.second);
-                    }
-                    if (this->containsMetaVariable(metaVariablePair.second)) {
-                        newContainedMetaVariables.insert(metaVariablePair.first);
-                    }
-                    
-                    // Add the variables to swap to the corresponding vectors.
-                    for (auto const& ddVariable : variable1.getDdVariables()) {
-                        from.push_back(ddVariable.getCuddMtbdd());
-                    }
-                    for (auto const& ddVariable : variable2.getDdVariables()) {
-                        to.push_back(ddVariable.getCuddMtbdd());
-                    }
+                // Keep track of the contained meta variables in the DD.
+                if (this->containsMetaVariable(metaVariablePair.first)) {
+                    newContainedMetaVariables.insert(metaVariablePair.second);
+                }
+                if (this->containsMetaVariable(metaVariablePair.second)) {
+                    newContainedMetaVariables.insert(metaVariablePair.first);
                 }
                 
-                // Finally, call CUDD to swap the variables.
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().SwapVariables(from, to), newContainedMetaVariables);
+                // Add the variables to swap to the corresponding vectors.
+                for (auto const& ddVariable : variable1.getDdVariables()) {
+                    from.push_back(ddVariable.toAdd().getCuddAdd());
+                }
+                for (auto const& ddVariable : variable2.getDdVariables()) {
+                    to.push_back(ddVariable.toAdd().getCuddAdd());
+                }
             }
+            
+            // Finally, call CUDD to swap the variables.
+            return Add<DdType::CUDD>(this->getDdManager(), this->getCuddAdd().SwapVariables(from, to), newContainedMetaVariables);
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::multiplyMatrix(Dd<DdType::CUDD> const& otherMatrix, std::set<storm::expressions::Variable> const& summationMetaVariables) const {
-            STORM_LOG_WARN_COND(this->isMtbdd() && otherMatrix.isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            
+        Add<DdType::CUDD> Add<DdType::CUDD>::multiplyMatrix(Add<DdType::CUDD> const& otherMatrix, std::set<storm::expressions::Variable> const& summationMetaVariables) const {
             // Create the CUDD summation variables.
             std::vector<ADD> summationDdVariables;
             for (auto const& metaVariable : summationMetaVariables) {
                 for (auto const& ddVariable : this->getDdManager()->getMetaVariable(metaVariable).getDdVariables()) {
-                    summationDdVariables.push_back(ddVariable.getCuddMtbdd());
+                    summationDdVariables.push_back(ddVariable.toAdd().getCuddAdd());
                 }
             }
             
@@ -508,154 +263,90 @@ namespace storm {
             std::set<storm::expressions::Variable> containedMetaVariables;
             std::set_difference(unionOfMetaVariables.begin(), unionOfMetaVariables.end(), summationMetaVariables.begin(), summationMetaVariables.end(), std::inserter(containedMetaVariables, containedMetaVariables.begin()));
             
-            return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().MatrixMultiply(otherMatrix.getCuddMtbdd(), summationDdVariables), containedMetaVariables);
-        }
-        
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::andExists(Dd<DdType::CUDD> const& other, std::set<storm::expressions::Variable> const& existentialVariables) const {
-            STORM_LOG_WARN_COND(this->isBdd() && other.isBdd(), "Performing logical operation on MTBDD(s).");
-            
-            Dd<DdType::CUDD> cubeDd(this->getDdManager()->getOne());
-            for (auto const& metaVariable : existentialVariables) {
-                DdMetaVariable<DdType::CUDD> const& ddMetaVariable = this->getDdManager()->getMetaVariable(metaVariable);
-                cubeDd &= ddMetaVariable.getCube();
-            }
-            
-            std::set<storm::expressions::Variable> unionOfMetaVariables;
-            std::set_union(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end(), other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end(), std::inserter(unionOfMetaVariables, unionOfMetaVariables.begin()));
-            std::set<storm::expressions::Variable> containedMetaVariables;
-            std::set_difference(unionOfMetaVariables.begin(), unionOfMetaVariables.end(), existentialVariables.begin(), existentialVariables.end(), std::inserter(containedMetaVariables, containedMetaVariables.begin()));
-            
-            return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().AndAbstract(other.getCuddBdd(), cubeDd.getCuddBdd()), containedMetaVariables);
+            return Add<DdType::CUDD>(this->getDdManager(), this->getCuddAdd().MatrixMultiply(otherMatrix.getCuddAdd(), summationDdVariables), containedMetaVariables);
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::greater(double value) const {
-            STORM_LOG_WARN_COND(this->isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().BddStrictThreshold(value), this->getContainedMetaVariables());
+        Bdd<DdType::CUDD> Add<DdType::CUDD>::greater(double value) const {
+            return Bdd<DdType::CUDD>(this->getDdManager(), this->getCuddAdd().BddStrictThreshold(value), this->getContainedMetaVariables());
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::greaterOrEqual(double value) const {
-            STORM_LOG_WARN_COND(this->isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().BddThreshold(value), this->getContainedMetaVariables());
+        Bdd<DdType::CUDD> Add<DdType::CUDD>::greaterOrEqual(double value) const {
+            return Bdd<DdType::CUDD>(this->getDdManager(), this->getCuddAdd().BddThreshold(value), this->getContainedMetaVariables());
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::notZero() const {
+        Bdd<DdType::CUDD> Add<DdType::CUDD>::notZero() const {
             return this->toBdd();
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::constrain(Dd<DdType::CUDD> const& constraint) const {
-            std::set<storm::expressions::Variable> metaVariables(this->getContainedMetaVariables());
-            metaVariables.insert(constraint.getContainedMetaVariables().begin(), constraint.getContainedMetaVariables().end());
-            
-            if (this->isBdd() && constraint.isBdd()) {
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().Constrain(constraint.getCuddBdd()), metaVariables);
-            } else {
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().Constrain(constraint.getCuddMtbdd()), metaVariables);
-            }
+        Add<DdType::CUDD> Add<DdType::CUDD>::constrain(Add<DdType::CUDD> const& constraint) const {
+            std::set<storm::expressions::Variable> metaVariables;
+            std::set_union(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end(), constraint.getContainedMetaVariables().begin(), constraint.getContainedMetaVariables().end(), std::inserter(metaVariables, metaVariables.begin()));
+            return Add<DdType::CUDD>(this->getDdManager(), this->getCuddAdd().Constrain(constraint.getCuddAdd()), metaVariables);
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::restrict(Dd<DdType::CUDD> const& constraint) const {
-            std::set<storm::expressions::Variable> metaVariables(this->getContainedMetaVariables());
-            metaVariables.insert(constraint.getContainedMetaVariables().begin(), constraint.getContainedMetaVariables().end());
-            
-            if (this->isBdd() && constraint.isBdd()) {
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().Restrict(constraint.getCuddBdd()), metaVariables);
-            } else {
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().Restrict(constraint.getCuddMtbdd()), metaVariables);
-            }
+        Add<DdType::CUDD> Add<DdType::CUDD>::restrict(Add<DdType::CUDD> const& constraint) const {
+            std::set<storm::expressions::Variable> metaVariables;
+            std::set_union(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end(), constraint.getContainedMetaVariables().begin(), constraint.getContainedMetaVariables().end(), std::inserter(metaVariables, metaVariables.begin()));
+            return Add<DdType::CUDD>(this->getDdManager(), this->getCuddAdd().Restrict(constraint.getCuddAdd()), metaVariables);
         }
         
-        Dd<DdType::CUDD> Dd<DdType::CUDD>::getSupport() const {
-            if (this->isBdd()) {
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().Support(), this->getContainedMetaVariables());
-            } else {
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().Support(), this->getContainedMetaVariables());
-            }
+        Bdd<DdType::CUDD> Add<DdType::CUDD>::getSupport() const {
+            return Bdd<DdType::CUDD>(this->getDdManager(), this->getCuddAdd().Support(), this->getContainedMetaVariables());
         }
         
-        uint_fast64_t Dd<DdType::CUDD>::getNonZeroCount() const {
+        uint_fast64_t Add<DdType::CUDD>::getNonZeroCount() const {
             std::size_t numberOfDdVariables = 0;
             for (auto const& metaVariable : this->getContainedMetaVariables()) {
                 numberOfDdVariables += this->getDdManager()->getMetaVariable(metaVariable).getNumberOfDdVariables();
             }
-            if (this->isBdd()) {
-                return static_cast<uint_fast64_t>(this->getCuddBdd().CountMinterm(static_cast<int>(numberOfDdVariables)));
-            } else {
-                return static_cast<uint_fast64_t>(this->getCuddMtbdd().CountMinterm(static_cast<int>(numberOfDdVariables)));
-            }
+            return static_cast<uint_fast64_t>(this->getCuddAdd().CountMinterm(static_cast<int>(numberOfDdVariables)));
         }
         
-        uint_fast64_t Dd<DdType::CUDD>::getLeafCount() const {
-            if (this->isBdd()) {
-                return static_cast<uint_fast64_t>(this->getCuddBdd().CountLeaves());
-            } else {
-                return static_cast<uint_fast64_t>(this->getCuddMtbdd().CountLeaves());
-            }
+        uint_fast64_t Add<DdType::CUDD>::getLeafCount() const {
+            return static_cast<uint_fast64_t>(this->getCuddAdd().CountLeaves());
         }
         
-        uint_fast64_t Dd<DdType::CUDD>::getNodeCount() const {
-            if (this->isBdd()) {
-                return static_cast<uint_fast64_t>(this->getCuddBdd().nodeCount());
-            } else {
-                return static_cast<uint_fast64_t>(this->getCuddMtbdd().nodeCount());
-            }
+        uint_fast64_t Add<DdType::CUDD>::getNodeCount() const {
+            return static_cast<uint_fast64_t>(this->getCuddAdd().nodeCount());
         }
         
-        double Dd<DdType::CUDD>::getMin() const {
-            STORM_LOG_WARN_COND(this->isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            
-            ADD constantMinAdd = this->getCuddMtbdd().FindMin();
+        double Add<DdType::CUDD>::getMin() const {
+            ADD constantMinAdd = this->getCuddAdd().FindMin();
             return static_cast<double>(Cudd_V(constantMinAdd.getNode()));
         }
         
-        double Dd<DdType::CUDD>::getMax() const {
-            STORM_LOG_WARN_COND(this->isMtbdd(), "Performing arithmetical operation on BDD(s).");
-            
-            ADD constantMaxAdd = this->getCuddMtbdd().FindMax();
+        double Add<DdType::CUDD>::getMax() const {
+            ADD constantMaxAdd = this->getCuddAdd().FindMax();
             return static_cast<double>(Cudd_V(constantMaxAdd.getNode()));
         }
         
-        void Dd<DdType::CUDD>::setValue(storm::expressions::Variable const& metaVariable, int_fast64_t variableValue, double targetValue) {
+        void Add<DdType::CUDD>::setValue(storm::expressions::Variable const& metaVariable, int_fast64_t variableValue, double targetValue) {
             std::map<storm::expressions::Variable, int_fast64_t> metaVariableToValueMap;
             metaVariableToValueMap.emplace(metaVariable, variableValue);
             this->setValue(metaVariableToValueMap, targetValue);
         }
         
-        void Dd<DdType::CUDD>::setValue(storm::expressions::Variable const& metaVariable1, int_fast64_t variableValue1, storm::expressions::Variable const& metaVariable2, int_fast64_t variableValue2, double targetValue) {
+        void Add<DdType::CUDD>::setValue(storm::expressions::Variable const& metaVariable1, int_fast64_t variableValue1, storm::expressions::Variable const& metaVariable2, int_fast64_t variableValue2, double targetValue) {
             std::map<storm::expressions::Variable, int_fast64_t> metaVariableToValueMap;
             metaVariableToValueMap.emplace(metaVariable1, variableValue1);
             metaVariableToValueMap.emplace(metaVariable2, variableValue2);
             this->setValue(metaVariableToValueMap, targetValue);
         }
         
-        void Dd<DdType::CUDD>::setValue(std::map<storm::expressions::Variable, int_fast64_t> const& metaVariableToValueMap, double targetValue) {
-            if (this->isBdd()) {
-                STORM_LOG_THROW(targetValue == storm::utility::zero<double>() || targetValue == storm::utility::one<double>(), storm::exceptions::InvalidArgumentException, "Cannot set encoding to non-0, non-1 value " << targetValue << " in BDD.");
-                Dd<DdType::CUDD> valueEncoding(this->getDdManager()->getOne());
-                for (auto const& nameValuePair : metaVariableToValueMap) {
-                    valueEncoding &= this->getDdManager()->getEncoding(nameValuePair.first, nameValuePair.second);
-                    // Also record that the DD now contains the meta variable.
-                    this->addContainedMetaVariable(nameValuePair.first);
-                }
-                if (targetValue == storm::utility::one<double>()) {
-                    this->cuddDd = valueEncoding.getCuddBdd().Ite(this->getDdManager()->getOne().getCuddBdd(), this->getCuddBdd());
-                } else {
-                    this->cuddDd = valueEncoding.getCuddBdd().Ite(this->getDdManager()->getZero().getCuddBdd(), this->getCuddBdd());
-                }
-            } else {
-                Dd<DdType::CUDD> valueEncoding(this->getDdManager()->getOne());
-                for (auto const& nameValuePair : metaVariableToValueMap) {
-                    valueEncoding &= this->getDdManager()->getEncoding(nameValuePair.first, nameValuePair.second);
-                    // Also record that the DD now contains the meta variable.
-                    this->addContainedMetaVariable(nameValuePair.first);
-                }
-                
-                this->cuddDd = valueEncoding.toMtbdd().getCuddMtbdd().Ite(this->getDdManager()->getConstant(targetValue).getCuddMtbdd(), this->getCuddMtbdd());
+        void Add<DdType::CUDD>::setValue(std::map<storm::expressions::Variable, int_fast64_t> const& metaVariableToValueMap, double targetValue) {
+            Bdd<DdType::CUDD> valueEncoding = this->getDdManager()->getBddOne();
+            for (auto const& nameValuePair : metaVariableToValueMap) {
+                valueEncoding &= this->getDdManager()->getEncoding(nameValuePair.first, nameValuePair.second);
+                // Also record that the DD now contains the meta variable.
+                this->addMetaVariable(nameValuePair.first);
             }
+            
+            this->cuddAdd = valueEncoding.toAdd().getCuddAdd().Ite(this->getDdManager()->getConstant(targetValue).getCuddAdd(), this->getCuddAdd());
         }
         
-        double Dd<DdType::CUDD>::getValue(std::map<storm::expressions::Variable, int_fast64_t> const& metaVariableToValueMap) const {
+        double Add<DdType::CUDD>::getValue(std::map<storm::expressions::Variable, int_fast64_t> const& metaVariableToValueMap) const {
             std::set<storm::expressions::Variable> remainingMetaVariables(this->getContainedMetaVariables());
-            Dd<DdType::CUDD> valueEncoding(this->getDdManager()->getOne());
+            Bdd<DdType::CUDD> valueEncoding = this->getDdManager()->getBddOne();
             for (auto const& nameValuePair : metaVariableToValueMap) {
                 valueEncoding &= this->getDdManager()->getEncoding(nameValuePair.first, nameValuePair.second);
                 if (this->containsMetaVariable(nameValuePair.first)) {
@@ -665,65 +356,41 @@ namespace storm {
             
             STORM_LOG_THROW(remainingMetaVariables.empty(), storm::exceptions::InvalidArgumentException, "Cannot evaluate function for which not all inputs were given.");
             
-            if (this->isBdd()) {
-                Dd<DdType::CUDD> value = *this && valueEncoding;
-                return value.isZero() ? 0 : 1;
-            } else {
-                Dd<DdType::CUDD> value = *this * valueEncoding.toMtbdd();
-                value = value.sumAbstract(this->getContainedMetaVariables());
-                return static_cast<double>(Cudd_V(value.getCuddMtbdd().getNode()));
-            }
+            Add<DdType::CUDD> value = *this * valueEncoding.toAdd();
+            value = value.sumAbstract(this->getContainedMetaVariables());
+            return static_cast<double>(Cudd_V(value.getCuddAdd().getNode()));
         }
         
-        bool Dd<DdType::CUDD>::isOne() const {
-            if (this->isBdd()) {
-                return this->getCuddBdd().IsOne();
-            } else {
-                return this->getCuddMtbdd().IsOne();
-            }
+        bool Add<DdType::CUDD>::isOne() const {
+            return this->getCuddAdd().IsOne();
         }
         
-        bool Dd<DdType::CUDD>::isZero() const {
-            if (this->isBdd()) {
-                return this->getCuddBdd().IsZero();
-            } else {
-                return this->getCuddMtbdd().IsZero();
-            }
+        bool Add<DdType::CUDD>::isZero() const {
+            return this->getCuddAdd().IsZero();
         }
         
-        bool Dd<DdType::CUDD>::isConstant() const {
-            if (this->isBdd()) {
-                return Cudd_IsConstant(this->getCuddBdd().getNode());
-            } else {
-                return Cudd_IsConstant(this->getCuddMtbdd().getNode());
-            }
+        bool Add<DdType::CUDD>::isConstant() const {
+            return Cudd_IsConstant(this->getCuddAdd().getNode());
         }
         
-        uint_fast64_t Dd<DdType::CUDD>::getIndex() const {
-            if (this->isBdd()) {
-                return static_cast<uint_fast64_t>(this->getCuddBdd().NodeReadIndex());
-            } else {
-                return static_cast<uint_fast64_t>(this->getCuddMtbdd().NodeReadIndex());
-            }
+        uint_fast64_t Add<DdType::CUDD>::getIndex() const {
+            return static_cast<uint_fast64_t>(this->getCuddAdd().NodeReadIndex());
         }
         
         template<typename ValueType>
-        std::vector<ValueType> Dd<DdType::CUDD>::toVector() const {
-            STORM_LOG_THROW(this->isMtbdd(), storm::exceptions::IllegalFunctionCallException, "Cannot create vector from BDD.");
+        std::vector<ValueType> Add<DdType::CUDD>::toVector() const {
             return this->toVector<ValueType>(Odd<DdType::CUDD>(*this));
         }
         
         template<typename ValueType>
-        std::vector<ValueType> Dd<DdType::CUDD>::toVector(Odd<DdType::CUDD> const& rowOdd) const {
-            STORM_LOG_THROW(this->isMtbdd(), storm::exceptions::IllegalFunctionCallException, "Cannot create vector from BDD.");
+        std::vector<ValueType> Add<DdType::CUDD>::toVector(Odd<DdType::CUDD> const& rowOdd) const {
             std::vector<ValueType> result(rowOdd.getTotalOffset());
             std::vector<uint_fast64_t> ddVariableIndices = this->getSortedVariableIndices();
             addToVectorRec(this->getCuddDdNode(), 0, ddVariableIndices.size(), 0, rowOdd, ddVariableIndices, result);
             return result;
         }
         
-        storm::storage::SparseMatrix<double> Dd<DdType::CUDD>::toMatrix() const {
-            STORM_LOG_THROW(this->isMtbdd(), storm::exceptions::IllegalFunctionCallException, "Cannot create matrix from BDD.");
+        storm::storage::SparseMatrix<double> Add<DdType::CUDD>::toMatrix() const {
             std::set<storm::expressions::Variable> rowVariables;
             std::set<storm::expressions::Variable> columnVariables;
             
@@ -735,11 +402,10 @@ namespace storm {
                 }
             }
             
-            return toMatrix(rowVariables, columnVariables, Odd<DdType::CUDD>(this->existsAbstract(rowVariables)), Odd<DdType::CUDD>(this->existsAbstract(columnVariables)));
+            return toMatrix(rowVariables, columnVariables, Odd<DdType::CUDD>(this->sumAbstract(rowVariables)), Odd<DdType::CUDD>(this->sumAbstract(columnVariables)));
         }
         
-        storm::storage::SparseMatrix<double> Dd<DdType::CUDD>::toMatrix(storm::dd::Odd<DdType::CUDD> const& rowOdd, storm::dd::Odd<DdType::CUDD> const& columnOdd) const {
-            STORM_LOG_THROW(this->isMtbdd(), storm::exceptions::IllegalFunctionCallException, "Cannot create matrix from BDD.");
+        storm::storage::SparseMatrix<double> Add<DdType::CUDD>::toMatrix(storm::dd::Odd<DdType::CUDD> const& rowOdd, storm::dd::Odd<DdType::CUDD> const& columnOdd) const {
             std::set<storm::expressions::Variable> rowMetaVariables;
             std::set<storm::expressions::Variable> columnMetaVariables;
             
@@ -754,8 +420,7 @@ namespace storm {
             return toMatrix(rowMetaVariables, columnMetaVariables, rowOdd, columnOdd);
         }
         
-        storm::storage::SparseMatrix<double> Dd<DdType::CUDD>::toMatrix(std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, storm::dd::Odd<DdType::CUDD> const& rowOdd, storm::dd::Odd<DdType::CUDD> const& columnOdd) const {
-            STORM_LOG_THROW(this->isMtbdd(), storm::exceptions::IllegalFunctionCallException, "Cannot create matrix from BDD.");
+        storm::storage::SparseMatrix<double> Add<DdType::CUDD>::toMatrix(std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, storm::dd::Odd<DdType::CUDD> const& rowOdd, storm::dd::Odd<DdType::CUDD> const& columnOdd) const {
             std::vector<uint_fast64_t> ddRowVariableIndices;
             std::vector<uint_fast64_t> ddColumnVariableIndices;
             
@@ -814,8 +479,7 @@ namespace storm {
             return storm::storage::SparseMatrix<double>(columnOdd.getTotalOffset(), std::move(rowIndications), std::move(columnsAndValues), std::move(trivialRowGroupIndices));
         }
         
-        storm::storage::SparseMatrix<double> Dd<DdType::CUDD>::toMatrix(std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd<DdType::CUDD> const& rowOdd, storm::dd::Odd<DdType::CUDD> const& columnOdd) const {
-            STORM_LOG_THROW(this->isMtbdd(), storm::exceptions::IllegalFunctionCallException, "Cannot create matrix from BDD.");
+        storm::storage::SparseMatrix<double> Add<DdType::CUDD>::toMatrix(std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd<DdType::CUDD> const& rowOdd, storm::dd::Odd<DdType::CUDD> const& columnOdd) const {
             std::vector<uint_fast64_t> ddRowVariableIndices;
             std::vector<uint_fast64_t> ddColumnVariableIndices;
             std::vector<uint_fast64_t> ddGroupVariableIndices;
@@ -845,7 +509,7 @@ namespace storm {
             // TODO: assert that the group variables are at the very top of the variable ordering?
             
             // Start by computing the offsets (in terms of rows) for each row group.
-            Dd<DdType::CUDD> stateToNumberOfChoices = this->notZero().existsAbstract(columnMetaVariables).sumAbstract(groupMetaVariables);
+            Add<DdType::CUDD> stateToNumberOfChoices = this->notZero().existsAbstract(columnMetaVariables).toAdd().sumAbstract(groupMetaVariables);
             std::vector<uint_fast64_t> rowGroupIndices = stateToNumberOfChoices.toVector<uint_fast64_t>(rowOdd);
             rowGroupIndices.resize(rowGroupIndices.size() + 1);
             uint_fast64_t tmp = 0;
@@ -859,7 +523,7 @@ namespace storm {
             
             // Next, we split the matrix into one for each group. This only works if the group variables are at the very
             // top.
-            std::vector<Dd<DdType::CUDD>> groups;
+            std::vector<Add<DdType::CUDD>> groups;
             splitGroupsRec(this->getCuddDdNode(), groups, ddGroupVariableIndices, 0, ddGroupVariableIndices.size(), rowAndColumnMetaVariables);
             
             // Create the actual storage for the non-zero entries.
@@ -867,13 +531,13 @@ namespace storm {
             
             // Now compute the indices at which the individual rows start.
             std::vector<uint_fast64_t> rowIndications(rowGroupIndices.back() + 1);
-            std::vector<storm::dd::Dd<DdType::CUDD>> statesWithGroupEnabled(groups.size());
+            std::vector<storm::dd::Add<DdType::CUDD>> statesWithGroupEnabled(groups.size());
             for (uint_fast64_t i = 0; i < groups.size(); ++i) {
                 auto const& dd = groups[i];
                 
                 toMatrixRec(dd.getCuddDdNode(), rowIndications, columnsAndValues, rowGroupIndices, rowOdd, columnOdd, 0, 0, ddRowVariableIndices.size() + ddColumnVariableIndices.size(), 0, 0, ddRowVariableIndices, ddColumnVariableIndices, false);
                 
-                statesWithGroupEnabled[i] = dd.notZero().existsAbstract(columnMetaVariables);
+                statesWithGroupEnabled[i] = dd.notZero().existsAbstract(columnMetaVariables).toAdd();
                 addToVectorRec(statesWithGroupEnabled[i].getCuddDdNode(), 0, ddRowVariableIndices.size(), 0, rowOdd, ddRowVariableIndices, rowGroupIndices);
             }
             
@@ -917,7 +581,7 @@ namespace storm {
             return storm::storage::SparseMatrix<double>(columnOdd.getTotalOffset(), std::move(rowIndications), std::move(columnsAndValues), std::move(rowGroupIndices));
         }
         
-        void Dd<DdType::CUDD>::toMatrixRec(DdNode const* dd, std::vector<uint_fast64_t>& rowIndications, std::vector<storm::storage::MatrixEntry<uint_fast64_t, double>>& columnsAndValues, std::vector<uint_fast64_t> const& rowGroupOffsets, Odd<DdType::CUDD> const& rowOdd, Odd<DdType::CUDD> const& columnOdd, uint_fast64_t currentRowLevel, uint_fast64_t currentColumnLevel, uint_fast64_t maxLevel, uint_fast64_t currentRowOffset, uint_fast64_t currentColumnOffset, std::vector<uint_fast64_t> const& ddRowVariableIndices, std::vector<uint_fast64_t> const& ddColumnVariableIndices, bool generateValues) const {
+        void Add<DdType::CUDD>::toMatrixRec(DdNode const* dd, std::vector<uint_fast64_t>& rowIndications, std::vector<storm::storage::MatrixEntry<uint_fast64_t, double>>& columnsAndValues, std::vector<uint_fast64_t> const& rowGroupOffsets, Odd<DdType::CUDD> const& rowOdd, Odd<DdType::CUDD> const& columnOdd, uint_fast64_t currentRowLevel, uint_fast64_t currentColumnLevel, uint_fast64_t maxLevel, uint_fast64_t currentRowOffset, uint_fast64_t currentColumnOffset, std::vector<uint_fast64_t> const& ddRowVariableIndices, std::vector<uint_fast64_t> const& ddColumnVariableIndices, bool generateValues) const {
             // For the empty DD, we do not need to add any entries.
             if (dd == Cudd_ReadZero(this->getDdManager()->getCuddManager().getManager())) {
                 return;
@@ -969,14 +633,14 @@ namespace storm {
             }
         }
         
-        void Dd<DdType::CUDD>::splitGroupsRec(DdNode* dd, std::vector<Dd<DdType::CUDD>>& groups, std::vector<uint_fast64_t> const& ddGroupVariableIndices, uint_fast64_t currentLevel, uint_fast64_t maxLevel, std::set<storm::expressions::Variable> const& remainingMetaVariables) const {
+        void Add<DdType::CUDD>::splitGroupsRec(DdNode* dd, std::vector<Add<DdType::CUDD>>& groups, std::vector<uint_fast64_t> const& ddGroupVariableIndices, uint_fast64_t currentLevel, uint_fast64_t maxLevel, std::set<storm::expressions::Variable> const& remainingMetaVariables) const {
             // For the empty DD, we do not need to create a group.
             if (dd == Cudd_ReadZero(this->getDdManager()->getCuddManager().getManager())) {
                 return;
             }
             
             if (currentLevel == maxLevel) {
-                groups.push_back(Dd<DdType::CUDD>(this->getDdManager(), ADD(this->getDdManager()->getCuddManager(), dd), remainingMetaVariables));
+                groups.push_back(Add<DdType::CUDD>(this->getDdManager(), ADD(this->getDdManager()->getCuddManager(), dd), remainingMetaVariables));
             } else if (ddGroupVariableIndices[currentLevel] < dd->index) {
                 splitGroupsRec(dd, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel, remainingMetaVariables);
                 splitGroupsRec(dd, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel, remainingMetaVariables);
@@ -987,7 +651,7 @@ namespace storm {
         }
         
         template<typename ValueType>
-        void Dd<DdType::CUDD>::addToVectorRec(DdNode const* dd, uint_fast64_t currentLevel, uint_fast64_t maxLevel, uint_fast64_t currentOffset, Odd<DdType::CUDD> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector) const {
+        void Add<DdType::CUDD>::addToVectorRec(DdNode const* dd, uint_fast64_t currentLevel, uint_fast64_t maxLevel, uint_fast64_t currentOffset, Odd<DdType::CUDD> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector) const {
             // For the empty DD, we do not need to add any entries.
             if (dd == Cudd_ReadZero(this->getDdManager()->getCuddManager().getManager())) {
                 return;
@@ -1007,53 +671,11 @@ namespace storm {
                 addToVectorRec(Cudd_T(dd), currentLevel + 1, maxLevel, currentOffset + odd.getElseOffset(), odd.getThenSuccessor(), ddVariableIndices, targetVector);
             }
         }
-        
-        std::vector<uint_fast64_t> Dd<DdType::CUDD>::getSortedVariableIndices() const {
-            std::vector<uint_fast64_t> ddVariableIndices;
-            for (auto const& metaVariableName : this->getContainedMetaVariables()) {
-                auto const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName);
-                for (auto const& ddVariable : metaVariable.getDdVariables()) {
-                    ddVariableIndices.push_back(ddVariable.getIndex());
-                }
-            }
-            
-            // Next, we need to sort them, since they may be arbitrarily ordered otherwise.
-            std::sort(ddVariableIndices.begin(), ddVariableIndices.end());
-            return ddVariableIndices;
-        }
-        
-        bool Dd<DdType::CUDD>::containsMetaVariable(storm::expressions::Variable const& metaVariable) const {
-            return containedMetaVariables.find(metaVariable) != containedMetaVariables.end();
-        }
-        
-        bool Dd<DdType::CUDD>::containsMetaVariables(std::set<storm::expressions::Variable> const& metaVariables) const {
-            for (auto const& metaVariable : metaVariables) {
-                auto const& ddMetaVariable = containedMetaVariables.find(metaVariable);
-                
-                if (ddMetaVariable == containedMetaVariables.end()) {
-                    return false;
-                }
-            }
-            return true;
-        }
-        
-        std::set<storm::expressions::Variable> const& Dd<DdType::CUDD>::getContainedMetaVariables() const {
-            return this->containedMetaVariables;
-        }
-        
-        std::set<storm::expressions::Variable>& Dd<DdType::CUDD>::getContainedMetaVariables() {
-            return this->containedMetaVariables;
-        }
-        
-        void Dd<DdType::CUDD>::exportToDot(std::string const& filename) const {
+
+        void Add<DdType::CUDD>::exportToDot(std::string const& filename) const {
             if (filename.empty()) {
-                if (this->isBdd()) {
-                    std::vector<BDD> cuddBddVector = { this->getCuddBdd() };
-                    this->getDdManager()->getCuddManager().DumpDot(cuddBddVector);
-                } else {
-                    std::vector<ADD> cuddAddVector = { this->getCuddMtbdd() };
-                    this->getDdManager()->getCuddManager().DumpDot(cuddAddVector);
-                }
+                std::vector<ADD> cuddAddVector = { this->getCuddAdd() };
+                this->getDdManager()->getCuddManager().DumpDot(cuddAddVector);
             } else {
                 // Build the name input of the DD.
                 std::vector<char*> ddNames;
@@ -1071,13 +693,8 @@ namespace storm {
                 
                 // Open the file, dump the DD and close it again.
                 FILE* filePointer = fopen(filename.c_str() , "w");
-                if (this->isBdd()) {
-                    std::vector<BDD> cuddBddVector = { this->getCuddBdd() };
-                    this->getDdManager()->getCuddManager().DumpDot(cuddBddVector, &ddVariableNames[0], &ddNames[0], filePointer);
-                } else {
-                    std::vector<ADD> cuddAddVector = { this->getCuddMtbdd() };
-                    this->getDdManager()->getCuddManager().DumpDot(cuddAddVector, &ddVariableNames[0], &ddNames[0], filePointer);
-                }
+                std::vector<ADD> cuddAddVector = { this->getCuddAdd() };
+                this->getDdManager()->getCuddManager().DumpDot(cuddAddVector, &ddVariableNames[0], &ddNames[0], filePointer);
                 fclose(filePointer);
                 
                 // Finally, delete the names.
@@ -1090,85 +707,28 @@ namespace storm {
             }
         }
         
-        void Dd<DdType::CUDD>::addContainedMetaVariable(storm::expressions::Variable const& metaVariable) {
-            this->getContainedMetaVariables().insert(metaVariable);
-        }
-        
-        void Dd<DdType::CUDD>::removeContainedMetaVariable(storm::expressions::Variable const& metaVariable) {
-            this->getContainedMetaVariables().erase(metaVariable);
-        }
-        
-        std::shared_ptr<DdManager<DdType::CUDD> const> Dd<DdType::CUDD>::getDdManager() const {
-            return this->ddManager;
-        }
-        
-        DdForwardIterator<DdType::CUDD> Dd<DdType::CUDD>::begin(bool enumerateDontCareMetaVariables) const {
+        DdForwardIterator<DdType::CUDD> Add<DdType::CUDD>::begin(bool enumerateDontCareMetaVariables) const {
             int* cube;
             double value;
-            DdGen* generator = this->getCuddDd().FirstCube(&cube, &value);
+            DdGen* generator = this->getCuddAdd().FirstCube(&cube, &value);
             return DdForwardIterator<DdType::CUDD>(this->getDdManager(), generator, cube, value, (Cudd_IsGenEmpty(generator) != 0), &this->getContainedMetaVariables(), enumerateDontCareMetaVariables);
         }
         
-        DdForwardIterator<DdType::CUDD> Dd<DdType::CUDD>::end(bool enumerateDontCareMetaVariables) const {
+        DdForwardIterator<DdType::CUDD> Add<DdType::CUDD>::end(bool enumerateDontCareMetaVariables) const {
             return DdForwardIterator<DdType::CUDD>(this->getDdManager(), nullptr, nullptr, 0, true, nullptr, enumerateDontCareMetaVariables);
         }
-        
-        storm::expressions::Expression Dd<DdType::CUDD>::toExpression() const {
-            return toExpressionRecur(this->getCuddDdNode(), this->getDdManager()->getDdVariables());
-        }
-        
-        storm::expressions::Expression Dd<DdType::CUDD>::getMintermExpression() const {
-            // Note that we first transform the ADD into a BDD to convert all non-zero terminals to ones and therefore
-            // make the DD more compact.
-            return getMintermExpressionRecur(this->getDdManager()->getCuddManager().getManager(), this->toBdd().getCuddDdNode(), this->getDdManager()->getDdVariables());
-        }
-        
-        storm::expressions::Expression Dd<DdType::CUDD>::toExpressionRecur(DdNode const* dd, std::vector<storm::expressions::Variable> const& variables) {
-            STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This feature is currently unavailable.");
-            // If the DD is a terminal node, we can simply return a constant expression.
-            //            if (Cudd_IsConstant(dd)) {
-            //                return storm::expressions::Expression::createDoubleLiteral(static_cast<double>(Cudd_V(dd)));
-            //            } else {
-            //                return storm::expressions::Expression::createBooleanVariable(variableNames[dd->index]).ite(toExpressionRecur(Cudd_T(dd), variableNames), toExpressionRecur(Cudd_E(dd), variableNames));
-            //            }
-        }
-        
-        storm::expressions::Expression Dd<DdType::CUDD>::getMintermExpressionRecur(::DdManager* manager, DdNode const* dd, std::vector<storm::expressions::Variable> const& variables) {
-            STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This feature is currently unavailable.");
-            // If the DD is a terminal node, we can simply return a constant expression.
-            //            if (Cudd_IsConstant(dd)) {
-            //                if (Cudd_IsComplement(dd)) {
-            //                    return storm::expressions::Expression::createBooleanLiteral(false);
-            //                } else {
-            //                    return storm::expressions::Expression::createBooleanLiteral((dd == Cudd_ReadOne(manager)) ? true : false);
-            //                }
-            //            } else {
-            //                // Get regular versions of the pointers.
-            //                DdNode* regularDd = Cudd_Regular(dd);
-            //                DdNode* thenDd = Cudd_T(regularDd);
-            //                DdNode* elseDd = Cudd_E(regularDd);
-            //
-            //                // Compute expression recursively.
-            //                storm::expressions::Expression result = storm::expressions::Expression::createBooleanVariable(variableNames[dd->index]).ite(getMintermExpressionRecur(manager, thenDd, variableNames), getMintermExpressionRecur(manager, elseDd, variableNames));
-            //                if (Cudd_IsComplement(dd)) {
-            //                    result = !result;
-            //                }
-            //
-            //                return result;
-            //            }
-        }
-        
-        std::ostream& operator<<(std::ostream& out, const Dd<DdType::CUDD>& dd) {
-            dd.exportToDot();
+                
+        std::ostream& operator<<(std::ostream& out, const Add<DdType::CUDD>& add) {
+            add.exportToDot();
             return out;
         }
         
         // Explicitly instantiate some templated functions.
-        template std::vector<double> Dd<DdType::CUDD>::toVector() const;
-        template std::vector<double> Dd<DdType::CUDD>::toVector(Odd<DdType::CUDD> const& rowOdd) const;
-        template void Dd<DdType::CUDD>::addToVectorRec(DdNode const* dd, uint_fast64_t currentLevel, uint_fast64_t maxLevel, uint_fast64_t currentOffset, Odd<DdType::CUDD> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<double>& targetVector) const;
-        template std::vector<uint_fast64_t> Dd<DdType::CUDD>::toVector() const;
-        template std::vector<uint_fast64_t> Dd<DdType::CUDD>::toVector(Odd<DdType::CUDD> const& rowOdd) const;
-        template void Dd<DdType::CUDD>::addToVectorRec(DdNode const* dd, uint_fast64_t currentLevel, uint_fast64_t maxLevel, uint_fast64_t currentOffset, Odd<DdType::CUDD> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<uint_fast64_t>& targetVector) const;
+        template std::vector<double> Add<DdType::CUDD>::toVector() const;
+        template std::vector<double> Add<DdType::CUDD>::toVector(Odd<DdType::CUDD> const& rowOdd) const;
+        template void Add<DdType::CUDD>::addToVectorRec(DdNode const* dd, uint_fast64_t currentLevel, uint_fast64_t maxLevel, uint_fast64_t currentOffset, Odd<DdType::CUDD> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<double>& targetVector) const;
+        template std::vector<uint_fast64_t> Add<DdType::CUDD>::toVector() const;
+        template std::vector<uint_fast64_t> Add<DdType::CUDD>::toVector(Odd<DdType::CUDD> const& rowOdd) const;
+        template void Add<DdType::CUDD>::addToVectorRec(DdNode const* dd, uint_fast64_t currentLevel, uint_fast64_t maxLevel, uint_fast64_t currentOffset, Odd<DdType::CUDD> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<uint_fast64_t>& targetVector) const;
     }
 }
\ No newline at end of file
diff --git a/src/storage/dd/CuddAdd.h b/src/storage/dd/CuddAdd.h
index f860e79bf..a43738d85 100644
--- a/src/storage/dd/CuddAdd.h
+++ b/src/storage/dd/CuddAdd.h
@@ -1,16 +1,10 @@
-#ifndef STORM_STORAGE_DD_CUDDDD_H_
-#define STORM_STORAGE_DD_CUDDDD_H_
+#ifndef STORM_STORAGE_DD_CUDDADD_H_
+#define STORM_STORAGE_DD_CUDDADD_H_
 
-#include <map>
-#include <set>
-#include <memory>
-#include <iostream>
-#include <boost/variant.hpp>
-
-#include "src/storage/dd/Dd.h"
+#include "src/storage/dd/Add.h"
+#include "src/storage/dd/CuddDd.h"
 #include "src/storage/dd/CuddDdForwardIterator.h"
 #include "src/storage/SparseMatrix.h"
-#include "src/storage/expressions/Expression.h"
 #include "src/storage/expressions/Variable.h"
 #include "src/utility/OsDetection.h"
 
@@ -22,22 +16,24 @@ namespace storm {
         // Forward-declare some classes.
         template<DdType Type> class DdManager;
         template<DdType Type> class Odd;
+        template<DdType Type> class Bdd;
         
         template<>
-        class Dd<DdType::CUDD> {
+        class Add<DdType::CUDD> : public Dd<DdType::CUDD> {
         public:
             // Declare the DdManager and DdIterator class as friend so it can access the internals of a DD.
             friend class DdManager<DdType::CUDD>;
             friend class DdForwardIterator<DdType::CUDD>;
+            friend class Bdd<DdType::CUDD>;
             friend class Odd<DdType::CUDD>;
             
             // Instantiate all copy/move constructors/assignments with the default implementation.
-            Dd() = default;
-            Dd(Dd<DdType::CUDD> const& other) = default;
-            Dd& operator=(Dd<DdType::CUDD> const& other) = default;
+            Add() = default;
+            Add(Add<DdType::CUDD> const& other) = default;
+            Add& operator=(Add<DdType::CUDD> const& other) = default;
 #ifndef WINDOWS
-            Dd(Dd<DdType::CUDD>&& other) = default;
-            Dd& operator=(Dd<DdType::CUDD>&& other) = default;
+            Add(Add<DdType::CUDD>&& other) = default;
+            Add& operator=(Add<DdType::CUDD>&& other) = default;
 #endif
             
             /*!
@@ -46,7 +42,7 @@ namespace storm {
              * @param other The DD that is to be compared with the current one.
              * @return True if the DDs represent the same function.
              */
-            bool operator==(Dd<DdType::CUDD> const& other) const;
+            bool operator==(Add<DdType::CUDD> const& other) const;
             
             /*!
              * Retrieves whether the two DDs represent different functions.
@@ -54,375 +50,309 @@ namespace storm {
              * @param other The DD that is to be compared with the current one.
              * @return True if the DDs represent the different functions.
              */
-            bool operator!=(Dd<DdType::CUDD> const& other) const;
+            bool operator!=(Add<DdType::CUDD> 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.
-             */
-            Dd<DdType::CUDD> ite(Dd<DdType::CUDD> const& thenDd, Dd<DdType::CUDD> const& elseDd) const;
-            
-            /*!
-             * Performs a logical or of the current and the given DD.
-             *
-             * @param other The second DD used for the operation.
-             * @return The logical or of the operands.
-             */
-            Dd<DdType::CUDD> operator||(Dd<DdType::CUDD> const& other) const;
-            
-            /*!
-             * Performs a logical or of the current and the given DD and assigns it to the current DD.
-             *
-             * @param other The second DD used for the operation.
-             * @return A reference to the current DD after the operation
-             */
-            Dd<DdType::CUDD>& operator|=(Dd<DdType::CUDD> const& other);
-            
-            /*!
-             * Performs a logical and of the current and the given DD.
-             *
-             * @param other The second DD used for the operation.
-             * @return The logical and of the operands.
-             */
-            Dd<DdType::CUDD> operator&&(Dd<DdType::CUDD> const& other) const;
-            
-            /*!
-             * Performs a logical and of the current and the given DD and assigns it to the current DD.
              *
-             * @param other The second DD used for the operation.
-             * @return A reference to the current DD after the operation
+             * @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.
              */
-            Dd<DdType::CUDD>& operator&=(Dd<DdType::CUDD> const& other);
+            Add<DdType::CUDD> ite(Add<DdType::CUDD> const& thenDd, Add<DdType::CUDD> const& elseDd) const;
             
             /*!
-             * Performs a logical iff of the current and the given DD.
+             * Logically inverts the current ADD. That is, all inputs yielding non-zero values will be mapped to zero in
+             * the result and vice versa.
              *
-             * @param other The second DD used for the operation.
-             * @return The logical iff of the operands.
+             * @return The resulting ADD.
              */
-            Dd<DdType::CUDD> iff(Dd<DdType::CUDD> const& other) const;
+            Add<DdType::CUDD> operator!() const;
             
             /*!
-             * Performs a logical exclusive-or of the current and the given DD.
+             * Performs a logical or of the current anBd the given ADD. As a prerequisite, the operand ADDs need to be
+             * 0/1 ADDs.
              *
-             * @param other The second DD used for the operation.
-             * @return The logical exclusive-or of the operands.
+             * @param other The second ADD used for the operation.
+             * @return The logical or of the operands.
              */
-            Dd<DdType::CUDD> exclusiveOr(Dd<DdType::CUDD> const& other) const;
+            Add<DdType::CUDD> operator||(Add<DdType::CUDD> const& other) const;
             
             /*!
-             * Performs a logical implication of the current and the given DD.
+             * Performs a logical or of the current and the given ADD and assigns it to the current ADD. As a
+             * prerequisite, the operand ADDs need to be 0/1 ADDs.
              *
-             * @param other The second DD used for the operation.
-             * @return The logical implication of the operands.
+             * @param other The second ADD used for the operation.
+             * @return A reference to the current ADD after the operation
              */
-            Dd<DdType::CUDD> implies(Dd<DdType::CUDD> const& other) const;
+            Add<DdType::CUDD>& operator|=(Add<DdType::CUDD> const& other);
             
             /*!
-             * Adds the two DDs.
+             * Adds the two ADDs.
              *
-             * @param other The DD to add to the current one.
+             * @param other The ADD to add to the current one.
              * @return The result of the addition.
              */
-            Dd<DdType::CUDD> operator+(Dd<DdType::CUDD> const& other) const;
+            Add<DdType::CUDD> operator+(Add<DdType::CUDD> const& other) const;
             
             /*!
-             * Adds the given DD to the current one.
+             * Adds the given ADD to the current one.
              *
-             * @param other The DD to add to the current one.
-             * @return A reference to the current DD after the operation.
+             * @param other The ADD to add to the current one.
+             * @return A reference to the current ADD after the operation.
              */
-            Dd<DdType::CUDD>& operator+=(Dd<DdType::CUDD> const& other);
+            Add<DdType::CUDD>& operator+=(Add<DdType::CUDD> const& other);
             
             /*!
-             * Multiplies the two DDs.
+             * Multiplies the two ADDs.
              *
-             * @param other The DD to multiply with the current one.
+             * @param other The ADD to multiply with the current one.
              * @return The result of the multiplication.
              */
-            Dd<DdType::CUDD> operator*(Dd<DdType::CUDD> const& other) const;
+            Add<DdType::CUDD> operator*(Add<DdType::CUDD> const& other) const;
             
             /*!
-             * Multiplies the given DD with the current one and assigns the result to the current DD.
+             * Multiplies the given ADD with the current one and assigns the result to the current ADD.
              *
-             * @param other The DD to multiply with the current one.
-             * @return A reference to the current DD after the operation.
+             * @param other The ADD to multiply with the current one.
+             * @return A reference to the current ADD after the operation.
              */
-            Dd<DdType::CUDD>& operator*=(Dd<DdType::CUDD> const& other);
+            Add<DdType::CUDD>& operator*=(Add<DdType::CUDD> const& other);
             
             /*!
-             * Subtracts the given DD from the current one.
+             * Subtracts the given ADD from the current one.
              *
-             * @param other The DD to subtract from the current one.
+             * @param other The ADD to subtract from the current one.
              * @return The result of the subtraction.
              */
-            Dd<DdType::CUDD> operator-(Dd<DdType::CUDD> const& other) const;
+            Add<DdType::CUDD> operator-(Add<DdType::CUDD> const& other) const;
             
             /*!
-             * Subtracts the DD from the constant zero function.
+             * Subtracts the ADD from the constant zero function.
              *
-             * @return The resulting function represented as a DD.
+             * @return The resulting function represented as a ADD.
              */
-            Dd<DdType::CUDD> operator-() const;
+            Add<DdType::CUDD> operator-() const;
             
             /*!
-             * Subtracts the given DD from the current one and assigns the result to the current DD.
+             * Subtracts the given ADD from the current one and assigns the result to the current ADD.
              *
-             * @param other The DD to subtract from the current one.
-             * @return A reference to the current DD after the operation.
+             * @param other The ADD to subtract from the current one.
+             * @return A reference to the current ADD after the operation.
              */
-            Dd<DdType::CUDD>& operator-=(Dd<DdType::CUDD> const& other);
+            Add<DdType::CUDD>& operator-=(Add<DdType::CUDD> const& other);
             
             /*!
-             * Divides the current DD by the given one.
+             * Divides the current ADD by the given one.
              *
-             * @param other The DD by which to divide the current one.
+             * @param other The ADD by which to divide the current one.
              * @return The result of the division.
              */
-            Dd<DdType::CUDD> operator/(Dd<DdType::CUDD> const& other) const;
-            
-            /*!
-             * Divides the current DD by the given one and assigns the result to the current DD.
-             *
-             * @param other The DD by which to divide the current one.
-             * @return A reference to the current DD after the operation.
-             */
-            Dd<DdType::CUDD>& operator/=(Dd<DdType::CUDD> const& other);
-            
-            /*!
-             * Retrieves the logical complement of the current DD. The result will map all encodings with a value
-             * unequal to zero to false and all others to true.
-             *
-             * @return The logical complement of the current DD.
-             */
-            Dd<DdType::CUDD> operator!() const;
+            Add<DdType::CUDD> operator/(Add<DdType::CUDD> const& other) const;
             
             /*!
-             * Logically complements the current DD. The result will map all encodings with a value
-             * unequal to zero to false and all others to true.
+             * Divides the current ADD by the given one and assigns the result to the current ADD.
              *
-             * @return A reference to the current DD after the operation.
+             * @param other The ADD by which to divide the current one.
+             * @return A reference to the current ADD after the operation.
              */
-            Dd<DdType::CUDD>& complement();
+            Add<DdType::CUDD>& operator/=(Add<DdType::CUDD> const& other);
             
             /*!
-             * Retrieves the function that maps all evaluations to one that have an identical function values.
+             * Retrieves the function that maps all evaluations to one that have identical function values.
              *
-             * @param other The DD with which to perform the operation.
-             * @return The resulting function represented as a DD.
+             * @param other The ADD with which to perform the operation.
+             * @return The resulting function represented as an ADD.
              */
-            Dd<DdType::CUDD> equals(Dd<DdType::CUDD> const& other) const;
+            Add<DdType::CUDD> equals(Add<DdType::CUDD> const& other) const;
             
             /*!
              * Retrieves the function that maps all evaluations to one that have distinct function values.
              *
-             * @param other The DD with which to perform the operation.
-             * @return The resulting function represented as a DD.
-             */
-            Dd<DdType::CUDD> notEquals(Dd<DdType::CUDD> const& other) const;
-            
-            /*!
-             * Retrieves the function that maps all evaluations to one whose function value in the first DD are less
-             * than the one in the given DD.
-             *
-             * @param other The DD with which to perform the operation.
-             * @return The resulting function represented as a DD.
-             */
-            Dd<DdType::CUDD> less(Dd<DdType::CUDD> const& other) const;
-            
-            /*!
-             * Retrieves the function that maps all evaluations to one whose function value in the first DD are less or
-             * equal than the one in the given DD.
-             *
-             * @param other The DD with which to perform the operation.
-             * @return The resulting function represented as a DD.
+             * @param other The ADD with which to perform the operation.
+             * @return The resulting function represented as an ADD.
              */
-            Dd<DdType::CUDD> lessOrEqual(Dd<DdType::CUDD> const& other) const;
+            Add<DdType::CUDD> notEquals(Add<DdType::CUDD> const& other) const;
             
             /*!
-             * Retrieves the function that maps all evaluations to one whose function value in the first DD are greater
-             * than the one in the given DD.
+             * Retrieves the function that maps all evaluations to one whose function value in the first ADD are less
+             * than the one in the given ADD.
              *
-             * @param other The DD with which to perform the operation.
-             * @return The resulting function represented as a DD.
+             * @param other The ADD with which to perform the operation.
+             * @return The resulting function represented as an ADD.
              */
-            Dd<DdType::CUDD> greater(Dd<DdType::CUDD> const& other) const;
+            Add<DdType::CUDD> less(Add<DdType::CUDD> const& other) const;
             
             /*!
-             * Retrieves the function that maps all evaluations to one whose function value in the first DD are greater
-             * or equal than the one in the given DD.
+             * Retrieves the function that maps all evaluations to one whose function value in the first ADD are less or
+             * equal than the one in the given ADD.
              *
              * @param other The DD with which to perform the operation.
-             * @return The resulting function represented as a DD.
+             * @return The resulting function represented as an ADD.
              */
-            Dd<DdType::CUDD> greaterOrEqual(Dd<DdType::CUDD> const& other) const;
+            Add<DdType::CUDD> lessOrEqual(Add<DdType::CUDD> const& other) const;
             
             /*!
-             * Retrieves the function that maps all evaluations to the minimum of the function values of the two DDs.
+             * Retrieves the function that maps all evaluations to one whose function value in the first ADD are greater
+             * than the one in the given ADD.
              *
-             * @param other The DD with which to perform the operation.
-             * @return The resulting function represented as a DD.
+             * @param other The ADD with which to perform the operation.
+             * @return The resulting function represented as an ADD.
              */
-            Dd<DdType::CUDD> minimum(Dd<DdType::CUDD> const& other) const;
+            Add<DdType::CUDD> greater(Add<DdType::CUDD> const& other) const;
             
             /*!
-             * Retrieves the function that maps all evaluations to the maximum of the function values of the two DDs.
+             * Retrieves the function that maps all evaluations to one whose function value in the first ADD are greater
+             * or equal than the one in the given ADD.
              *
-             * @param other The DD with which to perform the operation.
-             * @return The resulting function represented as a DD.
+             * @param other The ADD with which to perform the operation.
+             * @return The resulting function represented as an ADD.
              */
-            Dd<DdType::CUDD> maximum(Dd<DdType::CUDD> const& other) const;
+            Add<DdType::CUDD> greaterOrEqual(Add<DdType::CUDD> const& other) const;
             
             /*!
-             * Existentially abstracts from the given meta variables.
+             * Retrieves the function that maps all evaluations to the minimum of the function values of the two ADDs.
              *
-             * @param metaVariables The meta variables from which to abstract.
+             * @param other The ADD with which to perform the operation.
+             * @return The resulting function represented as an ADD.
              */
-            Dd<DdType::CUDD> existsAbstract(std::set<storm::expressions::Variable> const& metaVariables) const;
+            Add<DdType::CUDD> minimum(Add<DdType::CUDD> const& other) const;
             
             /*!
-             * Universally abstracts from the given meta variables.
+             * Retrieves the function that maps all evaluations to the maximum of the function values of the two ADDs.
              *
-             * @param metaVariables The meta variables from which to abstract.
+             * @param other The ADD with which to perform the operation.
+             * @return The resulting function represented as an ADD.
              */
-            Dd<DdType::CUDD> universalAbstract(std::set<storm::expressions::Variable> const& metaVariables) const;
+            Add<DdType::CUDD> maximum(Add<DdType::CUDD> const& other) const;
             
             /*!
              * Sum-abstracts from the given meta variables.
              *
              * @param metaVariables The meta variables from which to abstract.
              */
-            Dd<DdType::CUDD> sumAbstract(std::set<storm::expressions::Variable> const& metaVariables) const;
+            Add<DdType::CUDD> sumAbstract(std::set<storm::expressions::Variable> const& metaVariables) const;
             
             /*!
              * Min-abstracts from the given meta variables.
              *
              * @param metaVariables The meta variables from which to abstract.
              */
-            Dd<DdType::CUDD> minAbstract(std::set<storm::expressions::Variable> const& metaVariables) const;
+            Add<DdType::CUDD> minAbstract(std::set<storm::expressions::Variable> const& metaVariables) const;
             
             /*!
              * Max-abstracts from the given meta variables.
              *
              * @param metaVariables The meta variables from which to abstract.
              */
-            Dd<DdType::CUDD> maxAbstract(std::set<storm::expressions::Variable> const& metaVariables) const;
+            Add<DdType::CUDD> maxAbstract(std::set<storm::expressions::Variable> const& metaVariables) const;
             
             /*!
-             * Checks whether the current and the given DD represent the same function modulo some given precision.
+             * Checks whether the current and the given ADD represent the same function modulo some given precision.
              *
-             * @param other The DD with which to compare.
+             * @param other The ADD with which to compare.
              * @param precision An upper bound on the maximal difference between any two function values that is to be
              * tolerated.
              * @param relative If set to true, not the absolute values have to be within the precision, but the relative
              * values.
              */
-            bool equalModuloPrecision(Dd<DdType::CUDD> const& other, double precision, bool relative = true) const;
+            bool equalModuloPrecision(Add<DdType::CUDD> const& other, double precision, bool relative = true) const;
             
             /*!
-             * Swaps the given pairs of meta variables in the DD. The pairs of meta variables must be guaranteed to have
-             * the same number of underlying DD variables.
+             * Swaps the given pairs of meta variables in the ADD. The pairs of meta variables must be guaranteed to have
+             * the same number of underlying ADD variables.
              *
              * @param metaVariablePairs A vector of meta variable pairs that are to be swapped for one another.
-             * @return The resulting DD.
+             * @return The resulting ADD.
              */
-            Dd<DdType::CUDD> swapVariables(std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& metaVariablePairs);
+            Add<DdType::CUDD> swapVariables(std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& metaVariablePairs);
             
             /*!
-             * Multiplies the current DD (representing a matrix) with the given matrix by summing over the given meta
+             * Multiplies the current ADD (representing a matrix) with the given matrix by summing over the given meta
              * variables.
              *
              * @param otherMatrix The matrix with which to multiply.
              * @param summationMetaVariables The names of the meta variables over which to sum during the matrix-
              * matrix multiplication.
-             * @return A DD representing the result of the matrix-matrix multiplication.
-             */
-            Dd<DdType::CUDD> multiplyMatrix(Dd<DdType::CUDD> const& otherMatrix, std::set<storm::expressions::Variable> const& summationMetaVariables) const;
-            
-            /*!
-             * Computes the logical and of the current and the given DD and existentially abstracts from the given set
-             * of variables.
-             *
-             * @param other The second DD for the logical and.
-             * @param existentialVariables The variables from which to existentially abstract.
-             * @return A DD representing the result.
+             * @return An ADD representing the result of the matrix-matrix multiplication.
              */
-            Dd<DdType::CUDD> andExists(Dd<DdType::CUDD> const& other, std::set<storm::expressions::Variable> const& existentialVariables) const;
+            Add<DdType::CUDD> multiplyMatrix(Add<DdType::CUDD> const& otherMatrix, std::set<storm::expressions::Variable> const& summationMetaVariables) const;
             
             /*!
-             * Computes a DD that represents the function in which all assignments with a function value strictly larger
-             * than the given value are mapped to one and all others to zero.
+             * Computes a BDD that represents the function in which all assignments with a function value strictly
+             * larger than the given value are mapped to one and all others to zero.
              *
              * @param value The value used for the comparison.
-             * @return The resulting DD.
+             * @return The resulting BDD.
              */
-            Dd<DdType::CUDD> greater(double value) const;
+            Bdd<DdType::CUDD> greater(double value) const;
             
             /*!
-             * Computes a DD that represents the function in which all assignments with a function value larger or equal
+             * Computes a BDD that represents the function in which all assignments with a function value larger or equal
              * to the given value are mapped to one and all others to zero.
              *
              * @param value The value used for the comparison.
-             * @return The resulting DD.
+             * @return The resulting BDD.
              */
-            Dd<DdType::CUDD> greaterOrEqual(double value) const;
+            Bdd<DdType::CUDD> greaterOrEqual(double value) const;
             
             /*!
-             * Computes a DD that represents the function in which all assignments with a function value unequal to zero
-             * are mapped to one and all others to zero.
+             * Computes a BDD that represents the function in which all assignments with a function value unequal to
+             * zero are mapped to one and all others to zero.
              *
              * @return The resulting DD.
              */
-            Dd<DdType::CUDD> notZero() const;
+            Bdd<DdType::CUDD> notZero() const;
             
             /*!
-             * Computes the constraint of the current DD with the given constraint. That is, the function value of the
-             * resulting DD will be the same as the current ones for all assignments mapping to one in the constraint
+             * Computes the constraint of the current ADD with the given constraint. That is, the function value of the
+             * resulting ADD will be the same as the current ones for all assignments mapping to one in the constraint
              * and may be different otherwise.
              *
              * @param constraint The constraint to use for the operation.
-             * @return The resulting DD.
+             * @return The resulting ADD.
              */
-            Dd<DdType::CUDD> constrain(Dd<DdType::CUDD> const& constraint) const;
+            Add<DdType::CUDD> constrain(Add<DdType::CUDD> const& constraint) const;
             
             /*!
-             * Computes the restriction of the current DD with the given constraint. That is, the function value of the
+             * Computes the restriction of the current ADD with the given constraint. That is, the function value of the
              * resulting DD will be the same as the current ones for all assignments mapping to one in the constraint
              * and may be different otherwise.
              *
              * @param constraint The constraint to use for the operation.
-             * @return The resulting DD.
+             * @return The resulting ADD.
              */
-            Dd<DdType::CUDD> restrict(Dd<DdType::CUDD> const& constraint) const;
+            Add<DdType::CUDD> restrict(Add<DdType::CUDD> const& constraint) const;
             
             /*!
-             * Retrieves the support of the current DD.
+             * Retrieves the support of the current ADD.
              *
-             * @return The support represented as a DD.
+             * @return The support represented as a BDD.
              */
-            Dd<DdType::CUDD> getSupport() const;
+            Bdd<DdType::CUDD> getSupport() const;
             
             /*!
              * Retrieves the number of encodings that are mapped to a non-zero value.
              *
              * @return The number of encodings that are mapped to a non-zero value.
              */
-            uint_fast64_t getNonZeroCount() const;
+            virtual uint_fast64_t getNonZeroCount() const override;
             
             /*!
-             * Retrieves the number of leaves of the DD.
+             * Retrieves the number of leaves of the ADD.
              *
-             * @return The number of leaves of the DD.
+             * @return The number of leaves of the ADD.
              */
-            uint_fast64_t getLeafCount() const;
+            virtual uint_fast64_t getLeafCount() const override;
             
             /*!
              * Retrieves the number of nodes necessary to represent the DD.
              *
              * @return The number of nodes in this DD.
              */
-            uint_fast64_t getNodeCount() const;
+            virtual uint_fast64_t getNodeCount() const override;
             
             /*!
              * Retrieves the lowest function value of any encoding.
@@ -485,23 +415,23 @@ namespace storm {
             double getValue(std::map<storm::expressions::Variable, int_fast64_t> const& metaVariableToValueMap = std::map<storm::expressions::Variable, int_fast64_t>()) const;
             
             /*!
-             * Retrieves whether this DD represents the constant one function.
+             * Retrieves whether this ADD represents the constant one function.
              *
-             * @return True if this DD represents the constant one function.
+             * @return True if this ADD represents the constant one function.
              */
             bool isOne() const;
             
             /*!
-             * Retrieves whether this DD represents the constant zero function.
+             * Retrieves whether this ADD represents the constant zero function.
              *
-             * @return True if this DD represents the constant zero function.
+             * @return True if this ADD represents the constant zero function.
              */
             bool isZero() const;
             
             /*!
-             * Retrieves whether this DD represents a constant function.
+             * Retrieves whether this ADD represents a constant function.
              *
-             * @return True if this DD represents a constants function.
+             * @return True if this ADD represents a constants function.
              */
             bool isConstant() const;
             
@@ -510,101 +440,71 @@ namespace storm {
              *
              * @return The index of the topmost variable in DD.
              */
-            uint_fast64_t getIndex() const;
+            virtual uint_fast64_t getIndex() const override;
             
             /*!
-             * Converts the DD to a vector.
+             * Converts the ADD to a vector.
              *
-             * @return The double vector that is represented by this DD.
+             * @return The double vector that is represented by this ADD.
              */
             template<typename ValueType>
             std::vector<ValueType> toVector() const;
             
             /*!
-             * Converts the DD to a vector. The given offset-labeled DD is used to determine the correct row of
+             * Converts the ADD to a vector. The given offset-labeled DD is used to determine the correct row of
              * each entry.
              *
              * @param rowOdd The ODD used for determining the correct row.
-             * @return The double vector that is represented by this DD.
+             * @return The double vector that is represented by this ADD.
              */
             template<typename ValueType>
             std::vector<ValueType> toVector(storm::dd::Odd<DdType::CUDD> const& rowOdd) const;
             
             /*!
-             * Converts the DD to a (sparse) double matrix. All contained non-primed variables are assumed to encode the
+             * Converts the ADD to a (sparse) double matrix. All contained non-primed variables are assumed to encode the
              * row, whereas all primed variables are assumed to encode the column.
              *
-             * @return The matrix that is represented by this DD.
+             * @return The matrix that is represented by this ADD.
              */
             storm::storage::SparseMatrix<double> toMatrix() const;
             
             /*!
-             * Converts the DD to a (sparse) double matrix. All contained non-primed variables are assumed to encode the
+             * Converts the ADD to a (sparse) double matrix. All contained non-primed variables are assumed to encode the
              * row, whereas all primed variables are assumed to encode the column. The given offset-labeled DDs are used
              * to determine the correct row and column, respectively, for each entry.
              *
              * @param rowOdd The ODD used for determining the correct row.
              * @param columnOdd The ODD used for determining the correct column.
-             * @return The matrix that is represented by this DD.
+             * @return The matrix that is represented by this ADD.
              */
             storm::storage::SparseMatrix<double> toMatrix(storm::dd::Odd<DdType::CUDD> const& rowOdd, storm::dd::Odd<DdType::CUDD> const& columnOdd) const;
             
             /*!
-             * Converts the DD to a (sparse) double matrix. The given offset-labeled DDs are used to determine the
+             * Converts the ADD to a (sparse) double matrix. The given offset-labeled DDs are used to determine the
              * correct row and column, respectively, for each entry.
              *
              * @param rowMetaVariables The meta variables that encode the rows of the matrix.
              * @param columnMetaVariables The meta variables that encode the columns of the matrix.
              * @param rowOdd The ODD used for determining the correct row.
              * @param columnOdd The ODD used for determining the correct column.
-             * @return The matrix that is represented by this DD.
+             * @return The matrix that is represented by this ADD.
              */
             storm::storage::SparseMatrix<double> toMatrix(std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, storm::dd::Odd<DdType::CUDD> const& rowOdd, storm::dd::Odd<DdType::CUDD> const& columnOdd) const;
             
             /*!
-             * Converts the DD to a row-grouped (sparse) double matrix. The given offset-labeled DDs are used to
+             * Converts the ADD to a row-grouped (sparse) double matrix. The given offset-labeled DDs are used to
              * determine the correct row and column, respectively, for each entry. Note: this function assumes that
-             * the meta variables used to distinguish different row groups are at the very top of the DD.
+             * the meta variables used to distinguish different row groups are at the very top of the ADD.
              *
              * @param rowMetaVariables The meta variables that encode the rows of the matrix.
              * @param columnMetaVariables The meta variables that encode the columns of the matrix.
              * @param groupMetaVariables The meta variables that are used to distinguish different row groups.
              * @param rowOdd The ODD used for determining the correct row.
              * @param columnOdd The ODD used for determining the correct column.
-             * @return The matrix that is represented by this DD.
+             * @return The matrix that is represented by this ADD.
              */
             storm::storage::SparseMatrix<double> toMatrix(std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd<DdType::CUDD> const& rowOdd, storm::dd::Odd<DdType::CUDD> const& columnOdd) const;
             
-            /*!
-             * Retrieves whether the given meta variable is contained in the DD.
-             *
-             * @param metaVariable The meta variable for which to query membership.
-             * @return True iff the meta variable is contained in the DD.
-             */
-            bool containsMetaVariable(storm::expressions::Variable const& metaVariable) const;
-            
-            /*!
-             * Retrieves whether the given meta variables are all contained in the DD.
-             *
-             * @param metaVariables The meta variables for which to query membership.
-             * @return True iff all meta variables are contained in the DD.
-             */
-            bool containsMetaVariables(std::set<storm::expressions::Variable> const& metaVariables) const;
-            
-            /*!
-             * Retrieves the set of all meta variables contained in the DD.
-             *
-             * @return The set of all meta variables contained in the DD.
-             */
-            std::set<storm::expressions::Variable> const& getContainedMetaVariables() const;
-            
-            /*!
-             * Retrieves the set of all meta variables contained in the DD.
-             *
-             * @return The set of all meta variables contained in the DD.
-             */
-            std::set<storm::expressions::Variable>& getContainedMetaVariables();
-            
             /*!
              * Exports the DD to the given file in the dot format.
              *
@@ -612,13 +512,6 @@ namespace storm {
              */
             void exportToDot(std::string const& filename = "") const;
             
-            /*!
-             * Retrieves the manager that is responsible for this DD.
-             *
-             * A pointer to the manager that is responsible for this DD.
-             */
-            std::shared_ptr<DdManager<DdType::CUDD> const> getDdManager() const;
-            
             /*!
              * Retrieves an iterator that points to the first meta variable assignment with a non-zero function value.
              *
@@ -637,137 +530,40 @@ namespace storm {
              */
             DdForwardIterator<DdType::CUDD> end(bool enumerateDontCareMetaVariables = true) const;
             
-            /*!
-             * Converts the DD into a (heavily nested) if-then-else expression that represents the very same function.
-             * The variable names used in the expression are derived from the meta variable name and are extended with a
-             * suffix ".i" if the meta variable is integer-valued, expressing that the variable is the i-th bit of the
-             * meta variable.
-             *
-             * @return The resulting expression.
-             */
-            storm::expressions::Expression toExpression() const;
-            
-            /*!
-             * Converts the DD into a (heavily nested) if-then-else (with negations) expression that evaluates to true
-             * if and only if the assignment is minterm of the DD. The variable names used in the expression are derived
-             * from the meta variable name and are extended with a suffix ".i" if the meta variable is integer-valued,
-             * expressing that the variable is the i-th bit of the meta variable.
-             *
-             * @return The resulting expression.
-             */
-            storm::expressions::Expression getMintermExpression() const;
-            
-            friend std::ostream & operator<<(std::ostream& out, const Dd<DdType::CUDD>& dd);
+            friend std::ostream & operator<<(std::ostream& out, const Add<DdType::CUDD>& add);
             
             /*!
-             * Converts an MTBDD to a BDD by mapping all values unequal to zero to 1. This effectively does the same as
+             * Converts the ADD to a BDD by mapping all values unequal to zero to 1. This effectively does the same as
              * a call to notZero().
              *
              * @return The corresponding BDD.
              */
-            Dd<DdType::CUDD> toBdd() const;
-            
-            /*!
-             * Converts a BDD to an equivalent MTBDD.
-             *
-             * @return The corresponding MTBDD.
-             */
-            Dd<DdType::CUDD> toMtbdd() const;
-            
-            /*!
-             * Retrieves whether this DD is a BDD.
-             *
-             * @return True iff this DD is a BDD.
-             */
-            bool isBdd() const;
-            
-            /*!
-             * Retrieves whether this DD is an MTBDD. Even though MTBDDs technicall subsume BDDs, this will return false
-             * if the DD is actually a BDD.
-             *
-             * @return True iff this DD is an MTBDD.
-             */
-            bool isMtbdd() const;
+            Bdd<DdType::CUDD> toBdd() const;
             
         private:
-            /*!
-             * Retrieves the CUDD BDD object associated with this DD.
-             *
-             * @return The CUDD BDD object associated with this DD.
-             */
-            BDD getCuddBdd() const;
             
             /*!
-             * Retrieves the CUDD MTBDD object associated with this DD.
+             * Retrieves the CUDD ADD object associated with this ADD.
              *
-             * @return The CUDD MTBDD object associated with this DD.
+             * @return The CUDD ADD object associated with this ADD.
              */
-            ADD getCuddMtbdd() const;
+            ADD getCuddAdd() const;
             
             /*!
-             * Retrieves the CUDD object associated with this DD.
+             * Retrieves the raw DD node of CUDD associated with this ADD.
              *
-             * @return The CUDD object associated with this DD.
-             */
-            ABDD const& getCuddDd() const;
-            
-            /*!
-             * Retrieves the raw DD node of CUDD associated with this DD.
-             *
-             * @return The DD node of CUDD associated with this DD.
+             * @return The DD node of CUDD associated with this ADD.
              */
             DdNode* getCuddDdNode() const;
             
             /*!
-             * Adds the given meta variable to the set of meta variables that are contained in this DD.
-             *
-             * @param metaVariable The name of the meta variable to add.
-             */
-            void addContainedMetaVariable(storm::expressions::Variable const& metaVariable);
-            
-            /*!
-             * Removes the given meta variable to the set of meta variables that are contained in this DD.
-             *
-             * @param metaVariable The name of the meta variable to remove.
-             */
-            void removeContainedMetaVariable(storm::expressions::Variable const& metaVariable);
-            
-            /*!
-             * Performs the recursive step of toExpression on the given DD.
-             *
-             * @param dd The dd to translate into an expression.
-             * @param variables The variables to use in the expression.
-             * @return The resulting expression.
-             */
-            static storm::expressions::Expression toExpressionRecur(DdNode const* dd, std::vector<storm::expressions::Variable> const& variables);
-            
-            /*!
-             * Performs the recursive step of getMintermExpression on the given DD.
-             *
-             * @param manager The manager of the DD.
-             * @param dd The dd whose minterms to translate into an expression.
-             * @param variables The variables to use in the expression.
-             * @return The resulting expression.
-             */
-            static storm::expressions::Expression getMintermExpressionRecur(::DdManager* manager, DdNode const* dd, std::vector<storm::expressions::Variable> const& variables);
-            
-            /*!
-             * Creates a DD that encapsulates the given CUDD ADD.
-             *
-             * @param ddManager The manager responsible for this DD.
-             * @param cuddDd The CUDD ADD to store.
-             * @param containedMetaVariables The meta variables that appear in the DD.
-             */
-            Dd(std::shared_ptr<DdManager<DdType::CUDD> const> ddManager, ADD cuddDd, std::set<storm::expressions::Variable> const& containedMetaVariables = std::set<storm::expressions::Variable>());
-            
-            /*!
-             * Creates a DD that encapsulates the given CUDD ADD.
+             * Creates an ADD that encapsulates the given CUDD ADD.
              *
              * @param ddManager The manager responsible for this DD.
-             * @param cuddDd The CUDD ADD to store.
+             * @param cuddAdd The CUDD ADD to store.
              * @param containedMetaVariables The meta variables that appear in the DD.
              */
-            Dd(std::shared_ptr<DdManager<DdType::CUDD> const> ddManager, BDD cuddDd, std::set<storm::expressions::Variable> const& containedMetaVariables = std::set<storm::expressions::Variable>());
+            Add(std::shared_ptr<DdManager<DdType::CUDD> const> ddManager, ADD cuddAdd, std::set<storm::expressions::Variable> const& containedMetaVariables = std::set<storm::expressions::Variable>());
             
             /*!
              * Helper function to convert the DD into a (sparse) matrix.
@@ -806,7 +602,7 @@ namespace storm {
              * @param maxLevel The number of levels that need to be considered.
              * @param remainingMetaVariables The meta variables that remain in the DDs after the groups have been split.
              */
-            void splitGroupsRec(DdNode* dd, std::vector<Dd<DdType::CUDD>>& groups, std::vector<uint_fast64_t> const& ddGroupVariableIndices, uint_fast64_t currentLevel, uint_fast64_t maxLevel, std::set<storm::expressions::Variable> const& remainingMetaVariables) const;
+            void splitGroupsRec(DdNode* dd, std::vector<Add<DdType::CUDD>>& groups, std::vector<uint_fast64_t> const& ddGroupVariableIndices, uint_fast64_t currentLevel, uint_fast64_t maxLevel, std::set<storm::expressions::Variable> const& remainingMetaVariables) const;
             
             /*!
              * Performs a recursive step to add the given DD-based vector to the given explicit vector.
@@ -822,24 +618,10 @@ namespace storm {
             template<typename ValueType>
             void addToVectorRec(DdNode const* dd, uint_fast64_t currentLevel, uint_fast64_t maxLevel, uint_fast64_t currentOffset, Odd<DdType::CUDD> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector) const;
             
-            /*!
-             * Retrieves the indices of all DD variables that are contained in this DD (not necessarily in the support,
-             * because they could be "don't cares"). Additionally, the indices are sorted to allow for easy access.
-             *
-             * @return The (sorted) indices of all DD variables that are contained in this DD.
-             */
-            std::vector<uint_fast64_t> getSortedVariableIndices() const;
-            
-            // A pointer to the manager responsible for this DD.
-            std::shared_ptr<DdManager<DdType::CUDD> const> ddManager;
-            
             // The ADD created by CUDD.
-            boost::variant<BDD, ADD> cuddDd;
-            
-            // The meta variables that appear in this DD.
-            std::set<storm::expressions::Variable> containedMetaVariables;
+            ADD cuddAdd;
         };
     }
 }
 
-#endif /* STORM_STORAGE_DD_CUDDDD_H_ */
\ No newline at end of file
+#endif /* STORM_STORAGE_DD_CUDDADD_H_ */
\ No newline at end of file
diff --git a/src/storage/dd/CuddBdd.cpp b/src/storage/dd/CuddBdd.cpp
index dd095af21..b311682f8 100644
--- a/src/storage/dd/CuddBdd.cpp
+++ b/src/storage/dd/CuddBdd.cpp
@@ -5,9 +5,12 @@
 #include "src/storage/dd/CuddAdd.h"
 #include "src/storage/dd/CuddDdManager.h"
 
+#include "src/utility/macros.h"
+#include "src/exceptions/InvalidArgumentException.h"
+
 namespace storm {
     namespace dd {
-        Bdd<DdType::CUDD>::Bdd(std::shared_ptr<DdManager<DdType::CUDD> const> ddManager, BDD cuddDd, std::set<storm::expressions::Variable> const& containedMetaVariables) : Dd<DdType::CUDD>(ddManager, containedMetaVariables) {
+        Bdd<DdType::CUDD>::Bdd(std::shared_ptr<DdManager<DdType::CUDD> const> ddManager, BDD cuddBdd, std::set<storm::expressions::Variable> const& containedMetaVariables) : Dd<DdType::CUDD>(ddManager, containedMetaVariables), cuddBdd(cuddBdd) {
             // Intentionally left empty.
         }
         
@@ -47,10 +50,11 @@ namespace storm {
         
         Bdd<DdType::CUDD>& Bdd<DdType::CUDD>::complement() {
             this->cuddBdd = ~this->getCuddBdd();
+            return *this;
         }
         
         Bdd<DdType::CUDD> Bdd<DdType::CUDD>::operator&&(Bdd<DdType::CUDD> const& other) const {
-            Dd<DdType::CUDD> result(*this);
+            Bdd<DdType::CUDD> result(*this);
             result &= other;
             return result;
         }
@@ -92,7 +96,7 @@ namespace storm {
         }
         
         Bdd<DdType::CUDD> Bdd<DdType::CUDD>::existsAbstract(std::set<storm::expressions::Variable> const& metaVariables) const {
-            Dd<DdType::CUDD> cubeDd(this->getDdManager()->getBddOne());
+            Bdd<DdType::CUDD> cubeBdd = this->getDdManager()->getBddOne();
             
             std::set<storm::expressions::Variable> newMetaVariables = this->getContainedMetaVariables();
             for (auto const& metaVariable : metaVariables) {
@@ -101,14 +105,14 @@ namespace storm {
                 newMetaVariables.erase(metaVariable);
                 
                 DdMetaVariable<DdType::CUDD> const& ddMetaVariable = this->getDdManager()->getMetaVariable(metaVariable);
-                cubeDd &= ddMetaVariable.getCube();
+                cubeBdd &= ddMetaVariable.getCube();
             }
             
-            return Bdd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().ExistAbstract(cubeDd.getCuddBdd()), newMetaVariables);
+            return Bdd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().ExistAbstract(cubeBdd.getCuddBdd()), newMetaVariables);
         }
         
-        Dd<DdType::CUDD> Bdd<DdType::CUDD>::universalAbstract(std::set<storm::expressions::Variable> const& metaVariables) const {
-            Dd<DdType::CUDD> cubeDd(this->getDdManager()->getBddOne());
+        Bdd<DdType::CUDD> Bdd<DdType::CUDD>::universalAbstract(std::set<storm::expressions::Variable> const& metaVariables) const {
+            Bdd<DdType::CUDD> cubeBdd = this->getDdManager()->getBddOne();
             
             std::set<storm::expressions::Variable> newMetaVariables = this->getContainedMetaVariables();
             for (auto const& metaVariable : metaVariables) {
@@ -117,13 +121,13 @@ namespace storm {
                 newMetaVariables.erase(metaVariable);
                 
                 DdMetaVariable<DdType::CUDD> const& ddMetaVariable = this->getDdManager()->getMetaVariable(metaVariable);
-                cubeDd &= ddMetaVariable.getCube();
+                cubeBdd &= ddMetaVariable.getCube();
             }
             
-            return Bdd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().UnivAbstract(cubeDd.getCuddBdd()), newMetaVariables);
+            return Bdd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().UnivAbstract(cubeBdd.getCuddBdd()), newMetaVariables);
         }
         
-        Dd<DdType::CUDD> Bdd<DdType::CUDD>::swapVariables(std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& metaVariablePairs) {
+        Bdd<DdType::CUDD> Bdd<DdType::CUDD>::swapVariables(std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& metaVariablePairs) {
             std::set<storm::expressions::Variable> newContainedMetaVariables;
             std::vector<BDD> from;
             std::vector<BDD> to;
@@ -156,12 +160,10 @@ namespace storm {
         }
         
         Bdd<DdType::CUDD> Bdd<DdType::CUDD>::andExists(Bdd<DdType::CUDD> const& other, std::set<storm::expressions::Variable> const& existentialVariables) const {
-            STORM_LOG_WARN_COND(this->isBdd() && other.isBdd(), "Performing logical operation on MTBDD(s).");
-            
-            Dd<DdType::CUDD> cubeDd(this->getDdManager()->getOne());
+            Bdd<DdType::CUDD> cubeBdd(this->getDdManager()->getBddOne());
             for (auto const& metaVariable : existentialVariables) {
                 DdMetaVariable<DdType::CUDD> const& ddMetaVariable = this->getDdManager()->getMetaVariable(metaVariable);
-                cubeDd &= ddMetaVariable.getCube();
+                cubeBdd &= ddMetaVariable.getCube();
             }
             
             std::set<storm::expressions::Variable> unionOfMetaVariables;
@@ -169,37 +171,23 @@ namespace storm {
             std::set<storm::expressions::Variable> containedMetaVariables;
             std::set_difference(unionOfMetaVariables.begin(), unionOfMetaVariables.end(), existentialVariables.begin(), existentialVariables.end(), std::inserter(containedMetaVariables, containedMetaVariables.begin()));
             
-            return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().AndAbstract(other.getCuddBdd(), cubeDd.getCuddBdd()), containedMetaVariables);
+            return Bdd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().AndAbstract(other.getCuddBdd(), cubeBdd.getCuddBdd()), containedMetaVariables);
         }
         
-        Dd<DdType::CUDD> Bdd<DdType::CUDD>::constrain(Dd<DdType::CUDD> const& constraint) const {
-            std::set<storm::expressions::Variable> metaVariables(this->getContainedMetaVariables());
-            metaVariables.insert(constraint.getContainedMetaVariables().begin(), constraint.getContainedMetaVariables().end());
-            
-            if (this->isBdd() && constraint.isBdd()) {
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().Constrain(constraint.getCuddBdd()), metaVariables);
-            } else {
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().Constrain(constraint.getCuddMtbdd()), metaVariables);
-            }
+        Bdd<DdType::CUDD> Bdd<DdType::CUDD>::constrain(Bdd<DdType::CUDD> const& constraint) const {
+            std::set<storm::expressions::Variable> metaVariables;
+            std::set_union(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end(), constraint.getContainedMetaVariables().begin(), constraint.getContainedMetaVariables().end(), std::inserter(metaVariables, metaVariables.begin()));
+            return Bdd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().Constrain(constraint.getCuddBdd()), metaVariables);
         }
         
-        Dd<DdType::CUDD> Bdd<DdType::CUDD>::restrict(Dd<DdType::CUDD> const& constraint) const {
-            std::set<storm::expressions::Variable> metaVariables(this->getContainedMetaVariables());
-            metaVariables.insert(constraint.getContainedMetaVariables().begin(), constraint.getContainedMetaVariables().end());
-            
-            if (this->isBdd() && constraint.isBdd()) {
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().Restrict(constraint.getCuddBdd()), metaVariables);
-            } else {
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().Restrict(constraint.getCuddMtbdd()), metaVariables);
-            }
+        Bdd<DdType::CUDD> Bdd<DdType::CUDD>::restrict(Bdd<DdType::CUDD> const& constraint) const {
+            std::set<storm::expressions::Variable> metaVariables;
+            std::set_union(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end(), constraint.getContainedMetaVariables().begin(), constraint.getContainedMetaVariables().end(), std::inserter(metaVariables, metaVariables.begin()));
+            return Bdd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().Restrict(constraint.getCuddBdd()), metaVariables);
         }
         
-        Dd<DdType::CUDD> Bdd<DdType::CUDD>::getSupport() const {
-            if (this->isBdd()) {
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().Support(), this->getContainedMetaVariables());
-            } else {
-                return Dd<DdType::CUDD>(this->getDdManager(), this->getCuddMtbdd().Support(), this->getContainedMetaVariables());
-            }
+        Bdd<DdType::CUDD> Bdd<DdType::CUDD>::getSupport() const {
+            return Bdd<DdType::CUDD>(this->getDdManager(), this->getCuddBdd().Support(), this->getContainedMetaVariables());
         }
         
         uint_fast64_t Bdd<DdType::CUDD>::getNonZeroCount() const {
@@ -207,76 +195,33 @@ namespace storm {
             for (auto const& metaVariable : this->getContainedMetaVariables()) {
                 numberOfDdVariables += this->getDdManager()->getMetaVariable(metaVariable).getNumberOfDdVariables();
             }
-            if (this->isBdd()) {
-                return static_cast<uint_fast64_t>(this->getCuddBdd().CountMinterm(static_cast<int>(numberOfDdVariables)));
-            } else {
-                return static_cast<uint_fast64_t>(this->getCuddMtbdd().CountMinterm(static_cast<int>(numberOfDdVariables)));
-            }
+            return static_cast<uint_fast64_t>(this->getCuddBdd().CountMinterm(static_cast<int>(numberOfDdVariables)));
         }
-        
+                
         uint_fast64_t Bdd<DdType::CUDD>::getLeafCount() const {
-            if (this->isBdd()) {
-                return static_cast<uint_fast64_t>(this->getCuddBdd().CountLeaves());
-            } else {
-                return static_cast<uint_fast64_t>(this->getCuddMtbdd().CountLeaves());
-            }
+            return static_cast<uint_fast64_t>(this->getCuddBdd().CountLeaves());
         }
         
         uint_fast64_t Bdd<DdType::CUDD>::getNodeCount() const {
-            if (this->isBdd()) {
-                return static_cast<uint_fast64_t>(this->getCuddBdd().nodeCount());
-            } else {
-                return static_cast<uint_fast64_t>(this->getCuddMtbdd().nodeCount());
-            }
+            return static_cast<uint_fast64_t>(this->getCuddBdd().nodeCount());
         }
         
         bool Bdd<DdType::CUDD>::isOne() const {
-            if (this->isBdd()) {
-                return this->getCuddBdd().IsOne();
-            } else {
-                return this->getCuddMtbdd().IsOne();
-            }
+            return this->getCuddBdd().IsOne();
         }
         
         bool Bdd<DdType::CUDD>::isZero() const {
-            if (this->isBdd()) {
-                return this->getCuddBdd().IsZero();
-            } else {
-                return this->getCuddMtbdd().IsZero();
-            }
+            return this->getCuddBdd().IsZero();
         }
         
         uint_fast64_t Bdd<DdType::CUDD>::getIndex() const {
-            if (this->isBdd()) {
-                return static_cast<uint_fast64_t>(this->getCuddBdd().NodeReadIndex());
-            } else {
-                return static_cast<uint_fast64_t>(this->getCuddMtbdd().NodeReadIndex());
-            }
-        }
-        
-        std::vector<uint_fast64_t> Bdd<DdType::CUDD>::getSortedVariableIndices() const {
-            std::vector<uint_fast64_t> ddVariableIndices;
-            for (auto const& metaVariableName : this->getContainedMetaVariables()) {
-                auto const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName);
-                for (auto const& ddVariable : metaVariable.getDdVariables()) {
-                    ddVariableIndices.push_back(ddVariable.getIndex());
-                }
-            }
-            
-            // Next, we need to sort them, since they may be arbitrarily ordered otherwise.
-            std::sort(ddVariableIndices.begin(), ddVariableIndices.end());
-            return ddVariableIndices;
+            return static_cast<uint_fast64_t>(this->getCuddBdd().NodeReadIndex());
         }
         
         void Bdd<DdType::CUDD>::exportToDot(std::string const& filename) const {
             if (filename.empty()) {
-                if (this->isBdd()) {
-                    std::vector<BDD> cuddBddVector = { this->getCuddBdd() };
-                    this->getDdManager()->getCuddManager().DumpDot(cuddBddVector);
-                } else {
-                    std::vector<ADD> cuddAddVector = { this->getCuddMtbdd() };
-                    this->getDdManager()->getCuddManager().DumpDot(cuddAddVector);
-                }
+                std::vector<BDD> cuddBddVector = { this->getCuddBdd() };
+                this->getDdManager()->getCuddManager().DumpDot(cuddBddVector);
             } else {
                 // Build the name input of the DD.
                 std::vector<char*> ddNames;
@@ -294,13 +239,8 @@ namespace storm {
                 
                 // Open the file, dump the DD and close it again.
                 FILE* filePointer = fopen(filename.c_str() , "w");
-                if (this->isBdd()) {
-                    std::vector<BDD> cuddBddVector = { this->getCuddBdd() };
-                    this->getDdManager()->getCuddManager().DumpDot(cuddBddVector, &ddVariableNames[0], &ddNames[0], filePointer);
-                } else {
-                    std::vector<ADD> cuddAddVector = { this->getCuddMtbdd() };
-                    this->getDdManager()->getCuddManager().DumpDot(cuddAddVector, &ddVariableNames[0], &ddNames[0], filePointer);
-                }
+                std::vector<BDD> cuddBddVector = { this->getCuddBdd() };
+                this->getDdManager()->getCuddManager().DumpDot(cuddBddVector, &ddVariableNames[0], &ddNames[0], filePointer);
                 fclose(filePointer);
                 
                 // Finally, delete the names.
@@ -313,8 +253,8 @@ namespace storm {
             }
         }
         
-        std::ostream& operator<<(std::ostream& out, const Dd<DdType::CUDD>& dd) {
-            dd.exportToDot();
+        std::ostream& operator<<(std::ostream& out, const Bdd<DdType::CUDD>& bdd) {
+            bdd.exportToDot();
             return out;
         }
     }
diff --git a/src/storage/dd/CuddBdd.h b/src/storage/dd/CuddBdd.h
index 19335a3f4..7ba62cceb 100644
--- a/src/storage/dd/CuddBdd.h
+++ b/src/storage/dd/CuddBdd.h
@@ -23,6 +23,7 @@ namespace storm {
             // Declare the DdManager and DdIterator class as friend so it can access the internals of a DD.
             friend class DdManager<DdType::CUDD>;
             friend class DdForwardIterator<DdType::CUDD>;
+            friend class Add<DdType::CUDD>;
             friend class Odd<DdType::CUDD>;
             
             // Instantiate all copy/move constructors/assignments with the default implementation.
@@ -198,6 +199,13 @@ namespace storm {
              */
             virtual uint_fast64_t getNonZeroCount() const override;
             
+            /*!
+             * Retrieves the number of leaves of the DD.
+             *
+             * @return The number of leaves of the DD.
+             */
+            virtual uint_fast64_t getLeafCount() const override;
+            
             /*!
              * Retrieves the number of nodes necessary to represent the DD.
              *
@@ -261,10 +269,10 @@ namespace storm {
              * Creates a DD that encapsulates the given CUDD ADD.
              *
              * @param ddManager The manager responsible for this DD.
-             * @param cuddDd The CUDD ADD to store.
+             * @param cuddBdd The CUDD BDD to store.
              * @param containedMetaVariables The meta variables that appear in the DD.
              */
-            Bdd(std::shared_ptr<DdManager<DdType::CUDD> const> ddManager, BDD cuddDd, std::set<storm::expressions::Variable> const& containedMetaVariables = std::set<storm::expressions::Variable>());
+            Bdd(std::shared_ptr<DdManager<DdType::CUDD> const> ddManager, BDD cuddBdd, std::set<storm::expressions::Variable> const& containedMetaVariables = std::set<storm::expressions::Variable>());
             
             // The BDD created by CUDD.
             BDD cuddBdd;
diff --git a/src/storage/dd/CuddDd.cpp b/src/storage/dd/CuddDd.cpp
index 3ec7328f4..43e2afd3f 100644
--- a/src/storage/dd/CuddDd.cpp
+++ b/src/storage/dd/CuddDd.cpp
@@ -48,5 +48,19 @@ namespace storm {
             std::set_difference(containedMetaVariables.begin(), containedMetaVariables.end(), metaVariables.begin(), metaVariables.end(), std::inserter(result, result.begin()));
             containedMetaVariables = std::move(result);
         }
+        
+        std::vector<uint_fast64_t> Dd<DdType::CUDD>::getSortedVariableIndices() const {
+            std::vector<uint_fast64_t> ddVariableIndices;
+            for (auto const& metaVariableName : this->getContainedMetaVariables()) {
+                auto const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName);
+                for (auto const& ddVariable : metaVariable.getDdVariables()) {
+                    ddVariableIndices.push_back(ddVariable.getIndex());
+                }
+            }
+            
+            // Next, we need to sort them, since they may be arbitrarily ordered otherwise.
+            std::sort(ddVariableIndices.begin(), ddVariableIndices.end());
+            return ddVariableIndices;
+        }
     }
 }
\ No newline at end of file
diff --git a/src/storage/dd/CuddDd.h b/src/storage/dd/CuddDd.h
index 197d2454c..fdeb085ef 100644
--- a/src/storage/dd/CuddDd.h
+++ b/src/storage/dd/CuddDd.h
@@ -104,7 +104,14 @@ namespace storm {
              * A pointer to the manager that is responsible for this DD.
              */
             std::shared_ptr<DdManager<DdType::CUDD> const> getDdManager() const;
-                        
+            
+            /*!
+             * Retrieves the (sorted) list of the variable indices of DD variables contained in this DD.
+             *
+             * @return The sorted list of variable indices.
+             */
+            std::vector<uint_fast64_t> getSortedVariableIndices() const;
+            
         protected:
             
             /*!
diff --git a/src/storage/dd/CuddDdForwardIterator.h b/src/storage/dd/CuddDdForwardIterator.h
index 228c8e1b4..e6498458d 100644
--- a/src/storage/dd/CuddDdForwardIterator.h
+++ b/src/storage/dd/CuddDdForwardIterator.h
@@ -17,12 +17,12 @@ namespace storm {
     namespace dd {
         // Forward-declare the DdManager class.
         template<DdType Type> class DdManager;
-        template<DdType Type> class Dd;
+        template<DdType Type> class Add;
         
         template<>
         class DdForwardIterator<DdType::CUDD> {
         public:
-            friend class Dd<DdType::CUDD>;
+            friend class Add<DdType::CUDD>;
 
             // Default-instantiate the constructor.
             DdForwardIterator();
diff --git a/src/storage/dd/CuddDdManager.cpp b/src/storage/dd/CuddDdManager.cpp
index a844075ce..63a84a58b 100644
--- a/src/storage/dd/CuddDdManager.cpp
+++ b/src/storage/dd/CuddDdManager.cpp
@@ -37,27 +37,28 @@ namespace storm {
             }
         }
         
-        Dd<DdType::CUDD> DdManager<DdType::CUDD>::getOne(bool asMtbdd) const {
-            if (asMtbdd) {
-                return Dd<DdType::CUDD>(this->shared_from_this(), cuddManager.addOne());
-            } else {
-                return Dd<DdType::CUDD>(this->shared_from_this(), cuddManager.bddOne());
-            }
+        Bdd<DdType::CUDD> DdManager<DdType::CUDD>::getBddOne() const {
+            return Bdd<DdType::CUDD>(this->shared_from_this(), cuddManager.bddOne());
+        }
+
+        Add<DdType::CUDD> DdManager<DdType::CUDD>::getAddOne() const {
+            return Add<DdType::CUDD>(this->shared_from_this(), cuddManager.addOne());
         }
         
-        Dd<DdType::CUDD> DdManager<DdType::CUDD>::getZero(bool asMtbdd) const {
-            if (asMtbdd) {
-                return Dd<DdType::CUDD>(this->shared_from_this(), cuddManager.addZero());
-            } else {
-                return Dd<DdType::CUDD>(this->shared_from_this(), cuddManager.bddZero());
-            }
+        Bdd<DdType::CUDD> DdManager<DdType::CUDD>::getBddZero() const {
+            return Bdd<DdType::CUDD>(this->shared_from_this(), cuddManager.bddZero());
         }
         
-        Dd<DdType::CUDD> DdManager<DdType::CUDD>::getConstant(double value) const {
-            return Dd<DdType::CUDD>(this->shared_from_this(), cuddManager.constant(value));
+        Add<DdType::CUDD> DdManager<DdType::CUDD>::getAddZero() const {
+            return Add<DdType::CUDD>(this->shared_from_this(), cuddManager.addZero());
         }
         
-        Dd<DdType::CUDD> DdManager<DdType::CUDD>::getEncoding(storm::expressions::Variable const& variable, int_fast64_t value, bool asMtbdd) const {
+        
+        Add<DdType::CUDD> DdManager<DdType::CUDD>::getConstant(double value) const {
+            return Add<DdType::CUDD>(this->shared_from_this(), cuddManager.constant(value));
+        }
+        
+        Bdd<DdType::CUDD> DdManager<DdType::CUDD>::getEncoding(storm::expressions::Variable const& variable, int_fast64_t value) const {
             DdMetaVariable<DdType::CUDD> const& metaVariable = this->getMetaVariable(variable);
             
             STORM_LOG_THROW(value >= metaVariable.getLow() && value <= metaVariable.getHigh(), storm::exceptions::InvalidArgumentException, "Illegal value " << value << " for meta variable '" << variable.getName() << "'.");
@@ -65,9 +66,9 @@ namespace storm {
             // Now compute the encoding relative to the low value of the meta variable.
             value -= metaVariable.getLow();
             
-            std::vector<Dd<DdType::CUDD>> const& ddVariables = metaVariable.getDdVariables();
+            std::vector<Bdd<DdType::CUDD>> const& ddVariables = metaVariable.getDdVariables();
 
-            Dd<DdType::CUDD> result;
+            Bdd<DdType::CUDD> result;
             if (value & (1ull << (ddVariables.size() - 1))) {
                 result = ddVariables[0];
             } else {
@@ -82,31 +83,27 @@ namespace storm {
                 }
             }
             
-            if (asMtbdd) {
-                return result.toMtbdd();
-            } else {
-                return result;
-            }
+            return result;
         }
         
-        Dd<DdType::CUDD> DdManager<DdType::CUDD>::getRange(storm::expressions::Variable const& variable, bool asMtbdd) const {
+        Bdd<DdType::CUDD> DdManager<DdType::CUDD>::getRange(storm::expressions::Variable const& variable) const {
             storm::dd::DdMetaVariable<DdType::CUDD> const& metaVariable = this->getMetaVariable(variable);
             
-            Dd<DdType::CUDD> result = this->getZero(asMtbdd);
+            Bdd<DdType::CUDD> result = this->getBddZero();
             
             for (int_fast64_t value = metaVariable.getLow(); value <= metaVariable.getHigh(); ++value) {
-                result.setValue(variable, value, static_cast<double>(1));
+                result |= this->getEncoding(variable, value);
             }
             
             return result;
         }
         
-        Dd<DdType::CUDD> DdManager<DdType::CUDD>::getIdentity(storm::expressions::Variable const& variable) const {
+        Add<DdType::CUDD> DdManager<DdType::CUDD>::getIdentity(storm::expressions::Variable const& variable) const {
             storm::dd::DdMetaVariable<DdType::CUDD> const& metaVariable = this->getMetaVariable(variable);
             
-            Dd<DdType::CUDD> result = this->getZero(true);
+            Add<DdType::CUDD> result = this->getAddZero();
             for (int_fast64_t value = metaVariable.getLow(); value <= metaVariable.getHigh(); ++value) {
-                result.setValue(variable, value, static_cast<double>(value));
+                result += this->getEncoding(variable, value).toAdd() * this->getConstant(value);
             }
             return result;
         }
@@ -126,11 +123,11 @@ namespace storm {
             storm::expressions::Variable unprimed = manager->declareBitVectorVariable(name, numberOfBits);
             storm::expressions::Variable primed = manager->declareBitVectorVariable(name + "'", numberOfBits);
             
-            std::vector<Dd<DdType::CUDD>> variables;
-            std::vector<Dd<DdType::CUDD>> variablesPrime;
+            std::vector<Bdd<DdType::CUDD>> variables;
+            std::vector<Bdd<DdType::CUDD>> variablesPrime;
             for (std::size_t i = 0; i < numberOfBits; ++i) {
-                variables.emplace_back(Dd<DdType::CUDD>(this->shared_from_this(), cuddManager.bddVar(), {unprimed}));
-                variablesPrime.emplace_back(Dd<DdType::CUDD>(this->shared_from_this(), cuddManager.bddVar(), {primed}));
+                variables.emplace_back(Bdd<DdType::CUDD>(this->shared_from_this(), cuddManager.bddVar(), {unprimed}));
+                variablesPrime.emplace_back(Bdd<DdType::CUDD>(this->shared_from_this(), cuddManager.bddVar(), {primed}));
             }
             
             // Now group the non-primed and primed variable.
@@ -154,10 +151,10 @@ namespace storm {
             storm::expressions::Variable unprimed = manager->declareBooleanVariable(name);
             storm::expressions::Variable primed = manager->declareBooleanVariable(name + "'");
 
-            std::vector<Dd<DdType::CUDD>> variables;
-            std::vector<Dd<DdType::CUDD>> variablesPrime;
-            variables.emplace_back(Dd<DdType::CUDD>(this->shared_from_this(), cuddManager.bddVar(), {unprimed}));
-            variablesPrime.emplace_back(Dd<DdType::CUDD>(this->shared_from_this(), cuddManager.bddVar(), {primed}));
+            std::vector<Bdd<DdType::CUDD>> variables;
+            std::vector<Bdd<DdType::CUDD>> variablesPrime;
+            variables.emplace_back(Bdd<DdType::CUDD>(this->shared_from_this(), cuddManager.bddVar(), {unprimed}));
+            variablesPrime.emplace_back(Bdd<DdType::CUDD>(this->shared_from_this(), cuddManager.bddVar(), {primed}));
 
             // Now group the non-primed and primed variable.
             this->getCuddManager().MakeTreeNode(variables.front().getIndex(), 2, MTR_FIXED);
diff --git a/src/storage/dd/CuddDdManager.h b/src/storage/dd/CuddDdManager.h
index 4926e792c..07c11eb19 100644
--- a/src/storage/dd/CuddDdManager.h
+++ b/src/storage/dd/CuddDdManager.h
@@ -18,7 +18,8 @@ namespace storm {
         template<>
         class DdManager<DdType::CUDD> : public std::enable_shared_from_this<DdManager<DdType::CUDD>> {
         public:
-            friend class Dd<DdType::CUDD>;
+            friend class Bdd<DdType::CUDD>;
+            friend class Add<DdType::CUDD>;
             friend class Odd<DdType::CUDD>;
             friend class DdForwardIterator<DdType::CUDD>;
             
@@ -36,58 +37,68 @@ namespace storm {
 #endif
             
             /*!
-             * Retrieves a DD representing the constant one function. If the flag is set, the result will be given in
-             * terms of an MTBDD rather than a BDD.
+             * Retrieves a BDD representing the constant one function.
              *
-             * @return A DD representing the constant one function.
+             * @return A BDD representing the constant one function.
              */
-            Dd<DdType::CUDD> getOne(bool asMtbdd = false) const;
+            Bdd<DdType::CUDD> getBddOne() const;
             
             /*!
-             * Retrieves a DD representing the constant zero function. If the flag is set, the result will be given in
-             * terms of an MTBDD rather than a BDD.
+             * Retrieves an ADD representing the constant one function.
              *
-             * @return A DD representing the constant zero function.
+             * @return An ADD representing the constant one function.
              */
-            Dd<DdType::CUDD> getZero(bool asMtbdd = false) const;
+            Add<DdType::CUDD> getAddOne() const;
             
             /*!
-             * Retrieves a DD representing the constant function with the given value.
+             * Retrieves a BDD representing the constant zero function.
              *
-             * @return A DD representing the constant function with the given value.
+             * @return A BDD representing the constant zero function.
              */
-            Dd<DdType::CUDD> getConstant(double value) const;
+            Bdd<DdType::CUDD> getBddZero() const;
             
             /*!
-             * Retrieves the DD representing the function that maps all inputs which have the given meta variable equal
+             * Retrieves an ADD representing the constant zero function.
+             *
+             * @return An ADD representing the constant zero function.
+             */
+            Add<DdType::CUDD> getAddZero() const;
+            
+            /*!
+             * Retrieves an ADD representing the constant function with the given value.
+             *
+             * @return An ADD representing the constant function with the given value.
+             */
+            Add<DdType::CUDD> getConstant(double value) const;
+            
+            /*!
+             * Retrieves the BDD representing the function that maps all inputs which have the given meta variable equal
              * to the given value one.
              *
              * @param variable The expression variable associated with the meta variable.
              * @param value The value the meta variable is supposed to have.
-             * @param asMtbdd If set to true, the result will be given in terms of an MTBDD.
              * @return The DD representing the function that maps all inputs which have the given meta variable equal
              * to the given value one.
              */
-            Dd<DdType::CUDD> getEncoding(storm::expressions::Variable const& variable, int_fast64_t value, bool asMtbdd = false) const;
+            Bdd<DdType::CUDD> getEncoding(storm::expressions::Variable const& variable, int_fast64_t value) const;
             
             /*!
-             * Retrieves the DD representing the range of the meta variable, i.e., a function that maps all legal values
+             * Retrieves the BDD representing the range of the meta variable, i.e., a function that maps all legal values
              * of the range of the meta variable to one.
              *
              * @param variable The expression variable associated with the meta variable.
-             * @param asMtbdd If set to true, the result will be given in terms of an MTBDD.
              * @return The range of the meta variable.
              */
-            Dd<DdType::CUDD> getRange(storm::expressions::Variable const& variable, bool asMtbdd = false) const;
+            Bdd<DdType::CUDD> getRange(storm::expressions::Variable const& variable) const;
 
             /*!
-             * Retrieves the DD representing the identity of the meta variable, i.e., a function that maps all legal
+             * Retrieves the ADD representing the identity of the meta variable, i.e., a function that maps all legal
              * values of the range of the meta variable to themselves.
              *
              * @param variable The expression variable associated with the meta variable.
              * @return The identity of the meta variable.
              */
-            Dd<DdType::CUDD> getIdentity(storm::expressions::Variable const& variable) const;
+            Add<DdType::CUDD> getIdentity(storm::expressions::Variable const& variable) const;
             
             /*!
              * Adds an integer meta variable with the given range.
diff --git a/src/storage/dd/CuddDdMetaVariable.cpp b/src/storage/dd/CuddDdMetaVariable.cpp
index a53465682..4784f7235 100644
--- a/src/storage/dd/CuddDdMetaVariable.cpp
+++ b/src/storage/dd/CuddDdMetaVariable.cpp
@@ -3,20 +3,18 @@
 
 namespace storm {
     namespace dd {
-        DdMetaVariable<DdType::CUDD>::DdMetaVariable(std::string const& name, int_fast64_t low, int_fast64_t high, std::vector<Dd<DdType::CUDD>> const& ddVariables, std::shared_ptr<DdManager<DdType::CUDD>> manager) : name(name), type(MetaVariableType::Int), low(low), high(high), ddVariables(ddVariables), cube(manager->getOne()), cubeAsMtbdd(manager->getOne(true)), manager(manager) {
+        DdMetaVariable<DdType::CUDD>::DdMetaVariable(std::string const& name, int_fast64_t low, int_fast64_t high, std::vector<Bdd<DdType::CUDD>> const& ddVariables, std::shared_ptr<DdManager<DdType::CUDD>> manager) : name(name), type(MetaVariableType::Int), low(low), high(high), ddVariables(ddVariables), cube(manager->getBddOne()), manager(manager) {
             // Create the cube of all variables of this meta variable.
             for (auto const& ddVariable : this->ddVariables) {
                 this->cube &= ddVariable;
             }
-            this->cubeAsMtbdd = this->cube.toMtbdd();
         }
         
-        DdMetaVariable<DdType::CUDD>::DdMetaVariable(std::string const& name, std::vector<Dd<DdType::CUDD>> const& ddVariables, std::shared_ptr<DdManager<DdType::CUDD>> manager) : name(name), type(MetaVariableType::Bool), low(0), high(1), ddVariables(ddVariables), cube(manager->getOne()), cubeAsMtbdd(manager->getOne(true)), manager(manager) {
+        DdMetaVariable<DdType::CUDD>::DdMetaVariable(std::string const& name, std::vector<Bdd<DdType::CUDD>> const& ddVariables, std::shared_ptr<DdManager<DdType::CUDD>> manager) : name(name), type(MetaVariableType::Bool), low(0), high(1), ddVariables(ddVariables), cube(manager->getBddOne()), manager(manager) {
             // Create the cube of all variables of this meta variable.
             for (auto const& ddVariable : this->ddVariables) {
                 this->cube &= ddVariable;
             }
-            this->cubeAsMtbdd = this->cube.toMtbdd();
         }
         
         std::string const& DdMetaVariable<DdType::CUDD>::getName() const {
@@ -43,17 +41,12 @@ namespace storm {
             return this->manager;
         }
 
-        std::vector<Dd<DdType::CUDD>> const& DdMetaVariable<DdType::CUDD>::getDdVariables() const {
+        std::vector<Bdd<DdType::CUDD>> const& DdMetaVariable<DdType::CUDD>::getDdVariables() const {
             return this->ddVariables;
         }
         
-        Dd<DdType::CUDD> const& DdMetaVariable<DdType::CUDD>::getCube() const {
+        Bdd<DdType::CUDD> const& DdMetaVariable<DdType::CUDD>::getCube() const {
             return this->cube;
         }
-
-        Dd<DdType::CUDD> const& DdMetaVariable<DdType::CUDD>::getCubeAsMtbdd() const {
-            return this->cubeAsMtbdd;
-        }
-
     }
 }
\ No newline at end of file
diff --git a/src/storage/dd/CuddDdMetaVariable.h b/src/storage/dd/CuddDdMetaVariable.h
index aeea15389..4f016a6ce 100644
--- a/src/storage/dd/CuddDdMetaVariable.h
+++ b/src/storage/dd/CuddDdMetaVariable.h
@@ -7,8 +7,10 @@
 #include <string>
 
 #include "utility/OsDetection.h"
-#include "src/storage/dd/CuddDd.h"
+#include "src/storage/dd/CuddBdd.h"
+#include "src/storage/dd/CuddAdd.h"
 #include "src/storage/dd/DdMetaVariable.h"
+#include "src/storage/dd/CuddDdForwardIterator.h"
 #include "src/storage/expressions/Expression.h"
 
 namespace storm {
@@ -23,6 +25,8 @@ namespace storm {
             // Declare the DdManager class as friend so it can access the internals of a meta variable.
             friend class DdManager<DdType::CUDD>;
             friend class Dd<DdType::CUDD>;
+            friend class Bdd<DdType::CUDD>;
+            friend class Add<DdType::CUDD>;
             friend class Odd<DdType::CUDD>;
             friend class DdForwardIterator<DdType::CUDD>;
             
@@ -38,7 +42,7 @@ namespace storm {
              * @param ddVariables The vector of variables used to encode this variable.
              * @param manager A pointer to the manager that is responsible for this meta variable.
              */
-            DdMetaVariable(std::string const& name, int_fast64_t low, int_fast64_t high, std::vector<Dd<DdType::CUDD>> const& ddVariables, std::shared_ptr<DdManager<DdType::CUDD>> manager);
+            DdMetaVariable(std::string const& name, int_fast64_t low, int_fast64_t high, std::vector<Bdd<DdType::CUDD>> const& ddVariables, std::shared_ptr<DdManager<DdType::CUDD>> manager);
             
             /*!
              * Creates a boolean meta variable with the given name.
@@ -46,7 +50,7 @@ namespace storm {
              * @param ddVariables The vector of variables used to encode this variable.
              * @param manager A pointer to the manager that is responsible for this meta variable.
              */
-            DdMetaVariable(std::string const& name, std::vector<Dd<DdType::CUDD>> const& ddVariables, std::shared_ptr<DdManager<DdType::CUDD>> manager);
+            DdMetaVariable(std::string const& name, std::vector<Bdd<DdType::CUDD>> const& ddVariables, std::shared_ptr<DdManager<DdType::CUDD>> manager);
             
             // Explictly generate all default versions of copy/move constructors/assignments.
             DdMetaVariable(DdMetaVariable const& other) = default;
@@ -104,21 +108,14 @@ namespace storm {
              *
              * @return A vector of variables used to encode the meta variable.
              */
-            std::vector<Dd<DdType::CUDD>> const& getDdVariables() const;
+            std::vector<Bdd<DdType::CUDD>> const& getDdVariables() const;
             
             /*!
              * Retrieves the cube of all variables that encode this meta variable.
              *
              * @return The cube of all variables that encode this meta variable.
              */
-            Dd<DdType::CUDD> const& getCube() const;
-            
-            /*!
-             * Retrieves the cube of all variables that encode this meta variable represented as an MTBDD.
-             *
-             * @return The cube of all variables that encode this meta variable.
-             */
-            Dd<DdType::CUDD> const& getCubeAsMtbdd() const;
+            Bdd<DdType::CUDD> const& getCube() const;
             
             // The name of the meta variable.
             std::string name;
@@ -133,14 +130,10 @@ namespace storm {
             int_fast64_t high;
             
             // The vector of variables that are used to encode the meta variable.
-            std::vector<Dd<DdType::CUDD>> ddVariables;
+            std::vector<Bdd<DdType::CUDD>> ddVariables;
             
             // The cube consisting of all variables that encode the meta variable.
-            Dd<DdType::CUDD> cube;
-            
-            // The cube consisting of all variables that encode the meta variable represented by an MTBDD. This is
-            // used as a shortcut mainly for the abstraction methods.
-            Dd<DdType::CUDD> cubeAsMtbdd;
+            Bdd<DdType::CUDD> cube;
             
             // A pointer to the manager responsible for this meta variable.
             std::shared_ptr<DdManager<DdType::CUDD>> manager;
diff --git a/src/storage/dd/CuddOdd.cpp b/src/storage/dd/CuddOdd.cpp
index 8e489ec03..342f7458a 100644
--- a/src/storage/dd/CuddOdd.cpp
+++ b/src/storage/dd/CuddOdd.cpp
@@ -7,18 +7,18 @@
 
 namespace storm {
     namespace dd {
-        Odd<DdType::CUDD>::Odd(Dd<DdType::CUDD> const& dd) {
-            std::shared_ptr<DdManager<DdType::CUDD> const> manager = dd.getDdManager();
+        Odd<DdType::CUDD>::Odd(Add<DdType::CUDD> const& add) {
+            std::shared_ptr<DdManager<DdType::CUDD> const> manager = add.getDdManager();
             
             // First, we need to determine the involved DD variables indices.
-            std::vector<uint_fast64_t> ddVariableIndices = dd.getSortedVariableIndices();
+            std::vector<uint_fast64_t> ddVariableIndices = add.getSortedVariableIndices();
             
             // Prepare a unique table for each level that keeps the constructed ODD nodes unique.
             std::vector<std::map<DdNode*, std::shared_ptr<Odd<DdType::CUDD>>>> uniqueTableForLevels(ddVariableIndices.size() + 1);
             
             // Now construct the ODD structure.
             // Currently, the DD needs to be an MTBDD, because complement edges are not supported.
-            std::shared_ptr<Odd<DdType::CUDD>> rootOdd = buildOddRec(dd.toMtbdd().getCuddDdNode(), manager->getCuddManager(), 0, ddVariableIndices.size(), ddVariableIndices, uniqueTableForLevels);
+            std::shared_ptr<Odd<DdType::CUDD>> rootOdd = buildOddRec(add.getCuddDdNode(), manager->getCuddManager(), 0, ddVariableIndices.size(), ddVariableIndices, uniqueTableForLevels);
             
             // Finally, move the children of the root ODD into this ODD.
             this->elseNode = std::move(rootOdd->elseNode);
diff --git a/src/storage/dd/CuddOdd.h b/src/storage/dd/CuddOdd.h
index c12dfb67c..9d93d6e47 100644
--- a/src/storage/dd/CuddOdd.h
+++ b/src/storage/dd/CuddOdd.h
@@ -4,7 +4,7 @@
 #include <memory>
 
 #include "src/storage/dd/Odd.h"
-#include "src/storage/dd/CuddDd.h"
+#include "src/storage/dd/CuddAdd.h"
 #include "src/utility/OsDetection.h"
 
 // Include the C++-interface of CUDD.
@@ -18,9 +18,9 @@ namespace storm {
             /*!
              * Constructs an offset-labeled DD from the given DD.
              *
-             * @param dd The DD for which to build the offset-labeled DD.
+             * @param add The ADD for which to build the offset-labeled DD.
              */
-            Odd(Dd<DdType::CUDD> const& dd);
+            Odd(Add<DdType::CUDD> const& add);
             
             // Instantiate all copy/move constructors/assignments with the default implementation.
             Odd() = default;
diff --git a/src/utility/graph.h b/src/utility/graph.h
index 8eff8179d..13d30f34f 100644
--- a/src/utility/graph.h
+++ b/src/utility/graph.h
@@ -259,24 +259,24 @@ namespace storm {
              *
              * @param model The (symbolic) model for which to compute the set of states.
              * @param transitionMatrixBdd The transition matrix of the model as a BDD.
-             * @param phiStatesBdd The BDD containing all phi states of the model.
-             * @param psiStatesBdd The BDD containing all psi states of the model.
+             * @param phiStates The BDD containing all phi states of the model.
+             * @param psiStates The BDD containing all psi states of the model.
              * @return All states with positive probability.
              */
             template <storm::dd::DdType Type>
-            storm::dd::Dd<Type> performProbGreater0(storm::models::symbolic::DeterministicModel<Type> const& model, storm::dd::Dd<Type> const& transitionMatrixBdd, storm::dd::Dd<Type> const& phiStatesBdd, storm::dd::Dd<Type> const& psiStatesBdd) {
+            storm::dd::Bdd<Type> performProbGreater0(storm::models::symbolic::DeterministicModel<Type> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) {
                 // Initialize environment for backward search.
                 storm::dd::DdManager<Type> const& manager = model.getManager();
-                storm::dd::Dd<Type> lastIterationStates = manager.getZero();
-                storm::dd::Dd<Type> statesWithProbabilityGreater0 = psiStatesBdd;
+                storm::dd::Bdd<Type> lastIterationStates = manager.getBddZero();
+                storm::dd::Bdd<Type> statesWithProbabilityGreater0 = psiStates;
                 
                 uint_fast64_t iterations = 0;
                 while (lastIterationStates != statesWithProbabilityGreater0) {
                     lastIterationStates = statesWithProbabilityGreater0;
                     statesWithProbabilityGreater0 = statesWithProbabilityGreater0.swapVariables(model.getRowColumnMetaVariablePairs());
-                    statesWithProbabilityGreater0 &= transitionMatrixBdd;
+                    statesWithProbabilityGreater0 &= transitionMatrix;
                     statesWithProbabilityGreater0 = statesWithProbabilityGreater0.existsAbstract(model.getColumnVariables());
-                    statesWithProbabilityGreater0 &= phiStatesBdd;
+                    statesWithProbabilityGreater0 &= phiStates;
                     statesWithProbabilityGreater0 |= lastIterationStates;
                     ++iterations;
                 }
@@ -289,17 +289,16 @@ namespace storm {
              * deterministic model.
              *
              * @param model The (symbolic) model for which to compute the set of states.
-             * @param transitionMatrixBdd The transition matrix of the model as a BDD.
-             * @param phiStatesBdd The BDD containing all  phi states of the model.
-             * @param psiStatesBdd The BDD containing all psi states of the model.
-             * @return A pair of DDs that represent all states with probability 0 and 1, respectively.
+             * @param phiStates The BDD containing all  phi states of the model.
+             * @param psiStates The BDD containing all psi states of the model.
+             * @return A pair of BDDs that represent all states with probability 0 and 1, respectively.
              */
             template <storm::dd::DdType Type>
-            static std::pair<storm::dd::Dd<Type>, storm::dd::Dd<Type>> performProb01(storm::models::symbolic::DeterministicModel<Type> const& model, storm::dd::Dd<Type> const& phiStatesBdd, storm::dd::Dd<Type> const& psiStatesBdd) {
-                std::pair<storm::dd::Dd<Type>, storm::dd::Dd<Type>> result;
-                storm::dd::Dd<Type> transitionMatrixBdd = model.getTransitionMatrix().notZero();
-                result.first = performProbGreater0(model, transitionMatrixBdd, phiStatesBdd, psiStatesBdd);
-                result.second = !performProbGreater0(model, transitionMatrixBdd, !psiStatesBdd && model.getReachableStates(), !result.first && model.getReachableStates()) && model.getReachableStates();
+            static std::pair<storm::dd::Bdd<Type>, storm::dd::Bdd<Type>> performProb01(storm::models::symbolic::DeterministicModel<Type> const& model, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) {
+                std::pair<storm::dd::Bdd<Type>, storm::dd::Bdd<Type>> result;
+                storm::dd::Bdd<Type> transitionMatrix = model.getTransitionMatrix().notZero();
+                result.first = performProbGreater0(model, transitionMatrix, phiStates, psiStates);
+                result.second = !performProbGreater0(model, transitionMatrix, !psiStates && model.getReachableStates(), !result.first && model.getReachableStates()) && model.getReachableStates();
                 result.first = !result.first && model.getReachableStates();
                 return result;
             }
@@ -706,25 +705,25 @@ namespace storm {
              * zero of satisfying phi until psi.
              *
              * @param model The (symbolic) model for which to compute the set of states.
-             * @param transitionMatrixBdd The transition matrix of the model as a BDD.
-             * @param phiStatesBdd The BDD containing all phi states of the model.
-             * @param psiStatesBdd The BDD containing all psi states of the model.
-             * @return A DD representing all such states.
+             * @param transitionMatrix The transition matrix of the model as a BDD.
+             * @param phiStates The BDD containing all phi states of the model.
+             * @param psiStates The BDD containing all psi states of the model.
+             * @return A BDD representing all such states.
              */
             template <storm::dd::DdType Type>
-            storm::dd::Dd<Type> performProbGreater0E(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Dd<Type> const& transitionMatrixBdd, storm::dd::Dd<Type> const& phiStatesBdd, storm::dd::Dd<Type> const& psiStatesBdd) {
+            storm::dd::Bdd<Type> performProbGreater0E(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) {
                 // Initialize environment for backward search.
                 storm::dd::DdManager<Type> const& manager = model.getManager();
-                storm::dd::Dd<Type> lastIterationStates = manager.getZero();
-                storm::dd::Dd<Type> statesWithProbabilityGreater0E = psiStatesBdd;
+                storm::dd::Bdd<Type> lastIterationStates = manager.getBddZero();
+                storm::dd::Bdd<Type> statesWithProbabilityGreater0E = psiStates;
 
                 uint_fast64_t iterations = 0;
-                storm::dd::Dd<Type> abstractedTransitionMatrixBdd = transitionMatrixBdd.existsAbstract(model.getNondeterminismVariables());
+                storm::dd::Bdd<Type> abstractedTransitionMatrix = transitionMatrix.existsAbstract(model.getNondeterminismVariables());
                 while (lastIterationStates != statesWithProbabilityGreater0E) {
                     lastIterationStates = statesWithProbabilityGreater0E;
                     statesWithProbabilityGreater0E = statesWithProbabilityGreater0E.swapVariables(model.getRowColumnMetaVariablePairs());
-                    statesWithProbabilityGreater0E = statesWithProbabilityGreater0E.andExists(abstractedTransitionMatrixBdd, model.getColumnVariables());
-                    statesWithProbabilityGreater0E &= phiStatesBdd;
+                    statesWithProbabilityGreater0E = statesWithProbabilityGreater0E.andExists(abstractedTransitionMatrix, model.getColumnVariables());
+                    statesWithProbabilityGreater0E &= phiStates;
                     statesWithProbabilityGreater0E |= lastIterationStates;
                     ++iterations;
                 }
@@ -737,14 +736,14 @@ namespace storm {
              * than zero of satisfying phi until psi.
              *
              * @param model The (symbolic) model for which to compute the set of states.
-             * @param transitionMatrixBdd The transition matrix of the model as a BDD.
+             * @param transitionMatrix The transition matrix of the model as a BDD.
              * @param phiStates The phi states of the model.
              * @param psiStates The psi states of the model.
-             * @return A DD representing all such states.
+             * @return A BDD representing all such states.
              */
             template <storm::dd::DdType Type>
-            storm::dd::Dd<Type> performProb0A(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Dd<Type> const& transitionMatrixBdd, storm::dd::Dd<Type> const& phiStatesBdd, storm::dd::Dd<Type> const& psiStatesBdd) {
-                return !performProbGreater0E(model, transitionMatrixBdd, phiStatesBdd, psiStatesBdd) && model.getReachableStates();
+            storm::dd::Bdd<Type> performProb0A(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) {
+                return !performProbGreater0E(model, transitionMatrix, phiStates, psiStates) && model.getReachableStates();
             }
             
             /*!
@@ -752,27 +751,27 @@ namespace storm {
              * phi until psi.
              *
              * @param model The (symbolic) model for which to compute the set of states.
-             * @param transitionMatrixBdd The transition matrix of the model as a BDD.
-             * @param phiStatesBdd The BDD containing all phi states of the model.
-             * @param psiStatesBdd The BDD containing all psi states of the model.
-             * @return A DD representing all such states.
+             * @param transitionMatrix The transition matrix of the model as a BDD.
+             * @param phiStates The BDD containing all phi states of the model.
+             * @param psiStates The BDD containing all psi states of the model.
+             * @return A BDD representing all such states.
              */
             template <storm::dd::DdType Type>
-            storm::dd::Dd<Type> performProbGreater0A(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Dd<Type> const& transitionMatrixBdd, storm::dd::Dd<Type> const& phiStatesBdd, storm::dd::Dd<Type> const& psiStatesBdd) {
+            storm::dd::Bdd<Type> performProbGreater0A(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) {
                 // Initialize environment for backward search.
                 storm::dd::DdManager<Type> const& manager = model.getManager();
-                storm::dd::Dd<Type> lastIterationStates = manager.getZero();
-                storm::dd::Dd<Type> statesWithProbabilityGreater0A = psiStatesBdd;
+                storm::dd::Bdd<Type> lastIterationStates = manager.getBddZero();
+                storm::dd::Bdd<Type> statesWithProbabilityGreater0A = psiStates;
                 
                 uint_fast64_t iterations = 0;
                 while (lastIterationStates != statesWithProbabilityGreater0A) {
                     lastIterationStates = statesWithProbabilityGreater0A;
                     statesWithProbabilityGreater0A = statesWithProbabilityGreater0A.swapVariables(model.getRowColumnMetaVariablePairs());
-                    statesWithProbabilityGreater0A = statesWithProbabilityGreater0A.andExists(transitionMatrixBdd, model.getColumnVariables());
+                    statesWithProbabilityGreater0A = statesWithProbabilityGreater0A.andExists(transitionMatrix, model.getColumnVariables());
                     statesWithProbabilityGreater0A |= model.getIllegalMask();
                     statesWithProbabilityGreater0A = statesWithProbabilityGreater0A.universalAbstract(model.getNondeterminismVariables());
-                    statesWithProbabilityGreater0A &= phiStatesBdd;
-                    statesWithProbabilityGreater0A |= psiStatesBdd;
+                    statesWithProbabilityGreater0A &= phiStates;
+                    statesWithProbabilityGreater0A |= psiStates;
                     ++iterations;
                 }
                 
@@ -784,43 +783,43 @@ namespace storm {
              * phi until psi.
              *
              * @param model The (symbolic) model for which to compute the set of states.
-             * @param transitionMatrixBdd The transition matrix of the model as a BDD.
-             * @param phiStatesBdd The BDD containing all phi states of the model.
-             * @param psiStatesBdd The BDD containing all psi states of the model.
-             * @return A DD representing all such states.
+             * @param transitionMatrix The transition matrix of the model as a BDD.
+             * @param phiStates The BDD containing all phi states of the model.
+             * @param psiStates The BDD containing all psi states of the model.
+             * @return A BDD representing all such states.
              */
             template <storm::dd::DdType Type>
-            storm::dd::Dd<Type> performProb0E(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Dd<Type> const& transitionMatrixBdd, storm::dd::Dd<Type> const& phiStatesBdd, storm::dd::Dd<Type> const& psiStatesBdd) {
-                return !performProbGreater0A(model, transitionMatrixBdd, phiStatesBdd, psiStatesBdd) && model.getReachableStates();
+            storm::dd::Bdd<Type> performProb0E(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) {
+                return !performProbGreater0A(model, transitionMatrix, phiStates, psiStates) && model.getReachableStates();
             }
             
             /*!
              * Computes the set of states for which all schedulers achieve probability one of satisfying phi until psi.
              *
              * @param model The (symbolic) model for which to compute the set of states.
-             * @param transitionMatrixBdd The transition matrix of the model as a BDD.
-             * @param phiStatesBdd The BDD containing all phi states of the model.
-             * @param psiStatesBdd The BDD containing all psi states of the model.
+             * @param transitionMatrix The transition matrix of the model as a BDD.
+             * @param phiStates The BDD containing all phi states of the model.
+             * @param psiStates The BDD containing all psi states of the model.
              * @param statesWithProbabilityGreater0A The states of the model that have a probability greater zero under
              * all schedulers.
-             * @return A DD representing all such states.
+             * @return A BDD representing all such states.
              */
             template <storm::dd::DdType Type>
-            storm::dd::Dd<Type> performProb1A(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Dd<Type> const& transitionMatrixBdd, storm::dd::Dd<Type> const& phiStatesBdd, storm::dd::Dd<Type> const& psiStatesBdd, storm::dd::Dd<Type> const& statesWithProbabilityGreater0A) {
+            storm::dd::Bdd<Type> performProb1A(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates, storm::dd::Bdd<Type> const& statesWithProbabilityGreater0A) {
                 // Initialize environment for backward search.
                 storm::dd::DdManager<Type> const& manager = model.getManager();
-                storm::dd::Dd<Type> lastIterationStates = manager.getZero();
-                storm::dd::Dd<Type> statesWithProbability1A = psiStatesBdd || statesWithProbabilityGreater0A;
+                storm::dd::Bdd<Type> lastIterationStates = manager.getBddZero();
+                storm::dd::Bdd<Type> statesWithProbability1A = psiStates || statesWithProbabilityGreater0A;
                 
                 uint_fast64_t iterations = 0;
                 while (lastIterationStates != statesWithProbability1A) {
                     lastIterationStates = statesWithProbability1A;
                     statesWithProbability1A = statesWithProbability1A.swapVariables(model.getRowColumnMetaVariablePairs());
-                    statesWithProbability1A = transitionMatrixBdd.implies(statesWithProbability1A).universalAbstract(model.getColumnVariables());
+                    statesWithProbability1A = transitionMatrix.implies(statesWithProbability1A).universalAbstract(model.getColumnVariables());
                     statesWithProbability1A |= model.getIllegalMask();
                     statesWithProbability1A = statesWithProbability1A.universalAbstract(model.getNondeterminismVariables());
                     statesWithProbability1A &= statesWithProbabilityGreater0A;
-                    statesWithProbability1A |= psiStatesBdd;
+                    statesWithProbability1A |= psiStates;
                     ++iterations;
                 }
                 
@@ -832,35 +831,35 @@ namespace storm {
              * phi until psi.
              *
              * @param model The (symbolic) model for which to compute the set of states.
-             * @param transitionMatrixBdd The transition matrix of the model as a BDD.
-             * @param phiStatesBdd The BDD containing all phi states of the model.
-             * @param psiStatesBdd The BDD containing all psi states of the model.
+             * @param transitionMatrix The transition matrix of the model as a BDD.
+             * @param phiStates The BDD containing all phi states of the model.
+             * @param psiStates The BDD containing all psi states of the model.
              * @param statesWithProbabilityGreater0E The states of the model that have a scheduler that achieves a value
              * greater than zero.
-             * @return A DD representing all such states.
+             * @return A BDD representing all such states.
              */
             template <storm::dd::DdType Type>
-            storm::dd::Dd<Type> performProb1E(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Dd<Type> const& transitionMatrixBdd, storm::dd::Dd<Type> const& phiStatesBdd, storm::dd::Dd<Type> const& psiStatesBdd, storm::dd::Dd<Type> const& statesWithProbabilityGreater0E) {
+            storm::dd::Bdd<Type> performProb1E(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates, storm::dd::Bdd<Type> const& statesWithProbabilityGreater0E) {
                 // Initialize environment for backward search.
                 storm::dd::DdManager<Type> const& manager = model.getManager();
-                storm::dd::Dd<Type> statesWithProbability1E = statesWithProbabilityGreater0E;
+                storm::dd::Bdd<Type> statesWithProbability1E = statesWithProbabilityGreater0E;
 
                 uint_fast64_t iterations = 0;
                 bool outerLoopDone = false;
                 while (!outerLoopDone) {
-                    storm::dd::Dd<Type> innerStates = manager.getZero();
+                    storm::dd::Bdd<Type> innerStates = manager.getBddZero();
                     
                     bool innerLoopDone = false;
                     while (!innerLoopDone) {
-                        storm::dd::Dd<Type> temporary = statesWithProbability1E.swapVariables(model.getRowColumnMetaVariablePairs());
-                        temporary = transitionMatrixBdd.implies(temporary).universalAbstract(model.getColumnVariables());
+                        storm::dd::Bdd<Type> temporary = statesWithProbability1E.swapVariables(model.getRowColumnMetaVariablePairs());
+                        temporary = transitionMatrix.implies(temporary).universalAbstract(model.getColumnVariables());
                         
-                        storm::dd::Dd<Type> temporary2 = innerStates.swapVariables(model.getRowColumnMetaVariablePairs());
-                        temporary2 = transitionMatrixBdd.andExists(temporary2, model.getColumnVariables());
+                        storm::dd::Bdd<Type> temporary2 = innerStates.swapVariables(model.getRowColumnMetaVariablePairs());
+                        temporary2 = transitionMatrix.andExists(temporary2, model.getColumnVariables());
                         
                         temporary = temporary.andExists(temporary2, model.getNondeterminismVariables());
-                        temporary &= phiStatesBdd;
-                        temporary |= psiStatesBdd;
+                        temporary &= phiStates;
+                        temporary |= psiStates;
                         
                         if (innerStates == temporary) {
                             innerLoopDone = true;
@@ -881,20 +880,20 @@ namespace storm {
             }
             
             template <storm::dd::DdType Type>
-            std::pair<storm::dd::Dd<Type>, storm::dd::Dd<Type>> performProb01Max(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Dd<Type> const& phiStatesBdd, storm::dd::Dd<Type> const& psiStatesBdd) {
-                std::pair<storm::dd::Dd<Type>, storm::dd::Dd<Type>> result;
-                storm::dd::Dd<Type> transitionMatrixBdd = model.getTransitionMatrix().notZero();
-                result.first = performProb0A(model, transitionMatrixBdd, phiStatesBdd, psiStatesBdd);
-                result.second = performProb1E(model, transitionMatrixBdd, phiStatesBdd, psiStatesBdd, !result.first && model.getReachableStates());
+            std::pair<storm::dd::Bdd<Type>, storm::dd::Bdd<Type>> performProb01Max(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) {
+                std::pair<storm::dd::Bdd<Type>, storm::dd::Bdd<Type>> result;
+                storm::dd::Bdd<Type> transitionMatrix = model.getTransitionMatrix().notZero();
+                result.first = performProb0A(model, transitionMatrix, phiStates, psiStates);
+                result.second = performProb1E(model, transitionMatrix, phiStates, psiStates, !result.first && model.getReachableStates());
                 return result;
             }
 
             template <storm::dd::DdType Type>
-            std::pair<storm::dd::Dd<Type>, storm::dd::Dd<Type>> performProb01Min(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Dd<Type> const& phiStatesBdd, storm::dd::Dd<Type> const& psiStatesBdd) {
-                std::pair<storm::dd::Dd<Type>, storm::dd::Dd<Type>> result;
-                storm::dd::Dd<Type> transitionMatrixBdd = model.getTransitionMatrix().notZero();
-                result.first = performProb0E(model, transitionMatrixBdd, phiStatesBdd, psiStatesBdd);
-                result.second = performProb1A(model, transitionMatrixBdd, phiStatesBdd, psiStatesBdd, !result.first && model.getReachableStates());
+            std::pair<storm::dd::Bdd<Type>, storm::dd::Bdd<Type>> performProb01Min(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) {
+                std::pair<storm::dd::Bdd<Type>, storm::dd::Bdd<Type>> result;
+                storm::dd::Bdd<Type> transitionMatrix = model.getTransitionMatrix().notZero();
+                result.first = performProb0E(model, transitionMatrix, phiStates, psiStates);
+                result.second = performProb1A(model, transitionMatrix, phiStates, psiStates, !result.first && model.getReachableStates());
                 return result;
             }
             
diff --git a/test/functional/storage/CuddDdTest.cpp b/test/functional/storage/CuddDdTest.cpp
index 773334797..654283a90 100644
--- a/test/functional/storage/CuddDdTest.cpp
+++ b/test/functional/storage/CuddDdTest.cpp
@@ -2,14 +2,14 @@
 #include "storm-config.h"
 #include "src/exceptions/InvalidArgumentException.h"
 #include "src/storage/dd/CuddDdManager.h"
-#include "src/storage/dd/CuddDd.h"
+#include "src/storage/dd/CuddAdd.h"
 #include "src/storage/dd/CuddOdd.h"
 #include "src/storage/dd/DdMetaVariable.h"
 
 TEST(CuddDdManager, Constants) {
     std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
-    storm::dd::Dd<storm::dd::DdType::CUDD> zero;
-    ASSERT_NO_THROW(zero = manager->getZero());
+    storm::dd::Add<storm::dd::DdType::CUDD> zero;
+    ASSERT_NO_THROW(zero = manager->getAddZero());
     
     EXPECT_EQ(0, zero.getNonZeroCount());
     EXPECT_EQ(1, zero.getLeafCount());
@@ -17,8 +17,8 @@ TEST(CuddDdManager, Constants) {
     EXPECT_EQ(0, zero.getMin());
     EXPECT_EQ(0, zero.getMax());
     
-    storm::dd::Dd<storm::dd::DdType::CUDD> one;
-    ASSERT_NO_THROW(one = manager->getOne());
+    storm::dd::Add<storm::dd::DdType::CUDD> one;
+    ASSERT_NO_THROW(one = manager->getAddOne());
     
     EXPECT_EQ(1, one.getNonZeroCount());
     EXPECT_EQ(1, one.getLeafCount());
@@ -26,7 +26,7 @@ TEST(CuddDdManager, Constants) {
     EXPECT_EQ(1, one.getMin());
     EXPECT_EQ(1, one.getMax());
 
-    storm::dd::Dd<storm::dd::DdType::CUDD> two;
+    storm::dd::Add<storm::dd::DdType::CUDD> two;
     ASSERT_NO_THROW(two = manager->getConstant(2));
     
     EXPECT_EQ(1, two.getNonZeroCount());
@@ -57,7 +57,7 @@ TEST(CuddDdManager, EncodingTest) {
     std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
     std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
     
-    storm::dd::Dd<storm::dd::DdType::CUDD> encoding;
+    storm::dd::Bdd<storm::dd::DdType::CUDD> encoding;
     ASSERT_THROW(encoding = manager->getEncoding(x.first, 0), storm::exceptions::InvalidArgumentException);
     ASSERT_THROW(encoding = manager->getEncoding(x.first, 10), storm::exceptions::InvalidArgumentException);
     ASSERT_NO_THROW(encoding = manager->getEncoding(x.first, 4));
@@ -69,8 +69,8 @@ TEST(CuddDdManager, EncodingTest) {
     EXPECT_EQ(1, encoding.getLeafCount());
     
     // As an MTBDD, the 0-leaf is there, so the count is actually 2 and the node count is 6.
-    EXPECT_EQ(6, encoding.toMtbdd().getNodeCount());
-    EXPECT_EQ(2, encoding.toMtbdd().getLeafCount());
+    EXPECT_EQ(6, encoding.toAdd().getNodeCount());
+    EXPECT_EQ(2, encoding.toAdd().getLeafCount());
 }
 
 TEST(CuddDdManager, RangeTest) {
@@ -78,7 +78,7 @@ TEST(CuddDdManager, RangeTest) {
     std::pair<storm::expressions::Variable, storm::expressions::Variable> x;
     ASSERT_NO_THROW(x = manager->addMetaVariable("x", 1, 9));
     
-    storm::dd::Dd<storm::dd::DdType::CUDD> range;
+    storm::dd::Bdd<storm::dd::DdType::CUDD> range;
     ASSERT_NO_THROW(range = manager->getRange(x.first));
     
     EXPECT_EQ(9, range.getNonZeroCount());
@@ -90,29 +90,29 @@ TEST(CuddDdManager, IdentityTest) {
     std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
     std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
     
-    storm::dd::Dd<storm::dd::DdType::CUDD> range;
-    ASSERT_NO_THROW(range = manager->getIdentity(x.first));
+    storm::dd::Add<storm::dd::DdType::CUDD> identity;
+    ASSERT_NO_THROW(identity = manager->getIdentity(x.first));
     
-    EXPECT_EQ(9, range.getNonZeroCount());
-    EXPECT_EQ(10, range.getLeafCount());
-    EXPECT_EQ(21, range.getNodeCount());
+    EXPECT_EQ(9, identity.getNonZeroCount());
+    EXPECT_EQ(10, identity.getLeafCount());
+    EXPECT_EQ(21, identity.getNodeCount());
 }
 
 TEST(CuddDd, OperatorTest) {
     std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
     std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
-    EXPECT_TRUE(manager->getZero() == manager->getZero());
-    EXPECT_FALSE(manager->getZero() == manager->getOne());
+    EXPECT_TRUE(manager->getAddZero() == manager->getAddZero());
+    EXPECT_FALSE(manager->getAddZero() == manager->getAddOne());
 
-    EXPECT_FALSE(manager->getZero() != manager->getZero());
-    EXPECT_TRUE(manager->getZero() != manager->getOne());
+    EXPECT_FALSE(manager->getAddZero() != manager->getAddZero());
+    EXPECT_TRUE(manager->getAddZero() != manager->getAddOne());
     
-    storm::dd::Dd<storm::dd::DdType::CUDD> dd1 = manager->getOne(true);
-    storm::dd::Dd<storm::dd::DdType::CUDD> dd2 = manager->getOne(true);
-    storm::dd::Dd<storm::dd::DdType::CUDD> dd3 = dd1 + dd2;
+    storm::dd::Add<storm::dd::DdType::CUDD> dd1 = manager->getAddOne();
+    storm::dd::Add<storm::dd::DdType::CUDD> dd2 = manager->getAddOne();
+    storm::dd::Add<storm::dd::DdType::CUDD> dd3 = dd1 + dd2;
     EXPECT_TRUE(dd3 == manager->getConstant(2));
     
-    dd3 += manager->getZero(true);
+    dd3 += manager->getAddZero();
     EXPECT_TRUE(dd3 == manager->getConstant(2));
     
     dd3 = dd1 * manager->getConstant(3);
@@ -130,13 +130,13 @@ TEST(CuddDd, OperatorTest) {
     dd3 /= manager->getConstant(2);
     EXPECT_TRUE(dd3.isOne());
     
-    dd3 = dd3.toBdd().complement();
+    dd3 = !dd3;
     EXPECT_TRUE(dd3.isZero());
     
     dd1 = !dd3;
     EXPECT_TRUE(dd1.isOne());
 
-    dd3 = dd1 || dd2.toBdd();
+    dd3 = dd1 || dd2;
     EXPECT_TRUE(dd3.isOne());
     
     dd1 = manager->getIdentity(x.first);
@@ -145,7 +145,7 @@ TEST(CuddDd, OperatorTest) {
     dd3 = dd1.equals(dd2);
     EXPECT_EQ(1, dd3.getNonZeroCount());
     
-    storm::dd::Dd<storm::dd::DdType::CUDD> dd4 = dd1.notEquals(dd2);
+    storm::dd::Add<storm::dd::DdType::CUDD> dd4 = dd1.notEquals(dd2);
     EXPECT_TRUE(dd4.toBdd() == !dd3.toBdd());
     
     dd3 = dd1.less(dd2);
@@ -160,17 +160,17 @@ TEST(CuddDd, OperatorTest) {
     dd3 = dd1.greaterOrEqual(dd2);
     EXPECT_EQ(5, dd3.getNonZeroCount());
     
-    dd3 = (manager->getEncoding(x.first, 2)).ite(dd2, dd1);
+    dd3 = (manager->getEncoding(x.first, 2).toAdd()).ite(dd2, dd1);
     dd4 = dd3.less(dd2);
     EXPECT_EQ(10, dd4.getNonZeroCount());
     
     dd4 = dd3.minimum(dd1);
-    dd4 *= manager->getEncoding(x.first, 2, true);
+    dd4 *= manager->getEncoding(x.first, 2).toAdd();
     dd4 = dd4.sumAbstract({x.first});
     EXPECT_EQ(2, dd4.getValue());
 
     dd4 = dd3.maximum(dd1);
-    dd4 *= manager->getEncoding(x.first, 2, true);
+    dd4 *= manager->getEncoding(x.first, 2).toAdd();
     dd4 = dd4.sumAbstract({x.first});
     EXPECT_EQ(5, dd4.getValue());
 
@@ -183,25 +183,26 @@ TEST(CuddDd, OperatorTest) {
 TEST(CuddDd, AbstractionTest) {
     std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
     std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
-    storm::dd::Dd<storm::dd::DdType::CUDD> dd1;
-    storm::dd::Dd<storm::dd::DdType::CUDD> dd2;
-    storm::dd::Dd<storm::dd::DdType::CUDD> dd3;
+    storm::dd::Add<storm::dd::DdType::CUDD> dd1;
+    storm::dd::Add<storm::dd::DdType::CUDD> dd2;
+    storm::dd::Add<storm::dd::DdType::CUDD> dd3;
     
     dd1 = manager->getIdentity(x.first);
     dd2 = manager->getConstant(5);
     dd3 = dd1.equals(dd2);
-    EXPECT_EQ(1, dd3.getNonZeroCount());
-    ASSERT_THROW(dd3 = dd3.existsAbstract({x.second}), storm::exceptions::InvalidArgumentException);
-    ASSERT_NO_THROW(dd3 = dd3.existsAbstract({x.first}));
-    EXPECT_EQ(1, dd3.getNonZeroCount());
-    EXPECT_EQ(1, dd3.getMax());
+    storm::dd::Bdd<storm::dd::DdType::CUDD> dd3Bdd = dd3.toBdd();
+    EXPECT_EQ(1, dd3Bdd.getNonZeroCount());
+    ASSERT_THROW(dd3Bdd = dd3Bdd.existsAbstract({x.second}), storm::exceptions::InvalidArgumentException);
+    ASSERT_NO_THROW(dd3Bdd = dd3Bdd.existsAbstract({x.first}));
+    EXPECT_EQ(1, dd3Bdd.getNonZeroCount());
+    EXPECT_EQ(1, dd3Bdd.toAdd().getMax());
 
     dd3 = dd1.equals(dd2);
     dd3 *= manager->getConstant(3);
     EXPECT_EQ(1, dd3.getNonZeroCount());
-    ASSERT_THROW(dd3 = dd3.existsAbstract({x.second}), storm::exceptions::InvalidArgumentException);
-    ASSERT_NO_THROW(dd3 = dd3.existsAbstract({x.first}));
-    EXPECT_TRUE(dd3.isOne());
+    ASSERT_THROW(dd3Bdd = dd3.toBdd().existsAbstract({x.second}), storm::exceptions::InvalidArgumentException);
+    ASSERT_NO_THROW(dd3Bdd = dd3.toBdd().existsAbstract({x.first}));
+    EXPECT_TRUE(dd3Bdd.isOne());
 
     dd3 = dd1.equals(dd2);
     dd3 *= manager->getConstant(3);
@@ -230,8 +231,8 @@ TEST(CuddDd, SwapTest) {
     
     std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
     std::pair<storm::expressions::Variable, storm::expressions::Variable> z = manager->addMetaVariable("z", 2, 8);
-    storm::dd::Dd<storm::dd::DdType::CUDD> dd1;
-    storm::dd::Dd<storm::dd::DdType::CUDD> dd2;
+    storm::dd::Add<storm::dd::DdType::CUDD> dd1;
+    storm::dd::Add<storm::dd::DdType::CUDD> dd2;
     
     dd1 = manager->getIdentity(x.first);
     ASSERT_THROW(dd1 = dd1.swapVariables({std::make_pair(x.first, z.first)}), storm::exceptions::InvalidArgumentException);
@@ -243,9 +244,9 @@ TEST(CuddDd, MultiplyMatrixTest) {
     std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
     std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
     
-    storm::dd::Dd<storm::dd::DdType::CUDD> dd1 = manager->getIdentity(x.first).equals(manager->getIdentity(x.second));
-    storm::dd::Dd<storm::dd::DdType::CUDD> dd2 = manager->getRange(x.second);
-    storm::dd::Dd<storm::dd::DdType::CUDD> dd3;
+    storm::dd::Add<storm::dd::DdType::CUDD> dd1 = manager->getIdentity(x.first).equals(manager->getIdentity(x.second));
+    storm::dd::Add<storm::dd::DdType::CUDD> dd2 = manager->getRange(x.second).toAdd();
+    storm::dd::Add<storm::dd::DdType::CUDD> dd3;
     dd1 *= manager->getConstant(2);
     
     ASSERT_NO_THROW(dd3 = dd1.multiplyMatrix(dd2, {x.second}));
@@ -257,7 +258,7 @@ TEST(CuddDd, GetSetValueTest) {
     std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
     std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
     
-    storm::dd::Dd<storm::dd::DdType::CUDD> dd1 = manager->getOne(true);
+    storm::dd::Add<storm::dd::DdType::CUDD> dd1 = manager->getAddOne();
     ASSERT_NO_THROW(dd1.setValue(x.first, 4, 2));
     EXPECT_EQ(2, dd1.getLeafCount());
     
@@ -275,8 +276,8 @@ TEST(CuddDd, ForwardIteratorTest) {
     std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
     std::pair<storm::expressions::Variable, storm::expressions::Variable> y = manager->addMetaVariable("y", 0, 3);
     
-    storm::dd::Dd<storm::dd::DdType::CUDD> dd;
-    ASSERT_NO_THROW(dd = manager->getRange(x.first));
+    storm::dd::Add<storm::dd::DdType::CUDD> dd;
+    ASSERT_NO_THROW(dd = manager->getRange(x.first).toAdd());
     
     storm::dd::DdForwardIterator<storm::dd::DdType::CUDD> it, ite;
     ASSERT_NO_THROW(it = dd.begin());
@@ -290,8 +291,8 @@ TEST(CuddDd, ForwardIteratorTest) {
     }
     EXPECT_EQ(9, numberOfValuations);
 
-    dd = manager->getRange(x.first);
-    dd = dd.ite(manager->getOne(), manager->getOne());
+    dd = manager->getRange(x.first).toAdd();
+    dd = dd.ite(manager->getAddOne(), manager->getAddOne());
     ASSERT_NO_THROW(it = dd.begin());
     ASSERT_NO_THROW(ite = dd.end());
     numberOfValuations = 0;
@@ -313,81 +314,12 @@ TEST(CuddDd, ForwardIteratorTest) {
     EXPECT_EQ(1, numberOfValuations);
 }
 
-// FIXME: make toExpression work again and then fix this test.
-//TEST(CuddDd, ToExpressionTest) {
-//    std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
-//    std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
-//
-//    storm::dd::Dd<storm::dd::DdType::CUDD> dd;
-//    ASSERT_NO_THROW(dd = manager->getIdentity(x.first));
-//    
-//    storm::expressions::Expression ddAsExpression;
-//    ASSERT_NO_THROW(ddAsExpression = dd.toExpression());
-//
-//    storm::expressions::SimpleValuation valuation;
-//    for (std::size_t bit = 0; bit < manager->getMetaVariable(x.first).getNumberOfDdVariables(); ++bit) {
-//        valuation.addBooleanIdentifier("x." + std::to_string(bit));
-//    }
-//    
-//    storm::dd::DdMetaVariable<storm::dd::DdType::CUDD> const& metaVariable = manager->getMetaVariable("x");
-//
-//    for (auto valuationValuePair : dd) {
-//        for (std::size_t i = 0; i < metaVariable.getNumberOfDdVariables(); ++i) {
-//            // Check if the i-th bit is set or not and modify the valuation accordingly.
-//            if (((valuationValuePair.first.getIntegerValue("x") - metaVariable.getLow()) & (1ull << (metaVariable.getNumberOfDdVariables() - i - 1))) != 0) {
-//                valuation.setBooleanValue("x." + std::to_string(i), true);
-//            } else {
-//                valuation.setBooleanValue("x." + std::to_string(i), false);
-//            }
-//        }
-//        
-//        // At this point, the constructed valuation should make the expression obtained from the DD evaluate to the very
-//        // same value as the current value obtained from the DD.
-//        EXPECT_EQ(valuationValuePair.second, ddAsExpression.evaluateAsDouble(&valuation));
-//    }
-//    
-//    storm::expressions::Expression mintermExpression = dd.getMintermExpression();
-//    
-//    // Check whether all minterms are covered.
-//    for (auto valuationValuePair : dd) {
-//        for (std::size_t i = 0; i < metaVariable.getNumberOfDdVariables(); ++i) {
-//            // Check if the i-th bit is set or not and modify the valuation accordingly.
-//            if (((valuationValuePair.first.getIntegerValue("x") - metaVariable.getLow()) & (1ull << (metaVariable.getNumberOfDdVariables() - i - 1))) != 0) {
-//                valuation.setBooleanValue("x." + std::to_string(i), true);
-//            } else {
-//                valuation.setBooleanValue("x." + std::to_string(i), false);
-//            }
-//        }
-//        
-//        // At this point, the constructed valuation should make the expression obtained from the DD evaluate to the very
-//        // same value as the current value obtained from the DD.
-//        EXPECT_TRUE(mintermExpression.evaluateAsBool(&valuation));
-//    }
-//    
-//    // Now check no additional minterms are covered.
-//    dd = !dd;
-//    for (auto valuationValuePair : dd) {
-//        for (std::size_t i = 0; i < metaVariable.getNumberOfDdVariables(); ++i) {
-//            // Check if the i-th bit is set or not and modify the valuation accordingly.
-//            if (((valuationValuePair.first.getIntegerValue("x") - metaVariable.getLow()) & (1ull << (metaVariable.getNumberOfDdVariables() - i - 1))) != 0) {
-//                valuation.setBooleanValue("x." + std::to_string(i), true);
-//            } else {
-//                valuation.setBooleanValue("x." + std::to_string(i), false);
-//            }
-//        }
-//        
-//        // At this point, the constructed valuation should make the expression obtained from the DD evaluate to the very
-//        // same value as the current value obtained from the DD.
-//        EXPECT_FALSE(mintermExpression.evaluateAsBool(&valuation));
-//    }
-//}
-
 TEST(CuddDd, OddTest) {
     std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
     std::pair<storm::expressions::Variable, storm::expressions::Variable> a = manager->addMetaVariable("a");
     std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
     
-    storm::dd::Dd<storm::dd::DdType::CUDD> dd = manager->getIdentity(x.first);
+    storm::dd::Add<storm::dd::DdType::CUDD> dd = manager->getIdentity(x.first);
     storm::dd::Odd<storm::dd::DdType::CUDD> odd;
     ASSERT_NO_THROW(odd = storm::dd::Odd<storm::dd::DdType::CUDD>(dd));
     EXPECT_EQ(9, odd.getTotalOffset());
@@ -401,14 +333,14 @@ TEST(CuddDd, OddTest) {
     }
     
     // Create a non-trivial matrix.
-    dd = manager->getIdentity(x.first).equals(manager->getIdentity(x.second)) * manager->getRange(x.first);    
-    dd += manager->getEncoding(x.first, 1) * manager->getRange(x.second) + manager->getEncoding(x.second, 1) * manager->getRange(x.first);
+    dd = manager->getIdentity(x.first).equals(manager->getIdentity(x.second)) * manager->getRange(x.first).toAdd();
+    dd += manager->getEncoding(x.first, 1).toAdd() * manager->getRange(x.second).toAdd() + manager->getEncoding(x.second, 1).toAdd() * manager->getRange(x.first).toAdd();
     
     // Create the ODDs.
     storm::dd::Odd<storm::dd::DdType::CUDD> rowOdd;
-    ASSERT_NO_THROW(rowOdd = storm::dd::Odd<storm::dd::DdType::CUDD>(manager->getRange(x.first)));
+    ASSERT_NO_THROW(rowOdd = storm::dd::Odd<storm::dd::DdType::CUDD>(manager->getRange(x.first).toAdd()));
     storm::dd::Odd<storm::dd::DdType::CUDD> columnOdd;
-    ASSERT_NO_THROW(columnOdd = storm::dd::Odd<storm::dd::DdType::CUDD>(manager->getRange(x.second)));
+    ASSERT_NO_THROW(columnOdd = storm::dd::Odd<storm::dd::DdType::CUDD>(manager->getRange(x.second).toAdd()));
     
     // Try to translate the matrix.
     storm::storage::SparseMatrix<double> matrix;
@@ -418,7 +350,7 @@ TEST(CuddDd, OddTest) {
     EXPECT_EQ(9, matrix.getColumnCount());
     EXPECT_EQ(25, matrix.getNonzeroEntryCount());
     
-    dd = manager->getRange(x.first) * manager->getRange(x.second) * manager->getEncoding(a.first, 0).ite(dd, dd + manager->getConstant(1));
+    dd = manager->getRange(x.first).toAdd() * manager->getRange(x.second).toAdd() * manager->getEncoding(a.first, 0).toAdd().ite(dd, dd + manager->getConstant(1));
     ASSERT_NO_THROW(matrix = dd.toMatrix({x.first}, {x.second}, {a.first}, rowOdd, columnOdd));
     EXPECT_EQ(18, matrix.getRowCount());
     EXPECT_EQ(9, matrix.getRowGroupCount());
diff --git a/test/functional/utility/GraphTest.cpp b/test/functional/utility/GraphTest.cpp
index 68c62182a..bbb927001 100644
--- a/test/functional/utility/GraphTest.cpp
+++ b/test/functional/utility/GraphTest.cpp
@@ -17,7 +17,7 @@ TEST(GraphTest, SymbolicProb01) {
     
     ASSERT_TRUE(model->getType() == storm::models::ModelType::Dtmc);
     
-    std::pair<storm::dd::Dd<storm::dd::DdType::CUDD>, storm::dd::Dd<storm::dd::DdType::CUDD>> statesWithProbability01;
+    std::pair<storm::dd::Bdd<storm::dd::DdType::CUDD>, storm::dd::Bdd<storm::dd::DdType::CUDD>> statesWithProbability01;
 
     ASSERT_NO_THROW(statesWithProbability01 = storm::utility::graph::performProb01(*model->as<storm::models::symbolic::Dtmc<storm::dd::DdType::CUDD>>(), model->getReachableStates(), model->getStates("observe0Greater1")));
     EXPECT_EQ(4409, statesWithProbability01.first.getNonZeroCount());
@@ -38,7 +38,7 @@ TEST(GraphTest, SymbolicProb01MinMax) {
     
     ASSERT_TRUE(model->getType() == storm::models::ModelType::Mdp);
     
-    std::pair<storm::dd::Dd<storm::dd::DdType::CUDD>, storm::dd::Dd<storm::dd::DdType::CUDD>> statesWithProbability01;
+    std::pair<storm::dd::Bdd<storm::dd::DdType::CUDD>, storm::dd::Bdd<storm::dd::DdType::CUDD>> statesWithProbability01;
     
     ASSERT_NO_THROW(statesWithProbability01 = storm::utility::graph::performProb01Min(*model->as<storm::models::symbolic::Mdp<storm::dd::DdType::CUDD>>(), model->getReachableStates(), model->getStates("elected")));
     EXPECT_EQ(0, statesWithProbability01.first.getNonZeroCount());