diff --git a/src/builder/DdPrismModelBuilder.cpp b/src/builder/DdPrismModelBuilder.cpp
index acc7c5235..43f051eb5 100644
--- a/src/builder/DdPrismModelBuilder.cpp
+++ b/src/builder/DdPrismModelBuilder.cpp
@@ -82,23 +82,25 @@ namespace storm {
                 updateDd *= result;
             }
             
-            // FIXME: global boolean variables cause problems. They cannot be added here, because then synchronization goes wrong.
-//            for (uint_fast64_t i = 0; i < generationInfo.program.getGlobalBooleanVariables().size(); ++i) {
-//                storm::prism::BooleanVariable const& booleanVariable = generationInfo.program.getGlobalBooleanVariables().at(i);
-//                if (update.getAssignmentMapping().find(booleanVariable.getName()) == update.getAssignmentMapping().end()) {
-//                    // Multiply identity matrix
-//                    updateDd = updateDd * generationInfo.variableToIdentityDecisionDiagramMap.at(booleanVariable.getName());
-//                }
-//            }
-//            
-//            // All unused global integer variables do not change
-//            for (uint_fast64_t i = 0; i < generationInfo.program.getGlobalIntegerVariables().size(); ++i) {
-//                storm::prism::IntegerVariable const& integerVariable = generationInfo.program.getGlobalIntegerVariables().at(i);
-//                if (update.getAssignmentMapping().find(integerVariable.getName()) == update.getAssignmentMapping().end()) {
-//                    // Multiply identity matrix
-//                    updateDd = updateDd * generationInfo.variableToIdentityDecisionDiagramMap.at(integerVariable.getName());
-//                }
-//            }
+            // This works under the assumption that global variables are only written in non-synchronzing commands, but
+            // is not checked here.
+            for (auto const& booleanVariable : generationInfo.program.getGlobalBooleanVariables()) {
+                storm::expressions::Variable const& metaVariable = generationInfo.variableToRowMetaVariableMap.at(booleanVariable.getExpressionVariable());
+
+                if (assignedVariables.find(metaVariable) == assignedVariables.end()) {
+                    STORM_LOG_TRACE("Multiplying identity of variable " << booleanVariable.getName());
+                    updateDd *= generationInfo.variableToIdentityMap.at(booleanVariable.getExpressionVariable());
+                }
+            }
+            
+            // All unused global integer variables do not change
+            for (auto const& integerVariable : generationInfo.program.getGlobalIntegerVariables()) {
+                storm::expressions::Variable const& metaVariable = generationInfo.variableToRowMetaVariableMap.at(integerVariable.getExpressionVariable());
+                if (assignedVariables.find(metaVariable) == assignedVariables.end()) {
+                    STORM_LOG_TRACE("Multiplying identity of variable " << integerVariable.getName());
+                    updateDd *= generationInfo.variableToIdentityMap.at(integerVariable.getExpressionVariable());
+                }
+            }
             
             // All unassigned boolean variables need to keep their value.
             for (storm::prism::BooleanVariable const& booleanVariable : module.getBooleanVariables()) {
@@ -140,6 +142,7 @@ namespace storm {
                     commandDd += updateDd;
                 }
                 
+                (guardDd * commandDd).exportToDot(module.getName() + "_" + command.getActionName() + ".dot");
                 return ActionDecisionDiagram(guardDd, guardDd * commandDd);
             } else {
                 return ActionDecisionDiagram(*generationInfo.manager);
@@ -152,16 +155,28 @@ namespace storm {
             for (storm::prism::Command const& command : module.getCommands()) {
                 
                 // Determine whether the command is relevant for the selected action.
-                bool relevant = (!synchronizationActionIndex && !command.isLabeled()) || (synchronizationActionIndex && command.getActionIndex() == synchronizationActionIndex.get());
+                bool relevant = (!synchronizationActionIndex && !command.isLabeled()) || (synchronizationActionIndex && command.isLabeled() && command.getActionIndex() == synchronizationActionIndex.get());
                 
                 if (!relevant) {
                     continue;
                 }
                 
+                if (synchronizationActionIndex) {
+                    std::cout << command << " is relevant for synch " << synchronizationActionIndex.get() << std::endl;
+                }
+                
                 // At this point, the command is known to be relevant for the action.
                 commandDds.push_back(createCommandDecisionDiagram(generationInfo, module, command));
             }
             
+            if (synchronizationActionIndex && synchronizationActionIndex.get() == 0) {
+                int i = 0;
+                for (auto const& commandDd : commandDds) {
+                    commandDd.transitionsDd.exportToDot("cmd_" + std::to_string(i) + ".dot");
+                    ++i;
+                }
+            }
+            
             ActionDecisionDiagram result(*generationInfo.manager);
             if (!commandDds.empty()) {
                 switch (generationInfo.program.getModelType()){
@@ -318,6 +333,9 @@ namespace storm {
             storm::dd::Dd<Type> action1Extended = action1.transitionsDd * identityDd2;
             storm::dd::Dd<Type> action2Extended = action2.transitionsDd * identityDd1;
 
+            action1.transitionsDd.exportToDot("act1.dot");
+            action2.transitionsDd.exportToDot("act2.dot");
+            
             if (generationInfo.program.getModelType() == storm::prism::Program::ModelType::DTMC) {
                 return ActionDecisionDiagram(action1.guardDd + action2.guardDd, action1Extended + action2Extended, 0);
             } else if (generationInfo.program.getModelType() == storm::prism::Program::ModelType::MDP) {
@@ -329,24 +347,28 @@ 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);
+                std::cout << "max used nondet: " << numberOfUsedNondeterminismVariables << std::endl;
                 if (action1.numberOfUsedNondeterminismVariables > action2.numberOfUsedNondeterminismVariables) {
                     storm::dd::Dd<Type> nondeterminisimEncoding = generationInfo.manager->getOne();
                     
-                    for (uint_fast64_t i = action2.numberOfUsedNondeterminismVariables + 1; i <= action1.numberOfUsedNondeterminismVariables; ++i) {
+                    for (uint_fast64_t i = action2.numberOfUsedNondeterminismVariables; i < action1.numberOfUsedNondeterminismVariables; ++i) {
                         nondeterminisimEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0);
                     }
                     action2Extended *= nondeterminisimEncoding;
                 } else if (action2.numberOfUsedNondeterminismVariables > action1.numberOfUsedNondeterminismVariables) {
                     storm::dd::Dd<Type> nondeterminisimEncoding = generationInfo.manager->getOne();
                     
-                    for (uint_fast64_t i = action1.numberOfUsedNondeterminismVariables + 1; i <= action2.numberOfUsedNondeterminismVariables; ++i) {
+                    for (uint_fast64_t i = action1.numberOfUsedNondeterminismVariables; i < action2.numberOfUsedNondeterminismVariables; ++i) {
                         nondeterminisimEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0);
                     }
                     action1Extended *= nondeterminisimEncoding;
                 }
                 
+                action1Extended.exportToDot("act1ext.dot");
+                action2Extended.exportToDot("act2ext.dot");
+                
                 // Add a new variable that resolves the nondeterminism between the two choices.
-                storm::dd::Dd<Type> combinedTransitions = generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[numberOfUsedNondeterminismVariables + 1], 1).ite(action2Extended, action1Extended);
+                storm::dd::Dd<Type> combinedTransitions = generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[numberOfUsedNondeterminismVariables], 1).ite(action2Extended, action1Extended);
                 
                 return ActionDecisionDiagram(action1.guardDd || action2.guardDd, combinedTransitions, numberOfUsedNondeterminismVariables + 1);
             } else {
@@ -358,15 +380,18 @@ namespace storm {
         typename DdPrismModelBuilder<Type>::ModuleDecisionDiagram DdPrismModelBuilder<Type>::createModuleDecisionDiagram(GenerationInformation& generationInfo, storm::prism::Module const& module, std::map<uint_fast64_t, uint_fast64_t> const& synchronizingActionToOffsetMap) {
             // Start by creating the action DD for the independent action.
             ActionDecisionDiagram independentActionDd = createActionDecisionDiagram(generationInfo, module, boost::optional<uint_fast64_t>(), 0);
+            uint_fast64_t numberOfUsedNondeterminismVariables = independentActionDd.numberOfUsedNondeterminismVariables;
             
             // Create module DD for all synchronizing actions of the module.
             std::map<uint_fast64_t, ActionDecisionDiagram> actionIndexToDdMap;
             for (auto const& actionIndex : module.getActionIndices()) {
                 STORM_LOG_TRACE("Creating DD for action '" << actionIndex << "'.");
-                actionIndexToDdMap.emplace(actionIndex, createActionDecisionDiagram(generationInfo, module, actionIndex, synchronizingActionToOffsetMap.at(actionIndex)));
+                ActionDecisionDiagram tmp = createActionDecisionDiagram(generationInfo, module, actionIndex, synchronizingActionToOffsetMap.at(actionIndex));
+                numberOfUsedNondeterminismVariables = std::max(numberOfUsedNondeterminismVariables, tmp.numberOfUsedNondeterminismVariables);
+                actionIndexToDdMap.emplace(actionIndex, tmp);
             }
             
-            return ModuleDecisionDiagram(independentActionDd, actionIndexToDdMap, generationInfo.moduleToIdentityMap.at(module.getName()));
+            return ModuleDecisionDiagram(independentActionDd, actionIndexToDdMap, generationInfo.moduleToIdentityMap.at(module.getName()), numberOfUsedNondeterminismVariables);
         }
         
         template <storm::dd::DdType Type>
@@ -375,17 +400,15 @@ namespace storm {
             if (generationInfo.program.getModelType() == storm::prism::Program::ModelType::MDP) {
                 storm::dd::Dd<Type> result = generationInfo.manager->getZero();
                 
-                // First, determine the maximal variable index that is used.
-                uint_fast64_t numberOfUsedNondeterminismVariables = module.independentAction.numberOfUsedNondeterminismVariables;
-                for (auto const& synchronizingAction : module.synchronizingActionToDecisionDiagramMap) {
-                    numberOfUsedNondeterminismVariables = std::max(numberOfUsedNondeterminismVariables, synchronizingAction.second.numberOfUsedNondeterminismVariables);
-                }
+                // 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;
+                std::cout << "pumping number of used nondet variables to " << numberOfUsedNondeterminismVariables << std::endl;
 
-                // Now make all actions use the same amount of nondeterminism variables.
-                
                 // Add variables to independent action DD.
                 storm::dd::Dd<Type> nondeterminismEncoding = generationInfo.manager->getOne();
-                for (uint_fast64_t i = module.independentAction.numberOfUsedNondeterminismVariables + 1; i <= numberOfUsedNondeterminismVariables; ++i) {
+                for (uint_fast64_t i = module.independentAction.numberOfUsedNondeterminismVariables; i < numberOfUsedNondeterminismVariables; ++i) {
+                    std::cout << "adding " << i << " to independent" << std::endl;
                     nondeterminismEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0);
                 }
                 result = module.independentAction.transitionsDd * nondeterminismEncoding;
@@ -394,7 +417,7 @@ namespace storm {
                 std::map<uint_fast64_t, storm::dd::Dd<Type>> synchronizingActionToDdMap;
                 for (auto const& synchronizingAction : module.synchronizingActionToDecisionDiagramMap) {
                     nondeterminismEncoding = generationInfo.manager->getOne();
-                    for (uint_fast64_t i = synchronizingAction.second.numberOfUsedNondeterminismVariables + 1; i <= numberOfUsedNondeterminismVariables; ++i) {
+                    for (uint_fast64_t i = synchronizingAction.second.numberOfUsedNondeterminismVariables; i < numberOfUsedNondeterminismVariables; ++i) {
                         nondeterminismEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0);
                     }
                     synchronizingActionToDdMap.emplace(synchronizingAction.first, synchronizingAction.second.transitionsDd * nondeterminismEncoding);
@@ -422,8 +445,9 @@ namespace storm {
                 }
                 
                 // Now, we can simply add all synchronizing actions to the result.
-                for (auto const& synchronizingAction : module.synchronizingActionToDecisionDiagramMap) {
-                    result += synchronizingAction.second.transitionsDd;
+                for (auto const& synchronizingAction : synchronizingActionToDdMap) {
+                    synchronizingAction.second.exportToDot("synch" + std::to_string(synchronizingAction.first) + ".dot");
+                    result += synchronizingAction.second;
                 }
 
                 return result;
@@ -466,7 +490,9 @@ namespace storm {
                 ModuleDecisionDiagram nextModule = createModuleDecisionDiagram(generationInfo, currentModule, synchronizingActionToOffsetMap);
                 
                 // Combine the non-synchronizing action.
+                uint_fast64_t numberOfUsedNondeterminismVariables = nextModule.numberOfUsedNondeterminismVariables;
                 system.independentAction = combineUnsynchronizedActions(generationInfo, system.independentAction, nextModule.independentAction, system.identity, nextModule.identity);
+                numberOfUsedNondeterminismVariables = std::max(numberOfUsedNondeterminismVariables, system.independentAction.numberOfUsedNondeterminismVariables);
                 
                 // For all synchronizing actions that the next module does not have, we need to multiply the identity of the next module.
                 for (auto& action : system.synchronizingActionToDecisionDiagramMap) {
@@ -479,13 +505,19 @@ namespace storm {
                 for (auto const& actionIndex : currentModule.getActionIndices()) {
                     if (system.hasSynchronizingAction(actionIndex)) {
                         system.synchronizingActionToDecisionDiagramMap[actionIndex] = combineSynchronizingActions(generationInfo, system.synchronizingActionToDecisionDiagramMap[actionIndex], nextModule.synchronizingActionToDecisionDiagramMap[actionIndex]);
+                        numberOfUsedNondeterminismVariables = std::max(numberOfUsedNondeterminismVariables, system.synchronizingActionToDecisionDiagramMap[actionIndex].numberOfUsedNondeterminismVariables);
                     } else {
                         system.synchronizingActionToDecisionDiagramMap[actionIndex] = combineUnsynchronizedActions(generationInfo, ActionDecisionDiagram(*generationInfo.manager), nextModule.synchronizingActionToDecisionDiagramMap[actionIndex], system.identity, nextModule.identity);
+                        numberOfUsedNondeterminismVariables = std::max(numberOfUsedNondeterminismVariables, system.synchronizingActionToDecisionDiagramMap[actionIndex].numberOfUsedNondeterminismVariables);
                     }
                 }
                 
                 // Combine identity matrices.
                 system.identity = system.identity * nextModule.identity;
+                
+                // Keep track of the number of nondeterminism variables used.
+                std::cout << "num used: " << numberOfUsedNondeterminismVariables << std::endl;
+                system.numberOfUsedNondeterminismVariables = std::max(system.numberOfUsedNondeterminismVariables, numberOfUsedNondeterminismVariables);
             }
             
             storm::dd::Dd<Type> result = createSystemFromModule(generationInfo, system);
@@ -493,6 +525,15 @@ namespace storm {
             // For DTMCs, we normalize each row to 1 (to account for non-determinism).
             if (generationInfo.program.getModelType() == storm::prism::Program::ModelType::DTMC) {
                 result = result / result.sumAbstract(generationInfo.columnMetaVariables);
+            } else if (generationInfo.program.getModelType() == storm::prism::Program::ModelType::MDP) {
+                // For MDPs, we need to throw away the nondeterminism variables from the generation information that
+                // were never used.
+                std::cout << "System uses " << system.numberOfUsedNondeterminismVariables << "nd vars" << std::endl;
+                for (uint_fast64_t index = system.numberOfUsedNondeterminismVariables; index < generationInfo.nondeterminismMetaVariables.size(); ++index) {
+                    std::cout << "removing " << generationInfo.nondeterminismMetaVariables[index].getName() << std::endl;
+                    generationInfo.allNondeterminismVariables.erase(generationInfo.nondeterminismMetaVariables[index]);
+                }
+                generationInfo.nondeterminismMetaVariables.resize(system.numberOfUsedNondeterminismVariables);
             }
             
             return std::make_pair(result, system);
@@ -508,9 +549,24 @@ namespace storm {
                 preparedProgram = program;
             }
             
-            preparedProgram = preparedProgram.substituteConstants();
+            if (preparedProgram.hasUndefinedConstants()) {
+                std::vector<std::reference_wrapper<storm::prism::Constant const>> undefinedConstants = preparedProgram.getUndefinedConstants();
+                std::stringstream stream;
+                bool printComma = false;
+                for (auto const& constant : undefinedConstants) {
+                    if (printComma) {
+                        stream << ", ";
+                    } else {
+                        printComma = true;
+                    }
+                    stream << constant.get().getName() << " (" << constant.get().getType() << ")";
+                }
+                stream << ".";
+                STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Program still contains these undefined constants: " + stream.str());
+            }
             
-//            std::cout << "translated prog: " << preparedProgram << std::endl;
+            preparedProgram = preparedProgram.substituteConstants();
+            std::cout << "translated prog: " << preparedProgram << std::endl;
             
             // Start by initializing the structure used for storing all information needed during the model generation.
             // In particular, this creates the meta variables used to encode the model.
@@ -519,33 +575,55 @@ namespace storm {
             auto clock = std::chrono::high_resolution_clock::now();
             std::pair<storm::dd::Dd<Type>, ModuleDecisionDiagram> transitionMatrixModulePair = createSystemDecisionDiagram(generationInfo);
             storm::dd::Dd<Type> transitionMatrix = transitionMatrixModulePair.first;
+            transitionMatrix.exportToDot("trans.dot");
             ModuleDecisionDiagram const& globalModule = transitionMatrixModulePair.second;
             
             // Cut the transition matrix to the reachable fragment of the state space.
             storm::dd::Dd<Type> reachableStates = computeReachableStates(generationInfo, createInitialStatesDecisionDiagram(generationInfo), transitionMatrix);
             transitionMatrix *= reachableStates;
+            reachableStates.exportToDot("reach.dot");
 
             // Detect deadlocks and 1) fix them if requested 2) throw an error otherwise.
             storm::dd::Dd<Type> statesWithTransition = transitionMatrix.notZero();
             if (program.getModelType() == storm::prism::Program::ModelType::MDP) {
-                statesWithTransition.existsAbstract(generationInfo.allNondeterminismVariables);
+                statesWithTransition = statesWithTransition.existsAbstract(generationInfo.allNondeterminismVariables);
+                statesWithTransition.exportToDot("after_exists.dot");
             }
             statesWithTransition = statesWithTransition.existsAbstract(generationInfo.columnMetaVariables);
             storm::dd::Dd<Type> deadlockStates = reachableStates * !statesWithTransition;
+            deadlockStates.exportToDot("deadlocks.dot");
 
-            if (!deadlockStates.isZero()) {
-                // If we need to fix deadlocks, we do so now.
-                if (!storm::settings::generalSettings().isDontFixDeadlocksSet()) {
-                    STORM_LOG_WARN("Fixing deadlocks in " << deadlockStates.getNonZeroCount() << " states.");
-                    
-                    // FIXME: For MDPs, we need to use an action encoding if we do not want to attach a lot of self-loops.
-                    transitionMatrix += deadlockStates * globalModule.identity;
-                } else {
-                    STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "The model contains " << deadlockStates.getNonZeroCount() << " deadlock states. Please unset the option to not fix deadlocks, if you want to fix them automatically.");
-                }
+//            if (!deadlockStates.isZero()) {
+//                // If we need to fix deadlocks, we do so now.
+//                if (!storm::settings::generalSettings().isDontFixDeadlocksSet()) {
+//                    std::cout << "fixing " << deadlockStates.getNonZeroCount() << std::endl;
+//                    STORM_LOG_WARN("Fixing deadlocks in " << deadlockStates.getNonZeroCount() << " states.");
+//
+//                    if (program.getModelType() == storm::prism::Program::ModelType::DTMC) {
+//                        // For DTMCs, we can simply add the identity of the global module for all deadlock states.
+//                        transitionMatrix += deadlockStates * globalModule.identity;
+//                    } 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();
+//                        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;
+//                        (deadlockStates * globalModule.identity * action).exportToDot("selfloops.dot");
+//                    }
+//                } else {
+//                    STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "The model contains " << deadlockStates.getNonZeroCount() << " deadlock states. Please unset the option to not fix deadlocks, if you want to fix them automatically.");
+//                }
+//            } else {
+//                std::cout << "no deadlocks" << std::endl;
+//            }
+            
+            transitionMatrix.exportToDot("trans_reach.dot");
+            for (auto const& var : transitionMatrix.getContainedMetaVariables()) {
+                std::cout << "var: " << var.getName() << std::endl;
             }
             
-            return std::make_pair(reachableStates, transitionMatrix * reachableStates);
+            std::cout << reachableStates.getNonZeroCount() << " states and " << transitionMatrix.getNonZeroCount() << " transitions." << std::endl;
+            return std::make_pair(reachableStates, transitionMatrix);
         }
         
         template <storm::dd::DdType Type>
@@ -569,6 +647,7 @@ namespace storm {
                 transitionBdd = transitionBdd.existsAbstract(generationInfo.allNondeterminismVariables);
             }
             
+            transitionBdd.exportToDot("trans01.dot");
             
             // Perform the BFS to discover all reachable states.
             bool changed = true;
diff --git a/src/builder/DdPrismModelBuilder.h b/src/builder/DdPrismModelBuilder.h
index 05f380060..20d94cf45 100644
--- a/src/builder/DdPrismModelBuilder.h
+++ b/src/builder/DdPrismModelBuilder.h
@@ -91,15 +91,15 @@ namespace storm {
             
             // This structure holds all decision diagrams related to a module.
             struct ModuleDecisionDiagram {
-                ModuleDecisionDiagram() : independentAction(), synchronizingActionToDecisionDiagramMap(), identity() {
+                ModuleDecisionDiagram() : independentAction(), synchronizingActionToDecisionDiagramMap(), identity(), numberOfUsedNondeterminismVariables(0) {
                     // Intentionally left empty.
                 }
                 
-                ModuleDecisionDiagram(storm::dd::DdManager<Type> const& manager) : independentAction(manager), synchronizingActionToDecisionDiagramMap(), identity(manager.getZero()) {
+                ModuleDecisionDiagram(storm::dd::DdManager<Type> const& manager) : independentAction(manager), synchronizingActionToDecisionDiagramMap(), identity(manager.getZero()), numberOfUsedNondeterminismVariables(0) {
                     // Intentionally left empty.
                 }
 
-                ModuleDecisionDiagram(ActionDecisionDiagram const& independentAction, std::map<uint_fast64_t, ActionDecisionDiagram> const& synchronizingActionToDecisionDiagramMap, storm::dd::Dd<Type> const& identity) : independentAction(independentAction), synchronizingActionToDecisionDiagramMap(synchronizingActionToDecisionDiagramMap), identity(identity) {
+                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) {
                     // Intentionally left empty.
                 }
                 
@@ -118,6 +118,9 @@ namespace storm {
                 
                 // A decision diagram that represents the identity of this module.
                 storm::dd::Dd<Type> identity;
+                
+                // The number of variables encoding the nondeterminism that were actually used.
+                uint_fast64_t numberOfUsedNondeterminismVariables;
             };
             
             /*!
@@ -177,8 +180,8 @@ namespace storm {
                  */
                 void createMetaVariablesAndIdentities() {
                     // Add synchronization variables.
-                    for (uint_fast64_t i = 0; i < program.getActionIndices().size(); ++i) {
-                        std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair = manager->addMetaVariable("sync" + std::to_string(i));
+                    for (auto const& actionIndex : program.getActionIndices()) {
+                        std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair = manager->addMetaVariable(program.getActionName(actionIndex));
                         synchronizationMetaVariables.push_back(variablePair.first);
                         allNondeterminismVariables.insert(variablePair.first);
                     }
@@ -209,7 +212,8 @@ namespace storm {
                         storm::dd::Dd<Type> variableIdentity = manager->getIdentity(variablePair.first).equals(manager->getIdentity(variablePair.second)) * manager->getRange(variablePair.first);
                         variableToIdentityMap.emplace(integerVariable.getExpressionVariable(), variableIdentity);
                         rowColumnMetaVariablePairs.push_back(variablePair);
-                    }                    for (storm::prism::BooleanVariable const& booleanVariable : program.getGlobalBooleanVariables()) {
+                    }
+                    for (storm::prism::BooleanVariable const& booleanVariable : program.getGlobalBooleanVariables()) {
                         std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair = manager->addMetaVariable(booleanVariable.getName());
                         
                         rowMetaVariables.insert(variablePair.first);
diff --git a/src/builder/ExplicitPrismModelBuilder.cpp b/src/builder/ExplicitPrismModelBuilder.cpp
index 974d9d306..153ab0afe 100644
--- a/src/builder/ExplicitPrismModelBuilder.cpp
+++ b/src/builder/ExplicitPrismModelBuilder.cpp
@@ -103,6 +103,8 @@ namespace storm {
             
             // If the program still contains undefined constants and we are not in a parametric setting, assemble an appropriate error message.
 #ifdef STORM_HAVE_CARL
+            // If the program either has undefined constants or we are building a parametric model, but the parameters
+            // not only appear in the probabilities, we re
             if (!std::is_same<ValueType, storm::RationalFunction>::value && preparedProgram.hasUndefinedConstants()) {
 #else
             if (preparedProgram.hasUndefinedConstants()) {
@@ -120,6 +122,10 @@ namespace storm {
                 }
                 stream << ".";
                 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Program still contains these undefined constants: " + stream.str());
+#ifdef STORM_HAVE_CARL
+            } else if (std::is_same<ValueType, storm::RationalFunction>::value && !preparedProgram.hasUndefinedConstantsOnlyInUpdateProbabilitiesAndRewards()) {
+                STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "The program contains undefined constants that appear in some places other than update probabilities and reward value expressions, which is not admitted.");
+#endif
             }
             
             // Now that we have defined all the constants in the program, we need to substitute their appearances in
diff --git a/src/parser/PrismParser.cpp b/src/parser/PrismParser.cpp
index 3db49eb16..a96a5cd66 100644
--- a/src/parser/PrismParser.cpp
+++ b/src/parser/PrismParser.cpp
@@ -142,7 +142,7 @@ namespace storm {
             commandDefinition = (qi::lit("[") > -(identifier[qi::_a = qi::_1]) > qi::lit("]") > +(qi::char_ - qi::lit(";")) > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createCommand, phoenix::ref(*this), qi::_a, qi::_r1)];
             commandDefinition.name("command definition");
             
-            moduleDefinition = ((qi::lit("module") >> identifier >> *(variableDefinition(qi::_a, qi::_b))) > +commandDefinition(qi::_r1) > qi::lit("endmodule"))[qi::_val = phoenix::bind(&PrismParser::createModule, phoenix::ref(*this), qi::_1, qi::_a, qi::_b, qi::_2, qi::_r1)];
+            moduleDefinition = ((qi::lit("module") >> identifier >> *(variableDefinition(qi::_a, qi::_b))) > *commandDefinition(qi::_r1) > qi::lit("endmodule"))[qi::_val = phoenix::bind(&PrismParser::createModule, phoenix::ref(*this), qi::_1, qi::_a, qi::_b, qi::_2, qi::_r1)];
             moduleDefinition.name("module definition");
             
             moduleRenaming = ((qi::lit("module") >> identifier >> qi::lit("=")) > identifier > qi::lit("[")
diff --git a/src/storage/expressions/Expression.cpp b/src/storage/expressions/Expression.cpp
index 3b79861d5..630e17a8a 100644
--- a/src/storage/expressions/Expression.cpp
+++ b/src/storage/expressions/Expression.cpp
@@ -100,6 +100,13 @@ namespace storm {
             return result;
 		}
         
+        bool Expression::containsVariable(std::set<storm::expressions::Variable> const& variables) const {
+            std::set<storm::expressions::Variable> appearingVariables = this->getVariables();
+            std::set<storm::expressions::Variable> intersection;
+            std::set_intersection(variables.begin(), variables.end(), appearingVariables.begin(), appearingVariables.end(), std::inserter(intersection, intersection.begin()));
+            return !intersection.empty();
+        }
+        
         bool Expression::isRelationalExpression() const {
             if (!this->isFunctionApplication()) {
                 return false;
diff --git a/src/storage/expressions/Expression.h b/src/storage/expressions/Expression.h
index 205012331..afc04bf56 100644
--- a/src/storage/expressions/Expression.h
+++ b/src/storage/expressions/Expression.h
@@ -213,6 +213,14 @@ namespace storm {
              */
             std::set<storm::expressions::Variable> getVariables() const;
 
+            /*!
+             * Retrieves whether the expression contains any of the given variables.
+             *
+             * @param variables The variables to search for.
+             * @return True iff any of the variables appear in the expression.
+             */
+            bool containsVariable(std::set<storm::expressions::Variable> const& variables) const;
+            
             /*!
              * Retrieves the base expression underlying this expression object. Note that prior to calling this, the
              * expression object must be properly initialized.
diff --git a/src/storage/prism/Command.cpp b/src/storage/prism/Command.cpp
index a476e2fd9..7141ed455 100644
--- a/src/storage/prism/Command.cpp
+++ b/src/storage/prism/Command.cpp
@@ -48,6 +48,21 @@ namespace storm {
             return labeled;
         }
         
+        bool Command::containsVariablesOnlyInUpdateProbabilities(std::set<storm::expressions::Variable> const& undefinedConstantVariables) const {
+            if (this->getGuardExpression().containsVariable(undefinedConstantVariables)) {
+                return false;
+            }
+            for (auto const& update : this->getUpdates()) {
+                for (auto const& assignment : update.getAssignments()) {
+                    if (assignment.getExpression().containsVariable(undefinedConstantVariables)) {
+                        return false;
+                    }
+                }
+            }
+            
+            return true;
+        }
+        
         std::ostream& operator<<(std::ostream& stream, Command const& command) {
             stream << "[" << command.getActionName() << "] " << command.getGuardExpression() << " -> ";
             for (uint_fast64_t i = 0; i < command.getUpdates().size(); ++i) {
diff --git a/src/storage/prism/Command.h b/src/storage/prism/Command.h
index e0dac47f9..b983a1ca9 100644
--- a/src/storage/prism/Command.h
+++ b/src/storage/prism/Command.h
@@ -99,6 +99,15 @@ namespace storm {
              */
             bool isLabeled() const;
             
+            /*!
+             * Checks whether the given set of variables only appears in the update probabilities of the command.
+             *
+             * @param undefinedConstantVariables The set of variables that may only appear in the update probabilities
+             * of the command.
+             * @return True iff the given set of variables only appears in the update probabilities of the command.
+             */
+            bool containsVariablesOnlyInUpdateProbabilities(std::set<storm::expressions::Variable> const& undefinedConstantVariables) const;
+            
             friend std::ostream& operator<<(std::ostream& stream, Command const& command);
             
         private:
diff --git a/src/storage/prism/Module.cpp b/src/storage/prism/Module.cpp
index e6adf07b1..00b3e2828 100644
--- a/src/storage/prism/Module.cpp
+++ b/src/storage/prism/Module.cpp
@@ -170,6 +170,31 @@ namespace storm {
             return Module(this->getName(), newBooleanVariables, newIntegerVariables, newCommands, this->getFilename(), this->getLineNumber());
         }
         
+        bool Module::containsVariablesOnlyInUpdateProbabilities(std::set<storm::expressions::Variable> const& undefinedConstantVariables) const {
+            for (auto const& booleanVariable : this->getBooleanVariables()) {
+                if (booleanVariable.getInitialValueExpression().containsVariable(undefinedConstantVariables)) {
+                    return false;
+                }
+            }
+            for (auto const& integerVariable : this->getIntegerVariables()) {
+                if (integerVariable.getInitialValueExpression().containsVariable(undefinedConstantVariables)) {
+                    return false;
+                }
+                if (integerVariable.getLowerBoundExpression().containsVariable(undefinedConstantVariables)) {
+                    return false;
+                }
+                if (integerVariable.getUpperBoundExpression().containsVariable(undefinedConstantVariables)) {
+                    return false;
+                }
+            }
+            
+            for (auto const& command : this->getCommands()) {
+                command.containsVariablesOnlyInUpdateProbabilities(undefinedConstantVariables);
+            }
+            
+            return true;
+        }
+        
         std::ostream& operator<<(std::ostream& stream, Module const& module) {
             stream << "module " << module.getName() << std::endl;
             for (auto const& booleanVariable : module.getBooleanVariables()) {
diff --git a/src/storage/prism/Module.h b/src/storage/prism/Module.h
index e8686cce5..0dc1f4dde 100644
--- a/src/storage/prism/Module.h
+++ b/src/storage/prism/Module.h
@@ -196,6 +196,14 @@ namespace storm {
              */
             Module substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const;
             
+            /*!
+             * Checks whether the given variables only appear in the update probabilities of the module and nowhere else.
+             *
+             * @param undefinedConstantVariables A set of variables that may only appear in the update probabilities.
+             * @return True iff the given variables only appear in the update probabilities of the module and nowhere else.
+             */
+            bool containsVariablesOnlyInUpdateProbabilities(std::set<storm::expressions::Variable> const& undefinedConstantVariables) const;
+            
             friend std::ostream& operator<<(std::ostream& stream, Module const& module);
 
         private:
diff --git a/src/storage/prism/Program.cpp b/src/storage/prism/Program.cpp
index 5b2068a22..fc746ab00 100644
--- a/src/storage/prism/Program.cpp
+++ b/src/storage/prism/Program.cpp
@@ -11,7 +11,7 @@
 
 namespace storm {
     namespace prism {
-        Program::Program(std::shared_ptr<storm::expressions::ExpressionManager> manager, ModelType modelType, std::vector<Constant> const& constants, std::vector<BooleanVariable> const& globalBooleanVariables, std::vector<IntegerVariable> const& globalIntegerVariables, std::vector<Formula> const& formulas, std::vector<Module> const& modules, std::map<std::string, uint_fast64_t> const& actionToIndexMap, std::vector<RewardModel> const& rewardModels, bool fixInitialConstruct, storm::prism::InitialConstruct const& initialConstruct, std::vector<Label> const& labels, std::string const& filename, uint_fast64_t lineNumber, bool checkValidity) : LocatedInformation(filename, lineNumber), manager(manager), modelType(modelType), constants(constants), constantToIndexMap(), globalBooleanVariables(globalBooleanVariables), globalBooleanVariableToIndexMap(), globalIntegerVariables(globalIntegerVariables), globalIntegerVariableToIndexMap(), formulas(formulas), formulaToIndexMap(), modules(modules), moduleToIndexMap(), rewardModels(rewardModels), rewardModelToIndexMap(), initialConstruct(initialConstruct), labels(labels), actionToIndexMap(actionToIndexMap), actions(), actionIndices(), actionIndicesToModuleIndexMap(), variableToModuleIndexMap() {
+        Program::Program(std::shared_ptr<storm::expressions::ExpressionManager> manager, ModelType modelType, std::vector<Constant> const& constants, std::vector<BooleanVariable> const& globalBooleanVariables, std::vector<IntegerVariable> const& globalIntegerVariables, std::vector<Formula> const& formulas, std::vector<Module> const& modules, std::map<std::string, uint_fast64_t> const& actionToIndexMap, std::vector<RewardModel> const& rewardModels, bool fixInitialConstruct, storm::prism::InitialConstruct const& initialConstruct, std::vector<Label> const& labels, std::string const& filename, uint_fast64_t lineNumber, bool checkValidity) : LocatedInformation(filename, lineNumber), manager(manager), modelType(modelType), constants(constants), constantToIndexMap(), globalBooleanVariables(globalBooleanVariables), globalBooleanVariableToIndexMap(), globalIntegerVariables(globalIntegerVariables), globalIntegerVariableToIndexMap(), formulas(formulas), formulaToIndexMap(), modules(modules), moduleToIndexMap(), rewardModels(rewardModels), rewardModelToIndexMap(), initialConstruct(initialConstruct), labels(labels), actionToIndexMap(actionToIndexMap), indexToActionMap(), actions(), actionIndices(), actionIndicesToModuleIndexMap(), variableToModuleIndexMap() {
             this->createMappings();
             
             // Create a new initial construct if the corresponding flag was set.
@@ -53,6 +53,81 @@ namespace storm {
             return false;
         }
         
+        bool Program::hasUndefinedConstantsOnlyInUpdateProbabilitiesAndRewards() const {
+            if (!this->hasUndefinedConstants()) {
+                return true;
+            }
+            
+            // Gather the variables of all undefined constants.
+            std::set<storm::expressions::Variable> undefinedConstantVariables;
+            for (auto const& constant : this->getConstants()) {
+                if (!constant.isDefined()) {
+                    undefinedConstantVariables.insert(constant.getExpressionVariable());
+                }
+            }
+            
+            // Now it remains to check that the intersection of the variables used in the program with the undefined
+            // constants' variables is empty (except for the update probabilities).
+            
+            // Start by checking the defining expressions of all defined constants.
+            for (auto const& constant : this->getConstants()) {
+                if (constant.isDefined()) {
+                    if (constant.getExpression().containsVariable(undefinedConstantVariables)) {
+                        return false;
+                    }
+                }
+            }
+            
+            // Now check initial value expressions of global variables.
+            for (auto const& booleanVariable : this->getGlobalBooleanVariables()) {
+                if (booleanVariable.getInitialValueExpression().containsVariable(undefinedConstantVariables)) {
+                    return false;
+                }
+            }
+            for (auto const& integerVariable : this->getGlobalIntegerVariables()) {
+                if (integerVariable.getInitialValueExpression().containsVariable(undefinedConstantVariables)) {
+                    return false;
+                }
+                if (integerVariable.getLowerBoundExpression().containsVariable(undefinedConstantVariables)) {
+                    return false;
+                }
+                if (integerVariable.getUpperBoundExpression().containsVariable(undefinedConstantVariables)) {
+                    return false;
+                }
+            }
+            
+            // Then check the formulas.
+            for (auto const& formula : this->getFormulas()) {
+                if (formula.getExpression().containsVariable(undefinedConstantVariables)) {
+                    return false;
+                }
+            }
+            
+            // Proceed by checking each of the modules.
+            for (auto const& module : this->getModules()) {
+                module.containsVariablesOnlyInUpdateProbabilities(undefinedConstantVariables);
+            }
+
+            // Check the reward models.
+            for (auto const& rewardModel : this->getRewardModels()) {
+                rewardModel.containsVariablesOnlyInRewardValueExpressions(undefinedConstantVariables);
+            }
+                     
+            // Initial construct.
+            if (this->getInitialConstruct().getInitialStatesExpression().containsVariable(undefinedConstantVariables)) {
+                return false;
+            }
+            
+            // Labels.
+            for (auto const& label : this->getLabels()) {
+                if (label.getStatePredicateExpression().containsVariable(undefinedConstantVariables)) {
+                    return false;
+                }
+            }
+            
+            return true;
+        }
+        
         std::vector<std::reference_wrapper<storm::prism::Constant const>> Program::getUndefinedConstants() const {
             std::vector<std::reference_wrapper<storm::prism::Constant const>> result;
             for (auto const& constant : this->getConstants()) {
@@ -150,6 +225,12 @@ namespace storm {
             return this->actionIndices;
         }
         
+        std::string const& Program::getActionName(uint_fast64_t actionIndex) const {
+            auto const& indexNamePair = this->indexToActionMap.find(actionIndex);
+            STORM_LOG_THROW(indexNamePair != this->indexToActionMap.end(), storm::exceptions::InvalidArgumentException, "Unknown action index " << actionIndex << ".");
+            return indexNamePair->second;
+        }
+        
         std::set<uint_fast64_t> const& Program::getModuleIndicesByAction(std::string const& action) const {
             auto const& nameIndexPair = this->actionToIndexMap.find(action);
             STORM_LOG_THROW(nameIndexPair != this->actionToIndexMap.end(), storm::exceptions::OutOfRangeException, "Action name '" << action << "' does not exist.");
@@ -272,6 +353,7 @@ namespace storm {
             for (auto const& actionIndexPair : this->getActionNameToIndexMapping()) {
                 this->actions.insert(actionIndexPair.first);
                 this->actionIndices.insert(actionIndexPair.second);
+                this->indexToActionMap.emplace(actionIndexPair.second, actionIndexPair.first);
             }
             
             // Build the mapping from action names to module indices so that the lookup can later be performed quickly.
diff --git a/src/storage/prism/Program.h b/src/storage/prism/Program.h
index 2f6466109..5bb241a24 100644
--- a/src/storage/prism/Program.h
+++ b/src/storage/prism/Program.h
@@ -72,6 +72,15 @@ namespace storm {
              */
             bool hasUndefinedConstants() const;
 
+            /*!
+             * Retrieves whether there are undefined constants appearing in any place other than the update probabilities
+             * of the commands and the reward expressions. This is to be used for parametric model checking where the
+             * parameters are only allowed to govern the probabilities, not the underlying graph of the model.
+             *
+             * @return True iff all undefined constants of the model only appear in update probabilities.
+             */
+            bool hasUndefinedConstantsOnlyInUpdateProbabilitiesAndRewards() const;
+            
             /*!
              * Retrieves the undefined constants in the program.
              *
@@ -225,6 +234,14 @@ namespace storm {
              */
             std::set<uint_fast64_t> const& getActionIndices() const;
             
+            /*!
+             * Retrieves the action name of the given action index.
+             *
+             * @param actionIndex The index of the action whose name to retrieve.
+             * @return The name of the action.
+             */
+            std::string const& getActionName(uint_fast64_t actionIndex) const;
+            
             /*!
              * Retrieves the indices of all modules within this program that contain commands that are labelled with the
              * given action.
@@ -442,6 +459,9 @@ namespace storm {
             
             // A mapping from action names to their indices.
             std::map<std::string, uint_fast64_t> actionToIndexMap;
+
+            // A mapping from action indices to their names.
+            std::map<uint_fast64_t, std::string> indexToActionMap;
             
             // The set of actions present in this program.
             std::set<std::string> actions;
diff --git a/src/storage/prism/RewardModel.cpp b/src/storage/prism/RewardModel.cpp
index 2c1b49ae7..6e13cb695 100644
--- a/src/storage/prism/RewardModel.cpp
+++ b/src/storage/prism/RewardModel.cpp
@@ -45,6 +45,20 @@ namespace storm {
             return RewardModel(this->getName(), newStateRewards, newTransitionRewards, this->getFilename(), this->getLineNumber());
         }
         
+        bool RewardModel::containsVariablesOnlyInRewardValueExpressions(std::set<storm::expressions::Variable> const& undefinedConstantVariables) const {
+            for (auto const& stateReward : this->getStateRewards()) {
+                if (stateReward.getStatePredicateExpression().containsVariable(undefinedConstantVariables)) {
+                    return false;
+                }
+            }
+            for (auto const& transitionReward : this->getTransitionRewards()) {
+                if (transitionReward.getStatePredicateExpression().containsVariable(undefinedConstantVariables)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        
         std::ostream& operator<<(std::ostream& stream, RewardModel const& rewardModel) {
             stream << "rewards";
             if (rewardModel.getName() != "") {
diff --git a/src/storage/prism/RewardModel.h b/src/storage/prism/RewardModel.h
index 2a2b0ab97..f8586b9a9 100644
--- a/src/storage/prism/RewardModel.h
+++ b/src/storage/prism/RewardModel.h
@@ -83,6 +83,15 @@ namespace storm {
              */
             RewardModel substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const;
             
+            /*!
+             * Checks whether any of the given variables only appear in the expressions defining the reward value.
+             *
+             * @param undefinedConstantVariables A set of variables that may only appear in the expressions defining the
+             * reward values.
+             * @return True iff the given variables only appear in the expressions defining the reward value.
+             */
+            bool containsVariablesOnlyInRewardValueExpressions(std::set<storm::expressions::Variable> const& undefinedConstantVariables) const;
+            
             friend std::ostream& operator<<(std::ostream& stream, RewardModel const& rewardModel);
 
         private:
diff --git a/src/utility/cli.h b/src/utility/cli.h
index 2d6c48536..6cde40151 100644
--- a/src/utility/cli.h
+++ b/src/utility/cli.h
@@ -53,6 +53,9 @@ log4cplus::Logger printer;
 #include "src/builder/ExplicitPrismModelBuilder.h"
 #include "src/builder/DdPrismModelBuilder.h"
 
+// Headers for DD-related classes.
+#include "src/storage/dd/CuddDd.h"
+
 // Headers for model processing.
 #include "src/storage/NaiveDeterministicModelBisimulationDecomposition.h"
 #include "src/storage/DeterministicModelBisimulationDecomposition.h"
diff --git a/test/functional/builder/DdPrismModelBuilderTest.cpp b/test/functional/builder/DdPrismModelBuilderTest.cpp
index 34edc67fd..c81e46103 100644
--- a/test/functional/builder/DdPrismModelBuilderTest.cpp
+++ b/test/functional/builder/DdPrismModelBuilderTest.cpp
@@ -34,3 +34,30 @@ TEST(DdPrismModelBuilderTest, Dtmc) {
     EXPECT_EQ(1728, model.first.getNonZeroCount());
     EXPECT_EQ(2505, model.second.getNonZeroCount());
 }
+
+TEST(DdPrismModelBuilderTest, Mdp) {
+    storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/two_dice.nm");
+    std::pair<storm::dd::Dd<storm::dd::DdType::CUDD>, storm::dd::Dd<storm::dd::DdType::CUDD>> model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::translateProgram(program);
+    EXPECT_EQ(169, model.first.getNonZeroCount());
+    EXPECT_EQ(436, model.second.getNonZeroCount());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/leader3.nm");
+    model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::translateProgram(program);
+    EXPECT_EQ(364, model.first.getNonZeroCount());
+    EXPECT_EQ(654, model.second.getNonZeroCount());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/coin2-2.nm");
+    model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::translateProgram(program);
+    EXPECT_EQ(272, model.first.getNonZeroCount());
+    EXPECT_EQ(492, model.second.getNonZeroCount());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/csma2-2.nm");
+    model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::translateProgram(program);
+    EXPECT_EQ(1038, model.first.getNonZeroCount());
+    EXPECT_EQ(1282, model.second.getNonZeroCount());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/firewire3-0.5.nm");
+    model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::translateProgram(program);
+    EXPECT_EQ(4093, model.first.getNonZeroCount());
+    EXPECT_EQ(5585, model.second.getNonZeroCount());
+}
\ No newline at end of file
diff --git a/test/functional/builder/ExplicitPrismModelBuilderTest.cpp b/test/functional/builder/ExplicitPrismModelBuilderTest.cpp
index 4d3126997..b2861f33d 100644
--- a/test/functional/builder/ExplicitPrismModelBuilderTest.cpp
+++ b/test/functional/builder/ExplicitPrismModelBuilderTest.cpp
@@ -31,3 +31,31 @@ TEST(ExplicitPrismModelBuilderTest, Dtmc) {
     EXPECT_EQ(1728, model->getNumberOfStates());
     EXPECT_EQ(2505, model->getNumberOfTransitions());
 }
+
+TEST(ExplicitPrismModelBuilderTest, Mdp) {
+    storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/two_dice.nm");
+    
+    std::unique_ptr<storm::models::AbstractModel<double>> model = storm::builder::ExplicitPrismModelBuilder<double>::translateProgram(program);
+    EXPECT_EQ(169, model->getNumberOfStates());
+    EXPECT_EQ(436, model->getNumberOfTransitions());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/leader3.nm");
+    model = storm::builder::ExplicitPrismModelBuilder<double>::translateProgram(program);
+    EXPECT_EQ(364, model->getNumberOfStates());
+    EXPECT_EQ(654, model->getNumberOfTransitions());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/coin2-2.nm");
+    model = storm::builder::ExplicitPrismModelBuilder<double>::translateProgram(program);
+    EXPECT_EQ(272, model->getNumberOfStates());
+    EXPECT_EQ(492, model->getNumberOfTransitions());
+
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/csma2-2.nm");
+    model = storm::builder::ExplicitPrismModelBuilder<double>::translateProgram(program);
+    EXPECT_EQ(1038, model->getNumberOfStates());
+    EXPECT_EQ(1282, model->getNumberOfTransitions());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/firewire3-0.5.nm");
+    model = storm::builder::ExplicitPrismModelBuilder<double>::translateProgram(program);
+    EXPECT_EQ(4093, model->getNumberOfStates());
+    EXPECT_EQ(5585, model->getNumberOfTransitions());
+}
\ No newline at end of file
diff --git a/test/functional/builder/coin2-2.nm b/test/functional/builder/coin2-2.nm
new file mode 100644
index 000000000..17a222972
--- /dev/null
+++ b/test/functional/builder/coin2-2.nm
@@ -0,0 +1,60 @@
+// COIN FLIPPING PROTOCOL FOR POLYNOMIAL RANDOMIZED CONSENSUS [AH90] 
+// gxn/dxp 20/11/00
+
+mdp
+
+// constants
+const int N=2;
+const int K=2;
+const int range = 2*(K+1)*N;
+const int counter_init = (K+1)*N;
+const int left = N;
+const int right = 2*(K+1)*N - N;
+
+// shared coin
+global counter : [0..range] init counter_init;
+
+module process1
+	
+	// program counter
+	pc1 : [0..3];
+	// 0 - flip
+	// 1 - write 
+	// 2 - check
+	// 3 - finished
+	
+	// local coin
+	coin1 : [0..1];	
+
+	// flip coin
+	[] (pc1=0)  -> 0.5 : (coin1'=0) & (pc1'=1) + 0.5 : (coin1'=1) & (pc1'=1);
+	// write tails -1  (reset coin to add regularity)
+	[] (pc1=1) & (coin1=0) & (counter>0) -> 1 : (counter'=counter-1) & (pc1'=2) & (coin1'=0);
+	// write heads +1 (reset coin to add regularity)
+	[] (pc1=1) & (coin1=1) & (counter<range) -> 1 : (counter'=counter+1) & (pc1'=2) & (coin1'=0);
+	// check
+	// decide tails
+	[] (pc1=2) & (counter<=left) -> 1 : (pc1'=3) & (coin1'=0);
+	// decide heads
+	[] (pc1=2) & (counter>=right) -> 1 : (pc1'=3) & (coin1'=1);
+	// flip again
+	[] (pc1=2) & (counter>left) & (counter<right) -> 1 : (pc1'=0);
+	// loop (all loop together when done)
+	[done] (pc1=3) -> 1 : (pc1'=3);
+
+endmodule
+
+// construct remaining processes through renaming
+module process2 = process1[pc1=pc2,coin1=coin2] endmodule
+
+// labels
+label "finished" = pc1=3 & pc2=3 ;
+label "all_coins_equal_0" = coin1=0 & coin2=0 ;
+label "all_coins_equal_1" = coin1=1 & coin2=1 ;
+label "agree" = coin1=coin2 ;
+
+// rewards
+rewards "steps"
+	true : 1;
+endrewards
+
diff --git a/test/functional/builder/csma2-2.nm b/test/functional/builder/csma2-2.nm
new file mode 100644
index 000000000..18ec5c897
--- /dev/null
+++ b/test/functional/builder/csma2-2.nm
@@ -0,0 +1,130 @@
+// CSMA/CD protocol - probabilistic version of kronos model (3 stations)
+// gxn/dxp 04/12/01
+
+mdp
+
+// note made changes since cannot have strict inequalities
+// in digital clocks approach and suppose a station only sends one message
+
+// simplified parameters scaled
+const int sigma=1; // time for messages to propagate along the bus
+const int lambda=30; // time to send a message
+
+// actual parameters
+const int N = 2; // number of processes
+const int K = 2; // exponential backoff limit
+const int slot = 2*sigma; // length of slot
+// const int M = floor(pow(2, K))-1 ; // max number of slots to wait
+const int M = 3 ; // max number of slots to wait
+//const int lambda=782;
+//const int sigma=26;
+
+// formula min_backoff_after_success = min(s1=4?cd1:K+1,s2=4?cd2:K+1);
+// formula min_collisions = min(cd1,cd2);
+// formula max_collisions = max(cd1,cd2);
+
+//----------------------------------------------------------------------------------------------------------------------------
+// the bus
+module bus
+	
+	b : [0..2];
+	// b=0 - idle
+	// b=1 - active
+	// b=2 - collision
+	
+	// clocks of bus
+	y1 : [0..sigma+1]; // time since first send (used find time until channel sensed busy)
+	y2 : [0..sigma+1]; // time since second send (used to find time until collision detected)
+	
+	// a sender sends (ok - no other message being sent)
+	[send1] (b=0) -> (b'=1);
+	[send2] (b=0) -> (b'=1);
+	
+	// a sender sends (bus busy - collision)
+	[send1] (b=1|b=2) & (y1<sigma) -> (b'=2);
+	[send2] (b=1|b=2) & (y1<sigma) -> (b'=2);
+	
+	// finish sending
+	[end1] (b=1) -> (b'=0) & (y1'=0);
+	[end2] (b=1) -> (b'=0) & (y1'=0);
+	
+	// bus busy
+	[busy1] (b=1|b=2) & (y1>=sigma) -> (b'=b);  
+	[busy2] (b=1|b=2) & (y1>=sigma) -> (b'=b);  
+	
+	// collision detected
+	[cd] (b=2) & (y2<=sigma) -> (b'=0) & (y1'=0) & (y2'=0);
+	
+	// time passage
+	[time] (b=0) -> (y1'=0); // value of y1/y2 does not matter in state 0
+	[time] (b=1) -> (y1'=min(y1+1,sigma+1)); // no invariant in state 1
+	[time] (b=2) & (y2<sigma) -> (y1'=min(y1+1,sigma+1)) & (y2'=min(y2+1,sigma+1)); // invariant in state 2 (time until collision detected)
+	
+endmodule
+
+//----------------------------------------------------------------------------------------------------------------------------
+// model of first sender
+module station1
+	
+	// LOCAL STATE
+	s1 : [0..5];
+	// s1=0 - initial state
+	// s1=1 - transmit
+	// s1=2 - collision (set backoff)
+	// s1=3 - wait (bus busy)
+	// s1=4 - successfully sent
+	
+	// LOCAL CLOCK
+	x1 : [0..max(lambda,slot)];
+	
+	// BACKOFF COUNTER (number of slots to wait)
+	bc1 : [0..M];
+	
+	// COLLISION COUNTER
+	cd1 : [0..K];
+	
+	// start sending
+	[send1] (s1=0) -> (s1'=1) & (x1'=0); // start sending
+	[busy1] (s1=0) -> (s1'=2) & (x1'=0) & (cd1'=min(K,cd1+1)); // detects channel is busy so go into backoff
+	
+	// transmitting
+	[time] (s1=1) & (x1<lambda) -> (x1'=min(x1+1,lambda)); // let time pass
+	[end1]  (s1=1) & (x1=lambda) -> (s1'=4) & (x1'=0); // finished
+	[cd]   (s1=1) -> (s1'=2) & (x1'=0) & (cd1'=min(K,cd1+1)); // collision detected (increment backoff counter)
+	[cd] !(s1=1) -> (s1'=s1); // add loop for collision detection when not important
+	
+	// set backoff (no time can pass in this state)
+	// probability depends on which transmission this is (cd1)
+	[] s1=2 & cd1=1 ->  1/2 : (s1'=3) & (bc1'=0) + 1/2 : (s1'=3) & (bc1'=1) ;
+	[] s1=2 & cd1=2 ->  1/4 : (s1'=3) & (bc1'=0) + 1/4 : (s1'=3) & (bc1'=1) + 1/4 : (s1'=3) & (bc1'=2) + 1/4 : (s1'=3) & (bc1'=3) ;
+	
+	// wait until backoff counter reaches 0 then send again
+	[time] (s1=3) & (x1<slot) -> (x1'=x1+1); // let time pass (in slot)
+	[time] (s1=3) & (x1=slot) & (bc1>0) -> (x1'=1) & (bc1'=bc1-1); // let time pass (move slots)
+	[send1] (s1=3) & (x1=slot) & (bc1=0) -> (s1'=1) & (x1'=0); // finished backoff (bus appears free)
+	[busy1] (s1=3) & (x1=slot) & (bc1=0) -> (s1'=2) & (x1'=0) & (cd1'=min(K,cd1+1)); // finished backoff (bus busy)
+	
+	// once finished nothing matters
+	[time] (s1>=4) -> (x1'=0);
+
+endmodule
+
+//----------------------------------------------------------------------------------------------------------------------------
+
+// construct further stations through renaming
+module station2=station1[s1=s2,x1=x2,cd1=cd2,bc1=bc2,send1=send2,busy1=busy2,end1=end2] endmodule
+
+//----------------------------------------------------------------------------------------------------------------------------
+
+// reward structure for expected time
+rewards "time"
+	[time] true : 1;
+endrewards
+
+//----------------------------------------------------------------------------------------------------------------------------
+
+// labels/formulae
+label "all_delivered" = s1=4&s2=4;
+label "one_delivered" = s1=4|s2=4;
+label "collision_max_backoff" = (cd1=K & s1=1 & b=2)|(cd2=K & s2=1 & b=2);
+
diff --git a/test/functional/builder/firewire3-0.5.nm b/test/functional/builder/firewire3-0.5.nm
new file mode 100644
index 000000000..a941e623b
--- /dev/null
+++ b/test/functional/builder/firewire3-0.5.nm
@@ -0,0 +1,170 @@
+// firewire protocol with integer semantics
+// dxp/gxn 14/06/01
+
+// CLOCKS
+// x1 (x2) clock for node1 (node2)
+// y1 and y2 (z1 and z2) clocks for wire12 (wire21)
+mdp
+
+// maximum and minimum delays
+// fast
+const int rc_fast_max = 85;
+const int rc_fast_min = 76;
+// slow
+const int rc_slow_max = 167;
+const int rc_slow_min = 159;
+// delay caused by the wire length
+const int delay = 3;
+// probability of choosing fast
+const double fast = 0.5;
+const double slow=1-fast;
+
+module wire12
+	
+	// local state
+	w12 : [0..9];
+	// 0 - empty
+	// 1 -	rec_req
+	// 2 -  rec_req_ack
+	// 3 -	rec_ack
+	// 4 -	rec_ack_idle
+	// 5 -	rec_idle
+	// 6 -	rec_idle_req
+	// 7 -	rec_ack_req
+	// 8 -	rec_req_idle
+	// 9 -	rec_idle_ack
+	
+	// clock for wire12
+	y1 : [0..delay+1];
+	y2 : [0..delay+1];
+
+	// empty
+	// do not need y1 and y2 to increase as always reset when this state is left
+	// similarly can reset y1 and y2 when we re-enter this state
+	[snd_req12]  w12=0 -> (w12'=1) & (y1'=0) & (y2'=0);
+	[snd_ack12]  w12=0 -> (w12'=3) & (y1'=0) & (y2'=0);
+	[snd_idle12] w12=0 -> (w12'=5) & (y1'=0) & (y2'=0);
+	[time]       w12=0 -> (w12'=w12);	
+	// rec_req
+	[snd_req12]  w12=1 -> (w12'=1);
+	[rec_req12]  w12=1 -> (w12'=0) & (y1'=0) & (y2'=0);
+	[snd_ack12]  w12=1 -> (w12'=2) & (y2'=0);
+	[snd_idle12] w12=1 -> (w12'=8) & (y2'=0);
+	[time]       w12=1 & y2<delay ->  (y1'=min(y1+1,delay+1)) & (y2'=min(y2+1,delay+1));
+	// rec_req_ack
+	[snd_ack12] w12=2 -> (w12'=2);
+	[rec_req12] w12=2 -> (w12'=3);
+	[time]      w12=2 & y1<delay ->  (y1'=min(y1+1,delay+1)) & (y2'=min(y2+1,delay+1));
+	// rec_ack
+	[snd_ack12]  w12=3 -> (w12'=3);
+	[rec_ack12]  w12=3 -> (w12'=0) & (y1'=0) & (y2'=0);
+	[snd_idle12] w12=3 -> (w12'=4) & (y2'=0);
+	[snd_req12]  w12=3 -> (w12'=7) & (y2'=0);
+	[time]       w12=3 & y2<delay ->  (y1'=min(y1+1,delay+1)) & (y2'=min(y2+1,delay+1));
+	// rec_ack_idle
+	[snd_idle12] w12=4 -> (w12'=4);
+	[rec_ack12]  w12=4 -> (w12'=5);
+	[time]       w12=4 & y1<delay ->  (y1'=min(y1+1,delay+1)) & (y2'=min(y2+1,delay+1));
+	// rec_idle
+	[snd_idle12] w12=5 -> (w12'=5);
+	[rec_idle12] w12=5 -> (w12'=0) & (y1'=0) & (y2'=0);
+	[snd_req12]  w12=5 -> (w12'=6) & (y2'=0);
+	[snd_ack12]  w12=5 -> (w12'=9) & (y2'=0);
+	[time]       w12=5 & y2<delay ->  (y1'=min(y1+1,delay+1)) & (y2'=min(y2+1,delay+1));
+	// rec_idle_req
+	[snd_req12]  w12=6 -> (w12'=6);
+	[rec_idle12] w12=6 -> (w12'=1);
+	[time]       w12=6 & y1<delay ->  (y1'=min(y1+1,delay+1)) & (y2'=min(y2+1,delay+1));
+	// rec_ack_req
+	[snd_req12] w12=7 -> (w12'=7);
+	[rec_ack12] w12=7 -> (w12'=1);
+	[time]      w12=7 & y1<delay ->  (y1'=min(y1+1,delay+1)) & (y2'=min(y2+1,delay+1));
+	// rec_req_idle
+	[snd_idle12] w12=8 -> (w12'=8);
+	[rec_req12]  w12=8 -> (w12'=5);
+	[time]       w12=8 & y1<delay ->  (y1'=min(y1+1,delay+1)) & (y2'=min(y2+1,delay+1));
+	// rec_idle_ack
+	[snd_ack12]  w12=9 -> (w12'=9);
+	[rec_idle12] w12=9 -> (w12'=3);
+	[time]       w12=9 & y1<delay ->  (y1'=min(y1+1,delay+1)) & (y2'=min(y2+1,delay+1));
+	
+endmodule
+
+module node1
+	
+	// clock for node1
+	x1 : [0..168];
+	
+	// local state
+	s1 : [0..8];
+	// 0 - root contention
+	// 1 - rec_idle
+	// 2 - rec_req_fast
+	// 3 - rec_req_slow
+	// 4 - rec_idle_fast
+	// 5 - rec_idle_slow
+	// 6 - snd_req
+	// 7- almost_root
+	// 8 - almost_child
+	
+	// added resets to x1 when not considered again until after rest
+	// removed root and child (using almost root and almost child)
+	
+	// root contention immediate state)
+	[snd_idle12] s1=0 -> fast : (s1'=2) & (x1'=0) +  slow : (s1'=3) & (x1'=0);
+	[rec_idle21] s1=0 -> (s1'=1);
+	// rec_idle immediate state)
+	[snd_idle12] s1=1 -> fast : (s1'=4) & (x1'=0) +  slow : (s1'=5) & (x1'=0);
+	[rec_req21]  s1=1 -> (s1'=0);
+	// rec_req_fast
+	[rec_idle21] s1=2 -> (s1'=4);	
+	[snd_ack12]  s1=2 & x1>=rc_fast_min -> (s1'=7) & (x1'=0);
+	[time]       s1=2 & x1<rc_fast_max -> (x1'=min(x1+1,168));
+	// rec_req_slow
+	[rec_idle21] s1=3 -> (s1'=5);
+	[snd_ack12]  s1=3 & x1>=rc_slow_min -> (s1'=7) & (x1'=0);
+	[time]       s1=3 & x1<rc_slow_max -> (x1'=min(x1+1,168));
+	// rec_idle_fast
+	[rec_req21] s1=4 -> (s1'=2);
+	[snd_req12] s1=4 & x1>=rc_fast_min -> (s1'=6) & (x1'=0);
+	[time]      s1=4 & x1<rc_fast_max -> (x1'=min(x1+1,168));
+	// rec_idle_slow
+	[rec_req21] s1=5 -> (s1'=3);
+	[snd_req12] s1=5 & x1>=rc_slow_min -> (s1'=6) & (x1'=0);
+	[time]      s1=5 & x1<rc_slow_max -> (x1'=min(x1+1,168));
+	// snd_req 
+	// do not use x1 until reset (in state 0 or in state 1) so do not need to increase x1
+	// also can set x1 to 0 upon entering this state
+	[rec_req21] s1=6 -> (s1'=0);
+	[rec_ack21] s1=6 -> (s1'=8);
+	[time]      s1=6 -> (s1'=s1);
+	// almost root (immediate) 
+	// loop in final states to remove deadlock
+	[] s1=7 & s2=8 -> (s1'=s1);
+	[] s1=8 & s2=7 -> (s1'=s1);
+	[time] s1=7 -> (s1'=s1);
+	[time] s1=8 -> (s1'=s1);
+	
+endmodule
+
+// construct remaining automata through renaming
+module wire21=wire12[w12=w21, y1=z1, y2=z2, 
+	snd_req12=snd_req21, snd_idle12=snd_idle21, snd_ack12=snd_ack21,
+	rec_req12=rec_req21, rec_idle12=rec_idle21, rec_ack12=rec_ack21]
+endmodule
+module node2=node1[s1=s2, s2=s1, x1=x2, 
+	rec_req21=rec_req12, rec_idle21=rec_idle12, rec_ack21=rec_ack12,
+	snd_req12=snd_req21, snd_idle12=snd_idle21, snd_ack12=snd_ack21]
+endmodule
+
+// reward structures
+// time
+rewards "time"	
+	[time] true : 1;
+endrewards
+// time nodes sending
+rewards "time_sending"
+	[time] (w12>0 | w21>0) : 1;
+endrewards
+
+label "elected" = ((s1=8) & (s2=7)) | ((s1=7) & (s2=8));
diff --git a/test/functional/builder/leader3.nm b/test/functional/builder/leader3.nm
new file mode 100644
index 000000000..96339dd96
--- /dev/null
+++ b/test/functional/builder/leader3.nm
@@ -0,0 +1,91 @@
+// asynchronous leader election
+// 4 processes
+// gxn/dxp 29/01/01
+
+mdp
+
+const int N = 3; // number of processes
+
+//----------------------------------------------------------------------------------------------------------------------------
+module process1
+	
+	// COUNTER
+	c1 : [0..3-1];
+	
+	// STATES
+	s1 : [0..4];
+	// 0  make choice
+	// 1 have not received neighbours choice
+	// 2 active
+	// 3 inactive
+	// 4 leader
+	
+	// PREFERENCE
+	p1 : [0..1];
+	
+	// VARIABLES FOR SENDING AND RECEIVING
+	receive1 : [0..2];
+	// not received anything
+	// received choice
+	// received counter
+	sent1 : [0..2];
+	// not send anything
+	// sent choice
+	// sent counter
+	
+	// pick value
+	[] (s1=0) -> 0.5 : (s1'=1) & (p1'=0) + 0.5 : (s1'=1) & (p1'=1);
+
+	// send preference
+	[p12] (s1=1) & (sent1=0) -> (sent1'=1);
+	// receive preference
+	// stay active
+	[p31] (s1=1) & (receive1=0) & !( (p1=0) & (p3=1) ) -> (s1'=2) & (receive1'=1);
+	// become inactive
+	[p31] (s1=1) & (receive1=0) & (p1=0) & (p3=1) -> (s1'=3) & (receive1'=1);
+	
+	// send preference (can now reset preference)
+	[p12] (s1=2) & (sent1=0) -> (sent1'=1) & (p1'=0);
+	// send counter (already sent preference)
+	// not received counter yet
+	[c12] (s1=2) & (sent1=1) & (receive1=1) -> (sent1'=2);
+	// received counter (pick again)
+	[c12] (s1=2) & (sent1=1) & (receive1=2) -> (s1'=0) & (p1'=0) & (c1'=0) & (sent1'=0) & (receive1'=0);
+	
+	// receive counter and not sent yet (note in this case do not pass it on as will send own counter)
+	[c31] (s1=2) & (receive1=1) & (sent1<2) -> (receive1'=2);
+	// receive counter and sent counter
+	// only active process (decide)
+	[c31] (s1=2) & (receive1=1) & (sent1=2) & (c3=N-1) -> (s1'=4) & (p1'=0) & (c1'=0) & (sent1'=0) & (receive1'=0);
+	// other active process (pick again)
+	[c31] (s1=2) & (receive1=1) & (sent1=2) & (c3<N-1) -> (s1'=0) & (p1'=0) & (c1'=0) & (sent1'=0) & (receive1'=0);
+	
+	// send preference (must have received preference) and can now reset
+	[p12] (s1=3) & (receive1>0) & (sent1=0) -> (sent1'=1) & (p1'=0);
+	// send counter (must have received counter first) and can now reset
+	[c12] (s1=3) & (receive1=2) & (sent1=1) ->  (s1'=3) & (p1'=0) & (c1'=0) & (sent1'=0) & (receive1'=0);
+	
+	// receive preference
+	[p31] (s1=3) & (receive1=0) -> (p1'=p3) & (receive1'=1);
+	// receive counter
+	[c31] (s1=3) & (receive1=1) & (c3<N-1) -> (c1'=c3+1) & (receive1'=2);
+		
+	// done
+	[done] (s1=4) -> (s1'=s1);
+	// add loop for processes who are inactive
+	[done] (s1=3) -> (s1'=s1);
+
+endmodule
+
+//----------------------------------------------------------------------------------------------------------------------------
+
+// construct further stations through renaming
+module process2=process1[s1=s2,p1=p2,c1=c2,sent1=sent2,receive1=receive2,p12=p23,p31=p12,c12=c23,c31=c12,p3=p1,c3=c1] endmodule
+module process3=process1[s1=s3,p1=p3,c1=c3,sent1=sent3,receive1=receive3,p12=p31,p31=p23,c12=c31,c31=c23,p3=p2,c3=c2] endmodule
+
+//----------------------------------------------------------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------------------------------------------------------
+formula leaders = (s1=4?1:0)+(s2=4?1:0)+(s3=4?1:0);
+label "elected" = s1=4|s2=4|s3=4;
+
diff --git a/test/functional/builder/two_dice.nm b/test/functional/builder/two_dice.nm
new file mode 100644
index 000000000..778153138
--- /dev/null
+++ b/test/functional/builder/two_dice.nm
@@ -0,0 +1,40 @@
+// sum of two dice as the asynchronous parallel composition of
+// two copies of Knuth's model of a fair die using only fair coins
+
+mdp
+
+module die1
+
+	// local state
+	s1 : [0..7] init 0;
+	// value of the dice
+	d1 : [0..6] init 0;
+
+	[] s1=0 -> 0.5 : (s1'=1) + 0.5 : (s1'=2);
+	[] s1=1 -> 0.5 : (s1'=3) + 0.5 : (s1'=4);
+	[] s1=2 -> 0.5 : (s1'=5) + 0.5 : (s1'=6);
+	[] s1=3 -> 0.5 : (s1'=1) + 0.5 : (s1'=7) & (d1'=1);
+	[] s1=4 -> 0.5 : (s1'=7) & (d1'=2) + 0.5 : (s1'=7) & (d1'=3);
+	[] s1=5 -> 0.5 : (s1'=7) & (d1'=4) + 0.5 : (s1'=7) & (d1'=5);
+	[] s1=6 -> 0.5 : (s1'=2) + 0.5 : (s1'=7) & (d1'=6);
+	[] s1=7 & s2=7 -> 1: (s1'=7);
+endmodule
+
+module die2 = die1 [ s1=s2, s2=s1, d1=d2 ] endmodule
+
+rewards "coinflips"
+	[] s1<7 | s2<7 : 1;
+endrewards
+
+label "done" = s1=7 & s2=7;
+label "two" = s1=7 & s2=7 & d1+d2=2;
+label "three" = s1=7 & s2=7 & d1+d2=3;
+label "four" = s1=7 & s2=7 & d1+d2=4;
+label "five" = s1=7 & s2=7 & d1+d2=5;
+label "six" = s1=7 & s2=7 & d1+d2=6;
+label "seven" = s1=7 & s2=7 & d1+d2=7;
+label "eight" = s1=7 & s2=7 & d1+d2=8;
+label "nine" = s1=7 & s2=7 & d1+d2=9;
+label "ten" = s1=7 & s2=7 & d1+d2=10;
+label "eleven" = s1=7 & s2=7 & d1+d2=11;
+label "twelve" = s1=7 & s2=7 & d1+d2=12;
diff --git a/wlan0_collide.nm b/wlan0_collide.nm
new file mode 100644
index 000000000..5d94e23de
--- /dev/null
+++ b/wlan0_collide.nm
@@ -0,0 +1,13 @@
+mdp
+
+module station1
+    s1 : [0..12] init 0;
+
+//	[] s1=0 -> (s1'=8) ;
+
+	[] s1=1 -> (s1'=1);
+	[] s1=1 -> (s1'=1);
+	
+//[] s1=8 -> (s1'=8);
+
+endmodule