diff --git a/CMakeLists.txt b/CMakeLists.txt
index e8b342aed..4af9a135b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -258,10 +258,9 @@ file(GLOB_RECURSE STORM_SETTINGS_FILES ${PROJECT_SOURCE_DIR}/src/settings/*.h ${
 file(GLOB_RECURSE STORM_SOLVER_FILES ${PROJECT_SOURCE_DIR}/src/solver/*.h ${PROJECT_SOURCE_DIR}/src/solver/*.cpp)
 file(GLOB STORM_STORAGE_FILES ${PROJECT_SOURCE_DIR}/src/storage/*.h ${PROJECT_SOURCE_DIR}/src/storage/*.cpp)
 file(GLOB_RECURSE STORM_STORAGE_DD_FILES ${PROJECT_SOURCE_DIR}/src/storage/dd/*.h ${PROJECT_SOURCE_DIR}/src/storage/dd/*.cpp)
+file(GLOB_RECURSE STORM_STORAGE_EXPRESSIONS_FILES ${PROJECT_SOURCE_DIR}/src/storage/expressions/*.h ${PROJECT_SOURCE_DIR}/src/storage/expressions/*.cpp)
+file(GLOB_RECURSE STORM_STORAGE_PRISM_FILES ${PROJECT_SOURCE_DIR}/src/storage/prism/*.h ${PROJECT_SOURCE_DIR}/src/storage/prism/*.cpp)
 file(GLOB_RECURSE STORM_UTILITY_FILES ${PROJECT_SOURCE_DIR}/src/utility/*.h ${PROJECT_SOURCE_DIR}/src/utility/*.cpp)
-file(GLOB STORM_IR_FILES ${PROJECT_SOURCE_DIR}/src/ir/*.h ${PROJECT_SOURCE_DIR}/src/ir/*.cpp)
-file(GLOB_RECURSE STORM_IR_EXPRESSIONS_FILES ${PROJECT_SOURCE_DIR}/src/ir/expressions/*.h ${PROJECT_SOURCE_DIR}/src/ir/expressions/*.cpp)
-
 # Test Sources
 # Note that the tests also need the source files, except for the main file
 file(GLOB_RECURSE STORM_FUNCTIONAL_TEST_FILES ${STORM_CPP_TESTS_BASE_PATH}/functional/*.h ${STORM_CPP_TESTS_BASE_PATH}/functional/*.cpp)
@@ -280,8 +279,6 @@ source_group(formula\\csl FILES ${STORM_FORMULA_CSL_FILES})
 source_group(formula\\ltl FILES ${STORM_FORMULA_LTL_FILES})
 source_group(formula\\prctl FILES ${STORM_FORMULA_PRCTL_FILES})
 source_group(generated FILES ${STORM_BUILD_HEADERS})
-source_group(ir FILES ${STORM_IR_FILES})
-source_group(ir\\expressions FILES ${STORM_IR_EXPRESSIONS_FILES})
 source_group(modelchecker FILES ${STORM_MODELCHECKER_FILES})
 source_group(counterexamples FILES ${STORM_COUNTEREXAMPLES_FILES})
 source_group(models FILES ${STORM_MODELS_FILES})
@@ -291,6 +288,8 @@ source_group(settings FILES ${STORM_SETTINGS_FILES})
 source_group(solver FILES ${STORM_SOLVER_FILES})
 source_group(storage FILES ${STORM_STORAGE_FILES})
 source_group(storage\\dd FILES ${STORM_STORAGE_DD_FILES})
+source_group(storage\\expressions FILES ${STORM_STORAGE_EXPRESSIONS_FILES})
+source_group(storage\\prism FILES ${STORM_STORAGE_PRISM_FILES})
 source_group(utility FILES ${STORM_UTILITY_FILES})
 source_group(functional-test FILES ${STORM_FUNCTIONAL_TEST_FILES})
 source_group(performance-test FILES ${STORM_PERFORMANCE_TEST_FILES})
diff --git a/examples/dtmc/synchronous_leader/leader4_8.pm b/examples/dtmc/synchronous_leader/leader4_8.pm
index fc8f167a0..188039cf3 100644
--- a/examples/dtmc/synchronous_leader/leader4_8.pm
+++ b/examples/dtmc/synchronous_leader/leader4_8.pm
@@ -4,8 +4,8 @@
 dtmc
 
 // CONSTANTS
-const N = 4; // number of processes
-const K = 8; // range of probabilistic choice
+const int N = 4; // number of processes
+const int K = 8; // range of probabilistic choice
 
 // counter module used to count the number of processes that have been read
 // and to know when a process has decided
diff --git a/examples/dtmc/synchronous_leader/leader5_8.pm b/examples/dtmc/synchronous_leader/leader5_8.pm
index 72139fda9..4723ed5b0 100644
--- a/examples/dtmc/synchronous_leader/leader5_8.pm
+++ b/examples/dtmc/synchronous_leader/leader5_8.pm
@@ -4,8 +4,8 @@
 dtmc
 
 // CONSTANTS
-const N = 5; // number of processes
-const K = 8; // range of probabilistic choice
+const int N = 5; // number of processes
+const int K = 8; // range of probabilistic choice
 
 // counter module used to count the number of processes that have been read
 // and to know when a process has decided
diff --git a/examples/dtmc/synchronous_leader/leader6_8.pm b/examples/dtmc/synchronous_leader/leader6_8.pm
index 283042ad5..a31773b1d 100644
--- a/examples/dtmc/synchronous_leader/leader6_8.pm
+++ b/examples/dtmc/synchronous_leader/leader6_8.pm
@@ -4,8 +4,8 @@
 dtmc
 
 // CONSTANTS
-const N = 6; // number of processes
-const K = 8; // range of probabilistic choice
+const int N = 6; // number of processes
+const int K = 8; // range of probabilistic choice
 
 // counter module used to count the number of processes that have been read
 // and to know when a process has decided
diff --git a/resources/3rdparty/cudd-2.5.0/src/cudd/cudd.h b/resources/3rdparty/cudd-2.5.0/src/cudd/cudd.h
index 8e3686170..5a2c2f952 100644
--- a/resources/3rdparty/cudd-2.5.0/src/cudd/cudd.h
+++ b/resources/3rdparty/cudd-2.5.0/src/cudd/cudd.h
@@ -767,6 +767,8 @@ extern int Cudd_bddVarIsBound (DdManager *dd, int index);
 extern DdNode * Cudd_addExistAbstract (DdManager *manager, DdNode *f, DdNode *cube);
 extern DdNode * Cudd_addUnivAbstract (DdManager *manager, DdNode *f, DdNode *cube);
 extern DdNode * Cudd_addOrAbstract (DdManager *manager, DdNode *f, DdNode *cube);
+extern DdNode * Cudd_addMinAbstract(DdManager * manager, DdNode * f, DdNode * cube);
+extern DdNode * Cudd_addMaxAbstract(DdManager * manager, DdNode * f, DdNode * cube);
 extern DdNode * Cudd_addApply (DdManager *dd, DdNode * (*)(DdManager *, DdNode **, DdNode **), DdNode *f, DdNode *g);
 extern DdNode * Cudd_addPlus (DdManager *dd, DdNode **f, DdNode **g);
 extern DdNode * Cudd_addTimes (DdManager *dd, DdNode **f, DdNode **g);
diff --git a/resources/3rdparty/cudd-2.5.0/src/cudd/cuddAddAbs.c b/resources/3rdparty/cudd-2.5.0/src/cudd/cuddAddAbs.c
index 5e809c134..7d774586c 100644
--- a/resources/3rdparty/cudd-2.5.0/src/cudd/cuddAddAbs.c
+++ b/resources/3rdparty/cudd-2.5.0/src/cudd/cuddAddAbs.c
@@ -11,12 +11,16 @@
 		<li> Cudd_addExistAbstract()
 		<li> Cudd_addUnivAbstract()
 		<li> Cudd_addOrAbstract()
+        <li> Cudd_addMinAbstract()
+        <li> Cudd_addMaxAbstract()
 		</ul>
 	Internal procedures included in this module:
 		<ul>
 		<li> cuddAddExistAbstractRecur()
 		<li> cuddAddUnivAbstractRecur()
 		<li> cuddAddOrAbstractRecur()
+        <li> cuddAddMinAbstractRecur()
+        <li> cuddAddMaxAbstractRecur()
 		</ul>
 	Static procedures included in this module:
 		<ul>
@@ -229,6 +233,82 @@ Cudd_addOrAbstract(
 
 } /* end of Cudd_addOrAbstract */
 
+/**Function********************************************************************
+ 
+ Synopsis    [Abstracts all the variables in cube from the
+ ADD f by taking the minimum.]
+ 
+ Description [Abstracts all the variables in cube from the ADD f
+ by taking the minimum over all possible values taken by the
+ variables.  Returns the abstracted ADD if successful; NULL
+ otherwise.]
+ 
+ SideEffects [None]
+ 
+ SeeAlso     [Cudd_addUnivAbstract Cudd_addExistAbstract]
+ 
+ Note: Added by Dave Parker 14/6/99
+ 
+ ******************************************************************************/
+DdNode *
+Cudd_addMinAbstract(
+                    DdManager * manager,
+                    DdNode * f,
+                    DdNode * cube)
+{
+    DdNode *res;
+    
+    if (addCheckPositiveCube(manager, cube) == 0) {
+        (void) fprintf(manager->err,"Error: Can only abstract cubes");
+        return(NULL);
+    }
+    
+    do {
+        manager->reordered = 0;
+        res = cuddAddMinAbstractRecur(manager, f, cube);
+    } while (manager->reordered == 1);
+    return(res);
+    
+} /* end of Cudd_addMinAbstract */
+
+
+/**Function********************************************************************
+ 
+ Synopsis    [Abstracts all the variables in cube from the
+ ADD f by taking the maximum.]
+ 
+ Description [Abstracts all the variables in cube from the ADD f
+ by taking the maximum over all possible values taken by the
+ variables.  Returns the abstracted ADD if successful; NULL
+ otherwise.]
+ 
+ SideEffects [None]
+ 
+ SeeAlso     [Cudd_addUnivAbstract Cudd_addExistAbstract]
+ 
+ Note: Added by Dave Parker 14/6/99
+ 
+ ******************************************************************************/
+DdNode *
+Cudd_addMaxAbstract(
+                    DdManager * manager,
+                    DdNode * f,
+                    DdNode * cube)
+{
+    DdNode *res;
+    
+    if (addCheckPositiveCube(manager, cube) == 0) {
+        (void) fprintf(manager->err,"Error: Can only abstract cubes");
+        return(NULL);
+    }
+    
+    do {
+        manager->reordered = 0;
+        res = cuddAddMaxAbstractRecur(manager, f, cube);
+    } while (manager->reordered == 1);
+    return(res);
+    
+} /* end of Cudd_addMaxAbstract */
 
 /*---------------------------------------------------------------------------*/
 /* Definition of internal functions                                          */
@@ -542,7 +622,188 @@ cuddAddOrAbstractRecur(
 
 } /* end of cuddAddOrAbstractRecur */
 
+/**Function********************************************************************
+ 
+ Synopsis    [Performs the recursive step of Cudd_addMinAbstract.]
+ 
+ Description [Performs the recursive step of Cudd_addMinAbstract.
+ Returns the ADD obtained by abstracting the variables of cube from f,
+ if successful; NULL otherwise.]
+ 
+ SideEffects [None]
+ 
+ SeeAlso     []
+ 
+ ******************************************************************************/
+DdNode *
+cuddAddMinAbstractRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * cube)
+{
+	DdNode	*T, *E, *res, *res1, *res2, *zero;
+    
+	zero = DD_ZERO(manager);
+    
+	/* Cube is guaranteed to be a cube at this point. */
+	if (f == zero || cuddIsConstant(cube)) {
+		return(f);
+	}
+    
+    /* Abstract a variable that does not appear in f. */
+	if (cuddI(manager,f->index) > cuddI(manager,cube->index)) {
+		res = cuddAddMinAbstractRecur(manager, f, cuddT(cube));
+       	return(res);
+	}
+    
+	if ((res = cuddCacheLookup2(manager, Cudd_addMinAbstract, f, cube)) != NULL) {
+		return(res);
+	}
+    
+    
+	T = cuddT(f);
+	E = cuddE(f);
+    
+	/* If the two indices are the same, so are their levels. */
+	if (f->index == cube->index) {
+		res1 = cuddAddMinAbstractRecur(manager, T, cuddT(cube));
+		if (res1 == NULL) return(NULL);
+        cuddRef(res1);
+		res2 = cuddAddMinAbstractRecur(manager, E, cuddT(cube));
+		if (res2 == NULL) {
+            Cudd_RecursiveDeref(manager,res1);
+            return(NULL);
+		}
+		cuddRef(res2);
+		res = cuddAddApplyRecur(manager, Cudd_addMinimum, res1, res2);
+		if (res == NULL) {
+            Cudd_RecursiveDeref(manager,res1);
+            Cudd_RecursiveDeref(manager,res2);
+            return(NULL);
+		}
+		cuddRef(res);
+		Cudd_RecursiveDeref(manager,res1);
+		Cudd_RecursiveDeref(manager,res2);
+		cuddCacheInsert2(manager, Cudd_addMinAbstract, f, cube, res);
+		cuddDeref(res);
+        return(res);
+    }
+	else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */
+		res1 = cuddAddMinAbstractRecur(manager, T, cube);
+		if (res1 == NULL) return(NULL);
+        cuddRef(res1);
+		res2 = cuddAddMinAbstractRecur(manager, E, cube);
+		if (res2 == NULL) {
+			Cudd_RecursiveDeref(manager,res1);
+			return(NULL);
+		}
+        cuddRef(res2);
+		res = (res1 == res2) ? res1 :
+        cuddUniqueInter(manager, (int) f->index, res1, res2);
+		if (res == NULL) {
+            Cudd_RecursiveDeref(manager,res1);
+            Cudd_RecursiveDeref(manager,res2);
+            return(NULL);
+		}
+		cuddDeref(res1);
+		cuddDeref(res2);
+		cuddCacheInsert2(manager, Cudd_addMinAbstract, f, cube, res);
+        return(res);
+	}
+    
+} /* end of cuddAddMinAbstractRecur */
+
 
+/**Function********************************************************************
+ 
+ Synopsis    [Performs the recursive step of Cudd_addMaxAbstract.]
+ 
+ Description [Performs the recursive step of Cudd_addMaxAbstract.
+ Returns the ADD obtained by abstracting the variables of cube from f,
+ if successful; NULL otherwise.]
+ 
+ SideEffects [None]
+ 
+ SeeAlso     []
+ 
+ ******************************************************************************/
+DdNode *
+cuddAddMaxAbstractRecur(
+                        DdManager * manager,
+                        DdNode * f,
+                        DdNode * cube)
+{
+	DdNode	*T, *E, *res, *res1, *res2, *zero;
+    
+	zero = DD_ZERO(manager);
+    
+	/* Cube is guaranteed to be a cube at this point. */
+	if (f == zero || cuddIsConstant(cube)) {
+		return(f);
+	}
+    
+    /* Abstract a variable that does not appear in f. */
+	if (cuddI(manager,f->index) > cuddI(manager,cube->index)) {
+		res = cuddAddMaxAbstractRecur(manager, f, cuddT(cube));
+       	return(res);
+	}
+    
+	if ((res = cuddCacheLookup2(manager, Cudd_addMaxAbstract, f, cube)) != NULL) {
+		return(res);
+	}
+    
+    
+	T = cuddT(f);
+	E = cuddE(f);
+    
+	/* If the two indices are the same, so are their levels. */
+	if (f->index == cube->index) {
+		res1 = cuddAddMaxAbstractRecur(manager, T, cuddT(cube));
+		if (res1 == NULL) return(NULL);
+        cuddRef(res1);
+		res2 = cuddAddMaxAbstractRecur(manager, E, cuddT(cube));
+		if (res2 == NULL) {
+            Cudd_RecursiveDeref(manager,res1);
+            return(NULL);
+		}
+		cuddRef(res2);
+		res = cuddAddApplyRecur(manager, Cudd_addMaximum, res1, res2);
+		if (res == NULL) {
+            Cudd_RecursiveDeref(manager,res1);
+            Cudd_RecursiveDeref(manager,res2);
+            return(NULL);
+		}
+		cuddRef(res);
+		Cudd_RecursiveDeref(manager,res1);
+		Cudd_RecursiveDeref(manager,res2);
+		cuddCacheInsert2(manager, Cudd_addMaxAbstract, f, cube, res);
+		cuddDeref(res);
+        return(res);
+    }
+	else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */
+		res1 = cuddAddMaxAbstractRecur(manager, T, cube);
+		if (res1 == NULL) return(NULL);
+        cuddRef(res1);
+		res2 = cuddAddMaxAbstractRecur(manager, E, cube);
+		if (res2 == NULL) {
+			Cudd_RecursiveDeref(manager,res1);
+			return(NULL);
+		}
+        cuddRef(res2);
+		res = (res1 == res2) ? res1 :
+        cuddUniqueInter(manager, (int) f->index, res1, res2);
+		if (res == NULL) {
+            Cudd_RecursiveDeref(manager,res1);
+            Cudd_RecursiveDeref(manager,res2);
+            return(NULL);
+		}
+		cuddDeref(res1);
+		cuddDeref(res2);
+		cuddCacheInsert2(manager, Cudd_addMaxAbstract, f, cube, res);
+        return(res);
+	}	    
+    
+} /* end of cuddAddMaxAbstractRecur */
 
 /*---------------------------------------------------------------------------*/
 /* Definition of static functions                                            */
diff --git a/resources/3rdparty/cudd-2.5.0/src/cudd/cuddInt.h b/resources/3rdparty/cudd-2.5.0/src/cudd/cuddInt.h
index 398b057f7..313a56586 100644
--- a/resources/3rdparty/cudd-2.5.0/src/cudd/cuddInt.h
+++ b/resources/3rdparty/cudd-2.5.0/src/cudd/cuddInt.h
@@ -1000,6 +1000,8 @@ dd->nextSample += 250000;}
 extern DdNode * cuddAddExistAbstractRecur (DdManager *manager, DdNode *f, DdNode *cube);
 extern DdNode * cuddAddUnivAbstractRecur (DdManager *manager, DdNode *f, DdNode *cube);
 extern DdNode * cuddAddOrAbstractRecur (DdManager *manager, DdNode *f, DdNode *cube);
+extern DdNode * cuddAddMinAbstractRecur (DdManager *manager, DdNode *f, DdNode *cube);
+extern DdNode * cuddAddMaxAbstractRecur (DdManager *manager, DdNode *f, DdNode *cube);
 extern DdNode * cuddAddApplyRecur (DdManager *dd, DdNode * (*)(DdManager *, DdNode **, DdNode **), DdNode *f, DdNode *g);
 extern DdNode * cuddAddMonadicApplyRecur (DdManager * dd, DdNode * (*op)(DdManager *, DdNode *), DdNode * f);
 extern DdNode * cuddAddScalarInverseRecur (DdManager *dd, DdNode *f, DdNode *epsilon);
diff --git a/resources/3rdparty/cudd-2.5.0/src/obj/cuddObj.cc b/resources/3rdparty/cudd-2.5.0/src/obj/cuddObj.cc
index ffbaaf826..c9fcf7b11 100644
--- a/resources/3rdparty/cudd-2.5.0/src/obj/cuddObj.cc
+++ b/resources/3rdparty/cudd-2.5.0/src/obj/cuddObj.cc
@@ -2405,6 +2405,23 @@ ADD::OrAbstract(
 
 } // ADD::OrAbstract
 
+ADD
+ADD::MinAbstract(const ADD& cube) const
+{
+    DdManager *mgr = checkSameManager(cube);
+    DdNode *result = Cudd_addMinAbstract(mgr, node, cube.node);
+    checkReturnValue(result);
+    return ADD(p, result);
+} // ADD::MinAbstract
+
+ADD
+ADD::MaxAbstract(const ADD& cube) const
+{
+    DdManager *mgr = checkSameManager(cube);
+    DdNode *result = Cudd_addMaxAbstract(mgr, node, cube.node);
+    checkReturnValue(result);
+    return ADD(p, result);
+} // ADD::MaxAbstract
 
 ADD
 ADD::Plus(
diff --git a/resources/3rdparty/cudd-2.5.0/src/obj/cuddObj.hh b/resources/3rdparty/cudd-2.5.0/src/obj/cuddObj.hh
index 0dce65989..a1a859490 100644
--- a/resources/3rdparty/cudd-2.5.0/src/obj/cuddObj.hh
+++ b/resources/3rdparty/cudd-2.5.0/src/obj/cuddObj.hh
@@ -373,6 +373,8 @@ public:
     ADD ExistAbstract(const ADD& cube) const;
     ADD UnivAbstract(const ADD& cube) const;
     ADD OrAbstract(const ADD& cube) const;
+    ADD MinAbstract(const ADD& cube) const;
+    ADD MaxAbstract(const ADD& cube) const;
     ADD Plus(const ADD& g) const;
     ADD Times(const ADD& g) const;
     ADD Threshold(const ADD& g) const;
diff --git a/src/adapters/ExplicitModelAdapter.h b/src/adapters/ExplicitModelAdapter.h
index f1ef50396..777807c06 100644
--- a/src/adapters/ExplicitModelAdapter.h
+++ b/src/adapters/ExplicitModelAdapter.h
@@ -15,12 +15,11 @@
 #include <queue>
 #include <boost/functional/hash.hpp>
 #include <boost/container/flat_set.hpp>
+#include <boost/algorithm/string.hpp>
 
-#include "src/ir/Program.h"
-#include "src/ir/RewardModel.h"
-#include "src/ir/StateReward.h"
-#include "src/ir/TransitionReward.h"
-#include "src/utility/IRUtility.h"
+#include "src/storage/prism/Program.h"
+#include "src/storage/expressions/SimpleValuation.h"
+#include "src/utility/PrismUtility.h"
 #include "src/models/AbstractModel.h"
 #include "src/models/Dtmc.h"
 #include "src/models/Ctmc.h"
@@ -29,20 +28,22 @@
 #include "src/models/AtomicPropositionsLabeling.h"
 #include "src/storage/SparseMatrix.h"
 #include "src/settings/Settings.h"
+#include "src/exceptions/ExceptionMacros.h"
 #include "src/exceptions/WrongFormatException.h"
 
-#include "log4cplus/logger.h"
-#include "log4cplus/loggingmacros.h"
-extern log4cplus::Logger logger;
-
-using namespace storm::utility::ir;
-
 namespace storm {
     namespace adapters {
+        
+        using namespace storm::utility::prism;
                 
         template<typename ValueType>
         class ExplicitModelAdapter {
         public:
+            typedef storm::expressions::SimpleValuation StateType;
+            typedef storm::expressions::SimpleValuationPointerHash StateHash;
+            typedef storm::expressions::SimpleValuationPointerCompare StateCompare;
+            typedef storm::expressions::SimpleValuationPointerLess StateLess;
+            
             // A structure holding information about the reachable state space.
             struct StateInformation {
                 StateInformation() : reachableStates(), stateToIndexMap() {
@@ -52,10 +53,19 @@ namespace storm {
                 // A list of reachable states.
                 std::vector<StateType*> reachableStates;
                 
+                // A list of initial states.
+                std::vector<uint_fast64_t> initialStateIndices;
+                
                 // A mapping from states to indices in the list of reachable states.
                 std::unordered_map<StateType*, uint_fast64_t, StateHash, StateCompare> stateToIndexMap;
             };
             
+            // A structure storing information about the used variables of the program.
+            struct VariableInformation {
+                // A mapping of (integer) variable to their lower/upper bounds.
+                std::map<std::string, std::pair<int_fast64_t, int_fast64_t>> variableToBoundsMap;
+            };
+            
             // A structure holding the individual components of a model.
             struct ModelComponents {
                 ModelComponents() : transitionMatrix(), stateLabeling(),  stateRewards(), transitionRewardMatrix(), choiceLabeling() {
@@ -78,6 +88,62 @@ namespace storm {
                 std::vector<boost::container::flat_set<uint_fast64_t>> choiceLabeling;
             };
             
+            static std::map<std::string, storm::expressions::Expression> parseConstantDefinitionString(storm::prism::Program const& program, std::string const& constantDefinitionString) {
+                std::map<std::string, storm::expressions::Expression> constantDefinitions;
+                std::set<std::string> definedConstants;
+                
+                if (!constantDefinitionString.empty()) {
+                    // Parse the string that defines the undefined constants of the model and make sure that it contains exactly
+                    // one value for each undefined constant of the model.
+                    std::vector<std::string> definitions;
+                    boost::split(definitions, constantDefinitionString, boost::is_any_of(","));
+                    for (auto& definition : definitions) {
+                        boost::trim(definition);
+                        
+                        // Check whether the token could be a legal constant definition.
+                        uint_fast64_t positionOfAssignmentOperator = definition.find('=');
+                        if (positionOfAssignmentOperator == std::string::npos) {
+                            throw storm::exceptions::InvalidArgumentException() << "Illegal constant definition string: syntax error.";
+                        }
+                        
+                        // Now extract the variable name and the value from the string.
+                        std::string constantName = definition.substr(0, positionOfAssignmentOperator);
+                        boost::trim(constantName);
+                        std::string value = definition.substr(positionOfAssignmentOperator + 1);
+                        boost::trim(value);
+                        
+                        // Check whether the constant is a legal undefined constant of the program and if so, of what type it is.
+                        if (program.hasConstant(constantName)) {
+                            // Get the actual constant and check whether it's in fact undefined.
+                            auto const& constant = program.getConstant(constantName);
+                            LOG_THROW(!constant.isDefined(), storm::exceptions::InvalidArgumentException, "Illegally trying to define already defined constant '" << constantName <<"'.");
+                            LOG_THROW(definedConstants.find(constantName) == definedConstants.end(), storm::exceptions::InvalidArgumentException, "Illegally trying to define constant '" << constantName <<"' twice.");
+                            definedConstants.insert(constantName);
+                            
+                            if (constant.getType() == storm::expressions::ExpressionReturnType::Bool) {
+                                if (value == "true") {
+                                    constantDefinitions[constantName] = storm::expressions::Expression::createTrue();
+                                } else if (value == "false") {
+                                    constantDefinitions[constantName] = storm::expressions::Expression::createFalse();
+                                } else {
+                                    throw storm::exceptions::InvalidArgumentException() << "Illegal value for boolean constant: " << value << ".";
+                                }
+                            } else if (constant.getType() == storm::expressions::ExpressionReturnType::Int) {
+                                int_fast64_t integerValue = std::stoi(value);
+                                constantDefinitions[constantName] = storm::expressions::Expression::createIntegerLiteral(integerValue);
+                            } else if (constant.getType() == storm::expressions::ExpressionReturnType::Double) {
+                                double doubleValue = std::stod(value);
+                                constantDefinitions[constantName] = storm::expressions::Expression::createDoubleLiteral(doubleValue);
+                            }
+                        } else {
+                            throw storm::exceptions::InvalidArgumentException() << "Illegal constant definition string: unknown undefined constant " << constantName << ".";
+                        }
+                    }
+                }
+                
+                return constantDefinitions;
+            }
+            
             /*!
              * Convert the program given at construction time to an abstract model. The type of the model is the one
              * specified in the program. The given reward model name selects the rewards that the model will contain.
@@ -90,24 +156,33 @@ namespace storm {
              * rewards.
              * @return The explicit model that was given by the probabilistic program.
              */
-            static std::unique_ptr<storm::models::AbstractModel<ValueType>> translateProgram(storm::ir::Program program, std::string const& constantDefinitionString = "", std::string const& rewardModelName = "") {
+            static std::unique_ptr<storm::models::AbstractModel<ValueType>> translateProgram(storm::prism::Program program, std::string const& constantDefinitionString = "", std::string const& rewardModelName = "") {
                 // Start by defining the undefined constants in the model.
-                defineUndefinedConstants(program, constantDefinitionString);
+                // First, we need to parse the constant definition string.
+                std::map<std::string, storm::expressions::Expression> constantDefinitions = parseConstantDefinitionString(program, constantDefinitionString);
+                
+                storm::prism::Program preparedProgram = program.defineUndefinedConstants(constantDefinitions);
+                LOG_THROW(!preparedProgram.hasUndefinedConstants(), storm::exceptions::InvalidArgumentException, "Program still contains undefined constants.");
+                
+                // Now that we have defined all the constants in the program, we need to substitute their appearances in
+                // all expressions in the program so we can then evaluate them without having to store the values of the
+                // constants in the state (i.e., valuation).
+                preparedProgram = preparedProgram.substituteConstants();
                 
-                ModelComponents modelComponents = buildModelComponents(program, rewardModelName);
+                ModelComponents modelComponents = buildModelComponents(preparedProgram, rewardModelName);
                 
                 std::unique_ptr<storm::models::AbstractModel<ValueType>> result;
                 switch (program.getModelType()) {
-                    case storm::ir::Program::DTMC:
+                    case storm::prism::Program::ModelType::DTMC:
                         result = std::unique_ptr<storm::models::AbstractModel<ValueType>>(new storm::models::Dtmc<ValueType>(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling), rewardModelName != "" ? std::move(modelComponents.stateRewards) : boost::optional<std::vector<ValueType>>(), rewardModelName != "" ? std::move(modelComponents.transitionRewardMatrix) : boost::optional<storm::storage::SparseMatrix<ValueType>>(), std::move(modelComponents.choiceLabeling)));
                         break;
-                    case storm::ir::Program::CTMC:
+                    case storm::prism::Program::ModelType::CTMC:
                         result = std::unique_ptr<storm::models::AbstractModel<ValueType>>(new storm::models::Ctmc<ValueType>(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling), rewardModelName != "" ? std::move(modelComponents.stateRewards) : boost::optional<std::vector<ValueType>>(), rewardModelName != "" ? std::move(modelComponents.transitionRewardMatrix) : boost::optional<storm::storage::SparseMatrix<ValueType>>(), std::move(modelComponents.choiceLabeling)));
                         break;
-                    case storm::ir::Program::MDP:
+                    case storm::prism::Program::ModelType::MDP:
                         result = std::unique_ptr<storm::models::AbstractModel<ValueType>>(new storm::models::Mdp<ValueType>(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling), rewardModelName != "" ? std::move(modelComponents.stateRewards) : boost::optional<std::vector<ValueType>>(), rewardModelName != "" ? std::move(modelComponents.transitionRewardMatrix) : boost::optional<storm::storage::SparseMatrix<ValueType>>(), std::move(modelComponents.choiceLabeling)));
                         break;
-                    case storm::ir::Program::CTMDP:
+                    case storm::prism::Program::ModelType::CTMDP:
                         result = std::unique_ptr<storm::models::AbstractModel<ValueType>>(new storm::models::Ctmdp<ValueType>(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling), rewardModelName != "" ? std::move(modelComponents.stateRewards) : boost::optional<std::vector<ValueType>>(), rewardModelName != "" ? std::move(modelComponents.transitionRewardMatrix) : boost::optional<storm::storage::SparseMatrix<ValueType>>(), std::move(modelComponents.choiceLabeling)));
                         break;
                     default:
@@ -116,36 +191,19 @@ namespace storm {
                         break;
                 }
                 
-                // Undefine the constants so that the program can be used again somewhere else.
-                undefineUndefinedConstants(program);
-                
                 return result;
             }
             
         private:
-            /*!
-             * Transforms a state into a somewhat readable string.
-             *
-             * @param state The state to transform into a string.
-             * @return A string representation of the state.
-             */
-            static std::string toString(StateType const* state) {
-                std::stringstream ss;
-                for (unsigned int i = 0; i < state->first.size(); i++) ss << state->first[i] << "\t";
-                for (unsigned int i = 0; i < state->second.size(); i++) ss << state->second[i] << "\t";
-                return ss.str();
-            }
-            
             /*!
              * Applies an update to the given state and returns the resulting new state object. This methods does not
              * modify the given state but returns a new one.
              *
-             * @param variableInformation A structure with information about the variables in the program.
              * @params state The state to which to apply the update.
              * @params update The update to apply.
              * @return The resulting state.
              */
-            static StateType* applyUpdate(VariableInformation const& variableInformation, StateType const* state, storm::ir::Update const& update) {
+            static StateType* applyUpdate(VariableInformation const& variableInformation, StateType const* state, storm::prism::Update const& update) {
                 return applyUpdate(variableInformation, state, state, update);
             }
             
@@ -154,26 +212,28 @@ namespace storm {
              * over the variable values of the given base state. This methods does not modify the given state but
              * returns a new one.
              *
-             * @param variableInformation A structure with information about the variables in the program.
              * @param state The state to which to apply the update.
              * @param baseState The state used for evaluating the update.
              * @param update The update to apply.
              * @return The resulting state.
              */
-            static StateType* applyUpdate(VariableInformation const& variableInformation, StateType const* state, StateType const* baseState, storm::ir::Update const& update) {
+            static StateType* applyUpdate(VariableInformation const& variableInformation, StateType const* state, StateType const* baseState, storm::prism::Update const& update) {
                 StateType* newState = new StateType(*state);
-                for (auto variableAssignmentPair : update.getBooleanAssignments()) {
-                    setValue(newState, variableInformation.booleanVariableToIndexMap.at(variableAssignmentPair.first), variableAssignmentPair.second.getExpression()->getValueAsBool(baseState));
-                }
-                for (auto variableAssignmentPair : update.getIntegerAssignments()) {
-                    int_fast64_t newVariableValue = variableAssignmentPair.second.getExpression()->getValueAsInt(baseState);
-                    bool isLegalValueForVariable = newVariableValue >= variableInformation.lowerBounds.at(variableInformation.integerVariableToIndexMap.at(variableAssignmentPair.first)) && newVariableValue <= variableInformation.upperBounds.at(variableInformation.integerVariableToIndexMap.at(variableAssignmentPair.first));
-                    
-                    if (!isLegalValueForVariable) {
-                        throw storm::exceptions::InvalidStateException() << "Invalid value '" << newVariableValue << "' for variable \"" << variableInformation.integerVariables.at(variableInformation.integerVariableToIndexMap.at(variableAssignmentPair.first)).getName() << "\". Please strengthen the guards if necessary or enlarge the domains of the variables.";
+                
+                // This variable needs to be declared prior to the switch, because of C++ rules.
+                int_fast64_t newValue = 0;
+                for (auto const& assignment : update.getAssignments()) {
+                    switch (assignment.getExpression().getReturnType()) {
+                        case storm::expressions::ExpressionReturnType::Bool: newState->setBooleanValue(assignment.getVariableName(), assignment.getExpression().evaluateAsBool(baseState)); break;
+                        case storm::expressions::ExpressionReturnType::Int:
+                        {
+                            newValue = assignment.getExpression().evaluateAsInt(baseState);
+                            auto const& boundsPair = variableInformation.variableToBoundsMap.find(assignment.getVariableName());
+                            LOG_THROW(boundsPair->second.first <= newValue && newValue <= boundsPair->second.second, storm::exceptions::InvalidArgumentException, "Invalid value " << newValue << " for variable '" << assignment.getVariableName() << "'.");
+                            newState->setIntegerValue(assignment.getVariableName(), newValue); break;
+                        }
+                        default: LOG_ASSERT(false, "Invalid type of assignment."); break;
                     }
-                    
-                    setValue(newState, variableInformation.integerVariableToIndexMap.at(variableAssignmentPair.first), newVariableValue);
                 }
                 return newState;
             }
@@ -220,32 +280,32 @@ namespace storm {
              * @param action The action label to select.
              * @return A list of lists of active commands or nothing.
              */
-            static boost::optional<std::vector<std::list<storm::ir::Command>>> getActiveCommandsByAction(storm::ir::Program const& program, StateType const* state, std::string const& action) {
-                boost::optional<std::vector<std::list<storm::ir::Command>>> result((std::vector<std::list<storm::ir::Command>>()));
+            static boost::optional<std::vector<std::list<storm::prism::Command>>> getActiveCommandsByAction(storm::prism::Program const& program, StateType const* state, std::string const& action) {
+                boost::optional<std::vector<std::list<storm::prism::Command>>> result((std::vector<std::list<storm::prism::Command>>()));
                 
                 // Iterate over all modules.
                 for (uint_fast64_t i = 0; i < program.getNumberOfModules(); ++i) {
-                    storm::ir::Module const& module = program.getModule(i);
+                    storm::prism::Module const& module = program.getModule(i);
                     
                     // If the module has no command labeled with the given action, we can skip this module.
                     if (!module.hasAction(action)) {
                         continue;
                     }
                     
-                    std::set<uint_fast64_t> const& commandIndices = module.getCommandsByAction(action);
+                    std::set<uint_fast64_t> const& commandIndices = module.getCommandIndicesByAction(action);
                     
                     // If the module contains the action, but there is no command in the module that is labeled with
                     // this action, we don't have any feasible command combinations.
                     if (commandIndices.empty()) {
-                        return boost::optional<std::vector<std::list<storm::ir::Command>>>();
+                        return boost::optional<std::vector<std::list<storm::prism::Command>>>();
                     }
                     
-                    std::list<storm::ir::Command> commands;
+                    std::list<storm::prism::Command> commands;
                     
                     // Look up commands by their indices and add them if the guard evaluates to true in the given state.
                     for (uint_fast64_t commandIndex : commandIndices) {
-                        storm::ir::Command const& command = module.getCommand(commandIndex);
-                        if (command.getGuard()->getValueAsBool(state)) {
+                        storm::prism::Command const& command = module.getCommand(commandIndex);
+                        if (command.getGuardExpression().evaluateAsBool(state)) {
                             commands.push_back(command);
                         }
                     }
@@ -253,7 +313,7 @@ namespace storm {
                     // If there was no enabled command although the module has some command with the required action label,
                     // we must not return anything.
                     if (commands.size() == 0) {
-                        return boost::optional<std::vector<std::list<storm::ir::Command>>>();
+                        return boost::optional<std::vector<std::list<storm::prism::Command>>>();
                     }
                     
                     result.get().push_back(std::move(commands));
@@ -261,23 +321,26 @@ namespace storm {
                 return result;
             }
                         
-            static std::list<Choice<ValueType>> getUnlabeledTransitions(storm::ir::Program const& program, StateInformation& stateInformation, VariableInformation const& variableInformation, uint_fast64_t stateIndex, std::queue<uint_fast64_t>& stateQueue) {
+            static std::list<Choice<ValueType>> getUnlabeledTransitions(storm::prism::Program const& program, StateInformation& stateInformation, VariableInformation const& variableInformation, uint_fast64_t stateIndex, std::queue<uint_fast64_t>& stateQueue) {
                 std::list<Choice<ValueType>> result;
                 
                 StateType const* currentState = stateInformation.reachableStates[stateIndex];
 
                 // Iterate over all modules.
                 for (uint_fast64_t i = 0; i < program.getNumberOfModules(); ++i) {
-                    storm::ir::Module const& module = program.getModule(i);
+                    storm::prism::Module const& module = program.getModule(i);
                     
                     // Iterate over all commands.
                     for (uint_fast64_t j = 0; j < module.getNumberOfCommands(); ++j) {
-                        storm::ir::Command const& command = module.getCommand(j);
+                        storm::prism::Command const& command = module.getCommand(j);
                         
                         // Only consider unlabeled commands.
                         if (command.getActionName() != "") continue;
+
                         // Skip the command, if it is not enabled.
-                        if (!command.getGuard()->getValueAsBool(currentState)) continue;
+                        if (!command.getGuardExpression().evaluateAsBool(currentState)) {
+                            continue;
+                        }
                         
                         result.push_back(Choice<ValueType>(""));
                         Choice<ValueType>& choice = result.back();
@@ -286,7 +349,7 @@ namespace storm {
                         double probabilitySum = 0;
                         // Iterate over all updates of the current command.
                         for (uint_fast64_t k = 0; k < command.getNumberOfUpdates(); ++k) {
-                            storm::ir::Update const& update = command.getUpdate(k);
+                            storm::prism::Update const& update = command.getUpdate(k);
                             
                             // Obtain target state index.
                             std::pair<bool, uint_fast64_t> flagTargetStateIndexPair = getOrAddStateIndex(applyUpdate(variableInformation, currentState, update), stateInformation);
@@ -297,7 +360,7 @@ namespace storm {
                             }
                             
                             // Update the choice by adding the probability/target state to it.
-                            double probabilityToAdd = update.getLikelihoodExpression()->getValueAsDouble(currentState);
+                            double probabilityToAdd = update.getLikelihoodExpression().evaluateAsDouble(currentState);
                             probabilitySum += probabilityToAdd;
                             boost::container::flat_set<uint_fast64_t> labels;
 							labels.insert(update.getGlobalIndex());
@@ -305,27 +368,24 @@ namespace storm {
                         }
                         
                         // Check that the resulting distribution is in fact a distribution.
-                        if (std::abs(1 - probabilitySum) > storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()) {
-                            LOG4CPLUS_ERROR(logger, "Sum of update probabilities should be one for command:\n\t"  << command.toString());
-                            throw storm::exceptions::WrongFormatException() << "Sum of update probabilities should be one for command:\n\t"  << command.toString();
-                        }
+                        LOG_THROW(std::abs(1 - probabilitySum) < storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble(), storm::exceptions::WrongFormatException, "Probabilities do not sum to one for command '" << command << "'.");
                     }
                 }
                 
                 return result;
             }
             
-            static std::list<Choice<ValueType>> getLabeledTransitions(storm::ir::Program const& program, StateInformation& stateInformation, VariableInformation const& variableInformation, uint_fast64_t stateIndex, std::queue<uint_fast64_t>& stateQueue) {
+            static std::list<Choice<ValueType>> getLabeledTransitions(storm::prism::Program const& program, StateInformation& stateInformation, VariableInformation const& variableInformation, uint_fast64_t stateIndex, std::queue<uint_fast64_t>& stateQueue) {
                 std::list<Choice<ValueType>> result;
                 
                 for (std::string const& action : program.getActions()) {
                     StateType const* currentState = stateInformation.reachableStates[stateIndex];
-                    boost::optional<std::vector<std::list<storm::ir::Command>>> optionalActiveCommandLists = getActiveCommandsByAction(program, currentState, action);
+                    boost::optional<std::vector<std::list<storm::prism::Command>>> optionalActiveCommandLists = getActiveCommandsByAction(program, currentState, action);
                     
                     // Only process this action label, if there is at least one feasible solution.
                     if (optionalActiveCommandLists) {
-                        std::vector<std::list<storm::ir::Command>> const& activeCommandList = optionalActiveCommandLists.get();
-                        std::vector<std::list<storm::ir::Command>::const_iterator> iteratorList(activeCommandList.size());
+                        std::vector<std::list<storm::prism::Command>> const& activeCommandList = optionalActiveCommandLists.get();
+                        std::vector<std::list<storm::prism::Command>::const_iterator> iteratorList(activeCommandList.size());
                         
                         // Initialize the list of iterators.
                         for (size_t i = 0; i < activeCommandList.size(); ++i) {
@@ -342,17 +402,17 @@ namespace storm {
                             // FIXME: This does not check whether a global variable is written multiple times. While the
                             // behaviour for this is undefined anyway, a warning should be issued in that case.
                             for (uint_fast64_t i = 0; i < iteratorList.size(); ++i) {
-                                storm::ir::Command const& command = *iteratorList[i];
+                                storm::prism::Command const& command = *iteratorList[i];
                                 
                                 for (uint_fast64_t j = 0; j < command.getNumberOfUpdates(); ++j) {
-                                    storm::ir::Update const& update = command.getUpdate(j);
+                                    storm::prism::Update const& update = command.getUpdate(j);
                                     
                                     for (auto const& stateProbabilityPair : *currentTargetStates) {
                                         StateType* newTargetState = applyUpdate(variableInformation, stateProbabilityPair.first, currentState, update);
 
                                         storm::storage::LabeledValues<double> newProbability;
                                         
-                                        double updateProbability = update.getLikelihoodExpression()->getValueAsDouble(currentState);
+                                        double updateProbability = update.getLikelihoodExpression().evaluateAsDouble(currentState);
                                         for (auto const& valueLabelSetPair : stateProbabilityPair.second) {
                                             // Copy the label set, so we can modify it.
                                             boost::container::flat_set<uint_fast64_t> newLabelSet = valueLabelSetPair.second;
@@ -459,13 +519,29 @@ namespace storm {
              * @return A tuple containing a vector with all rows at which the nondeterministic choices of each state begin
              * and a vector containing the labels associated with each choice.
              */
-            static std::vector<boost::container::flat_set<uint_fast64_t>> buildMatrices(storm::ir::Program const& program, VariableInformation const& variableInformation, std::vector<storm::ir::TransitionReward> const& transitionRewards, StateInformation& stateInformation, bool deterministicModel, storm::storage::SparseMatrixBuilder<ValueType>& transitionMatrixBuilder, storm::storage::SparseMatrixBuilder<ValueType>& transitionRewardMatrixBuilder) {
+            static std::vector<boost::container::flat_set<uint_fast64_t>> buildMatrices(storm::prism::Program const& program, VariableInformation const& variableInformation, std::vector<storm::prism::TransitionReward> const& transitionRewards, StateInformation& stateInformation, bool deterministicModel, storm::storage::SparseMatrixBuilder<ValueType>& transitionMatrixBuilder, storm::storage::SparseMatrixBuilder<ValueType>& transitionRewardMatrixBuilder) {
                 std::vector<boost::container::flat_set<uint_fast64_t>> choiceLabels;
                 
                 // Initialize a queue and insert the initial state.
                 std::queue<uint_fast64_t> stateQueue;
-                StateType* initialState = getInitialState(program, variableInformation);
-                getOrAddStateIndex(initialState, stateInformation);
+                StateType* initialState = new StateType;
+                for (auto const& booleanVariable : program.getGlobalBooleanVariables()) {
+                    initialState->addBooleanIdentifier(booleanVariable.getName(), booleanVariable.getInitialValueExpression().evaluateAsBool());
+                }
+                for (auto const& integerVariable : program.getGlobalIntegerVariables()) {
+                    initialState->addIntegerIdentifier(integerVariable.getName(), integerVariable.getInitialValueExpression().evaluateAsInt());
+                }
+                for (auto const& module : program.getModules()) {
+                    for (auto const& booleanVariable : module.getBooleanVariables()) {
+                        initialState->addBooleanIdentifier(booleanVariable.getName(), booleanVariable.getInitialValueExpression().evaluateAsBool());
+                    }
+                    for (auto const& integerVariable : module.getIntegerVariables()) {
+                        initialState->addIntegerIdentifier(integerVariable.getName(), integerVariable.getInitialValueExpression().evaluateAsInt());
+                    }
+                }
+        
+                std::pair<bool, uint_fast64_t> addIndexPair = getOrAddStateIndex(initialState, stateInformation);
+                stateInformation.initialStateIndices.push_back(addIndexPair.second);
                 stateQueue.push(stateInformation.stateToIndexMap[initialState]);
                 
                 // Now explore the current state until there is no more reachable state.
@@ -505,8 +581,8 @@ namespace storm {
                                     
                                     // Now add all rewards that match this choice.
                                     for (auto const& transitionReward : transitionRewards) {
-                                        if (transitionReward.getActionName() == "" && transitionReward.getStatePredicate()->getValueAsBool(stateInformation.reachableStates.at(currentState))) {
-                                            stateToRewardMap[stateProbabilityPair.first] += ValueType(transitionReward.getRewardValue()->getValueAsDouble(stateInformation.reachableStates.at(currentState)));
+                                        if (transitionReward.getActionName() == "" && transitionReward.getStatePredicateExpression().evaluateAsBool(stateInformation.reachableStates.at(currentState))) {
+                                            stateToRewardMap[stateProbabilityPair.first] += ValueType(transitionReward.getRewardValueExpression().evaluateAsDouble(stateInformation.reachableStates.at(currentState)));
                                         }
                                     }
                                 }
@@ -518,8 +594,8 @@ namespace storm {
                                 
                                     // Now add all rewards that match this choice.
                                     for (auto const& transitionReward : transitionRewards) {
-                                        if (transitionReward.getActionName() == choice.getActionLabel() && transitionReward.getStatePredicate()->getValueAsBool(stateInformation.reachableStates.at(currentState))) {
-                                            stateToRewardMap[stateProbabilityPair.first] += ValueType(transitionReward.getRewardValue()->getValueAsDouble(stateInformation.reachableStates.at(currentState)));
+                                        if (transitionReward.getActionName() == choice.getActionLabel() && transitionReward.getStatePredicateExpression().evaluateAsBool(stateInformation.reachableStates.at(currentState))) {
+                                            stateToRewardMap[stateProbabilityPair.first] += ValueType(transitionReward.getRewardValueExpression().evaluateAsDouble(stateInformation.reachableStates.at(currentState)));
                                         }
                                     }
                                 }
@@ -556,8 +632,8 @@ namespace storm {
                                     
                                     // Now add all rewards that match this choice.
                                     for (auto const& transitionReward : transitionRewards) {
-                                        if (transitionReward.getActionName() == "" && transitionReward.getStatePredicate()->getValueAsBool(stateInformation.reachableStates.at(currentState))) {
-                                            stateToRewardMap[stateProbabilityPair.first] += ValueType(transitionReward.getRewardValue()->getValueAsDouble(stateInformation.reachableStates.at(currentState)));
+                                        if (transitionReward.getActionName() == "" && transitionReward.getStatePredicateExpression().evaluateAsBool(stateInformation.reachableStates.at(currentState))) {
+                                            stateToRewardMap[stateProbabilityPair.first] += ValueType(transitionReward.getRewardValueExpression().evaluateAsDouble(stateInformation.reachableStates.at(currentState)));
                                         }
                                     }
 
@@ -583,8 +659,8 @@ namespace storm {
                                     
                                     // Now add all rewards that match this choice.
                                     for (auto const& transitionReward : transitionRewards) {
-                                        if (transitionReward.getActionName() == choice.getActionLabel() && transitionReward.getStatePredicate()->getValueAsBool(stateInformation.reachableStates.at(currentState))) {
-                                            stateToRewardMap[stateProbabilityPair.first] += ValueType(transitionReward.getRewardValue()->getValueAsDouble(stateInformation.reachableStates.at(currentState)));
+                                        if (transitionReward.getActionName() == choice.getActionLabel() && transitionReward.getStatePredicateExpression().evaluateAsBool(stateInformation.reachableStates.at(currentState))) {
+                                            stateToRewardMap[stateProbabilityPair.first] += ValueType(transitionReward.getRewardValueExpression().evaluateAsDouble(stateInformation.reachableStates.at(currentState)));
                                         }
                                     }
 
@@ -616,20 +692,28 @@ namespace storm {
              * is considered.
              * @return A structure containing the components of the resulting model.
              */
-            static ModelComponents buildModelComponents(storm::ir::Program const& program, std::string const& rewardModelName) {
+            static ModelComponents buildModelComponents(storm::prism::Program const& program, std::string const& rewardModelName) {
                 ModelComponents modelComponents;
                 
-                VariableInformation variableInformation = createVariableInformation(program);
+                VariableInformation variableInformation;
+                for (auto const& integerVariable : program.getGlobalIntegerVariables()) {
+                    variableInformation.variableToBoundsMap[integerVariable.getName()] = std::make_pair(integerVariable.getLowerBoundExpression().evaluateAsInt(), integerVariable.getUpperBoundExpression().evaluateAsInt());
+                }
+                for (auto const& module : program.getModules()) {
+                    for (auto const& integerVariable : module.getIntegerVariables()) {
+                        variableInformation.variableToBoundsMap[integerVariable.getName()] = std::make_pair(integerVariable.getLowerBoundExpression().evaluateAsInt(), integerVariable.getUpperBoundExpression().evaluateAsInt());
+                    }
+                }
                 
                 // Create the structure for storing the reachable state space.
                 StateInformation stateInformation;
                 
                 // Get the selected reward model or create an empty one if none is selected.
-                storm::ir::RewardModel const& rewardModel = rewardModelName != "" ? program.getRewardModel(rewardModelName) : storm::ir::RewardModel();
+                storm::prism::RewardModel const& rewardModel = rewardModelName != "" ? program.getRewardModel(rewardModelName) : storm::prism::RewardModel();
                 
                 // Determine whether we have to combine different choices to one or whether this model can have more than
                 // one choice per state.
-                bool deterministicModel = program.getModelType() == storm::ir::Program::DTMC || program.getModelType() == storm::ir::Program::CTMC;
+                bool deterministicModel = program.getModelType() == storm::prism::Program::ModelType::DTMC || program.getModelType() == storm::prism::Program::ModelType::CTMC;
 
                 // Build the transition and reward matrices.
                 storm::storage::SparseMatrixBuilder<ValueType> transitionMatrixBuilder(0, 0, 0, !deterministicModel, 0);
@@ -662,30 +746,29 @@ namespace storm {
              * @param stateInformation Information about the state space of the program.
              * @return The state labeling of the given program.
              */
-            static storm::models::AtomicPropositionsLabeling buildStateLabeling(storm::ir::Program const& program, VariableInformation const& variableInformation, StateInformation const& stateInformation) {
-                std::map<std::string, std::unique_ptr<storm::ir::expressions::BaseExpression>> const& labels = program.getLabels();
+            static storm::models::AtomicPropositionsLabeling buildStateLabeling(storm::prism::Program const& program, VariableInformation const& variableInformation, StateInformation const& stateInformation) {
+                std::vector<storm::prism::Label> const& labels = program.getLabels();
                 
                 storm::models::AtomicPropositionsLabeling result(stateInformation.reachableStates.size(), labels.size() + 1);
                 
                 // Initialize labeling.
-                for (auto const& labelExpressionPair : labels) {
-                    result.addAtomicProposition(labelExpressionPair.first);
+                for (auto const& label : labels) {
+                    result.addAtomicProposition(label.getName());
                 }
                 for (uint_fast64_t index = 0; index < stateInformation.reachableStates.size(); index++) {
-                    for (auto const& labelExpressionPair: labels) {
+                    for (auto const& label : labels) {
                         // Add label to state, if the corresponding expression is true.
-                        if (labelExpressionPair.second->getValueAsBool(stateInformation.reachableStates[index])) {
-                            result.addAtomicPropositionToState(labelExpressionPair.first, index);
+                        if (label.getStatePredicateExpression().evaluateAsBool(stateInformation.reachableStates[index])) {
+                            result.addAtomicPropositionToState(label.getName(), index);
                         }
                     }
                 }
                 
                 // Also label the initial state with the special label "init".
                 result.addAtomicProposition("init");
-                StateType* initialState = getInitialState(program, variableInformation);
-                uint_fast64_t initialIndex = stateInformation.stateToIndexMap.at(initialState);
-                result.addAtomicPropositionToState("init", initialIndex);
-                delete initialState;
+                for (auto const& index : stateInformation.initialStateIndices) {
+                    result.addAtomicPropositionToState("init", index);
+                }
                 
                 return result;
             }
@@ -697,14 +780,14 @@ namespace storm {
              * @param stateInformation Information about the state space.
              * @return A vector containing the state rewards for the state space.
              */
-            static std::vector<ValueType> buildStateRewards(std::vector<storm::ir::StateReward> const& rewards, StateInformation const& stateInformation) {
+            static std::vector<ValueType> buildStateRewards(std::vector<storm::prism::StateReward> const& rewards, StateInformation const& stateInformation) {
                 std::vector<ValueType> result(stateInformation.reachableStates.size());
                 for (uint_fast64_t index = 0; index < stateInformation.reachableStates.size(); index++) {
                     result[index] = ValueType(0);
                     for (auto const& reward : rewards) {
                         // Add this reward to the state if the state is included in the state reward.
-                        if (reward.getStatePredicate()->getValueAsBool(stateInformation.reachableStates[index])) {
-                            result[index] += ValueType(reward.getRewardValue()->getValueAsDouble(stateInformation.reachableStates[index]));
+                        if (reward.getStatePredicateExpression().evaluateAsBool(stateInformation.reachableStates[index])) {
+                            result[index] += ValueType(reward.getRewardValueExpression().evaluateAsDouble(stateInformation.reachableStates[index]));
                         }
                     }
                 }
diff --git a/src/counterexamples/MILPMinimalLabelSetGenerator.h b/src/counterexamples/MILPMinimalLabelSetGenerator.h
index de9c6b057..197db76ab 100644
--- a/src/counterexamples/MILPMinimalLabelSetGenerator.h
+++ b/src/counterexamples/MILPMinimalLabelSetGenerator.h
@@ -11,7 +11,7 @@
 #include <chrono>
 
 #include "src/models/Mdp.h"
-#include "src/ir/Program.h"
+#include "src/storage/prism/Program.h"
 #include "src/exceptions/NotImplementedException.h"
 #include "src/exceptions/InvalidArgumentException.h"
 #include "src/exceptions/InvalidStateException.h"
@@ -92,8 +92,7 @@ namespace storm {
                 StateInformation result;
                 result.relevantStates = storm::utility::graph::performProbGreater0E(labeledMdp.getTransitionMatrix(), labeledMdp.getNondeterministicChoiceIndices(), labeledMdp.getBackwardTransitions(), phiStates, psiStates);
                 result.relevantStates &= ~psiStates;
-                result.problematicStates = storm::utility::graph::performProbGreater0E(labeledMdp.getTransitionMatrix(), labeledMdp.getNondeterministicChoiceIndices(), labeledMdp.getBackwardTransitions(), phiStates, psiStates);
-                result.problematicStates.complement();
+                result.problematicStates = storm::utility::graph::performProb0E(labeledMdp.getTransitionMatrix(), labeledMdp.getNondeterministicChoiceIndices(), labeledMdp.getBackwardTransitions(), phiStates, psiStates);
                 result.problematicStates &= result.relevantStates;
                 LOG4CPLUS_DEBUG(logger, "Found " << phiStates.getNumberOfSetBits() << " filter states.");
                 LOG4CPLUS_DEBUG(logger, "Found " << psiStates.getNumberOfSetBits() << " target states.");
@@ -1001,7 +1000,7 @@ namespace storm {
              * @param formulaPtr A pointer to a safety formula. The outermost operator must be a probabilistic bound operator with a strict upper bound. The nested
              * formula can be either an unbounded until formula or an eventually formula.
              */
-            static void computeCounterexample(storm::ir::Program const& program, storm::models::Mdp<T> const& labeledMdp, storm::property::prctl::AbstractPrctlFormula<double> const* formulaPtr) {
+            static void computeCounterexample(storm::prism::Program const& program, storm::models::Mdp<T> const& labeledMdp, storm::property::prctl::AbstractPrctlFormula<double> const* formulaPtr) {
                 std::cout << std::endl << "Generating minimal label counterexample for formula " << formulaPtr->toString() << std::endl;
                 // First, we need to check whether the current formula is an Until-Formula.
                 storm::property::prctl::ProbabilisticBoundOperator<double> const* probBoundFormula = dynamic_cast<storm::property::prctl::ProbabilisticBoundOperator<double> const*>(formulaPtr);
@@ -1046,9 +1045,8 @@ namespace storm {
                 std::cout << std::endl << "Computed minimal label set of size " << usedLabelSet.size() << " in " << std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count() << "ms." << std::endl;
 
                 std::cout << "Resulting program:" << std::endl;
-                storm::ir::Program restrictedProgram(program);
-                restrictedProgram.restrictCommands(usedLabelSet);
-                std::cout << restrictedProgram.toString() << std::endl;
+                storm::prism::Program restrictedProgram = program.restrictCommands(usedLabelSet);
+                std::cout << restrictedProgram << std::endl;
                 std::cout << std::endl << "-------------------------------------------" << std::endl;
                 
                 // FIXME: Return the DTMC that results from applying the max scheduler in the MDP restricted to the computed label set.
diff --git a/src/counterexamples/SMTMinimalCommandSetGenerator.h b/src/counterexamples/SMTMinimalCommandSetGenerator.h
index f95bc2806..da5d4a7ad 100644
--- a/src/counterexamples/SMTMinimalCommandSetGenerator.h
+++ b/src/counterexamples/SMTMinimalCommandSetGenerator.h
@@ -25,7 +25,7 @@
 #include "src/solver/GmmxxNondeterministicLinearEquationSolver.h"
 
 #include "src/utility/counterexamples.h"
-#include "src/utility/IRUtility.h"
+#include "src/utility/PrismUtility.h"
 
 namespace storm {
     namespace counterexamples {
diff --git a/src/exceptions/ExceptionMacros.h b/src/exceptions/ExceptionMacros.h
new file mode 100644
index 000000000..09e7058ec
--- /dev/null
+++ b/src/exceptions/ExceptionMacros.h
@@ -0,0 +1,31 @@
+#ifndef STORM_EXCEPTIONS_EXCEPTIONMACROS_H_
+#define STORM_EXCEPTIONS_EXCEPTIONMACROS_H_
+
+#include <cassert>
+
+#include "log4cplus/logger.h"
+#include "log4cplus/loggingmacros.h"
+
+extern log4cplus::Logger logger;
+
+#ifndef NDEBUG
+#define LOG_ASSERT(cond, message)               \
+{                                               \
+    if (!(cond)) {                              \
+        LOG4CPLUS_ERROR(logger, message);       \
+        assert(cond);                           \
+    }                                           \
+} while (false)
+#else
+#define LOG_ASSERT(cond, message) /* empty */
+#endif
+
+#define LOG_THROW(cond, exception, message)     \
+{                                               \
+if (!(cond)) {                              \
+LOG4CPLUS_ERROR(logger, message);       \
+throw exception() << message;           \
+}                                           \
+} while (false)
+
+#endif /* STORM_EXCEPTIONS_EXCEPTIONMACROS_H_ */
\ No newline at end of file
diff --git a/src/exceptions/InvalidOperationException.h b/src/exceptions/InvalidOperationException.h
new file mode 100644
index 000000000..728f7ff1c
--- /dev/null
+++ b/src/exceptions/InvalidOperationException.h
@@ -0,0 +1,17 @@
+#ifndef STORM_EXCEPTIONS_INVALIDOPERATIONEXCEPTION_H_
+#define STORM_EXCEPTIONS_INVALIDOPERATIONEXCEPTION_H_
+
+#include "src/exceptions/BaseException.h"
+
+namespace storm {
+    
+    namespace exceptions {
+        
+        /*!
+         * @brief This exception is thrown when an operation is invalid in this context
+         */
+        STORM_EXCEPTION_DEFINE_NEW(InvalidOperationException)
+        
+    } // namespace exceptions
+} // namespace storm
+#endif // STORM_EXCEPTIONS_INVALIDOPERATIONEXCEPTION_H_
diff --git a/src/exceptions/InvalidTypeException.h b/src/exceptions/InvalidTypeException.h
new file mode 100644
index 000000000..de2874218
--- /dev/null
+++ b/src/exceptions/InvalidTypeException.h
@@ -0,0 +1,18 @@
+#ifndef STORM_EXCEPTIONS_INVALIDTYPEEXCEPTION_H_
+#define STORM_EXCEPTIONS_INVALIDTYPEEXCEPTION_H_
+
+#include "src/exceptions/BaseException.h"
+
+namespace storm {
+    
+    namespace exceptions {
+        
+        /*!
+         * @brief This exception is thrown when a type is invalid in this context
+         */
+        STORM_EXCEPTION_DEFINE_NEW(InvalidTypeException)
+        
+    } // namespace exceptions
+    
+} // namespace storm
+#endif // STORM_EXCEPTIONS_INVALIDTYPEEXCEPTION_H_
diff --git a/src/ir/Assignment.cpp b/src/ir/Assignment.cpp
deleted file mode 100644
index a50847afb..000000000
--- a/src/ir/Assignment.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Assignment.cpp
- *
- *  Created on: 12.01.2013
- *      Author: Christian Dehnert
- */
-
-#include <sstream>
-
-#include "Assignment.h"
-#include "src/parser/prismparser/VariableState.h"
-
-namespace storm {
-    namespace ir {
-        
-        Assignment::Assignment() : variableName(), expression() {
-            // Nothing to do here.
-        }
-        
-        Assignment::Assignment(std::string const& variableName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& expression)
-        : variableName(variableName), expression(std::move(expression)) {
-            // Nothing to do here.
-        }
-        
-        Assignment::Assignment(Assignment const& oldAssignment, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState)
-        : variableName(oldAssignment.variableName), expression(oldAssignment.expression->clone(renaming, variableState)) {
-            auto renamingPair = renaming.find(oldAssignment.variableName);
-            if (renamingPair != renaming.end()) {
-                this->variableName = renamingPair->second;
-            }
-        }
-        
-        Assignment::Assignment(Assignment const& otherAssignment) : variableName(otherAssignment.variableName), expression() {
-            if (otherAssignment.expression != nullptr) {
-                expression = otherAssignment.expression->clone();
-            }
-        }
-        
-        Assignment& Assignment::operator=(Assignment const& otherAssignment) {
-            if (this != &otherAssignment) {
-                this->variableName = otherAssignment.variableName;
-                this->expression = otherAssignment.expression->clone();
-            }
-            
-            return *this;
-        }
-        
-        std::string const& Assignment::getVariableName() const {
-            return variableName;
-        }
-        
-        std::unique_ptr<storm::ir::expressions::BaseExpression> const& Assignment::getExpression() const {
-            return expression;
-        }
-        
-        std::string Assignment::toString() const {
-            std::stringstream result;
-            result << "(" << variableName << "' = " << expression->toString() << ")";
-            return result.str();
-        }
-        
-    } // namespace ir
-} // namespace storm
diff --git a/src/ir/Assignment.h b/src/ir/Assignment.h
deleted file mode 100644
index 12d96a413..000000000
--- a/src/ir/Assignment.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Assignment.h
- *
- *  Created on: 06.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_ASSIGNMENT_H_
-#define STORM_IR_ASSIGNMENT_H_
-
-#include <memory>
-
-#include "expressions/BaseExpression.h"
-
-namespace storm {
-    
-    namespace parser {
-        namespace prism {
-            class VariableState;
-        } // namespace prismparser
-    } // namespace parser
-    
-    namespace ir {
-        
-        /*!
-         * A class representing the assignment of an expression to a variable.
-         */
-        class Assignment {
-        public:
-            /*!
-             * Default constructor. Creates an empty assignment.
-             */
-            Assignment();
-            
-            /*!
-             * Constructs an assignment using the given variable name and expression.
-             *
-             * @param variableName The variable that this assignment targets.
-             * @param expression The expression to assign to the variable.
-             */
-            Assignment(std::string const& variableName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& expression);
-            
-            /*!
-             * Creates a copy of the given assignment and performs the provided renaming.
-             *
-             * @param oldAssignment The assignment to copy.
-             * @param renaming A mapping from names that are to be renamed to the names they are to be
-             * replaced with.
-             * @param variableState An object knowing about the variables in the system.
-             */
-            Assignment(Assignment const& oldAssignment, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState);
-            
-            /*!
-             * Performs a deep-copy of the given assignment.
-             *
-             * @param otherAssignment The assignment to copy.
-             */
-            Assignment(Assignment const& otherAssignment);
-            
-            /*!
-             * Performs a deep-copy of the given assignment and assigns it to the current one.
-             *
-             * @param otherAssignment The assignment to assign.
-             */
-            Assignment& operator=(Assignment const& otherAssignment);
-            
-            /*!
-             * Retrieves the name of the variable that this assignment targets.
-             *
-             * @return The name of the variable that this assignment targets.
-             */
-            std::string const& getVariableName() const;
-            
-            /*!
-             * Retrieves the expression that is assigned to the variable.
-             *
-             * @return The expression that is assigned to the variable.
-             */
-            std::unique_ptr<storm::ir::expressions::BaseExpression> const& getExpression() const;
-            
-            /*!
-             * Retrieves a string representation of this assignment.
-             * @returns a string representation of this assignment.
-             */
-            std::string toString() const;
-            
-        private:
-            // The name of the variable that this assignment targets.
-            std::string variableName;
-            
-            // The expression that is assigned to the variable.
-            std::unique_ptr<storm::ir::expressions::BaseExpression> expression;
-        };
-        
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_ASSIGNMENT_H_ */
diff --git a/src/ir/BooleanVariable.cpp b/src/ir/BooleanVariable.cpp
deleted file mode 100644
index 843655be9..000000000
--- a/src/ir/BooleanVariable.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * BooleanVariable.cpp
- *
- *  Created on: 12.01.2013
- *      Author: Christian Dehnert
- */
-
-#include <sstream>
-
-#include "BooleanVariable.h"
-#include "src/parser/prismparser/VariableState.h"
-
-namespace storm {
-    namespace ir {
-        
-        BooleanVariable::BooleanVariable() : Variable() {
-            // Nothing to do here.
-        }
-        
-        BooleanVariable::BooleanVariable(uint_fast64_t localIndex, uint_fast64_t globalIndex, std::string const& variableName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& initialValue)
-		: Variable(localIndex, globalIndex, variableName, std::move(initialValue)) {
-            // Nothing to do here.
-        }
-        
-        BooleanVariable::BooleanVariable(BooleanVariable const& oldVariable, std::string const& newName, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState)
-        : Variable(oldVariable, newName, newGlobalIndex, renaming, variableState) {
-            // Nothing to do here.
-        }
-        
-        BooleanVariable& BooleanVariable::operator=(BooleanVariable const& otherVariable) {
-            if (this != &otherVariable) {
-                Variable::operator=(otherVariable);
-            }
-            
-            return *this;
-        }
-        
-        std::string BooleanVariable::toString() const {
-            std::stringstream result;
-            result << this->getName() << ": bool";
-            if (this->getInitialValue() != nullptr) {
-                result << " init " << this->getInitialValue()->toString();
-            }
-            result << ";";
-            return result.str();
-        }
-        
-    } // namespace ir
-} // namespace storm
diff --git a/src/ir/BooleanVariable.h b/src/ir/BooleanVariable.h
deleted file mode 100644
index b968d7890..000000000
--- a/src/ir/BooleanVariable.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * BooleanVariable.h
- *
- *  Created on: 08.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_BOOLEANVARIABLE_H_
-#define STORM_IR_BOOLEANVARIABLE_H_
-
-#include <memory>
-#include <map>
-
-#include "src/ir/Variable.h"
-
-namespace storm {
-    
-    namespace parser {
-        namespace prism {
-            class VariableState;
-        } // namespace prismparser
-    } // namespace parser
-    
-    namespace ir {
-        
-        /*!
-         * A class representing a boolean variable.
-         */
-        class BooleanVariable : public Variable {
-        public:
-            /*!
-             * Default constructor. Creates a boolean variable without a name.
-             */
-            BooleanVariable();
-            
-            /*!
-             * Creates a boolean variable with the given name and the given initial value.
-             *
-             * @param localIndex A module-local unique index for the variable.
-             * @param globalIndex A globally unique index for the variable.
-             * @param variableName The name of the variable.
-             * @param initialValue The expression that defines the initial value of the variable.
-             */
-            BooleanVariable(uint_fast64_t localIndex, uint_fast64_t globalIndex, std::string const& variableName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& initialValue = nullptr);
-            
-            /*!
-             * Creates a copy of the given boolean variable and performs the provided renaming.
-             *
-             * @param oldVariable The variable to copy.
-             * @param newName New name of this variable.
-             * @param newGlobalIndex The new global index of the variable.
-             * @param renaming A mapping from names that are to be renamed to the names they are to be
-             * replaced with.
-             * @param variableState An object knowing about the variables in the system.
-             */
-            BooleanVariable(BooleanVariable const& oldVariable, std::string const& newName, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState);
-            
-            BooleanVariable& operator=(BooleanVariable const& otherVariable);
-            
-            /*!
-             * Retrieves a string representation of this variable.
-             * @returns a string representation of this variable.
-             */
-            std::string toString() const;
-        };
-        
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_BOOLEANVARIABLE_H_ */
diff --git a/src/ir/Command.cpp b/src/ir/Command.cpp
deleted file mode 100644
index dbb1eef64..000000000
--- a/src/ir/Command.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Command.cpp
- *
- *  Created on: 12.01.2013
- *      Author: Christian Dehnert
- */
-
-#include <sstream>
-#include <iostream>
-
-#include "Command.h"
-#include "src/parser/prismparser/VariableState.h"
-
-namespace storm {
-    namespace ir {
-        
-        Command::Command() : actionName(), guardExpression(), updates(), globalIndex() {
-            // Nothing to do here.
-        }
-        
-        Command::Command(uint_fast64_t globalIndex, std::string const& actionName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& guardExpression, std::vector<storm::ir::Update> const& updates)
-        : actionName(actionName), guardExpression(std::move(guardExpression)), updates(updates), globalIndex(globalIndex) {
-            // Nothing to do here.
-        }
-        
-        Command::Command(Command const& oldCommand, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState& variableState)
-        : actionName(oldCommand.getActionName()), guardExpression(oldCommand.guardExpression->clone(renaming, variableState)), globalIndex(newGlobalIndex) {
-            auto renamingPair = renaming.find(this->actionName);
-            if (renamingPair != renaming.end()) {
-                this->actionName = renamingPair->second;
-            }
-            this->updates.reserve(oldCommand.getNumberOfUpdates());
-            for (Update const& update : oldCommand.updates) {
-                this->updates.emplace_back(update, variableState.getNextGlobalUpdateIndex(), renaming, variableState);
-                variableState.nextGlobalUpdateIndex++;
-            }
-        }
-        
-        Command::Command(Command const& otherCommand) : actionName(otherCommand.actionName), guardExpression(), updates(otherCommand.updates), globalIndex(otherCommand.globalIndex) {
-            if (otherCommand.guardExpression != nullptr) {
-                guardExpression = otherCommand.guardExpression->clone();
-            }
-        }
-        
-        Command& Command::operator=(Command const& otherCommand) {
-            if (this != &otherCommand) {
-                this->actionName = otherCommand.actionName;
-                this->guardExpression = otherCommand.guardExpression->clone();
-                this->updates = otherCommand.updates;
-                this->globalIndex = otherCommand.globalIndex;
-            }
-            
-            return *this;
-        }
-        
-        std::string const& Command::getActionName() const {
-            return this->actionName;
-        }
-        
-        std::unique_ptr<storm::ir::expressions::BaseExpression> const& Command::getGuard() const {
-            return guardExpression;
-        }
-        
-        uint_fast64_t Command::getNumberOfUpdates() const {
-            return this->updates.size();
-        }
-        
-        storm::ir::Update const& Command::getUpdate(uint_fast64_t index) const {
-            return this->updates[index];
-        }
-        
-        std::vector<storm::ir::Update> const& Command::getUpdates() const {
-            return this->updates;
-        }
-        
-        uint_fast64_t Command::getGlobalIndex() const {
-            return this->globalIndex;
-        }
-        
-        std::string Command::toString() const {
-            std::stringstream result;
-            result << "[" << actionName << "] " << guardExpression->toString() << " -> ";
-            for (uint_fast64_t i = 0; i < updates.size(); ++i) {
-                result << updates[i].toString();
-                if (i < updates.size() - 1) {
-                    result << " + ";
-                }
-            }
-            result << ";";
-            return result.str();
-        }
-        
-    } // namespace ir
-} // namespace storm
diff --git a/src/ir/Command.h b/src/ir/Command.h
deleted file mode 100644
index 04efe8b86..000000000
--- a/src/ir/Command.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Command.h
- *
- *  Created on: 06.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_COMMAND_H_
-#define STORM_IR_COMMAND_H_
-
-#include <vector>
-#include <string>
-#include <map>
-
-#include "expressions/BaseExpression.h"
-#include "Update.h"
-
-namespace storm {
-    
-    namespace parser {
-        namespace prism {
-            class VariableState;
-        } // namespace prismparser
-    } // namespace parser
-    
-    namespace ir {
-        
-        /*!
-         * A class representing a command.
-         */
-        class Command {
-        public:
-            /*!
-             * Default constructor. Creates a a command without name, guard and updates.
-             */
-            Command();
-            
-            /*!
-             * Creates a command with the given name, guard and updates.
-             *
-             * @param globalIndex The global index of the command.
-             * @param actionName The action name of the command.
-             * @param guardExpression the expression that defines the guard of the command.
-             * @param updates A list of updates that is associated with this command.
-             */
-            Command(uint_fast64_t globalIndex, std::string const& actionName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& guardExpression, std::vector<storm::ir::Update> const& updates);
-            
-            /*!
-             * Creates a copy of the given command and performs the provided renaming.
-             *
-             * @param oldCommand The command to copy.
-             * @param newGlobalIndex The global index of the copy of the command.
-             * @param renaming A mapping from names that are to be renamed to the names they are to be
-             * replaced with.
-             * @param variableState An object knowing about the variables in the system.
-             */
-            Command(Command const& oldCommand, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState& variableState);
-            
-            /*!
-             * Performs a deep-copy of the given command.
-             *
-             * @param otherCommand The command to copy.
-             */
-            Command(Command const& otherCommand);
-            
-            Command& operator=(Command const& otherCommand);
-            
-            /*!
-             * Retrieves the action name of this command.
-             *
-             * @return The action name of this command.
-             */
-            std::string const& getActionName() const;
-            
-            /*!
-             * Retrieves a reference to the guard of the command.
-             *
-             * @return A reference to the guard of the command.
-             */
-            std::unique_ptr<storm::ir::expressions::BaseExpression> const& getGuard() const;
-            
-            /*!
-             * Retrieves the number of updates associated with this command.
-             *
-             * @return The number of updates associated with this command.
-             */
-            uint_fast64_t getNumberOfUpdates() const;
-            
-            /*!
-             * Retrieves a reference to the update with the given index.
-             *
-             * @return A reference to the update with the given index.
-             */
-            storm::ir::Update const& getUpdate(uint_fast64_t index) const;
-            
-            /*!
-             * Retrieves a vector of all updates associated with this command.
-             *
-             * @return A vector of updates associated with this command.
-             */
-            std::vector<storm::ir::Update> const& getUpdates() const;
-            
-            /*!
-             * Retrieves the global index of the command, that is, a unique index over all modules.
-             *
-             * @return The global index of the command.
-             */
-            uint_fast64_t getGlobalIndex() const;
-            
-            /*!
-             * Retrieves a string representation of this command.
-             *
-             * @return A string representation of this command.
-             */
-            std::string toString() const;
-            
-        private:
-            // The name of the command.
-            std::string actionName;
-            
-            // The expression that defines the guard of the command.
-            std::unique_ptr<storm::ir::expressions::BaseExpression> guardExpression;
-            
-            // The list of updates of the command.
-            std::vector<storm::ir::Update> updates;
-            
-            // The global index of the command.
-            uint_fast64_t globalIndex;
-        };
-        
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_COMMAND_H_ */
diff --git a/src/ir/IR.h b/src/ir/IR.h
deleted file mode 100644
index 80a794002..000000000
--- a/src/ir/IR.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * IR.h
- *
- *  Created on: 06.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_IR_H_
-#define STORM_IR_IR_H_
-
-// Bundle all headers to make it easy to include them.
-#include "expressions/Expressions.h"
-#include "Assignment.h"
-#include "Update.h"
-#include "Command.h"
-#include "Variable.h"
-#include "BooleanVariable.h"
-#include "IntegerVariable.h"
-#include "Module.h"
-#include "StateReward.h"
-#include "TransitionReward.h"
-#include "RewardModel.h"
-#include "Program.h"
-
-#endif /* STORM_IR_IR_H_ */
diff --git a/src/ir/IntegerVariable.cpp b/src/ir/IntegerVariable.cpp
deleted file mode 100644
index b98b30d07..000000000
--- a/src/ir/IntegerVariable.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * IntegerVariable.cpp
- *
- *  Created on: 12.01.2013
- *      Author: Christian Dehnert
- */
-
-#include <sstream>
-#include <iostream>
-
-#include "IntegerVariable.h"
-#include "src/parser/prismparser/VariableState.h"
-
-namespace storm {
-    namespace ir {
-        
-        IntegerVariable::IntegerVariable() : lowerBound(), upperBound() {
-            // Nothing to do here.
-        }
-        
-        IntegerVariable::IntegerVariable(uint_fast64_t localIndex, uint_fast64_t globalIndex, std::string const& variableName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& lowerBound, std::unique_ptr<storm::ir::expressions::BaseExpression>&& upperBound, std::unique_ptr<storm::ir::expressions::BaseExpression>&& initialValue)
-        : Variable(localIndex, globalIndex, variableName, std::move(initialValue)), lowerBound(std::move(lowerBound)), upperBound(std::move(upperBound)) {
-            // Nothing to do here.
-        }
-        
-        IntegerVariable::IntegerVariable(IntegerVariable const& oldVariable, std::string const& newName, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState)
-        : Variable(oldVariable, newName, newGlobalIndex, renaming, variableState), lowerBound(oldVariable.lowerBound->clone(renaming, variableState)), upperBound(oldVariable.upperBound->clone(renaming, variableState)) {
-            // Nothing to do here.
-        }
-        
-        IntegerVariable::IntegerVariable(IntegerVariable const& otherVariable) : Variable(otherVariable.getLocalIndex(), otherVariable.getGlobalIndex(), otherVariable.getName(), nullptr), lowerBound(), upperBound() {
-            if (otherVariable.getInitialValue() != nullptr) {
-                setInitialValue(otherVariable.getInitialValue()->clone());
-            }
-            if (otherVariable.lowerBound != nullptr) {
-                lowerBound = otherVariable.lowerBound->clone();
-            }
-            if (otherVariable.upperBound != nullptr) {
-                upperBound = otherVariable.upperBound->clone();
-            }
-        }
-        
-        IntegerVariable& IntegerVariable::operator=(IntegerVariable const& otherVariable) {
-            if (this != &otherVariable) {
-                Variable::operator=(otherVariable);
-                this->lowerBound = otherVariable.lowerBound->clone();
-                this->upperBound = otherVariable.upperBound->clone();
-            }
-            
-            return *this;
-        }
-        
-        std::unique_ptr<storm::ir::expressions::BaseExpression> const& IntegerVariable::getLowerBound() const {
-            return this->lowerBound;
-        }
-        
-        std::unique_ptr<storm::ir::expressions::BaseExpression> const& IntegerVariable::getUpperBound() const {
-            return this->upperBound;
-        }
-        
-        std::string IntegerVariable::toString() const {
-            std::stringstream result;
-            result << this->getName() << ": [" << lowerBound->toString() << ".." << upperBound->toString() << "]";
-            if (this->getInitialValue() != nullptr) {
-                result << " init " + this->getInitialValue()->toString();
-            }
-            result << ";";
-            return result.str();
-        }
-        
-    } // namespace ir
-} // namespace storm
diff --git a/src/ir/IntegerVariable.h b/src/ir/IntegerVariable.h
deleted file mode 100644
index 930e1d0b8..000000000
--- a/src/ir/IntegerVariable.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * IntegerVariable.h
- *
- *  Created on: 08.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_INTEGERVARIABLE_H_
-#define STORM_IR_INTEGERVARIABLE_H_
-
-#include <memory>
-
-#include "src/ir/Variable.h"
-#include "expressions/BaseExpression.h"
-
-namespace storm {
-    
-    namespace parser {
-        namespace prism {
-            class VariableState;
-        } // namespace prismparser
-    } // namespace parser
-    
-    namespace ir {
-        
-        /*!
-         * A class representing an integer variable.
-         */
-        class IntegerVariable : public Variable {
-        public:
-            /*!
-             * Default constructor. Creates an integer variable without a name and lower and upper bounds.
-             */
-            IntegerVariable();
-            
-            /*!
-             * Creates a boolean variable with the given name and the given initial value.
-             *
-             * @param localIndex A module-local unique index for the variable.
-             * @param globalIndex A globally unique index for the variable.
-             * @param variableName The name of the variable.
-             * @param lowerBound the lower bound of the domain of the variable.
-             * @param upperBound the upper bound of the domain of the variable.
-             * @param initialValue the expression that defines the initial value of the variable.
-             */
-            IntegerVariable(uint_fast64_t localIndex, uint_fast64_t globalIndex, std::string const& variableName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& lowerBound, std::unique_ptr<storm::ir::expressions::BaseExpression>&& upperBound, std::unique_ptr<storm::ir::expressions::BaseExpression>&& initialValue = nullptr);
-            
-            /*!
-             * Creates a copy of the given integer variable and performs the provided renaming.
-             *
-             * @param oldVariable The variable to copy.
-             * @param newName New name of this variable.
-             * @param newGlobalIndex The new global index of the variable.
-             * @param renaming A mapping from names that are to be renamed to the names they are to be
-             * replaced with.
-             * @param variableState An object knowing about the variables in the system.
-             */
-            IntegerVariable(IntegerVariable const& oldVariable, std::string const& newName, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState);
-            
-            /*!
-             * Performs a deep-copy of the given variable.
-             *
-             * @param otherVariable The variable to copy.
-             */
-            IntegerVariable(IntegerVariable const& otherVariable);
-            
-            IntegerVariable& operator=(IntegerVariable const& otherVariable);
-            
-            /*!
-             * Retrieves the lower bound for this integer variable.
-             * @returns the lower bound for this integer variable.
-             */
-            std::unique_ptr<storm::ir::expressions::BaseExpression> const& getLowerBound() const;
-            
-            /*!
-             * Retrieves the upper bound for this integer variable.
-             * @returns the upper bound for this integer variable.
-             */
-            std::unique_ptr<storm::ir::expressions::BaseExpression> const& getUpperBound() const;
-            
-            /*!
-             * Retrieves a string representation of this variable.
-             * @returns a string representation of this variable.
-             */
-            std::string toString() const;
-            
-        private:
-            // The lower bound of the domain of the variable.
-            std::unique_ptr<storm::ir::expressions::BaseExpression> lowerBound;
-            
-            // The upper bound of the domain of the variable.
-            std::unique_ptr<storm::ir::expressions::BaseExpression> upperBound;
-        };
-        
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_INTEGERVARIABLE_H_ */
diff --git a/src/ir/Module.cpp b/src/ir/Module.cpp
deleted file mode 100644
index 5724db8df..000000000
--- a/src/ir/Module.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Module.cpp
- *
- *  Created on: 12.01.2013
- *      Author: Christian Dehnert
- */
-
-#include <sstream>
-#include <iostream>
-#include "utility/OsDetection.h"
-
-#include "Module.h"
-#include "src/parser/prismparser/VariableState.h"
-#include "src/exceptions/OutOfRangeException.h"
-#include "src/exceptions/InvalidArgumentException.h"
-
-#include "log4cplus/logger.h"
-#include "log4cplus/loggingmacros.h"
-extern log4cplus::Logger logger;
-
-namespace storm {
-    namespace ir {
-        
-        Module::Module() : moduleName(), booleanVariables(), integerVariables(), booleanVariableToLocalIndexMap(),
-        integerVariableToLocalIndexMap(), commands(), actions(), actionsToCommandIndexMap() {
-            // Nothing to do here.
-        }
-        
-        Module::Module(std::string const& moduleName,
-                       std::vector<storm::ir::BooleanVariable> const& booleanVariables,
-                       std::vector<storm::ir::IntegerVariable> const& integerVariables,
-                       std::map<std::string, uint_fast64_t> const& booleanVariableToLocalIndexMap,
-                       std::map<std::string, uint_fast64_t> const& integerVariableToLocalIndexMap,
-                       std::vector<storm::ir::Command> const& commands)
-        : moduleName(moduleName), booleanVariables(booleanVariables), integerVariables(integerVariables),
-        booleanVariableToLocalIndexMap(booleanVariableToLocalIndexMap),
-        integerVariableToLocalIndexMap(integerVariableToLocalIndexMap), commands(commands), actions(), actionsToCommandIndexMap() {
-            // Initialize the internal mappings for fast information retrieval.
-            this->collectActions();
-        }
-        
-        Module::Module(Module const& oldModule, std::string const& newModuleName, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState& variableState)
-        : moduleName(newModuleName), booleanVariableToLocalIndexMap(oldModule.booleanVariableToLocalIndexMap), integerVariableToLocalIndexMap(oldModule.integerVariableToLocalIndexMap) {
-            LOG4CPLUS_TRACE(logger, "Start renaming " << oldModule.getName() << " to " << moduleName << ".");
-            
-            // Iterate over boolean variables and rename them. If a variable was not renamed, this is an error and an exception
-            // is thrown.
-            this->booleanVariables.reserve(oldModule.getNumberOfBooleanVariables());
-            for (BooleanVariable const& booleanVariable : oldModule.booleanVariables) {
-                auto renamingPair = renaming.find(booleanVariable.getName());
-                if (renamingPair == renaming.end()) {
-                    LOG4CPLUS_ERROR(logger, "Boolean variable " << moduleName << "." << booleanVariable.getName() << " was not renamed.");
-                    throw storm::exceptions::InvalidArgumentException() << "Boolean variable " << moduleName << "." << booleanVariable.getName() << " was not renamed.";
-                } else {
-                    uint_fast64_t globalIndex = variableState.addBooleanVariable(renamingPair->second);
-                    this->booleanVariables.emplace_back(booleanVariable, renamingPair->second, globalIndex, renaming, variableState);
-                }
-            }
-            // Now do the same for the integer variables.
-            this->integerVariables.reserve(oldModule.getNumberOfIntegerVariables());
-            for (IntegerVariable const& integerVariable : oldModule.integerVariables) {
-                auto renamingPair = renaming.find(integerVariable.getName());
-                if (renamingPair == renaming.end()) {
-                    LOG4CPLUS_ERROR(logger, "Integer variable " << moduleName << "." << integerVariable.getName() << " was not renamed.");
-                    throw storm::exceptions::InvalidArgumentException() << "Integer variable " << moduleName << "." << integerVariable.getName() << " was not renamed.";
-                } else {
-                    uint_fast64_t globalIndex = variableState.addIntegerVariable(renamingPair->second);
-                    this->integerVariables.emplace_back(integerVariable, renamingPair->second, globalIndex, renaming, variableState);
-                }
-            }
-            
-            // Now we are ready to clone all commands and rename them if requested.
-            this->commands.reserve(oldModule.getNumberOfCommands());
-            for (Command const& command : oldModule.commands) {
-                this->commands.emplace_back(command, variableState.getNextGlobalCommandIndex(), renaming, variableState);
-                variableState.nextGlobalCommandIndex++;
-            }
-            this->collectActions();
-            
-            LOG4CPLUS_TRACE(logger, "Finished renaming...");
-        }
-        
-        uint_fast64_t Module::getNumberOfBooleanVariables() const {
-            return this->booleanVariables.size();
-        }
-        
-        storm::ir::BooleanVariable const& Module::getBooleanVariable(uint_fast64_t index) const {
-            return this->booleanVariables[index];
-        }
-        
-        storm::ir::BooleanVariable const& Module::getBooleanVariable(std::string const& variableName) const {
-            uint_fast64_t index = this->getBooleanVariableIndex(variableName);
-            return this->booleanVariables[index];
-        }
-        
-        uint_fast64_t Module::getNumberOfIntegerVariables() const {
-            return this->integerVariables.size();
-        }
-        
-        storm::ir::IntegerVariable const& Module::getIntegerVariable(uint_fast64_t index) const {
-            return this->integerVariables[index];
-        }
-        
-        storm::ir::IntegerVariable const& Module::getIntegerVariable(std::string const& variableName) const {
-            uint_fast64_t index = this->getIntegerVariableIndex(variableName);
-            return this->integerVariables[index];
-        }
-        
-        uint_fast64_t Module::getNumberOfCommands() const {
-            return this->commands.size();
-        }
-        
-        uint_fast64_t Module::getBooleanVariableIndex(std::string const& variableName) const {
-            auto it = booleanVariableToLocalIndexMap.find(variableName);
-            if (it != booleanVariableToLocalIndexMap.end()) {
-                return it->second;
-            }
-            LOG4CPLUS_ERROR(logger, "Cannot retrieve index of unknown boolean variable " << variableName << ".");
-            throw storm::exceptions::InvalidArgumentException() << "Cannot retrieve index of unknown boolean variable " << variableName << ".";
-        }
-        
-        uint_fast64_t Module::getIntegerVariableIndex(std::string const& variableName) const {
-            auto it = integerVariableToLocalIndexMap.find(variableName);
-            if (it != integerVariableToLocalIndexMap.end()) {
-                return it->second;
-            }
-            LOG4CPLUS_ERROR(logger, "Cannot retrieve index of unknown integer variable " << variableName << ".");
-            throw storm::exceptions::InvalidArgumentException() << "Cannot retrieve index of unknown integer variable " << variableName << ".";
-        }
-        
-        storm::ir::Command const& Module::getCommand(uint_fast64_t index) const {
-            return this->commands[index];
-        }
-        
-        std::string const& Module::getName() const {
-            return this->moduleName;
-        }
-        
-        std::string Module::toString() const {
-            std::stringstream result;
-            result << "module " << moduleName << std::endl;
-            for (auto variable : booleanVariables) {
-                result << "\t" << variable.toString() << std::endl;
-            }
-            for (auto variable : integerVariables) {
-                result << "\t" << variable.toString() << std::endl;
-            }
-            for (auto command : commands) {
-                result << "\t" << command.toString() << std::endl;
-            }
-            result << "endmodule" << std::endl;
-            return result.str();
-        }
-        
-        std::set<std::string> const& Module::getActions() const {
-            return this->actions;
-        }
-        
-        bool Module::hasAction(std::string const& action) const {
-            auto const& actionEntry = this->actions.find(action);
-            if (actionEntry != this->actions.end()) {
-                return true;
-            }
-            return false;
-        }
-        
-        std::set<uint_fast64_t> const& Module::getCommandsByAction(std::string const& action) const {
-            auto actionsCommandSetPair = this->actionsToCommandIndexMap.find(action);
-            if (actionsCommandSetPair != this->actionsToCommandIndexMap.end()) {
-                return actionsCommandSetPair->second;
-            }
-            
-            LOG4CPLUS_ERROR(logger, "Action name '" << action << "' does not exist in module.");
-            throw storm::exceptions::OutOfRangeException() << "Action name '" << action << "' does not exist in module.";
-        }
-        
-        void Module::collectActions() {
-            // Clear the current mapping.
-            this->actionsToCommandIndexMap.clear();
-            
-            // Add the mapping for all commands.
-            for (unsigned int id = 0; id < this->commands.size(); id++) {
-                std::string const& action = this->commands[id].getActionName();
-                if (action != "") {
-                    if (this->actionsToCommandIndexMap.find(action) == this->actionsToCommandIndexMap.end()) {
-                        this->actionsToCommandIndexMap.emplace(action, std::set<uint_fast64_t>());
-                    }
-                    this->actionsToCommandIndexMap[action].insert(id);
-                    this->actions.insert(action);
-                }
-            }
-            
-            // For all actions that are "in the module", but for which no command exists, we add the mapping to an empty
-            // set of commands.
-            for (auto const& action : this->actions) {
-                if (this->actionsToCommandIndexMap.find(action) == this->actionsToCommandIndexMap.end()) {
-                    this->actionsToCommandIndexMap[action] = std::set<uint_fast64_t>();
-                }
-            }
-        }
-        
-        void Module::restrictCommands(boost::container::flat_set<uint_fast64_t> const& indexSet) {
-            // First construct the new vector of commands.
-            std::vector<storm::ir::Command> newCommands;
-            for (auto const& command : commands) {
-                if (indexSet.find(command.getGlobalIndex()) != indexSet.end()) {
-                    newCommands.push_back(std::move(command));
-                }
-            }
-            commands = std::move(newCommands);
-            
-            // Then refresh the internal mappings.
-            this->collectActions();
-        }
-        
-    } // namespace ir
-} // namespace storm
diff --git a/src/ir/Module.h b/src/ir/Module.h
deleted file mode 100644
index d9570c652..000000000
--- a/src/ir/Module.h
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Module.h
- *
- *  Created on: 04.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_MODULE_H_
-#define STORM_IR_MODULE_H_
-
-#include "utility/OsDetection.h"
-#include <boost/container/flat_set.hpp>
-
-#ifdef LINUX
-#include <boost/container/map.hpp>
-#endif
-#include <map>
-
-#include <set>
-#include <string>
-#include <vector>
-#include <memory>
-
-#include "BooleanVariable.h"
-#include "IntegerVariable.h"
-#include "Command.h"
-#include "expressions/VariableExpression.h"
-
-namespace storm {
-    
-    namespace parser {
-        namespace prism {
-            class VariableState;
-        } // namespace prismparser
-    } // namespace parser
-    
-    namespace ir {
-        
-        /*!
-         * A class representing a module.
-         */
-        class Module {
-        public:
-            /*!
-             * Default constructor. Creates an empty module.
-             */
-            Module();
-            
-            /*!
-             * Creates a module with the given name, variables and commands.
-             *
-             * @param moduleName The name of the module.
-             * @param booleanVariables The boolean variables defined by the module.
-             * @param integerVariables The integer variables defined by the module.
-             * @param booleanVariableToLocalIndexMap A mapping of boolean variables to local (i.e. module-local) indices.
-             * @param integerVariableToLocalIndexMap A mapping of integer variables to local (i.e. module-local) indices.
-             * @param commands The commands of the module.
-             */
-            Module(std::string const& moduleName, std::vector<storm::ir::BooleanVariable> const& booleanVariables,
-                   std::vector<storm::ir::IntegerVariable> const& integerVariables,
-                   std::map<std::string, uint_fast64_t> const& booleanVariableToLocalIndexMap,
-                   std::map<std::string, uint_fast64_t> const& integerVariableToLocalIndexMap,
-                   std::vector<storm::ir::Command> const& commands);
-            
-            /*!
-             * Special copy constructor, implementing the module renaming functionality.
-             * This will create a new module having all identifiers renamed according to the given map.
-             *
-             * @param oldModule The module to be copied.
-             * @param newModuleName The name of the new module.
-             * @param renaming A mapping of identifiers to the new identifiers they are to be replaced with.
-             * @param variableState An object knowing about the variables in the system.
-             */
-            Module(Module const& oldModule, std::string const& newModuleName, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState& variableState);
-            
-            /*!
-             * Retrieves the number of boolean variables in the module.
-             *
-             * @return the number of boolean variables in the module.
-             */
-            uint_fast64_t getNumberOfBooleanVariables() const;
-            
-            /*!
-             * Retrieves a reference to the boolean variable with the given index.
-             *
-             * @return A reference to the boolean variable with the given index.
-             */
-            storm::ir::BooleanVariable const& getBooleanVariable(uint_fast64_t index) const;
-            
-            /*!
-             * Retrieves a reference to the boolean variable with the given name.
-             *
-             * @return A reference to the boolean variable with the given name.
-             */
-            storm::ir::BooleanVariable const& getBooleanVariable(std::string const& variableName) const;
-            
-            /*!
-             * Retrieves the number of integer variables in the module.
-             *
-             * @return The number of integer variables in the module.
-             */
-            uint_fast64_t getNumberOfIntegerVariables() const;
-            
-            /*!
-             * Retrieves a reference to the integer variable with the given index.
-             *
-             * @return A reference to the integer variable with the given index.
-             */
-            storm::ir::IntegerVariable const& getIntegerVariable(uint_fast64_t index) const;
-            
-            /*!
-             * Retrieves a reference to the boolean variable with the given name.
-             *
-             * @return A reference to the boolean variable with the given name.
-             */
-            storm::ir::IntegerVariable const& getIntegerVariable(std::string const& variableName) const;
-            
-            /*!
-             * Retrieves the number of commands of this module.
-             *
-             * @return the number of commands of this module.
-             */
-            uint_fast64_t getNumberOfCommands() const;
-            
-            /*!
-             * Retrieves the index of the boolean variable with the given name.
-             *
-             * @param variableName The name of the boolean variable whose index to retrieve.
-             * @return The index of the boolean variable with the given name.
-             */
-            uint_fast64_t getBooleanVariableIndex(std::string const& variableName) const;
-            
-            /*!
-             * Retrieves the index of the integer variable with the given name.
-             *
-             * @param variableName The name of the integer variable whose index to retrieve.
-             * @return The index of the integer variable with the given name.
-             */
-            uint_fast64_t getIntegerVariableIndex(std::string const& variableName) const;
-            
-            /*!
-             * Retrieves a reference to the command with the given index.
-             *
-             * @return A reference to the command with the given index.
-             */
-            storm::ir::Command const& getCommand(uint_fast64_t index) const;
-            
-            /*!
-             * Retrieves the name of the module.
-             *
-             * @return The name of the module.
-             */
-            std::string const& getName() const;
-            
-            /*!
-             * Retrieves a string representation of this module.
-             *
-             * @return a string representation of this module.
-             */
-            std::string toString() const;
-            
-            /*!
-             * Retrieves the set of actions present in this module.
-             *
-             * @return the set of actions present in this module.
-             */
-            std::set<std::string> const& getActions() const;
-            
-            /*!
-             * Retrieves whether or not this module contains a command labeled with the given action.
-             *
-             * @param action The action name to look for in this module.
-             * @return True if the module has at least one command labeled with the given action.
-             */
-            bool hasAction(std::string const& action) const;
-            
-            /*!
-             * Retrieves the indices of all commands within this module that are labelled by the given action.
-             *
-             * @param action The action with which the commands have to be labelled.
-             * @return A set of indices of commands that are labelled with the given action.
-             */
-            std::set<uint_fast64_t> const& getCommandsByAction(std::string const& action) const;
-            
-            /*!
-             * Deletes all commands with indices not in the given set from the module.
-             *
-             * @param indexSet The set of indices for which to keep the commands.
-             */
-            void restrictCommands(boost::container::flat_set<uint_fast64_t> const& indexSet);
-            
-        private:
-            /*!
-             * Computes the locally maintained mappings for fast data retrieval.
-             */
-            void collectActions();
-            
-            // The name of the module.
-            std::string moduleName;
-            
-            // A list of boolean variables.
-            std::vector<storm::ir::BooleanVariable> booleanVariables;
-            
-            // A list of integer variables.
-            std::vector<storm::ir::IntegerVariable> integerVariables;
-            
-            // A map of boolean variable names to their index.
-            std::map<std::string, uint_fast64_t> booleanVariableToLocalIndexMap;
-            
-            // A map of integer variable names to their index.
-            std::map<std::string, uint_fast64_t> integerVariableToLocalIndexMap;
-            
-            // The commands associated with the module.
-            std::vector<storm::ir::Command> commands;
-            
-            // The set of actions present in this module.
-            std::set<std::string> actions;
-            
-            // A map of actions to the set of commands labeled with this action.
-            std::map<std::string, std::set<uint_fast64_t>> actionsToCommandIndexMap;
-        };
-        
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_MODULE_H_ */
diff --git a/src/ir/Program.cpp b/src/ir/Program.cpp
deleted file mode 100644
index 33c75c44f..000000000
--- a/src/ir/Program.cpp
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Program.cpp
- *
- *  Created on: 12.01.2013
- *      Author: Christian Dehnert
- */
-
-#include <sstream>
-#include <iostream>
-
-#include "Program.h"
-#include "exceptions/InvalidArgumentException.h"
-#include "src/exceptions/OutOfRangeException.h"
-
-#include "log4cplus/logger.h"
-#include "log4cplus/loggingmacros.h"
-extern log4cplus::Logger logger;
-
-namespace storm {
-    namespace ir {
-        
-        Program::Program() : modelType(UNDEFINED), booleanUndefinedConstantExpressions(), integerUndefinedConstantExpressions(), doubleUndefinedConstantExpressions(), modules(), rewards(), actions(), actionsToModuleIndexMap(), variableToModuleIndexMap() {
-            // Nothing to do here.
-        }
-        
-        Program::Program(ModelType modelType,
-                         std::map<std::string, std::unique_ptr<storm::ir::expressions::BooleanConstantExpression>> const& booleanUndefinedConstantExpressions,
-                         std::map<std::string, std::unique_ptr<storm::ir::expressions::IntegerConstantExpression>> const& integerUndefinedConstantExpressions,
-                         std::map<std::string, std::unique_ptr<storm::ir::expressions::DoubleConstantExpression>> const& doubleUndefinedConstantExpressions,
-                         std::vector<BooleanVariable> const& globalBooleanVariables,
-                         std::vector<IntegerVariable> const& globalIntegerVariables,
-                         std::map<std::string, uint_fast64_t> const& globalBooleanVariableToIndexMap,
-                         std::map<std::string, uint_fast64_t> const& globalIntegerVariableToIndexMap,
-                         std::vector<storm::ir::Module> const& modules,
-                         std::map<std::string, storm::ir::RewardModel> const& rewards,
-                         std::map<std::string, std::unique_ptr<storm::ir::expressions::BaseExpression>> const& labels)
-        : modelType(modelType), globalBooleanVariables(globalBooleanVariables), globalIntegerVariables(globalIntegerVariables),
-        globalBooleanVariableToIndexMap(globalBooleanVariableToIndexMap), globalIntegerVariableToIndexMap(globalIntegerVariableToIndexMap),
-        modules(modules), rewards(rewards), actionsToModuleIndexMap(), variableToModuleIndexMap() {
-            
-            // Perform a deep-copy of the maps.
-            for (auto const& booleanUndefinedConstant : booleanUndefinedConstantExpressions) {
-                this->booleanUndefinedConstantExpressions[booleanUndefinedConstant.first] = std::unique_ptr<storm::ir::expressions::BooleanConstantExpression>(new storm::ir::expressions::BooleanConstantExpression(*booleanUndefinedConstant.second));
-            }
-            for (auto const& integerUndefinedConstant : integerUndefinedConstantExpressions) {
-                this->integerUndefinedConstantExpressions[integerUndefinedConstant.first] = std::unique_ptr<storm::ir::expressions::IntegerConstantExpression>(new storm::ir::expressions::IntegerConstantExpression(*integerUndefinedConstant.second));
-            }
-            for (auto const& doubleUndefinedConstant : doubleUndefinedConstantExpressions) {
-                this->doubleUndefinedConstantExpressions[doubleUndefinedConstant.first] = std::unique_ptr<storm::ir::expressions::DoubleConstantExpression>(new storm::ir::expressions::DoubleConstantExpression(*doubleUndefinedConstant.second));
-            }
-            for (auto const& label : labels) {
-                this->labels[label.first] = label.second->clone();
-            }
-            
-            // Now build the mapping from action names to module indices so that the lookup can later be performed quickly.
-            for (unsigned int moduleIndex = 0; moduleIndex < this->modules.size(); moduleIndex++) {
-                Module const& module = this->modules[moduleIndex];
-                
-                for (auto const& action : module.getActions()) {
-                    if (this->actionsToModuleIndexMap.count(action) == 0) {
-                        this->actionsToModuleIndexMap[action] = std::set<uint_fast64_t>();
-                    }
-                    this->actionsToModuleIndexMap[action].insert(moduleIndex);
-                    this->actions.insert(action);
-                }
-                
-                // Put in the appropriate entries for the mapping from variable names to module index.
-                for (uint_fast64_t booleanVariableIndex = 0; booleanVariableIndex < module.getNumberOfBooleanVariables(); ++booleanVariableIndex) {
-                    this->variableToModuleIndexMap[module.getBooleanVariable(booleanVariableIndex).getName()] = moduleIndex;
-                }
-                for (uint_fast64_t integerVariableIndex = 0; integerVariableIndex < module.getNumberOfIntegerVariables(); ++integerVariableIndex) {
-                    this->variableToModuleIndexMap[module.getIntegerVariable(integerVariableIndex).getName()] = moduleIndex;
-                }
-            }
-        }
-        
-        Program::Program(Program const& otherProgram) : modelType(otherProgram.modelType), globalBooleanVariables(otherProgram.globalBooleanVariables),
-        globalIntegerVariables(otherProgram.globalIntegerVariables), globalBooleanVariableToIndexMap(otherProgram.globalBooleanVariableToIndexMap),
-        globalIntegerVariableToIndexMap(otherProgram.globalIntegerVariableToIndexMap), modules(otherProgram.modules), rewards(otherProgram.rewards),
-        actions(otherProgram.actions), actionsToModuleIndexMap(), variableToModuleIndexMap() {
-            // Perform deep-copy of the maps.
-            for (auto const& booleanUndefinedConstant : otherProgram.booleanUndefinedConstantExpressions) {
-                this->booleanUndefinedConstantExpressions[booleanUndefinedConstant.first] = std::unique_ptr<storm::ir::expressions::BooleanConstantExpression>(new storm::ir::expressions::BooleanConstantExpression(*booleanUndefinedConstant.second));
-            }
-            for (auto const& integerUndefinedConstant : otherProgram.integerUndefinedConstantExpressions) {
-                this->integerUndefinedConstantExpressions[integerUndefinedConstant.first] = std::unique_ptr<storm::ir::expressions::IntegerConstantExpression>(new storm::ir::expressions::IntegerConstantExpression(*integerUndefinedConstant.second));
-            }
-            for (auto const& doubleUndefinedConstant : otherProgram.doubleUndefinedConstantExpressions) {
-                this->doubleUndefinedConstantExpressions[doubleUndefinedConstant.first] = std::unique_ptr<storm::ir::expressions::DoubleConstantExpression>(new storm::ir::expressions::DoubleConstantExpression(*doubleUndefinedConstant.second));
-            }
-            for (auto const& label : otherProgram.labels) {
-                this->labels[label.first] = label.second->clone();
-            }
-        }
-        
-        Program& Program::operator=(Program const& otherProgram) {
-            if (this != &otherProgram) {
-                this->modelType = otherProgram.modelType;
-                this->globalBooleanVariables = otherProgram.globalBooleanVariables;
-                this->globalIntegerVariables = otherProgram.globalIntegerVariables;
-                this->globalBooleanVariableToIndexMap = otherProgram.globalBooleanVariableToIndexMap;
-                this->globalIntegerVariableToIndexMap = otherProgram.globalIntegerVariableToIndexMap;
-                this->modules = otherProgram.modules;
-                this->rewards = otherProgram.rewards;
-                this->actions = otherProgram.actions;
-                this->actionsToModuleIndexMap = otherProgram.actionsToModuleIndexMap;
-                this->variableToModuleIndexMap = otherProgram.variableToModuleIndexMap;
-                
-                // Perform deep-copy of the maps.
-                for (auto const& booleanUndefinedConstant : otherProgram.booleanUndefinedConstantExpressions) {
-                    this->booleanUndefinedConstantExpressions[booleanUndefinedConstant.first] = std::unique_ptr<storm::ir::expressions::BooleanConstantExpression>(new storm::ir::expressions::BooleanConstantExpression(*booleanUndefinedConstant.second));
-                }
-                for (auto const& integerUndefinedConstant : otherProgram.integerUndefinedConstantExpressions) {
-                    this->integerUndefinedConstantExpressions[integerUndefinedConstant.first] = std::unique_ptr<storm::ir::expressions::IntegerConstantExpression>(new storm::ir::expressions::IntegerConstantExpression(*integerUndefinedConstant.second));
-                }
-                for (auto const& doubleUndefinedConstant : otherProgram.doubleUndefinedConstantExpressions) {
-                    this->doubleUndefinedConstantExpressions[doubleUndefinedConstant.first] = std::unique_ptr<storm::ir::expressions::DoubleConstantExpression>(new storm::ir::expressions::DoubleConstantExpression(*doubleUndefinedConstant.second));
-                }
-                for (auto const& label : otherProgram.labels) {
-                    this->labels[label.first] = label.second->clone();
-                }
-            }
-            
-            return *this;
-        }
-        
-        Program::ModelType Program::getModelType() const {
-            return modelType;
-        }
-        
-        std::string Program::toString() const {
-            std::stringstream result;
-            switch (modelType) {
-                case UNDEFINED: result << "undefined"; break;
-                case DTMC: result << "dtmc"; break;
-                case CTMC: result << "ctmc"; break;
-                case MDP: result << "mdp"; break;
-                case CTMDP: result << "ctmdp"; break;
-            }
-            result << std::endl;
-            
-            for (auto const& element : booleanUndefinedConstantExpressions) {
-                result << "const bool " << element.second->toString() << ";" << std::endl;
-            }
-            for (auto const& element : integerUndefinedConstantExpressions) {
-                result << "const int " << element.second->toString() << ";" << std::endl;
-            }
-            for (auto const& element : doubleUndefinedConstantExpressions) {
-                result << "const double " << element.second->toString() << ";" << std::endl;
-            }
-            result << std::endl;
-            
-            for (auto const& element : globalBooleanVariables) {
-                result << "global " << element.toString() << std::endl;
-            }
-            for (auto const& element : globalIntegerVariables) {
-                result << "global " << element.toString() << std::endl;
-            }
-            result << std::endl;
-            
-            for (auto const& module : modules) {
-                result << module.toString() << std::endl;
-            }
-            
-            for (auto const& rewardModel : rewards) {
-                result << rewardModel.second.toString() << std::endl;
-            }
-            
-            for (auto const& label : labels) {
-                result << "label \"" << label.first << "\" = " << label.second->toString() <<";" << std::endl;
-            }
-            
-            return result.str();
-        }
-        
-        storm::ir::BooleanVariable const& Program::getGlobalBooleanVariable(uint_fast64_t index) const {
-            return this->globalBooleanVariables[index];
-        }
-        
-        storm::ir::IntegerVariable const& Program::getGlobalIntegerVariable(uint_fast64_t index) const {
-            return this->globalIntegerVariables[index];
-        }
-        
-        uint_fast64_t Program::getNumberOfModules() const {
-            return this->modules.size();
-        }
-        
-        storm::ir::Module const& Program::getModule(uint_fast64_t index) const {
-            return this->modules[index];
-        }
-        
-        std::set<std::string> const& Program::getActions() const {
-            return this->actions;
-        }
-        
-        std::set<uint_fast64_t> const& Program::getModulesByAction(std::string const& action) const {
-            auto actionModuleSetPair = this->actionsToModuleIndexMap.find(action);
-            if (actionModuleSetPair == this->actionsToModuleIndexMap.end()) {
-                LOG4CPLUS_ERROR(logger, "Action name '" << action << "' does not exist.");
-                throw storm::exceptions::OutOfRangeException() << "Action name '" << action << "' does not exist.";
-            }
-            return actionModuleSetPair->second;
-        }
-        
-        uint_fast64_t Program::getModuleIndexForVariable(std::string const& variableName) const {
-            auto variableNameToModuleIndexPair = this->variableToModuleIndexMap.find(variableName);
-            if (variableNameToModuleIndexPair != this->variableToModuleIndexMap.end()) {
-                return variableNameToModuleIndexPair->second;
-            }
-            throw storm::exceptions::OutOfRangeException() << "Variable '" << variableName << "' does not exist.";
-        }
-        
-        uint_fast64_t Program::getNumberOfGlobalBooleanVariables() const {
-            return this->globalBooleanVariables.size();
-        }
-        
-        uint_fast64_t Program::getNumberOfGlobalIntegerVariables() const {
-            return this->globalIntegerVariables.size();
-        }
-        
-        storm::ir::RewardModel const& Program::getRewardModel(std::string const& name) const {
-            auto nameRewardModelPair = this->rewards.find(name);
-            if (nameRewardModelPair == this->rewards.end()) {
-                LOG4CPLUS_ERROR(logger, "Reward model '" << name << "' does not exist.");
-                throw storm::exceptions::OutOfRangeException() << "Reward model '" << name << "' does not exist.";
-            }
-            return nameRewardModelPair->second;
-        }
-        
-        std::map<std::string, std::unique_ptr<storm::ir::expressions::BaseExpression>> const& Program::getLabels() const {
-            return this->labels;
-        }
-        
-        bool Program::hasUndefinedBooleanConstant(std::string const& constantName) const {
-            return this->booleanUndefinedConstantExpressions.find(constantName) != this->booleanUndefinedConstantExpressions.end();
-        }
-        
-        std::unique_ptr<storm::ir::expressions::BooleanConstantExpression> const& Program::getUndefinedBooleanConstantExpression(std::string const& constantName) const {
-            auto constantExpressionPair = this->booleanUndefinedConstantExpressions.find(constantName);
-            if (constantExpressionPair != this->booleanUndefinedConstantExpressions.end()) {
-                return constantExpressionPair->second;
-            } else {
-                throw storm::exceptions::InvalidArgumentException() << "Unknown undefined boolean constant " << constantName << ".";
-            }
-        }
-        
-        bool Program::hasUndefinedIntegerConstant(std::string const& constantName) const {
-            return this->integerUndefinedConstantExpressions.find(constantName) != this->integerUndefinedConstantExpressions.end();
-        }
-        
-        std::unique_ptr<storm::ir::expressions::IntegerConstantExpression> const& Program::getUndefinedIntegerConstantExpression(std::string const& constantName) const {
-            auto constantExpressionPair = this->integerUndefinedConstantExpressions.find(constantName);
-            if (constantExpressionPair != this->integerUndefinedConstantExpressions.end()) {
-                return constantExpressionPair->second;
-            } else {
-                throw storm::exceptions::InvalidArgumentException() << "Unknown undefined integer constant " << constantName << ".";
-            }
-        }
-        
-        bool Program::hasUndefinedDoubleConstant(std::string const& constantName) const {
-            return this->doubleUndefinedConstantExpressions.find(constantName) != this->doubleUndefinedConstantExpressions.end();
-        }
-        
-        std::unique_ptr<storm::ir::expressions::DoubleConstantExpression> const& Program::getUndefinedDoubleConstantExpression(std::string const& constantName) const {
-            auto constantExpressionPair = this->doubleUndefinedConstantExpressions.find(constantName);
-            if (constantExpressionPair != this->doubleUndefinedConstantExpressions.end()) {
-                return constantExpressionPair->second;
-            } else {
-                throw storm::exceptions::InvalidArgumentException() << "Unknown undefined double constant " << constantName << ".";
-            }
-        }
-        
-        std::map<std::string, std::unique_ptr<storm::ir::expressions::BooleanConstantExpression>> const& Program::getBooleanUndefinedConstantExpressionsMap() const {
-            return this->booleanUndefinedConstantExpressions;
-        }
-        
-        std::map<std::string, std::unique_ptr<storm::ir::expressions::IntegerConstantExpression>> const& Program::getIntegerUndefinedConstantExpressionsMap() const {
-            return this->integerUndefinedConstantExpressions;
-        }
-        
-        std::map<std::string, std::unique_ptr<storm::ir::expressions::DoubleConstantExpression>> const& Program::getDoubleUndefinedConstantExpressionsMap() const {
-            return this->doubleUndefinedConstantExpressions;
-        }
-        
-        uint_fast64_t Program::getGlobalIndexOfBooleanVariable(std::string const& variableName) const {
-            return this->globalBooleanVariableToIndexMap.at(variableName);
-        }
-        
-        uint_fast64_t Program::getGlobalIndexOfIntegerVariable(std::string const& variableName) const {
-            return this->globalIntegerVariableToIndexMap.at(variableName);
-        }
-        
-        void Program::restrictCommands(boost::container::flat_set<uint_fast64_t> const& indexSet) {
-            for (auto& module : modules) {
-                module.restrictCommands(indexSet);
-            }
-        }
-        
-    } // namespace ir
-} // namepsace storm
diff --git a/src/ir/Program.h b/src/ir/Program.h
deleted file mode 100644
index 8ce96bc87..000000000
--- a/src/ir/Program.h
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Program.h
- *
- *  Created on: 04.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_PROGRAM_H_
-#define STORM_IR_PROGRAM_H_
-
-#include <map>
-#include <vector>
-#include <memory>
-#include <set>
-#include <boost/container/flat_set.hpp>
-
-#include "expressions/BaseExpression.h"
-#include "expressions/BooleanConstantExpression.h"
-#include "expressions/IntegerConstantExpression.h"
-#include "expressions/DoubleConstantExpression.h"
-#include "Module.h"
-#include "RewardModel.h"
-
-namespace storm {
-    namespace ir {
-        
-        /*!
-         * A class representing a program.
-         */
-        class Program {
-        public:
-            
-            /*!
-             * An enum for the different model types.
-             */
-            enum ModelType {UNDEFINED, DTMC, CTMC, MDP, CTMDP};
-            
-            /*!
-             * Default constructor. Creates an empty program.
-             */
-            Program();
-            
-            /*!
-             * Creates a program with the given model type, undefined constants, modules, rewards and labels.
-             *
-             * @param modelType The type of the model that this program gives rise to.
-             * @param booleanUndefinedConstantExpressions A map of undefined boolean constants to their
-             * expression nodes.
-             * @param integerUndefinedConstantExpressions A map of undefined integer constants to their
-             * expression nodes.
-             * @param doubleUndefinedConstantExpressions A map of undefined double constants to their
-             * expression nodes.
-             * @param globalBooleanVariables A list of global boolean variables.
-             * @param globalIntegerVariables A list of global integer variables.
-             * @param globalBooleanVariableToIndexMap A mapping from global boolean variable names to the index in the
-             * list of global boolean variables.
-             * @param globalIntegerVariableToIndexMap A mapping from global integer variable names to the index in the
-             * list of global integer variables.
-             * @param modules The modules of the program.
-             * @param rewards The reward models of the program.
-             * @param labels The labels defined for this model.
-             */
-            Program(ModelType modelType,
-                    std::map<std::string, std::unique_ptr<storm::ir::expressions::BooleanConstantExpression>> const& booleanUndefinedConstantExpressions,
-                    std::map<std::string, std::unique_ptr<storm::ir::expressions::IntegerConstantExpression>> const& integerUndefinedConstantExpressions,
-                    std::map<std::string, std::unique_ptr<storm::ir::expressions::DoubleConstantExpression>> const& doubleUndefinedConstantExpressions,
-                    std::vector<BooleanVariable> const& globalBooleanVariables,
-                    std::vector<IntegerVariable> const& globalIntegerVariables,
-                    std::map<std::string, uint_fast64_t> const& globalBooleanVariableToIndexMap,
-                    std::map<std::string, uint_fast64_t> const& globalIntegerVariableToIndexMap,
-                    std::vector<storm::ir::Module> const& modules,
-                    std::map<std::string, storm::ir::RewardModel> const& rewards,
-                    std::map<std::string, std::unique_ptr<storm::ir::expressions::BaseExpression>> const& labels);
-            
-            /*!
-             * Performs a deep-copy of the given program.
-             *
-             * @param otherProgram The program to copy.
-             */
-            Program(Program const& otherProgram);
-
-            /*!
-             * Performs a deep-copy of the given program and assigns it to the current one.
-             *
-             * @param otherProgram The program to assign.
-             */
-            Program& operator=(Program const& otherProgram);
-            
-            /*!
-             * Retrieves the number of modules in the program.
-             *
-             * @return The number of modules in the program.
-             */
-            uint_fast64_t getNumberOfModules() const;
-            
-            /*!
-             * Retrieves a reference to the module with the given index.
-             *
-             * @param index The index of the module to retrieve.
-             * @return The module with the given index.
-             */
-            storm::ir::Module const& getModule(uint_fast64_t index) const;
-            
-            /*!
-             * Retrieves the model type of the model.
-             *
-             * @return The type of the model.
-             */
-            ModelType getModelType() const;
-            
-            /*!
-             * Retrieves a string representation of this program.
-             *
-             * @return A string representation of this program.
-             */
-            std::string toString() const;
-            
-            /*!
-             * Retrieves a reference to the global boolean variable with the given index.
-             *
-             * @return A reference to the global boolean variable with the given index.
-             */
-            storm::ir::BooleanVariable const& getGlobalBooleanVariable(uint_fast64_t index) const;
-            
-            /*!
-             * Retrieves a reference to the global integer variable with the given index.
-             *
-             * @return A reference to the global integer variable with the given index.
-             */
-            storm::ir::IntegerVariable const& getGlobalIntegerVariable(uint_fast64_t index) const;
-            
-            /*!
-             * Retrieves the set of actions present in this module.
-             *
-             * @return The set of actions present in this module.
-             */
-            std::set<std::string> const& getActions() const;
-            
-            /*!
-             * Retrieves the indices of all modules within this program that contain commands that are labelled with the given
-             * action.
-             *
-             * @param action The name of the action the modules are supposed to possess.
-             * @return A set of indices of all matching modules.
-             */
-            std::set<uint_fast64_t> const& getModulesByAction(std::string const& action) const;
-            
-            /*!
-             * Retrieves the index of the module in which the given variable name was declared.
-             *
-             * @param variableName The name of the variable to search.
-             * @return The index of the module in which the given variable name was declared.
-             */
-            uint_fast64_t getModuleIndexForVariable(std::string const& variableName) const;
-            
-            /*!
-             * Retrieves the number of global boolean variables of the program.
-             *
-             * @return The number of global boolean variables of the program.
-             */
-            uint_fast64_t getNumberOfGlobalBooleanVariables() const;
-            
-            /*!
-             * Retrieves the number of global integer variables of the program.
-             *
-             * @return The number of global integer variables of the program.
-             */
-            uint_fast64_t getNumberOfGlobalIntegerVariables() const;
-            
-            /*!
-             * Retrieves the reward model with the given name.
-             *
-             * @param name The name of the reward model to return.
-             * @return The reward model with the given name.
-             */
-            storm::ir::RewardModel const& getRewardModel(std::string const& name) const;
-            
-            /*!
-             * Retrieves all labels that are defined by the probabilitic program.
-             *
-             * @return A set of labels that are defined in the program.
-             */
-            std::map<std::string, std::unique_ptr<storm::ir::expressions::BaseExpression>> const& getLabels() const;
-            
-            /*!
-             * Retrieves whether the given constant name is an undefined boolean constant of the program.
-             *
-             * @return True if the given constant name is an undefined boolean constant of the program.
-             */
-            bool hasUndefinedBooleanConstant(std::string const& constantName) const;
-            
-            /*!
-             * Retrieves the expression associated with the given undefined boolean constant.
-             *
-             * @param constantName The name of the undefined boolean constant for which to retrieve the expression.
-             * @return The expression associated with the given undefined boolean constant.
-             */
-            std::unique_ptr<storm::ir::expressions::BooleanConstantExpression> const& getUndefinedBooleanConstantExpression(std::string const& constantName) const;
-            
-            /*!
-             * Retrieves whether the given constant name is an undefined integer constant of the program.
-             *
-             * @return True if the given constant name is an undefined integer constant of the program.
-             */
-            bool hasUndefinedIntegerConstant(std::string const& constantName) const;
-            
-            /*!
-             * Retrieves the expression associated with the given undefined integer constant.
-             *
-             * @param constantName The name of the undefined integer constant for which to retrieve the expression.
-             * @return The expression associated with the given undefined integer constant.
-             */
-            std::unique_ptr<storm::ir::expressions::IntegerConstantExpression> const& getUndefinedIntegerConstantExpression(std::string const& constantName) const;
-
-            /*!
-             * Retrieves whether the given constant name is an undefined double constant of the program.
-             *
-             * @return True if the given constant name is an undefined double constant of the program.
-             */
-            bool hasUndefinedDoubleConstant(std::string const& constantName) const;
-            
-            /*!
-             * Retrieves the expression associated with the given undefined double constant.
-             *
-             * @param constantName The name of the undefined double constant for which to retrieve the expression.
-             * @return The expression associated with the given undefined double constant.
-             */
-            std::unique_ptr<storm::ir::expressions::DoubleConstantExpression> const& getUndefinedDoubleConstantExpression(std::string const& constantName) const;
-            
-            /*!
-             * Retrieves the mapping of undefined boolean constant names to their expression objects.
-             *
-             * @return The mapping of undefined boolean constant names to their expression objects.
-             */
-            std::map<std::string, std::unique_ptr<storm::ir::expressions::BooleanConstantExpression>> const& getBooleanUndefinedConstantExpressionsMap() const;
-
-            /*!
-             * Retrieves the mapping of undefined integer constant names to their expression objects.
-             *
-             * @return The mapping of undefined integer constant names to their expression objects.
-             */
-            std::map<std::string, std::unique_ptr<storm::ir::expressions::IntegerConstantExpression>> const& getIntegerUndefinedConstantExpressionsMap() const;
-
-            /*!
-             * Retrieves the mapping of undefined double constant names to their expression objects.
-             *
-             * @return The mapping of undefined double constant names to their expression objects.
-             */
-            std::map<std::string, std::unique_ptr<storm::ir::expressions::DoubleConstantExpression>> const& getDoubleUndefinedConstantExpressionsMap() const;
-            
-            /*!
-             * Retrieves the global index of the given boolean variable.
-             *
-             * @param variableName The name of the boolean variable whose index to retrieve.
-             */
-            uint_fast64_t getGlobalIndexOfBooleanVariable(std::string const& variableName) const;
-            
-            /*!
-             * Retrieves the global index of the integer boolean variable.
-             *
-             * @param variableName The name of the integer variable whose index to retrieve.
-             */
-            uint_fast64_t getGlobalIndexOfIntegerVariable(std::string const& variableName) const;
-            
-            /*!
-             * Deletes all commands with indices not in the given set from the program.
-             *
-             * @param indexSet The set of indices for which to keep the commands.
-             */
-            void restrictCommands(boost::container::flat_set<uint_fast64_t> const& indexSet);
-        private:
-            // The type of the model.
-            ModelType modelType;
-            
-            // A map of undefined boolean constants to their expression nodes.
-            std::map<std::string, std::unique_ptr<storm::ir::expressions::BooleanConstantExpression>> booleanUndefinedConstantExpressions;
-            
-            // A map of undefined integer constants to their expressions nodes.
-            std::map<std::string, std::unique_ptr<storm::ir::expressions::IntegerConstantExpression>> integerUndefinedConstantExpressions;
-            
-            // A map of undefined double constants to their expressions nodes.
-            std::map<std::string, std::unique_ptr<storm::ir::expressions::DoubleConstantExpression>> doubleUndefinedConstantExpressions;
-            
-            // A list of global boolean variables.
-            std::vector<BooleanVariable> globalBooleanVariables;
-            
-            // A list of global integer variables.
-            std::vector<IntegerVariable> globalIntegerVariables;
-            
-            // A mapping from global boolean variable names to their indices.
-            std::map<std::string, uint_fast64_t> globalBooleanVariableToIndexMap;
-            
-            // A mapping from global integer variable names to their indices.
-            std::map<std::string, uint_fast64_t> globalIntegerVariableToIndexMap;
-            
-            // The modules associated with the program.
-            std::vector<storm::ir::Module> modules;
-            
-            // The reward models associated with the program.
-            std::map<std::string, storm::ir::RewardModel> rewards;
-            
-            // The labels that are defined for this model.
-            std::map<std::string, std::unique_ptr<storm::ir::expressions::BaseExpression>> labels;
-            
-            // The set of actions present in this program.
-            std::set<std::string> actions;
-            
-            // A map of actions to the set of modules containing commands labelled with this action.
-            std::map<std::string, std::set<uint_fast64_t>> actionsToModuleIndexMap;
-            
-            // A mapping from variable names to the modules in which they were declared.
-            std::map<std::string, uint_fast64_t> variableToModuleIndexMap;
-        };
-        
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_PROGRAM_H_ */
diff --git a/src/ir/RewardModel.cpp b/src/ir/RewardModel.cpp
deleted file mode 100644
index 9d6a79ed3..000000000
--- a/src/ir/RewardModel.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * RewardModel.cpp
- *
- *  Created on: 12.01.2013
- *      Author: Christian Dehnert
- */
-
-#include <sstream>
-
-#include "RewardModel.h"
-
-namespace storm {
-    namespace ir {
-        
-        RewardModel::RewardModel() : rewardModelName(), stateRewards(), transitionRewards() {
-            // Nothing to do here.
-        }
-        
-        RewardModel::RewardModel(std::string const& rewardModelName, std::vector<storm::ir::StateReward> const& stateRewards, std::vector<storm::ir::TransitionReward> const& transitionRewards) : rewardModelName(rewardModelName), stateRewards(stateRewards), transitionRewards(transitionRewards) {
-            // Nothing to do here.
-        }
-        
-        std::string RewardModel::toString() const {
-            std::stringstream result;
-            result << "rewards \"" << rewardModelName << "\"" << std::endl;
-            for (auto const& reward : stateRewards) {
-                result << reward.toString() << std::endl;
-            }
-            for (auto const& reward : transitionRewards) {
-                result << reward.toString() << std::endl;
-            }
-            result << "endrewards" << std::endl;
-            return result.str();
-        }
-        
-        bool RewardModel::hasStateRewards() const {
-            return this->stateRewards.size() > 0;
-        }
-        
-        std::vector<storm::ir::StateReward> const& RewardModel::getStateRewards() const {
-            return this->stateRewards;
-        }
-        
-        bool RewardModel::hasTransitionRewards() const {
-            return this->transitionRewards.size() > 0;
-        }
-        
-        std::vector<storm::ir::TransitionReward> const& RewardModel::getTransitionRewards() const {
-            return this->transitionRewards;
-        }
-        
-    } // namespace ir
-} // namespace storm
diff --git a/src/ir/RewardModel.h b/src/ir/RewardModel.h
deleted file mode 100644
index 827248810..000000000
--- a/src/ir/RewardModel.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * RewardModel.h
- *
- *  Created on: 04.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_REWARDMODEL_H_
-#define STORM_IR_REWARDMODEL_H_
-
-#include <string>
-#include <vector>
-
-#include "StateReward.h"
-#include "TransitionReward.h"
-
-namespace storm {
-    namespace ir {
-        
-        /*!
-         * A class representing a reward model.
-         */
-        class RewardModel {
-        public:
-            /*!
-             * Default constructor. Creates an empty reward model.
-             */
-            RewardModel();
-            
-            /*!
-             * Creates a reward module with the given name, state and transition rewards.
-             *
-             * @param rewardModelName The name of the reward model.
-             * @param stateRewards A vector of state-based rewards.
-             * @param transitionRewards A vector of transition-based rewards.
-             */
-            RewardModel(std::string const& rewardModelName, std::vector<storm::ir::StateReward> const& stateRewards, std::vector<storm::ir::TransitionReward> const& transitionRewards);
-            
-            /*!
-             * Retrieves a string representation of this reward model.
-             *
-             * @return a string representation of this reward model.
-             */
-            std::string toString() const;
-            
-            /*!
-             * Check, if there are any state rewards.
-             *
-             * @return True, iff there are any state rewards.
-             */
-            bool hasStateRewards() const;
-            
-            /*!
-             * Retrieves a vector of state rewards associated with this reward model.
-             *
-             * @return A vector containing the state rewards associated with this reward model.
-             */
-            std::vector<storm::ir::StateReward> const& getStateRewards() const;
-            
-            /*!
-             * Check, if there are any transition rewards.
-             *
-             * @return True, iff there are any transition rewards associated with this reward model.
-             */
-            bool hasTransitionRewards() const;
-            
-            /*!
-             * Retrieves a vector of transition rewards associated with this reward model.
-             *
-             * @return A vector of transition rewards associated with this reward model.
-             */
-            std::vector<storm::ir::TransitionReward> const& getTransitionRewards() const;
-            
-        private:
-            // The name of the reward model.
-            std::string rewardModelName;
-            
-            // The state-based rewards associated with this reward model.
-            std::vector<storm::ir::StateReward> stateRewards;
-            
-            // The transition-based rewards associated with this reward model.
-            std::vector<storm::ir::TransitionReward> transitionRewards;
-        };
-        
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_REWARDMODEL_H_ */
diff --git a/src/ir/StateReward.cpp b/src/ir/StateReward.cpp
deleted file mode 100644
index ff3c815ce..000000000
--- a/src/ir/StateReward.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * StateReward.cpp
- *
- *  Created on: 12.01.2013
- *      Author: Christian Dehnert
- */
-
-#include <sstream>
-
-#include "StateReward.h"
-
-namespace storm {
-    namespace ir {
-        
-        StateReward::StateReward() : statePredicate(), rewardValue() {
-            // Nothing to do here.
-        }
-        
-        StateReward::StateReward(std::unique_ptr<storm::ir::expressions::BaseExpression>&& statePredicate, std::unique_ptr<storm::ir::expressions::BaseExpression>&& rewardValue) : statePredicate(std::move(statePredicate)), rewardValue(std::move(rewardValue)) {
-            // Nothing to do here.
-        }
-        
-        StateReward::StateReward(StateReward const& otherReward) {
-            if (otherReward.statePredicate != nullptr) {
-                statePredicate = otherReward.statePredicate->clone();
-            }
-            if (otherReward.rewardValue != nullptr) {
-                rewardValue = otherReward.rewardValue->clone();
-            }
-        }
-        
-        StateReward& StateReward::operator=(StateReward const& otherReward) {
-            if (this != & otherReward) {
-                if (otherReward.statePredicate != nullptr) {
-                    this->statePredicate = otherReward.statePredicate->clone();
-                }
-                if (otherReward.rewardValue != nullptr) {
-                    this->rewardValue = otherReward.rewardValue->clone();
-                }
-            }
-            
-            return *this;
-        }
-        
-        std::string StateReward::toString() const {
-            std::stringstream result;
-            result << "\t" << statePredicate->toString() << ": " << rewardValue->toString() << ";";
-            return result.str();
-        }
-        
-        std::unique_ptr<storm::ir::expressions::BaseExpression> const& StateReward::getStatePredicate() const {
-            return this->statePredicate;
-        }
-        
-        std::unique_ptr<storm::ir::expressions::BaseExpression> const& StateReward::getRewardValue() const {
-            return this->rewardValue;
-        }
-        
-    } // namespace ir
-} // namespace storm
diff --git a/src/ir/StateReward.h b/src/ir/StateReward.h
deleted file mode 100644
index 117544d6d..000000000
--- a/src/ir/StateReward.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * StateReward.h
- *
- *  Created on: Jan 10, 2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_STATEREWARD_H_
-#define STORM_IR_STATEREWARD_H_
-
-#include <memory>
-
-#include "expressions/BaseExpression.h"
-
-namespace storm {
-    namespace ir {
-        
-        /*!
-         * A class representing a state reward.
-         */
-        class StateReward {
-        public:
-            /*!
-             * Default constructor. Creates an empty state reward.
-             */
-            StateReward();
-            
-            /*!
-             * Creates a state reward for the states satisfying the given expression with the value given
-             * by a second expression.
-             *
-             * @param statePredicate The predicate that states earning this state-based reward need to
-             * satisfy.
-             * @param rewardValue An expression specifying the values of the rewards to attach to the
-             * states.
-             */
-            StateReward(std::unique_ptr<storm::ir::expressions::BaseExpression>&& statePredicate, std::unique_ptr<storm::ir::expressions::BaseExpression>&& rewardValue);
-            
-            /*!
-             * Performs a deep-copy of the given reward.
-             *
-             * @param otherReward The reward to copy.
-             */
-            StateReward(StateReward const& otherReward);
-
-            /*!
-             * Performs a deep-copy of the given reward and assigns it to the current one.
-             *
-             * @param otherReward The reward to assign.
-             */
-            StateReward& operator=(StateReward const& otherReward);
-            
-            /*!
-             * Retrieves a string representation of this state reward.
-             *
-             * @return A string representation of this state reward.
-             */
-            std::string toString() const;
-            
-            /*!
-             * Retrieves the state predicate that is associated with this state reward.
-             *
-             * @return The state predicate that is associated with this state reward.
-             */
-            std::unique_ptr<storm::ir::expressions::BaseExpression> const& getStatePredicate() const;
-            
-            /*!
-             * Retrieves the reward value associated with this state reward.
-             *
-             * @return The reward value associated with this state reward.
-             */
-            std::unique_ptr<storm::ir::expressions::BaseExpression> const& getRewardValue() const;
-            
-        private:
-            // The predicate that characterizes the states that obtain this reward.
-            std::unique_ptr<storm::ir::expressions::BaseExpression> statePredicate;
-            
-            // The expression that specifies the value of the reward obtained.
-            std::unique_ptr<storm::ir::expressions::BaseExpression> rewardValue;
-        };
-        
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_STATEREWARD_H_ */
diff --git a/src/ir/TransitionReward.cpp b/src/ir/TransitionReward.cpp
deleted file mode 100644
index bd9664529..000000000
--- a/src/ir/TransitionReward.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * TransitionReward.cpp
- *
- *  Created on: 12.01.2013
- *      Author: Christian Dehnert
- */
-
-#include <sstream>
-
-#include "TransitionReward.h"
-
-namespace storm {
-    namespace ir {
-        
-        TransitionReward::TransitionReward() : commandName(), statePredicate(), rewardValue() {
-            // Nothing to do here.
-        }
-        
-        TransitionReward::TransitionReward(std::string const& commandName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& statePredicate, std::unique_ptr<storm::ir::expressions::BaseExpression>&& rewardValue) : commandName(commandName), statePredicate(std::move(statePredicate)), rewardValue(std::move(rewardValue)) {
-            // Nothing to do here.
-        }
-        
-        TransitionReward::TransitionReward(TransitionReward const& otherReward) : commandName(otherReward.commandName), statePredicate(), rewardValue() {
-            if (otherReward.statePredicate != nullptr) {
-                statePredicate = otherReward.statePredicate->clone();
-            }
-            if (otherReward.rewardValue != nullptr) {
-                rewardValue = otherReward.rewardValue->clone();
-            }
-        }
-        
-        TransitionReward& TransitionReward::operator=(TransitionReward const& otherReward) {
-            if (this != &otherReward) {
-                this->commandName = otherReward.commandName;
-                if (otherReward.statePredicate != nullptr) {
-                    this->statePredicate = otherReward.statePredicate->clone();
-                }
-                if (otherReward.rewardValue != nullptr) {
-                    this->rewardValue = otherReward.rewardValue->clone();
-                }
-            }
-            
-            return *this;
-        }
-        
-        std::string TransitionReward::toString() const {
-            std::stringstream result;
-            result << "\t[" << commandName << "] " << statePredicate->toString() << ": " << rewardValue->toString() << ";";
-            return result.str();
-        }
-        
-        std::string const& TransitionReward::getActionName() const {
-            return this->commandName;
-        }
-        
-        std::unique_ptr<storm::ir::expressions::BaseExpression> const& TransitionReward::getStatePredicate() const {
-            return this->statePredicate;
-        }
-        
-        std::unique_ptr<storm::ir::expressions::BaseExpression> const& TransitionReward::getRewardValue() const {
-            return this->rewardValue;
-        }
-        
-    } // namespace ir
-} // namespace storm
diff --git a/src/ir/TransitionReward.h b/src/ir/TransitionReward.h
deleted file mode 100644
index 298d17024..000000000
--- a/src/ir/TransitionReward.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * TransitionReward.h
- *
- *  Created on: Jan 10, 2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_TRANSITIONREWARD_H_
-#define STORM_IR_TRANSITIONREWARD_H_
-
-#include <memory>
-
-#include "expressions/BaseExpression.h"
-
-namespace storm {
-
-namespace ir {
-
-/*!
- * A class representing a transition reward.
- */
-class TransitionReward {
-public:
-	/*!
-	 * Default constructor. Creates an empty transition reward.
-	 */
-	TransitionReward();
-
-	/*!
-	 * Creates a transition reward for the transitions with the given name emanating from states
-	 * satisfying the given expression with the value given by another expression.
-     *
-	 * @param commandName The name of the command that obtains this reward.
-	 * @param statePredicate The predicate that needs to hold before taking a transition with the
-	 * previously specified name in order to obtain the reward.
-	 * @param rewardValue An expression specifying the values of the rewards to attach to the
-	 * transitions.
-	 */
-	TransitionReward(std::string const& commandName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& statePredicate, std::unique_ptr<storm::ir::expressions::BaseExpression>&& rewardValue);
-
-    /*!
-     * Performs a deep-copy of the given transition reward.
-     *
-     * @param otherReward The transition reward to copy.
-     */
-    TransitionReward(TransitionReward const& otherReward);
-    
-    /*!
-     * Performs a deep-copy of the given transition reward and assigns it to the current one.
-     *
-     * @param otherReward The reward to assign.
-     */
-    TransitionReward& operator=(TransitionReward const& otherReward);
-    
-	/*!
-	 * Retrieves a string representation of this transition reward.
-     *
-	 * @return A string representation of this transition reward.
-	 */
-	std::string toString() const;
-    
-    /*!
-     * Retrieves the action name that is associated with this transition reward.
-     *
-     * @return The action name that is associated with this transition reward.
-     */
-    std::string const& getActionName() const;
-    
-    /*!
-     * Retrieves the state predicate that is associated with this state reward.
-     *
-     * @return The state predicate that is associated with this state reward.
-     */
-    std::unique_ptr<storm::ir::expressions::BaseExpression> const& getStatePredicate() const;
-    
-    /*!
-     * Retrieves the reward value associated with this state reward.
-     *
-     * @return The reward value associated with this state reward.
-     */
-    std::unique_ptr<storm::ir::expressions::BaseExpression> const& getRewardValue() const;
-
-private:
-	// The name of the command this transition-based reward is attached to.
-	std::string commandName;
-
-	// A predicate that needs to be satisfied by states for the reward to be obtained (by taking
-	// a corresponding command transition).
-	std::unique_ptr<storm::ir::expressions::BaseExpression> statePredicate;
-
-	// The expression specifying the value of the reward obtained along the transitions.
-	std::unique_ptr<storm::ir::expressions::BaseExpression> rewardValue;
-};
-
-} // namespace ir
-
-} // namespace storm
-
-#endif /* STORM_IR_TRANSITIONREWARD_H_ */
diff --git a/src/ir/Update.cpp b/src/ir/Update.cpp
deleted file mode 100644
index aac7b3ca0..000000000
--- a/src/ir/Update.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Update.cpp
- *
- *  Created on: 12.01.2013
- *      Author: Christian Dehnert
- */
-
-#include <sstream>
-
-#include "Update.h"
-#include "src/parser/prismparser/VariableState.h"
-#include "src/exceptions/OutOfRangeException.h"
-
-namespace storm {
-    namespace ir {
-        
-        Update::Update() : likelihoodExpression(), booleanAssignments(), integerAssignments(), globalIndex() {
-            // Nothing to do here.
-        }
-        
-        Update::Update(uint_fast64_t globalIndex, std::unique_ptr<storm::ir::expressions::BaseExpression>&& likelihoodExpression, std::map<std::string, storm::ir::Assignment> const& booleanAssignments, std::map<std::string, storm::ir::Assignment> const& integerAssignments)
-        : likelihoodExpression(std::move(likelihoodExpression)), booleanAssignments(booleanAssignments), integerAssignments(integerAssignments), globalIndex(globalIndex) {
-            // Nothing to do here.
-        }
-        
-        Update::Update(Update const& update, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState& variableState) : globalIndex(newGlobalIndex) {
-            for (auto const& variableAssignmentPair : update.booleanAssignments) {
-                if (renaming.count(variableAssignmentPair.first) > 0) {
-                    this->booleanAssignments[renaming.at(variableAssignmentPair.first)] = Assignment(variableAssignmentPair.second, renaming, variableState);
-                } else {
-                    this->booleanAssignments[variableAssignmentPair.first] = Assignment(variableAssignmentPair.second, renaming, variableState);
-                }
-            }
-            for (auto const& variableAssignmentPair : update.integerAssignments) {
-                if (renaming.count(variableAssignmentPair.first) > 0) {
-                    this->integerAssignments[renaming.at(variableAssignmentPair.first)] = Assignment(variableAssignmentPair.second, renaming, variableState);
-                } else {
-                    this->integerAssignments[variableAssignmentPair.first] = Assignment(variableAssignmentPair.second, renaming, variableState);
-                }
-            }
-            this->likelihoodExpression = update.likelihoodExpression->clone(renaming, variableState);
-        }
-        
-        Update::Update(Update const& otherUpdate) : likelihoodExpression(), booleanAssignments(otherUpdate.booleanAssignments), integerAssignments(otherUpdate.integerAssignments), globalIndex(otherUpdate.globalIndex) {
-            if (otherUpdate.likelihoodExpression != nullptr) {
-                likelihoodExpression = otherUpdate.likelihoodExpression->clone();
-            }
-        }
-        
-        Update& Update::operator=(Update const& otherUpdate) {
-            if (this != &otherUpdate) {
-                if (otherUpdate.likelihoodExpression != nullptr) {
-                    this->likelihoodExpression = otherUpdate.likelihoodExpression->clone();
-                }
-                this->booleanAssignments = otherUpdate.booleanAssignments;
-                this->integerAssignments = otherUpdate.integerAssignments;
-                this->globalIndex = otherUpdate.globalIndex;
-            }
-            
-            return *this;
-        }
-        
-        std::unique_ptr<storm::ir::expressions::BaseExpression> const& Update::getLikelihoodExpression() const {
-            return likelihoodExpression;
-        }
-        
-        uint_fast64_t Update::getNumberOfBooleanAssignments() const {
-            return booleanAssignments.size();
-        }
-        
-        uint_fast64_t Update::getNumberOfIntegerAssignments() const {
-            return integerAssignments.size();
-        }
-        
-        std::map<std::string, storm::ir::Assignment> const& Update::getBooleanAssignments() const {
-            return booleanAssignments;
-        }
-        
-        std::map<std::string, storm::ir::Assignment> const& Update::getIntegerAssignments() const {
-            return integerAssignments;
-        }
-        
-        storm::ir::Assignment const& Update::getBooleanAssignment(std::string const& variableName) const {
-            auto variableAssignmentPair = booleanAssignments.find(variableName);
-            if (variableAssignmentPair == booleanAssignments.end()) {
-                throw storm::exceptions::OutOfRangeException() << "Cannot find boolean assignment for variable '"
-				<< variableName << "' in update " << this->toString() << ".";
-            }
-            
-            return variableAssignmentPair->second;
-        }
-        
-        storm::ir::Assignment const& Update::getIntegerAssignment(std::string const& variableName) const {
-            auto variableAssignmentPair = integerAssignments.find(variableName);
-            if (variableAssignmentPair == integerAssignments.end()) {
-                throw storm::exceptions::OutOfRangeException() << "Cannot find integer assignment for variable '"
-				<< variableName << "' in update " << this->toString() << ".";
-            }
-            
-            return variableAssignmentPair->second;
-        }
-        
-        uint_fast64_t Update::getGlobalIndex() const {
-            return this->globalIndex;
-        }
-        
-        std::string Update::toString() const {
-            std::stringstream result;
-            result << likelihoodExpression->toString() << " : ";
-            uint_fast64_t i = 0;
-            for (auto const& assignment : booleanAssignments) {
-                result << assignment.second.toString();
-                if (i < booleanAssignments.size() - 1 || integerAssignments.size() > 0) {
-                    result << " & ";
-                }
-                ++i;
-            }
-            i = 0;
-            for (auto const& assignment : integerAssignments) {
-                result << assignment.second.toString();
-                if (i < integerAssignments.size() - 1) {
-                    result << " & ";
-                }
-                ++i;
-            }
-            return result.str();
-        }
-        
-    } // namespace ir
-} // namespace storm
diff --git a/src/ir/Update.h b/src/ir/Update.h
deleted file mode 100644
index 07b9a7d24..000000000
--- a/src/ir/Update.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Update.h
- *
- *  Created on: 06.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_UPDATE_H_
-#define STORM_IR_UPDATE_H_
-
-#include <map>
-#include <memory>
-
-#include "expressions/BaseExpression.h"
-#include "Assignment.h"
-
-namespace storm {
-    
-    namespace parser {
-        namespace prism {
-            class VariableState;
-        } // namespace prismparser
-    } // namespace parser
-    
-    namespace ir {
-        
-        /*!
-         * A class representing an update of a command.
-         */
-        class Update {
-        public:
-            /*!
-             * Default constructor. Creates an empty update.
-             */
-            Update();
-            
-            /*!
-             * Creates an update with the given expression specifying the likelihood and the mapping of
-             * variable to their assignments.
-             *
-             * @param globalIndex The global index of the update.
-             * @param likelihoodExpression An expression specifying the likelihood of this update.
-             * @param assignments A map of variable names to their assignments.
-             */
-            Update(uint_fast64_t globalIndex, std::unique_ptr<storm::ir::expressions::BaseExpression>&& likelihoodExpression, std::map<std::string, storm::ir::Assignment> const& booleanAssignments, std::map<std::string, storm::ir::Assignment> const& integerAssignments);
-            
-            /*!
-             * Creates a copy of the given update and performs the provided renaming.
-             *
-             * @param update The update that is to be copied.
-             * @param newGlobalIndex The global index of the resulting update.
-             * @param renaming A mapping from names that are to be renamed to the names they are to be
-             * replaced with.
-             * @param variableState An object knowing about the variables in the system.
-             */
-            Update(Update const& update, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState& variableState);
-            
-            /*!
-             * Peforms a deep-copy of the given update.
-             *
-             * @param otherUpdate The update to copy.
-             */
-            Update(Update const& otherUpdate);
-            
-            /*!
-             * Performs a deep-copy of the given update and assigns it to the current one.
-             *
-             * @param otherUpdate The update to assign.
-             */
-            Update& operator=(Update const& otherUpdate);
-            
-            /*!
-             * Retrieves the expression for the likelihood of this update.
-             *
-             * @return The expression for the likelihood of this update.
-             */
-            std::unique_ptr<storm::ir::expressions::BaseExpression> const& getLikelihoodExpression() const;
-            
-            /*!
-             * Retrieves the number of boolean assignments associated with this update.
-             *
-             * @return The number of boolean assignments associated with this update.
-             */
-            uint_fast64_t getNumberOfBooleanAssignments() const;
-            
-            /*!
-             * Retrieves the number of integer assignments associated with this update.
-             *
-             * @return The number of integer assignments associated with this update.
-             */
-            uint_fast64_t getNumberOfIntegerAssignments() const;
-            
-            /*!
-             * Retrieves a reference to the map of boolean variable names to their respective assignments.
-             *
-             * @return A reference to the map of boolean variable names to their respective assignments.
-             */
-            std::map<std::string, storm::ir::Assignment> const& getBooleanAssignments() const;
-            
-            /*!
-             * Retrieves a reference to the map of integer variable names to their respective assignments.
-             *
-             * @return A reference to the map of integer variable names to their respective assignments.
-             */
-            std::map<std::string, storm::ir::Assignment> const& getIntegerAssignments() const;
-            
-            /*!
-             * Retrieves a reference to the assignment for the boolean variable with the given name.
-             *
-             * @return A reference to the assignment for the boolean variable with the given name.
-             */
-            storm::ir::Assignment const& getBooleanAssignment(std::string const& variableName) const;
-            
-            /*!
-             * Retrieves a reference to the assignment for the integer variable with the given name.
-             *
-             * @return A reference to the assignment for the integer variable with the given name.
-             */
-            storm::ir::Assignment const& getIntegerAssignment(std::string const& variableName) const;
-            
-            /*!
-             * Retrieves the global index of the update, that is, a unique index over all modules.
-             *
-             * @return The global index of the update.
-             */
-            uint_fast64_t getGlobalIndex() const;
-            
-            /*!
-             * Retrieves a string representation of this update.
-             *
-             * @return A string representation of this update.
-             */
-            std::string toString() const;
-            
-        private:
-            // An expression specifying the likelihood of taking this update.
-            std::unique_ptr<storm::ir::expressions::BaseExpression> likelihoodExpression;
-            
-            // A mapping of boolean variable names to their assignments in this update.
-            std::map<std::string, storm::ir::Assignment> booleanAssignments;
-            
-            // A mapping of integer variable names to their assignments in this update.
-            std::map<std::string, storm::ir::Assignment> integerAssignments;
-            
-            // The global index of the update.
-            uint_fast64_t globalIndex;
-        };
-        
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_UPDATE_H_ */
diff --git a/src/ir/Variable.cpp b/src/ir/Variable.cpp
deleted file mode 100644
index 83cb2a33a..000000000
--- a/src/ir/Variable.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Variable.cpp
- *
- *  Created on: 12.01.2013
- *      Author: Christian Dehnert
- */
-
-#include <sstream>
-#include <map>
-#include <iostream>
-
-#include "Variable.h"
-#include "src/parser/prismparser/VariableState.h"
-
-namespace storm {
-    namespace ir {
-        
-        Variable::Variable() : localIndex(0), globalIndex(0), variableName(), initialValue() {
-            // Nothing to do here.
-        }
-        
-        Variable::Variable(uint_fast64_t localIndex, uint_fast64_t globalIndex, std::string const& variableName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& initialValue)
-        : localIndex(localIndex), globalIndex(globalIndex), variableName(variableName), initialValue(std::move(initialValue)) {
-            // Nothing to do here.
-        }
-        
-        Variable::Variable(Variable const& otherVariable) : localIndex(otherVariable.localIndex), globalIndex(otherVariable.globalIndex), variableName(otherVariable.variableName), initialValue() {
-            if (otherVariable.initialValue != nullptr) {
-                initialValue = otherVariable.initialValue->clone();
-            }
-        }
-        
-        Variable::Variable(Variable const& var, std::string const& newName, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState)
-        : localIndex(var.getLocalIndex()), globalIndex(newGlobalIndex), variableName(newName), initialValue() {
-            if (var.initialValue != nullptr) {
-                this->initialValue = var.initialValue->clone(renaming, variableState);
-            }
-        }
-        
-        Variable& Variable::operator=(Variable const& otherVariable) {
-            if (this != &otherVariable) {
-                this->localIndex = otherVariable.localIndex;
-                this->globalIndex = otherVariable.globalIndex;
-                this->variableName = otherVariable.variableName;
-                if (otherVariable.initialValue != nullptr) {
-                    this->initialValue = otherVariable.initialValue->clone();
-                }
-            }
-            
-            return *this;
-        }
-        
-        std::string const& Variable::getName() const {
-            return variableName;
-        }
-        
-        uint_fast64_t Variable::getGlobalIndex() const {
-            return globalIndex;
-        }
-        
-        uint_fast64_t Variable::getLocalIndex() const {
-            return localIndex;
-        }
-        
-        std::unique_ptr<storm::ir::expressions::BaseExpression> const& Variable::getInitialValue() const {
-            return initialValue;
-        }
-        
-        void Variable::setInitialValue(std::unique_ptr<storm::ir::expressions::BaseExpression>&& initialValue) {
-            this->initialValue = std::move(initialValue);
-        }
-        
-    } // namespace ir
-} // namespace storm
diff --git a/src/ir/Variable.h b/src/ir/Variable.h
deleted file mode 100644
index 53b2f3b98..000000000
--- a/src/ir/Variable.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Variable.h
- *
- *  Created on: 06.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_VARIABLE_H_
-#define STORM_IR_VARIABLE_H_
-
-#include <string>
-#include <memory>
-
-#include "expressions/BaseExpression.h"
-
-namespace storm {
-    
-    namespace parser {
-        namespace prism {
-            class VariableState;
-        } // namespace prismparser
-    } // namespace parser
-    
-    namespace ir {
-        
-        /*!
-         * A class representing a untyped variable.
-         */
-        class Variable {
-        public:
-            /*!
-             * Default constructor. Creates an unnamed, untyped variable without initial value.
-             */
-            Variable();
-            
-            /*!
-             * Creates an untyped variable with the given name and initial value.
-             *
-             * @param localIndex A module-local index for the variable.
-             * @param globalIndex A globally unique (among the variables of equal type) index for the variable.
-             * @param variableName the name of the variable.
-             * @param initialValue the expression that defines the initial value of the variable.
-             */
-            Variable(uint_fast64_t localIndex, uint_fast64_t globalIndex, std::string const& variableName, std::unique_ptr<storm::ir::expressions::BaseExpression>&& initialValue = nullptr);
-            
-            /*!
-             * Creates a copy of the given variable and performs the provided renaming.
-             *
-             * @param oldVariable The variable to copy.
-             * @param newName New name of this variable.
-             * @param newGlobalIndex The new global index of the variable.
-             * @param renaming A mapping from names that are to be renamed to the names they are to be
-             * replaced with.
-             * @param variableState An object knowing about the variables in the system.
-             */
-            Variable(Variable const& oldVariable, std::string const& newName, uint_fast64_t newGlobalIndex, std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState);
-            
-            /*!
-             * Creates a deep-copy of the given variable.
-             *
-             * @param otherVariable The variable to copy.
-             */
-            Variable(Variable const& otherVariable);
-            
-            /*!
-             * Creates a deep-copy of the given variable and assigns it to the current one.
-             */
-            Variable& operator=(Variable const& otherVariable);
-            
-            /*!
-             * Retrieves the name of the variable.
-             *
-             * @return The name of the variable.
-             */
-            std::string const& getName() const;
-            
-            /*!
-             * Retrieves the global index of the variable, i.e. the index in all variables of equal type
-             * of all modules.
-             *
-             * @return The global index of the variable.
-             */
-            uint_fast64_t getGlobalIndex() const;
-            
-            /*!
-             * Retrieves the global index of the variable, i.e. the index in all variables of equal type in
-             * the same module.
-             *
-             * @return The local index of the variable.
-             */
-            uint_fast64_t getLocalIndex() const;
-            
-            /*!
-             * Retrieves the expression defining the initial value of the variable.
-             *
-             * @return The expression defining the initial value of the variable.
-             */
-            std::unique_ptr<storm::ir::expressions::BaseExpression> const& getInitialValue() const;
-            
-            /*!
-             * Sets the initial value to the given expression.
-             *
-             * @param initialValue The new initial value.
-             */
-            void setInitialValue(std::unique_ptr<storm::ir::expressions::BaseExpression>&& initialValue);
-            
-        private:
-            // A unique (among the variables of equal type) index for the variable inside its module.
-            uint_fast64_t localIndex;
-
-            // A unique (among the variables of equal type) index for the variable over all modules.
-            uint_fast64_t globalIndex;
-            
-            // The name of the variable.
-            std::string variableName;
-            
-            // The expression defining the initial value of the variable.
-            std::unique_ptr<storm::ir::expressions::BaseExpression> initialValue;
-        };
-        
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_VARIABLE_H_ */
diff --git a/src/ir/expressions/BaseExpression.cpp b/src/ir/expressions/BaseExpression.cpp
deleted file mode 100644
index 66771d6b0..000000000
--- a/src/ir/expressions/BaseExpression.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * BaseExpression.cpp
- *
- *  Created on: 10.06.2013
- *      Author: Christian Dehnert
- */
-
-#include "BaseExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            BaseExpression::BaseExpression() : type(undefined) {
-                // Nothing to do here.
-            }
-            
-            BaseExpression::BaseExpression(ReturnType type) : type(type) {
-                // Nothing to do here.
-            }
-            
-            BaseExpression::BaseExpression(BaseExpression const& baseExpression) : type(baseExpression.type) {
-                // Nothing to do here.
-            }
-            
-            BaseExpression::~BaseExpression() {
-                // Nothing to do here.
-            }
-            
-            std::unique_ptr<BaseExpression> BaseExpression::substitute(std::unique_ptr<BaseExpression>&& expression, std::map<std::string, std::reference_wrapper<BaseExpression>> const& substitution) {
-                BaseExpression* result = expression->performSubstitution(substitution);
-                
-                if (result != expression.get()) {
-                    return std::unique_ptr<BaseExpression>(result);
-                } else {
-                    return std::move(expression);
-                }
-            }
-            
-            int_fast64_t BaseExpression::getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const {
-                if (type != int_) {
-                    throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression of type '"
-                    << this->getTypeName() << "' as 'int'.";
-                }
-                throw storm::exceptions::NotImplementedException() << "Cannot evaluate expression of type '"
-                << this->getTypeName() << " because evaluation implementation is missing.";
-            }
-            
-            bool BaseExpression::getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const {
-                if (type != bool_) {
-                    throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression of type '"
-                    << this->getTypeName() << "' as 'bool'.";
-                }
-                throw storm::exceptions::NotImplementedException() << "Cannot evaluate expression of type '"
-                << this->getTypeName() << " because evaluation implementation is missing.";
-            }
-            
-            double BaseExpression::getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const {
-                if (type != double_ && type != int_) {
-                    throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression of type '"
-                    << this->getTypeName() << "' as 'double'.";
-                }
-                throw storm::exceptions::NotImplementedException() << "Cannot evaluate expression of type '"
-                << this->getTypeName() << " because evaluation implementation is missing.";
-            }
-            
-            std::string BaseExpression::getTypeName() const {
-                switch(type) {
-                    case bool_: return std::string("bool");
-                    case int_: return std::string("int");
-                    case double_: return std::string("double");
-                    default: return std::string("undefined");
-                }
-            }
-            
-            BaseExpression::ReturnType BaseExpression::getType() const {
-                return type;
-            }
-            
-            BaseExpression* BaseExpression::performSubstitution(std::map<std::string, std::reference_wrapper<BaseExpression>> const& substitution) {
-                return this;
-            }
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
diff --git a/src/ir/expressions/BaseExpression.h b/src/ir/expressions/BaseExpression.h
deleted file mode 100644
index 948ed9d88..000000000
--- a/src/ir/expressions/BaseExpression.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * BaseExpression.h
- *
- *  Created on: 03.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_EXPRESSIONS_BASEEXPRESSION_H_
-#define STORM_IR_EXPRESSIONS_BASEEXPRESSION_H_
-
-#include <string>
-#include <vector>
-#include <map>
-#include <memory>
-
-#include "src/exceptions/ExpressionEvaluationException.h"
-#include "src/exceptions/NotImplementedException.h"
-#include "ExpressionVisitor.h"
-
-namespace storm {
-    
-    // Forward-declare VariableState.
-	namespace parser {
-		namespace prism {
-			class VariableState;
-		} // namespace prismparser
-	} // namespace parser
-    
-    namespace ir {
-        namespace expressions {
-            
-            /*!
-             * The base class for all expressions.
-             */
-            class BaseExpression {
-            public:
-                // Forward declare friend classes to allow access to substitute.
-                friend class BinaryExpression;
-                friend class UnaryExpression;
-
-                /*!
-                 * Each node in an expression tree has a uniquely defined type from this enum.
-                 */
-                enum ReturnType {undefined, bool_, int_, double_};
-                
-                /*!
-                 * Creates an expression with undefined type.
-                 */
-                BaseExpression();
-                
-                /*!
-                 * Creates an expression with the given type.
-                 *
-                 * @param type The type of the expression.
-                 */
-                BaseExpression(ReturnType type);
-                
-                /*!
-                 * Copy-constructs from the given expression.
-                 *
-                 * @param baseExpression The expression to copy.
-                 */
-                BaseExpression(BaseExpression const& baseExpression);
-                
-                /*!
-                 * Destructor.
-                 */
-                virtual ~BaseExpression();
-                
-                /*!
-                 * Performes a deep-copy of the expression.
-                 *
-                 * @return A deep-copy of the expression.
-                 */
-                virtual std::unique_ptr<BaseExpression> clone() const = 0;
-                
-                /*!
-                 * Copies the expression tree underneath (including) the current node and performs the provided renaming.
-                 *
-                 * @param renaming A mapping from identifier names to strings they are to be replaced with.
-                 * @param variableState An object knowing about the global variable state.
-                 */
-                virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const = 0;
-                
-                /*!
-                 * Performs the given substitution by replacing each variable in the given expression that is a key in
-                 * the map by a copy of the mapped expression.
-                 *
-                 * @param expression The expression in which to perform the substitution.
-                 * @param substitution The substitution to apply.
-                 * @return The resulting expression.
-                 */
-                static std::unique_ptr<BaseExpression> substitute(std::unique_ptr<BaseExpression>&& expression, std::map<std::string, std::reference_wrapper<BaseExpression>> const& substitution);
-                
-                /*!
-                 * Retrieves the value of the expression as an integer given the provided variable valuation.
-                 *
-                 * @param variableValues The variable valuation under which to evaluate the expression. If set to null,
-                 * constant expressions can be evaluated without variable values. However, upon encountering a variable
-                 * expression an expression is thrown, because evaluation is impossible without the variable values then.
-                 * @return The value of the expression as an integer.
-                 */
-                virtual int_fast64_t getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const;
-                
-                /*!
-                 * Retrieves the value of the expression as a boolean given the provided variable valuation.
-                 *
-                 * @param variableValues The variable valuation under which to evaluate the expression. If set to null,
-                 * constant expressions can be evaluated without variable values. However, upon encountering a variable
-                 * expression an expression is thrown, because evaluation is impossible without the variable values then.
-                 * @return The value of the expression as a boolean.
-                 */
-                virtual bool getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const;
-                
-                /*!
-                 * Retrieves the value of the expression as a double given the provided variable valuation.
-                 *
-                 * @param variableValues The variable valuation under which to evaluate the expression. If set to null,
-                 * constant expressions can be evaluated without variable values. However, upon encountering a variable
-                 * expression an expression is thrown, because evaluation is impossible without the variable values then.
-                 * @return The value of the expression as a double.
-                 */
-                virtual double getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const;
-                
-                /*!
-                 * Acceptor method for visitor pattern.
-                 *
-                 * @param visitor The visitor that is supposed to visit each node of the expression tree.
-                 */
-                virtual void accept(ExpressionVisitor* visitor) = 0;
-                
-                /*!
-                 * Retrieves a string representation of the expression tree underneath the current node.
-                 *
-                 * @return A string representation of the expression tree underneath the current node.
-                 */
-                virtual std::string toString() const = 0;
-                
-                /*!
-                 * Retrieves a string representation of the type to which this node evaluates.
-                 *
-                 * @return A string representation of the type to which this node evaluates.
-                 */
-                std::string getTypeName() const;
-                
-                /*!
-                 * Retrieves the type to which the node evaluates.
-                 *
-                 * @return The type to which the node evaluates.
-                 */
-                ReturnType getType() const;
-                
-            protected:
-                /*!
-                 * Performs the given substitution on the expression, i.e. replaces all variables whose names are keys
-                 * of the map by a copy of the expression they are associated with in the map. This is intended as a helper
-                 * function for substitute.
-                 *
-                 * @param substitution The substitution to perform
-                 */
-                virtual BaseExpression* performSubstitution(std::map<std::string, std::reference_wrapper<BaseExpression>> const& substitution);
-                
-            private:
-                // The type to which this node evaluates.
-                ReturnType type;
-            };
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_EXPRESSIONS_BASEEXPRESSION_H_ */
diff --git a/src/ir/expressions/BinaryBooleanFunctionExpression.cpp b/src/ir/expressions/BinaryBooleanFunctionExpression.cpp
deleted file mode 100644
index 83cb1d82f..000000000
--- a/src/ir/expressions/BinaryBooleanFunctionExpression.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * BinaryBooleanFunctionExpression.cpp
- *
- *  Created on: 10.06.2013
- *      Author: Christian Dehnert
- */
-
-#include <sstream>
-
-#include "BinaryBooleanFunctionExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            BinaryBooleanFunctionExpression::BinaryBooleanFunctionExpression(std::unique_ptr<BaseExpression>&& left, std::unique_ptr<BaseExpression>&& right, FunctionType functionType)
-            : BinaryExpression(bool_, std::move(left), std::move(right)), functionType(functionType) {
-                // Nothing to do here.
-            }
-            
-            BinaryBooleanFunctionExpression::BinaryBooleanFunctionExpression(BinaryBooleanFunctionExpression const& binaryBooleanFunctionExpression)
-            : BinaryExpression(binaryBooleanFunctionExpression), functionType(binaryBooleanFunctionExpression.functionType) {
-                // Nothing to do here.
-            }
-
-            std::unique_ptr<BaseExpression> BinaryBooleanFunctionExpression::clone() const {
-                return std::unique_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(this->getLeft()->clone(), this->getRight()->clone(), functionType));
-            }
-            
-            std::unique_ptr<BaseExpression> BinaryBooleanFunctionExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const {
-                return std::unique_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(this->getLeft()->clone(renaming, variableState), this->getRight()->clone(renaming, variableState), this->functionType));
-            }
-            
-            bool BinaryBooleanFunctionExpression::getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const {
-                bool resultLeft = this->getLeft()->getValueAsBool(variableValues);
-                bool resultRight = this->getRight()->getValueAsBool(variableValues);
-                switch(functionType) {
-                    case AND: return resultLeft & resultRight; break;
-                    case OR: return resultLeft | resultRight; break;
-                    default: throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: "
-                        << "Unknown boolean binary operator: '" << functionType << "'.";
-                }
-            }
-            
-            BinaryBooleanFunctionExpression::FunctionType BinaryBooleanFunctionExpression::getFunctionType() const {
-                return functionType;
-            }
-            
-            void BinaryBooleanFunctionExpression::accept(ExpressionVisitor* visitor) {
-                visitor->visit(this);
-            }
-            
-            std::string BinaryBooleanFunctionExpression::toString() const {
-                std::stringstream result;
-                result << "(" << this->getLeft()->toString();
-                switch (functionType) {
-                    case AND: result << " & "; break;
-                    case OR: result << " | "; break;
-                }
-                result << this->getRight()->toString() << ")";
-                
-                return result.str();
-            }
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
diff --git a/src/ir/expressions/BinaryBooleanFunctionExpression.h b/src/ir/expressions/BinaryBooleanFunctionExpression.h
deleted file mode 100644
index b0cec5906..000000000
--- a/src/ir/expressions/BinaryBooleanFunctionExpression.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * BinaryBooleanFunctionExpression.h
- *
- *  Created on: 03.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_EXPRESSIONS_BINARYBOOLEANFUNCTIONEXPRESSION_H_
-#define STORM_IR_EXPRESSIONS_BINARYBOOLEANFUNCTIONEXPRESSION_H_
-
-#include "BinaryExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            /*!
-             * A class representing a binary function expression of boolean type.
-             */
-            class BinaryBooleanFunctionExpression : public BinaryExpression {
-            public:
-                /*!
-                 * An enum type specifying the different functions applicable.
-                 */
-                enum FunctionType {AND, OR};
-                
-                /*!
-                 * Creates a binary boolean function expression tree node with the given children and function type.
-                 *
-                 * @param left The left child of the node.
-                 * @param right The right child of the node.
-                 * @param functionType The operator that is to be applied to the two children.
-                 */
-                BinaryBooleanFunctionExpression(std::unique_ptr<BaseExpression>&& left, std::unique_ptr<BaseExpression>&& right, FunctionType functionType);
-                
-                /*!
-                 * Copy-constructs from the given expression.
-                 *
-                 * @param binaryBooleanFunctionExpression The expression to copy.
-                 */
-                BinaryBooleanFunctionExpression(BinaryBooleanFunctionExpression const& binaryBooleanFunctionExpression);
-                
-                virtual std::unique_ptr<BaseExpression> clone() const override;
-                
-                virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override;
-                
-                virtual bool getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override;
-                
-                /*!
-                 * Retrieves the operator that is associated with this node.
-                 *
-                 * @param The operator that is associated with this node.
-                 */
-                FunctionType getFunctionType() const;
-                
-                virtual void accept(ExpressionVisitor* visitor) override;
-                
-                virtual std::string toString() const override;
-                                
-            private:
-                // The operator that is associated with this node.
-                FunctionType functionType;
-            };
-            
-        } // namespace expressions
-    } // namespace ir    
-} // namespace storm
-
-#endif /* STORM_IR_EXPRESSIONS_BINARYBOOLEANFUNCTIONEXPRESSION_H_ */
diff --git a/src/ir/expressions/BinaryExpression.cpp b/src/ir/expressions/BinaryExpression.cpp
deleted file mode 100644
index 417cc9301..000000000
--- a/src/ir/expressions/BinaryExpression.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * BinaryBooleanFunctionExpression.cpp
- *
- *  Created on: 10.06.2013
- *      Author: Christian Dehnert
- */
-
-#include "BinaryExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            BinaryExpression::BinaryExpression(ReturnType type, std::unique_ptr<BaseExpression>&& left, std::unique_ptr<BaseExpression>&& right)
-            : BaseExpression(type), left(std::move(left)), right(std::move(right)) {
-                // Nothing to do here.
-            }
-            
-            BinaryExpression::BinaryExpression(BinaryExpression const& binaryExpression) : BaseExpression(binaryExpression.getType()), left(binaryExpression.left->clone()), right(binaryExpression.right->clone()) {
-                // Nothing to do here.
-            }
-
-            BaseExpression* BinaryExpression::performSubstitution(std::map<std::string, std::reference_wrapper<BaseExpression>> const& substitution) {
-                // Get the new left successor recursively.
-                BaseExpression* newLeftSuccessor = left->performSubstitution(substitution);
-                
-                // If the left successor changed, we need to update it. If it did not change, this must not be executed,
-                // because assigning to the unique_ptr will destroy the current successor immediately.
-                if (newLeftSuccessor != left.get()) {
-                    left = std::unique_ptr<BaseExpression>(newLeftSuccessor);
-                }
-                
-                // Now do the same thing for the right successor.
-                BaseExpression* newRightSuccessor = right->performSubstitution(substitution);
-                if (newRightSuccessor != right.get()) {
-                    right = std::unique_ptr<BaseExpression>(newRightSuccessor);
-                }
-            
-                return this;
-            }
-            
-            std::unique_ptr<BaseExpression> const& BinaryExpression::getLeft() const {
-                return left;
-            }
-            
-            std::unique_ptr<BaseExpression> const& BinaryExpression::getRight() const {
-                return right;
-            }
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
\ No newline at end of file
diff --git a/src/ir/expressions/BinaryExpression.h b/src/ir/expressions/BinaryExpression.h
deleted file mode 100644
index 1d6560863..000000000
--- a/src/ir/expressions/BinaryExpression.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * BinaryExpression.h
- *
- *  Created on: 27.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_EXPRESSIONS_BINARYEXPRESSION_H_
-#define STORM_IR_EXPRESSIONS_BINARYEXPRESSION_H_
-
-#include "src/ir/expressions/BaseExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            /*!
-             * A class representing a generic binary expression.
-             */
-            class BinaryExpression : public BaseExpression {
-            public:
-                /*!
-                 * Constructs a binary expression with the given type and children.
-                 * @param type The type of the binary expression.
-                 * @param left The left child of the binary expression.
-                 * @param right The right child of the binary expression.
-                 */
-                BinaryExpression(ReturnType type, std::unique_ptr<BaseExpression>&& left, std::unique_ptr<BaseExpression>&& right);
-                
-                /*!
-                 * Copy-constructs from the given expression.
-                 *
-                 * @param binaryExpression The expression to copy.
-                 */
-                BinaryExpression(BinaryExpression const& binaryExpression);
-                                
-                /*!
-                 * Retrieves the left child of the expression node.
-                 *
-                 * @return The left child of the expression node.
-                 */
-                std::unique_ptr<BaseExpression> const& getLeft() const;
-                
-                /*!
-                 * Retrieves the right child of the expression node.
-                 *
-                 * @return The right child of the expression node.
-                 */
-                std::unique_ptr<BaseExpression> const& getRight() const;
-                
-            protected:
-                virtual BaseExpression* performSubstitution(std::map<std::string, std::reference_wrapper<BaseExpression>> const& substitution) override;
-                
-            private:
-                // The left child of the binary expression.
-                std::unique_ptr<BaseExpression> left;
-                
-                // The right child of the binary expression.
-                std::unique_ptr<BaseExpression> right;
-            };
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_EXPRESSIONS_BINARYEXPRESSION_H_ */
diff --git a/src/ir/expressions/BinaryNumericalFunctionExpression.cpp b/src/ir/expressions/BinaryNumericalFunctionExpression.cpp
deleted file mode 100644
index a80e04ae4..000000000
--- a/src/ir/expressions/BinaryNumericalFunctionExpression.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * BinaryBooleanFunctionExpression.cpp
- *
- *  Created on: 10.06.2013
- *      Author: Christian Dehnert
- */
-
-#include <sstream>
-#include <algorithm>
-
-#include "BinaryNumericalFunctionExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            BinaryNumericalFunctionExpression::BinaryNumericalFunctionExpression(ReturnType type, std::unique_ptr<BaseExpression>&& left, std::unique_ptr<BaseExpression>&& right, FunctionType functionType)
-            : BinaryExpression(type, std::move(left), std::move(right)), functionType(functionType) {
-                // Nothing to do here.
-            }
-            
-            BinaryNumericalFunctionExpression::BinaryNumericalFunctionExpression(BinaryNumericalFunctionExpression const& binaryNumericalFunctionExpression)
-            : BinaryExpression(binaryNumericalFunctionExpression), functionType(binaryNumericalFunctionExpression.functionType) {
-                // Nothing to do here.
-            }
-
-            std::unique_ptr<BaseExpression> BinaryNumericalFunctionExpression::clone() const {
-                return std::unique_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(this->getType(), this->getLeft()->clone(), this->getRight()->clone(), functionType));
-            }
-
-            std::unique_ptr<BaseExpression> BinaryNumericalFunctionExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const {
-                return std::unique_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(this->getType(), this->getLeft()->clone(renaming, variableState), this->getRight()->clone(renaming, variableState), this->functionType));
-            }
-            
-            BinaryNumericalFunctionExpression::FunctionType BinaryNumericalFunctionExpression::getFunctionType() const {
-                return functionType;
-            }
-            
-            int_fast64_t BinaryNumericalFunctionExpression::getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const {
-                if (this->getType() != int_) {
-                    BaseExpression::getValueAsInt(variableValues);
-                }
-                
-                int_fast64_t resultLeft = this->getLeft()->getValueAsInt(variableValues);
-                int_fast64_t resultRight = this->getRight()->getValueAsInt(variableValues);
-                switch(functionType) {
-                    case PLUS: return resultLeft + resultRight; break;
-                    case MINUS: return resultLeft - resultRight; break;
-                    case TIMES: return resultLeft * resultRight; break;
-                    case DIVIDE: return resultLeft / resultRight; break;
-                    case MIN: return std::min(resultLeft, resultRight); break;
-                    case MAX: return std::max(resultLeft, resultRight); break;
-                    default: throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: "
-                        << "Unknown numeric binary operator: '" << functionType << "'.";
-                }
-            }
-                        
-            double BinaryNumericalFunctionExpression::getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const {
-                if (this->getType() != double_ && this->getType() != int_) {
-                    BaseExpression::getValueAsDouble(variableValues);
-                }
-                
-                double resultLeft = this->getLeft()->getValueAsDouble(variableValues);
-                double resultRight = this->getRight()->getValueAsDouble(variableValues);
-                switch(functionType) {
-                    case PLUS: return resultLeft + resultRight; break;
-                    case MINUS: return resultLeft - resultRight; break;
-                    case TIMES: return resultLeft * resultRight; break;
-                    case DIVIDE: return resultLeft / resultRight; break;
-                    case MIN: return std::min(resultLeft, resultRight); break;
-                    case MAX: return std::max(resultLeft, resultRight); break;
-                    default: throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: "
-                        << "Unknown numeric binary operator: '" << functionType << "'.";
-                }
-            }
-            
-            void BinaryNumericalFunctionExpression::accept(ExpressionVisitor* visitor) {
-                visitor->visit(this);
-            }
-            
-            std::string BinaryNumericalFunctionExpression::toString() const {
-                std::stringstream result;
-                switch (functionType) {
-                    case PLUS: result << "(" << this->getLeft()->toString() << " + " << this->getRight()->toString() << ")"; break;
-                    case MINUS: result << "(" << this->getLeft()->toString() << " - " << this->getRight()->toString() << ")"; break;
-                    case TIMES: result << "(" << this->getLeft()->toString() << " * " << this->getRight()->toString() << ")"; break;
-                    case DIVIDE: result << "(" << this->getLeft()->toString() << " / " << this->getRight()->toString() << ")"; break;
-                    case MIN: result << "min(" << this->getLeft()->toString() << ", " << this->getRight()->toString() << ")"; break;
-                    case MAX: result << "max(" << this->getLeft()->toString() << ", " << this->getRight()->toString() << ")"; break;
-                }
-                return result.str();
-            }
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
\ No newline at end of file
diff --git a/src/ir/expressions/BinaryNumericalFunctionExpression.h b/src/ir/expressions/BinaryNumericalFunctionExpression.h
deleted file mode 100644
index 846ceb99a..000000000
--- a/src/ir/expressions/BinaryNumericalFunctionExpression.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * BinaryFunctionExpression.h
- *
- *  Created on: 03.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_EXPRESSIONS_BINARYFUNCTIONEXPRESSION_H_
-#define STORM_IR_EXPRESSIONS_BINARYFUNCTIONEXPRESSION_H_
-
-#include "src/ir/expressions/BinaryExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            /*!
-             * A class representing a binary function expression of numerical type.
-             */
-            class BinaryNumericalFunctionExpression : public BinaryExpression {
-            public:
-                /*!
-                 * An enum type specifying the different functions applicable.
-                 */
-                enum FunctionType {PLUS, MINUS, TIMES, DIVIDE, MIN, MAX};
-                
-                /*!
-                 * Creates a binary numerical function expression with the given type, children and function type.
-                 *
-                 * @param type The type of the expression tree node.
-                 * @param left The left child of the expression tree node.
-                 * @param right The right child of the  expression tree node.
-                 * @param functionType The function that is applied to the children of this node.
-                 */
-                BinaryNumericalFunctionExpression(ReturnType type, std::unique_ptr<BaseExpression>&& left, std::unique_ptr<BaseExpression>&& right, FunctionType functionType);
-                
-                /*!
-                 * Performs a deep-copy of the given expression.
-                 *
-                 * @param binaryNumericalFunctionExpression The expression to copy.
-                 */
-                BinaryNumericalFunctionExpression(BinaryNumericalFunctionExpression const& binaryNumericalFunctionExpression);
-
-                virtual std::unique_ptr<BaseExpression> clone() const override;
-                
-                virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override;
-                
-                /*!
-                 * Retrieves the operator that is associated with this node.
-                 *
-                 * @param The operator that is associated with this node.
-                 */
-                FunctionType getFunctionType() const;
-                
-                virtual int_fast64_t getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override;
-                
-                virtual double getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override;
-                
-                virtual void accept(ExpressionVisitor* visitor) override;
-                
-                virtual std::string toString() const override;
-                
-            private:
-                // The operator that is associated with this node.
-                FunctionType functionType;
-            };
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_EXPRESSIONS_BINARYFUNCTIONEXPRESSION_H_ */
diff --git a/src/ir/expressions/BinaryRelationExpression.cpp b/src/ir/expressions/BinaryRelationExpression.cpp
deleted file mode 100644
index 5c08e7f33..000000000
--- a/src/ir/expressions/BinaryRelationExpression.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * BinaryBooleanFunctionExpression.cpp
- *
- *  Created on: 10.06.2013
- *      Author: Christian Dehnert
- */
-
-#include <sstream>
-
-#include "BinaryRelationExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            BinaryRelationExpression::BinaryRelationExpression(std::unique_ptr<BaseExpression>&& left, std::unique_ptr<BaseExpression>&& right, RelationType relationType)
-            : BinaryExpression(bool_, std::move(left), std::move(right)), relationType(relationType) {
-                // Nothing to do here.
-            }
-            
-            BinaryRelationExpression::BinaryRelationExpression(BinaryRelationExpression const& binaryRelationExpression)
-            : BinaryExpression(binaryRelationExpression), relationType(binaryRelationExpression.relationType) {
-                // Nothing to do here.
-            }
-            
-            std::unique_ptr<BaseExpression> BinaryRelationExpression::clone() const {
-                return std::unique_ptr<BaseExpression>(new BinaryRelationExpression(this->getLeft()->clone(), this->getRight()->clone(), relationType));
-            }
-
-            std::unique_ptr<BaseExpression> BinaryRelationExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const {
-                return std::unique_ptr<BaseExpression>(new BinaryRelationExpression(this->getLeft()->clone(renaming, variableState), this->getRight()->clone(renaming, variableState), this->relationType));
-            }
-            
-            bool BinaryRelationExpression::getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const {
-                int_fast64_t resultLeft = this->getLeft()->getValueAsInt(variableValues);
-                int_fast64_t resultRight = this->getRight()->getValueAsInt(variableValues);
-                switch(relationType) {
-                    case EQUAL: return resultLeft == resultRight; break;
-                    case NOT_EQUAL: return resultLeft != resultRight; break;
-                    case LESS: return resultLeft < resultRight; break;
-                    case LESS_OR_EQUAL: return resultLeft <= resultRight; break;
-                    case GREATER: return resultLeft > resultRight; break;
-                    case GREATER_OR_EQUAL: return resultLeft >= resultRight; break;
-                    default: throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: "
-                        << "Unknown boolean binary relation: '" << relationType << "'.";
-                }
-            }
-            
-            BinaryRelationExpression::RelationType BinaryRelationExpression::getRelationType() const {
-                return relationType;
-            }
-            
-            void BinaryRelationExpression::accept(ExpressionVisitor* visitor) {
-                visitor->visit(this);
-            }
-            
-            std::string BinaryRelationExpression::toString() const {
-                std::stringstream result;
-                result << "(" << this->getLeft()->toString();
-                switch (relationType) {
-                    case EQUAL: result << " = "; break;
-                    case NOT_EQUAL: result << " != "; break;
-                    case LESS: result << " < "; break;
-                    case LESS_OR_EQUAL: result << " <= "; break;
-                    case GREATER: result << " > "; break;
-                    case GREATER_OR_EQUAL: result << " >= "; break;
-                }
-                result << this->getRight()->toString() << ")";
-                
-                return result.str();
-            }
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
\ No newline at end of file
diff --git a/src/ir/expressions/BinaryRelationExpression.h b/src/ir/expressions/BinaryRelationExpression.h
deleted file mode 100644
index 873cbe5bf..000000000
--- a/src/ir/expressions/BinaryRelationExpression.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * BinaryRelationExpression.h
- *
- *  Created on: 03.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_EXPRESSIONS_BINARYRELATIONEXPRESSION_H_
-#define STORM_IR_EXPRESSIONS_BINARYRELATIONEXPRESSION_H_
-
-#include "src/ir/expressions/BinaryExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            /*!
-             * A class representing a binary relation expression of boolean type.
-             */
-            class BinaryRelationExpression : public BinaryExpression {
-            public:
-                /*!
-                 * An enum type specifying the different relations applicable.
-                 */
-                enum RelationType {EQUAL, NOT_EQUAL, LESS, LESS_OR_EQUAL, GREATER, GREATER_OR_EQUAL};
-                
-                /*!
-                 * Creates a binary relation expression tree node with the given children and relation type.
-                 *
-                 * @param left The left child of the binary expression.
-                 * @param right The right child of the binary expression.
-                 * @param relationType The type of the relation associated with this node.
-                 */
-                BinaryRelationExpression(std::unique_ptr<BaseExpression>&& left, std::unique_ptr<BaseExpression>&& right, RelationType relationType);
-                
-                /*!
-                 * Copy-constructs from the given expression.
-                 *
-                 * @param binaryRelationExpression The expression to copy.
-                 */
-                BinaryRelationExpression(BinaryRelationExpression const& binaryRelationExpression);
-                
-                virtual std::unique_ptr<BaseExpression> clone() const override;
-                
-                virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override;
-                
-                virtual bool getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override;
-                
-                /*!
-                 * Retrieves the relation that is associated with this node.
-                 *
-                 * @param The relation that is associated with this node.
-                 */
-                RelationType getRelationType() const;
-                
-                virtual void accept(ExpressionVisitor* visitor) override;
-                
-                virtual std::string toString() const override;
-                
-            private:
-                // The relation operator associated with this node.
-                RelationType relationType;
-            };
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_EXPRESSIONS_BINARYRELATIONEXPRESSION_H_ */
diff --git a/src/ir/expressions/BooleanConstantExpression.cpp b/src/ir/expressions/BooleanConstantExpression.cpp
deleted file mode 100644
index 2022e8796..000000000
--- a/src/ir/expressions/BooleanConstantExpression.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * BooleanConstantExpression.cpp
- *
- *  Created on: 10.06.2013
- *      Author: Christian Dehnert
- */
-
-#include "BooleanConstantExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            BooleanConstantExpression::BooleanConstantExpression(std::string const& constantName) : ConstantExpression<bool>(bool_, constantName) {
-                // Nothing to do here.
-            }
-            
-            BooleanConstantExpression::BooleanConstantExpression(BooleanConstantExpression const& booleanConstantExpression) : ConstantExpression(booleanConstantExpression) {
-                // Nothing to do here.
-            }
-
-            std::unique_ptr<BaseExpression> BooleanConstantExpression::clone() const {
-                return std::unique_ptr<BaseExpression>(new BooleanConstantExpression(*this));
-            }
-
-            std::unique_ptr<BaseExpression> BooleanConstantExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const {
-                return std::unique_ptr<BaseExpression>(new BooleanConstantExpression(*this));
-            }
-            
-            bool BooleanConstantExpression::getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const {
-                if (!this->isDefined()) {
-                    throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: "
-                    << "Boolean constant '" << this->getConstantName() << "' is undefined.";
-                } else {
-                    return this->getValue();
-                }
-            }
-            
-            void BooleanConstantExpression::accept(ExpressionVisitor* visitor) {
-                visitor->visit(this);
-            }
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
\ No newline at end of file
diff --git a/src/ir/expressions/BooleanConstantExpression.h b/src/ir/expressions/BooleanConstantExpression.h
deleted file mode 100644
index 4838ba595..000000000
--- a/src/ir/expressions/BooleanConstantExpression.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * BooleanConstantExpression.h
- *
- *  Created on: 04.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_EXPRESSIONS_BOOLEANCONSTANTEXPRESSION_H_
-#define STORM_IR_EXPRESSIONS_BOOLEANCONSTANTEXPRESSION_H_
-
-#include "ConstantExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            /*!
-             * A class representing a boolean constant expression.
-             */
-            class BooleanConstantExpression : public ConstantExpression<bool> {
-            public:
-                /*!
-                 * Creates a boolean constant expression with the given constant name.
-                 *
-                 * @param constantName The name of the constant to use.
-                 */
-                BooleanConstantExpression(std::string const& constantName);
-                
-                /*!
-                 * Copy-constructs from the given expression.
-                 *
-                 * @param booleanConstantExpression The expression to copy.
-                 */
-                BooleanConstantExpression(BooleanConstantExpression const& booleanConstantExpression);
-                
-                virtual std::unique_ptr<BaseExpression> clone() const override;
-
-                virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override;
-                
-                virtual bool getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override;
-                
-                virtual void accept(ExpressionVisitor* visitor) override;
-            };
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_EXPRESSIONS_BOOLEANCONSTANTEXPRESSION_H_ */
diff --git a/src/ir/expressions/BooleanLiteralExpression.cpp b/src/ir/expressions/BooleanLiteralExpression.cpp
deleted file mode 100644
index 89e6b7876..000000000
--- a/src/ir/expressions/BooleanLiteralExpression.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * BooleanLiteralExpression.cpp
- *
- *  Created on: 04.01.2013
- *      Author: Christian Dehnert
- */
-
-#include "BooleanLiteralExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            BooleanLiteralExpression::BooleanLiteralExpression(bool value) : BaseExpression(bool_), value(value) {
-                // Nothing to do here.
-            }
-            
-            BooleanLiteralExpression::BooleanLiteralExpression(BooleanLiteralExpression const& booleanLiteralExpression)
-            : BaseExpression(booleanLiteralExpression), value(booleanLiteralExpression.value) {
-                // Nothing to do here.
-            }
-
-            std::unique_ptr<BaseExpression> BooleanLiteralExpression::clone() const {
-                return std::unique_ptr<BaseExpression>(new BooleanLiteralExpression(*this));
-            }
-                                                       
-            std::unique_ptr<BaseExpression> BooleanLiteralExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const {
-                return std::unique_ptr<BaseExpression>(new BooleanLiteralExpression(this->value));
-            }
-            
-            bool BooleanLiteralExpression::getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const {
-                return value;
-            }
-            
-            void BooleanLiteralExpression::accept(ExpressionVisitor* visitor) {
-                visitor->visit(this);
-            }
-            
-            std::string BooleanLiteralExpression::toString() const {
-                if (value) {
-                    return std::string("true");
-                } else {
-                    return std::string("false");
-                }
-            }
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
\ No newline at end of file
diff --git a/src/ir/expressions/BooleanLiteralExpression.h b/src/ir/expressions/BooleanLiteralExpression.h
deleted file mode 100644
index 1fb747a78..000000000
--- a/src/ir/expressions/BooleanLiteralExpression.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * BooleanLiteralExpression.h
- *
- *  Created on: 03.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_EXPRESSIONS_BOOLEANLITERALEXPRESSION_H_
-#define STORM_IR_EXPRESSIONS_BOOLEANLITERALEXPRESSION_H_
-
-#include "src/ir/expressions/BaseExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            /*!
-             * A class representing a boolean literal.
-             */
-            class BooleanLiteralExpression : public BaseExpression {
-            public:
-                /*!
-                 * Creates a boolean literal expression with the given value.
-                 *
-                 * @param value The value for the boolean literal.
-                 */
-                BooleanLiteralExpression(bool value);
-                
-                /*!
-                 * Copy-constructs from the given expression.
-                 *
-                 * @param booleanLiteralExpression The expression to copy.
-                 */
-                BooleanLiteralExpression(BooleanLiteralExpression const& booleanLiteralExpression);
-                
-                virtual std::unique_ptr<BaseExpression> clone() const override;
-                
-                virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override;
-                
-                virtual bool getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override;
-                
-                virtual void accept(ExpressionVisitor* visitor) override;
-                
-                virtual std::string toString() const override;
-                
-            private:
-                // The value of the boolean literal.
-                bool value;
-            };
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_EXPRESSIONS_BOOLEANLITERALEXPRESSION_H_ */
diff --git a/src/ir/expressions/ConstantExpression.h b/src/ir/expressions/ConstantExpression.h
deleted file mode 100644
index dc1763c33..000000000
--- a/src/ir/expressions/ConstantExpression.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * ConstantExpression.h
- *
- *  Created on: 03.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_EXPRESSIONS_CONSTANTEXPRESSION_H_
-#define STORM_IR_EXPRESSIONS_CONSTANTEXPRESSION_H_
-
-#include "BaseExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            // A struct for storing whether the constant was defined and if so, what value it holds.
-            template<class T>
-            struct ConstantDefinitionStruct {
-                /*!
-                 * Constructs a structure indicating that the constant has been defined with the given value.
-                 *
-                 * @param value The value with which the constant was defined.
-                 */
-                ConstantDefinitionStruct(T value) : value(value), defined(true) {
-                   // Nothing to do here. 
-                }
-                
-                /*!
-                 * Constructs a structure indicating that the constant has not yet been defined.
-                 *
-                 * @param value The value with which the constant was defined.
-                 */
-                ConstantDefinitionStruct() : value(), defined(false) {
-                    // Nothing to do here. 
-                }
-                
-                T value;
-                bool defined;
-            };
-            
-            /*!
-             * A class representing a generic constant expression.
-             */
-            template<class T>
-            class ConstantExpression : public BaseExpression {
-            public:
-                /*!
-                 * Constructs a constant expression of the given type with the given constant name.
-                 *
-                 * @param type The type of the constant.
-                 * @param constantName The name of the constant.
-                 */
-                ConstantExpression(ReturnType type, std::string const& constantName) : BaseExpression(type), constantName(constantName), valueStructPointer(new ConstantDefinitionStruct<T>()) {
-                    // Nothing to do here.
-                }
-                
-                /*!
-                 * Copy-constructs from the given expression.
-                 *
-                 * @param constantExpression The expression to copy.
-                 */
-                ConstantExpression(ConstantExpression const& constantExpression) : BaseExpression(constantExpression), constantName(constantExpression.constantName), valueStructPointer(constantExpression.valueStructPointer) {
-                    // Nothing to do here.
-                }
-                
-                /*!
-                 * Retrieves the name of the constant.
-                 *
-                 * @return The name of the constant.
-                 */
-                std::string const& getConstantName() const {
-                    return constantName;
-                }
-                
-                virtual std::string toString() const override {
-                    std::stringstream result;
-                    if (this->valueStructPointer->defined) {
-                        result << this->valueStructPointer->value;
-                    } else {
-                        result << this->getConstantName();
-                    }
-                    return result.str();
-                }
-                
-                /*!
-                 * Retrieves whether the constant is defined or not.
-                 *
-                 * @return True if the constant is defined.
-                 */
-                bool isDefined() const {
-                    return this->valueStructPointer->defined;
-                }
-                
-                /*!
-                 * Retrieves the value of the constant if it is defined.
-                 */
-                T getValue() const {
-                    return this->valueStructPointer->value;
-                }
-                
-                /*!
-                 * Defines the constant using the given value.
-                 *
-                 * @param value The value to use for defining the constant.
-                 */
-                void define(T value) {
-                    this->valueStructPointer->defined = true;
-                    this->valueStructPointer->value = value;
-                }
-                
-                /*!
-                 * Undefines the value that was previously set for this constant (if any).
-                 */
-                void undefine() {
-                    this->valueStructPointer->defined = false;
-                    this->valueStructPointer->value = T();
-                }
-                
-            private:
-                // The name of the constant.
-                std::string constantName;
-                
-                // The definedness status and (if applicable) the value of the constant.
-                std::shared_ptr<ConstantDefinitionStruct<T>> valueStructPointer;
-            };
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_EXPRESSIONS_CONSTANTEXPRESSION_H_ */
diff --git a/src/ir/expressions/DoubleConstantExpression.cpp b/src/ir/expressions/DoubleConstantExpression.cpp
deleted file mode 100644
index bc29cbf26..000000000
--- a/src/ir/expressions/DoubleConstantExpression.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * DoubleConstantExpression.cpp
- *
- *  Created on: 10.06.2013
- *      Author: Christian Dehnert
- */
-
-#include "DoubleConstantExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            DoubleConstantExpression::DoubleConstantExpression(std::string const& constantName) : ConstantExpression<double>(double_, constantName) {
-                // Nothing to do here.
-            }
-            
-            DoubleConstantExpression::DoubleConstantExpression(DoubleConstantExpression const& doubleConstantExpression) : ConstantExpression(doubleConstantExpression) {
-                // Nothing to do here.
-            }
-            
-            std::unique_ptr<BaseExpression> DoubleConstantExpression::clone() const {
-                return std::unique_ptr<BaseExpression>(new DoubleConstantExpression(*this));
-            }
-            
-            std::unique_ptr<BaseExpression> DoubleConstantExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const {
-                return std::unique_ptr<BaseExpression>(new DoubleConstantExpression(*this));
-            }
-            
-            double DoubleConstantExpression::getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const {
-                if (!this->isDefined()) {
-                    throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: "
-                    << "Double constant '" << this->getConstantName() << "' is undefined.";
-                } else {
-                    return this->getValue();
-                }
-            }
-            
-            void DoubleConstantExpression::accept(ExpressionVisitor* visitor) {
-                visitor->visit(this);
-            }
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
\ No newline at end of file
diff --git a/src/ir/expressions/DoubleConstantExpression.h b/src/ir/expressions/DoubleConstantExpression.h
deleted file mode 100644
index 9eaa6eb18..000000000
--- a/src/ir/expressions/DoubleConstantExpression.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * DoubleConstantExpression.h
- *
- *  Created on: 04.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_EXPRESSIONS_DOUBLECONSTANTEXPRESSION_H_
-#define STORM_IR_EXPRESSIONS_DOUBLECONSTANTEXPRESSION_H_
-
-#include "ConstantExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            /*!
-             * A class representing a constant expression of type double.
-             */
-            class DoubleConstantExpression : public ConstantExpression<double> {
-            public:
-                /*!
-                 * Creates a double constant expression with the given constant name.
-                 *
-                 * @param constantName The name of the constant to use.
-                 */
-                DoubleConstantExpression(std::string const& constantName);
-                
-                /*!
-                 * Copy-constructs from the given expression.
-                 *
-                 * @param doubleConstantExpression The expression to copy.
-                 */
-                DoubleConstantExpression(DoubleConstantExpression const& doubleConstantExpression);
-                
-                virtual std::unique_ptr<BaseExpression> clone() const override;
-                
-                virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override;
-                
-                virtual double getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override;
-                
-                virtual void accept(ExpressionVisitor* visitor) override;
-            };
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_EXPRESSIONS_DOUBLECONSTANTEXPRESSION_H_ */
diff --git a/src/ir/expressions/DoubleLiteralExpression.cpp b/src/ir/expressions/DoubleLiteralExpression.cpp
deleted file mode 100644
index 08663f8f7..000000000
--- a/src/ir/expressions/DoubleLiteralExpression.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * DoubleLiteralExpression.cpp
- *
- *  Created on: 10.06.2013
- *      Author: Christian Dehnert
- */
-
-#include <sstream>
-
-#include "DoubleLiteralExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            DoubleLiteralExpression::DoubleLiteralExpression(double value) : BaseExpression(double_), value(value) {
-                // Nothing to do here.
-            }
-            
-            DoubleLiteralExpression::DoubleLiteralExpression(DoubleLiteralExpression const& doubleLiteralExpression)
-            : BaseExpression(doubleLiteralExpression), value(doubleLiteralExpression.value) {
-                // Nothing to do here.
-            }
-            
-            std::unique_ptr<BaseExpression> DoubleLiteralExpression::clone() const {
-                return std::unique_ptr<BaseExpression>(new DoubleLiteralExpression(*this));
-            }
-
-            std::unique_ptr<BaseExpression> DoubleLiteralExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const {
-                return std::unique_ptr<BaseExpression>(new DoubleLiteralExpression(this->value));
-            }
-            
-            double DoubleLiteralExpression::getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const {
-                return value;
-            }
-            
-            void DoubleLiteralExpression::accept(ExpressionVisitor* visitor) {
-                visitor->visit(this);
-            }
-            
-            std::string DoubleLiteralExpression::toString() const {
-                std::stringstream result;
-                result << value;
-                return result.str();
-            }
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
\ No newline at end of file
diff --git a/src/ir/expressions/DoubleLiteralExpression.h b/src/ir/expressions/DoubleLiteralExpression.h
deleted file mode 100644
index 7105858c2..000000000
--- a/src/ir/expressions/DoubleLiteralExpression.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * DoubleLiteralExpression.h
- *
- *  Created on: 03.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_EXPRESSIONS_DOUBLELITERALEXPRESSION_H_
-#define STORM_IR_EXPRESSIONS_DOUBLELITERALEXPRESSION_H_
-
-#include "src/ir/expressions/BaseExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            /*!
-             * A class representing a double literal.
-             */
-            class DoubleLiteralExpression : public BaseExpression {
-            public:
-                /*!
-                 * Creates a double literal expression with the given value.
-                 *
-                 * @param value The value for the double literal.
-                 */
-                DoubleLiteralExpression(double value);
-                
-                /*!
-                 * Copy-constructs from the given expression.
-                 *
-                 * @param doubleLiteralExpression The expression to copy.
-                 */
-                DoubleLiteralExpression(DoubleLiteralExpression const& doubleLiteralExpression);
-                
-                virtual std::unique_ptr<BaseExpression> clone() const override;
-                
-                virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override;
-                
-                virtual double getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override;
-                
-                virtual void accept(ExpressionVisitor* visitor) override;
-                
-                virtual std::string toString() const override;
-                
-            private:
-                // The value of the double literal.
-                double value;
-            };
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_EXPRESSIONS_DOUBLELITERALEXPRESSION_H_ */
diff --git a/src/ir/expressions/ExpressionVisitor.h b/src/ir/expressions/ExpressionVisitor.h
deleted file mode 100644
index d301e9792..000000000
--- a/src/ir/expressions/ExpressionVisitor.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * ExpressionVisitor.h
- *
- *  Created on: 26.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_EXPRESSIONS_EXPRESSIONVISITOR_H_
-#define STORM_IR_EXPRESSIONS_EXPRESSIONVISITOR_H_
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            class BaseExpression;
-            class BinaryBooleanFunctionExpression;
-            class BinaryNumericalFunctionExpression;
-            class BinaryRelationExpression;
-            class BooleanConstantExpression;
-            class BooleanLiteralExpression;
-            class DoubleConstantExpression;
-            class DoubleLiteralExpression;
-            class IntegerConstantExpression;
-            class IntegerLiteralExpression;
-            class UnaryBooleanFunctionExpression;
-            class UnaryNumericalFunctionExpression;
-            class VariableExpression;
-            
-            class ExpressionVisitor {
-            public:
-                virtual void visit(BinaryBooleanFunctionExpression* expression) = 0;
-                virtual void visit(BinaryNumericalFunctionExpression* expression) = 0;
-                virtual void visit(BinaryRelationExpression* expression) = 0;
-                virtual void visit(BooleanConstantExpression* expression) = 0;
-                virtual void visit(BooleanLiteralExpression* expression) = 0;
-                virtual void visit(DoubleConstantExpression* expression) = 0;
-                virtual void visit(DoubleLiteralExpression* expression) = 0;
-                virtual void visit(IntegerConstantExpression* expression) = 0;
-                virtual void visit(IntegerLiteralExpression* expression) = 0;
-                virtual void visit(UnaryBooleanFunctionExpression* expression) = 0;
-                virtual void visit(UnaryNumericalFunctionExpression* expression) = 0;
-                virtual void visit(VariableExpression* expression) = 0;
-            };
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_EXPRESSIONS_EXPRESSIONVISITOR_H_ */
diff --git a/src/ir/expressions/Expressions.h b/src/ir/expressions/Expressions.h
deleted file mode 100644
index 634a0585d..000000000
--- a/src/ir/expressions/Expressions.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Expressions.h
- *
- *  Created on: 03.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_EXPRESSIONS_EXPRESSIONS_H_
-#define STORM_IR_EXPRESSIONS_EXPRESSIONS_H_
-
-#include "BaseExpression.h"
-#include "BinaryBooleanFunctionExpression.h"
-#include "BinaryNumericalFunctionExpression.h"
-#include "BinaryRelationExpression.h"
-#include "BooleanLiteralExpression.h"
-#include "DoubleLiteralExpression.h"
-#include "IntegerLiteralExpression.h"
-#include "UnaryBooleanFunctionExpression.h"
-#include "UnaryNumericalFunctionExpression.h"
-#include "VariableExpression.h"
-#include "ConstantExpression.h"
-#include "BooleanConstantExpression.h"
-#include "IntegerConstantExpression.h"
-#include "DoubleConstantExpression.h"
-
-#endif /* STORM_IR_EXPRESSIONS_EXPRESSIONS_H_ */
diff --git a/src/ir/expressions/IntegerConstantExpression.cpp b/src/ir/expressions/IntegerConstantExpression.cpp
deleted file mode 100644
index bcc5cb0eb..000000000
--- a/src/ir/expressions/IntegerConstantExpression.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * IntegerConstantExpression.cpp
- *
- *  Created on: 10.06.2013
- *      Author: Christian Dehnert
- */
-
-#include "IntegerConstantExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            IntegerConstantExpression::IntegerConstantExpression(std::string const& constantName) : ConstantExpression(int_, constantName) {
-                // Nothing to do here.
-            }
-            
-            IntegerConstantExpression::IntegerConstantExpression(IntegerConstantExpression const& integerConstantExpression) : ConstantExpression(integerConstantExpression) {
-                // Nothing to do here.
-            }
-            
-            std::unique_ptr<BaseExpression> IntegerConstantExpression::clone() const {
-                return std::unique_ptr<BaseExpression>(new IntegerConstantExpression(*this));
-            }
-            
-            std::unique_ptr<BaseExpression> IntegerConstantExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const {
-                return std::unique_ptr<BaseExpression>(new IntegerConstantExpression(*this));
-            }
-            
-            double IntegerConstantExpression::getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const {
-                return static_cast<double>(getValueAsInt(variableValues));
-            }
-            
-            int_fast64_t IntegerConstantExpression::getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const {
-                if (!this->isDefined()) {
-                    throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: "
-                    << "Integer constant '" << this->getConstantName() << "' is undefined.";
-                } else {
-                    return this->getValue();
-                }
-            }
-            
-            void IntegerConstantExpression::accept(ExpressionVisitor* visitor) {
-                visitor->visit(this);
-            }
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
\ No newline at end of file
diff --git a/src/ir/expressions/IntegerConstantExpression.h b/src/ir/expressions/IntegerConstantExpression.h
deleted file mode 100644
index 04370574d..000000000
--- a/src/ir/expressions/IntegerConstantExpression.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * IntegerConstantExpression.h
- *
- *  Created on: 04.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_EXPRESSIONS_INTEGERCONSTANTEXPRESSION_H_
-#define STORM_IR_EXPRESSIONS_INTEGERCONSTANTEXPRESSION_H_
-
-#include "ConstantExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            /*!
-             * A class representing a constant expression of type integer.
-             */
-            class IntegerConstantExpression : public ConstantExpression<int_fast64_t> {
-            public:
-                /*!
-                 * Creates an integer constant expression with the given constant name.
-                 *
-                 * @param constantName The name of the constant to use.
-                 */
-                IntegerConstantExpression(std::string const& constantName);
-                
-                /*!
-                 * Copy-constructs from the given expression.
-                 *
-                 * @param integerConstantExpression The expression to copy.
-                 */
-                IntegerConstantExpression(IntegerConstantExpression const& integerConstantExpression);
-                
-                virtual std::unique_ptr<BaseExpression> clone() const override;
-                
-                virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override;
-                
-                virtual double getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override;
-                
-                virtual int_fast64_t getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override;
-                
-                virtual void accept(ExpressionVisitor* visitor) override;
-            };
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_EXPRESSIONS_INTEGERCONSTANTEXPRESSION_H_ */
diff --git a/src/ir/expressions/IntegerLiteralExpression.cpp b/src/ir/expressions/IntegerLiteralExpression.cpp
deleted file mode 100644
index ed3277f18..000000000
--- a/src/ir/expressions/IntegerLiteralExpression.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * IntegerLiteralExpression.cpp
- *
- *  Created on: 03.01.2013
- *      Author: Christian Dehnert
- */
-
-#include <sstream>
-
-#include "IntegerLiteralExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            IntegerLiteralExpression::IntegerLiteralExpression(int_fast64_t value) : BaseExpression(int_), value(value) {
-                // Nothing to do here.
-            }
-            
-            IntegerLiteralExpression::IntegerLiteralExpression(IntegerLiteralExpression const& integerLiteralExpression)
-            : BaseExpression(integerLiteralExpression), value(integerLiteralExpression.value) {
-                // Nothing to do here.
-            }
-            
-            std::unique_ptr<BaseExpression> IntegerLiteralExpression::clone() const {
-                return std::unique_ptr<BaseExpression>(new IntegerLiteralExpression(*this));
-            }
-            
-            std::unique_ptr<BaseExpression> IntegerLiteralExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const {
-                return std::unique_ptr<BaseExpression>(new IntegerLiteralExpression(this->value));
-            }
-            
-            double IntegerLiteralExpression::getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const {
-                return static_cast<double>(value);
-            }
-            
-            int_fast64_t IntegerLiteralExpression::getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const {
-                return value;
-            }
-            
-            void IntegerLiteralExpression::accept(ExpressionVisitor* visitor) {
-                visitor->visit(this);
-            }
-            
-            std::string IntegerLiteralExpression::toString() const {
-                std::stringstream result;
-                result << value;
-                return result.str();
-            }
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
\ No newline at end of file
diff --git a/src/ir/expressions/IntegerLiteralExpression.h b/src/ir/expressions/IntegerLiteralExpression.h
deleted file mode 100644
index cb1041684..000000000
--- a/src/ir/expressions/IntegerLiteralExpression.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * IntegerLiteralExpression.h
- *
- *  Created on: 03.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_EXPRESSIONS_INTEGERLITERALEXPRESSION_H_
-#define STORM_IR_EXPRESSIONS_INTEGERLITERALEXPRESSION_H_
-
-#include "src/ir/expressions/BaseExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            /*!
-             * A class representing an integer literal.
-             */
-            class IntegerLiteralExpression : public BaseExpression {
-            public:
-                /*!
-                 * Creates an integer literal expression with the given value.
-                 *
-                 * @param value The value for the integer literal.
-                 */
-                IntegerLiteralExpression(int_fast64_t value);
-                
-                /*!
-                 * Copy-constructs from the given expression.
-                 *
-                 * @param integerLiteralExpression The expression to copy.
-                 */
-                IntegerLiteralExpression(IntegerLiteralExpression const& integerLiteralExpression);
-                
-                virtual std::unique_ptr<BaseExpression> clone() const override;
-                
-                virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override;
-                
-                virtual double getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override;
-                
-                virtual int_fast64_t getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override;
-                
-                virtual void accept(ExpressionVisitor* visitor) override;
-                
-                virtual std::string toString() const override;
-                
-            private:
-                // The value of the double literal.
-                int_fast64_t value;
-            };
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_EXPRESSIONS_INTEGERLITERALEXPRESSION_H_ */
diff --git a/src/ir/expressions/UnaryBooleanFunctionExpression.cpp b/src/ir/expressions/UnaryBooleanFunctionExpression.cpp
deleted file mode 100644
index 3b0e6ca03..000000000
--- a/src/ir/expressions/UnaryBooleanFunctionExpression.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * UnaryBooleanFunctionExpression.cpp
- *
- *  Created on: 10.06.2013
- *      Author: Christian Dehnert
- */
-
-#include <sstream>
-
-#include "UnaryBooleanFunctionExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            UnaryBooleanFunctionExpression::UnaryBooleanFunctionExpression(std::unique_ptr<BaseExpression>&& child, FunctionType functionType) : UnaryExpression(bool_, std::move(child)), functionType(functionType) {
-                // Nothing to do here.
-            }
-            
-            UnaryBooleanFunctionExpression::UnaryBooleanFunctionExpression(UnaryBooleanFunctionExpression const& unaryBooleanFunctionExpression) : UnaryExpression(unaryBooleanFunctionExpression), functionType(unaryBooleanFunctionExpression.functionType) {
-                // Nothing to do here.
-            }
-            
-            std::unique_ptr<BaseExpression> UnaryBooleanFunctionExpression::clone() const {
-                return std::unique_ptr<BaseExpression>(new UnaryBooleanFunctionExpression(this->getChild()->clone(), functionType));
-            }
-            
-            std::unique_ptr<BaseExpression> UnaryBooleanFunctionExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const {
-                return std::unique_ptr<BaseExpression>(new UnaryBooleanFunctionExpression(this->getChild()->clone(renaming, variableState), this->functionType));
-            }
-            
-            UnaryBooleanFunctionExpression::FunctionType UnaryBooleanFunctionExpression::getFunctionType() const {
-                return functionType;
-            }
-            
-            bool UnaryBooleanFunctionExpression::getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const {
-                bool resultChild = this->getChild()->getValueAsBool(variableValues);
-                switch(functionType) {
-                    case NOT: return !resultChild; break;
-                    default: throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: "
-                        << "Unknown boolean unary operator: '" << functionType << "'.";
-                }
-            }
-            
-            void UnaryBooleanFunctionExpression::accept(ExpressionVisitor* visitor) {
-                visitor->visit(this);
-            }
-            
-            std::string UnaryBooleanFunctionExpression::toString() const {
-                std::stringstream result;
-                result << "(";
-                switch (functionType) {
-                    case NOT: result << "!"; break;
-                }
-                result << this->getChild()->toString() << ")";
-                
-                return result.str();
-            }
-
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
diff --git a/src/ir/expressions/UnaryBooleanFunctionExpression.h b/src/ir/expressions/UnaryBooleanFunctionExpression.h
deleted file mode 100644
index a3087f5e5..000000000
--- a/src/ir/expressions/UnaryBooleanFunctionExpression.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * UnaryBooleanFunctionExpression.h
- *
- *  Created on: 03.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_EXPRESSIONS_UNARYBOOLEANFUNCTIONEXPRESSION_H_
-#define STORM_IR_EXPRESSIONS_UNARYBOOLEANFUNCTIONEXPRESSION_H_
-
-#include "UnaryExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            /*!
-             * A class representing a unary function expression of boolean type.
-             */
-            class UnaryBooleanFunctionExpression : public UnaryExpression {
-            public:
-                /*!
-                 * An enum type specifying the different functions applicable.
-                 */
-                enum FunctionType {NOT};
-                
-                /*!
-                 * Creates a unary boolean function expression tree node with the given child and function type.
-                 *
-                 * @param child The child of the node.
-                 * @param functionType The operator that is to be applied to the two children.
-                 */
-                UnaryBooleanFunctionExpression(std::unique_ptr<BaseExpression>&& child, FunctionType functionType);
-                
-                /*!
-                 * Copy-constructs from the given expression.
-                 *
-                 * @param unaryBooleanFunctionExpression The expression to copy.
-                 */
-                UnaryBooleanFunctionExpression(UnaryBooleanFunctionExpression const& unaryBooleanFunctionExpression);
-                
-                virtual std::unique_ptr<BaseExpression> clone() const override;
-                
-                virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override;
-
-                /*!
-                 * Retrieves the operator that is associated with this node.
-                 *
-                 * @param The operator that is associated with this node.
-                 */
-                FunctionType getFunctionType() const;
-                
-                virtual bool getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override;
-                
-                virtual void accept(ExpressionVisitor* visitor) override;
-                
-                virtual std::string toString() const override;
-                                
-            private:
-                // The operator that is associated with this node.
-                FunctionType functionType;
-            };
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_EXPRESSIONS_UNARYBOOLEANFUNCTIONEXPRESSION_H_ */
diff --git a/src/ir/expressions/UnaryExpression.cpp b/src/ir/expressions/UnaryExpression.cpp
deleted file mode 100644
index 31463aff3..000000000
--- a/src/ir/expressions/UnaryExpression.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * UnaryExpression.cpp
- *
- *  Created on: 27.01.2013
- *      Author: Christian Dehnert
- */
-
-#include "UnaryExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-    
-            UnaryExpression::UnaryExpression(ReturnType type, std::unique_ptr<BaseExpression>&& child) : BaseExpression(type), child(std::move(child)) {
-                // Nothing to do here.
-            }
-            
-            UnaryExpression::UnaryExpression(UnaryExpression const& unaryExpression) : BaseExpression(unaryExpression), child(unaryExpression.child->clone()) {
-                // Nothing to do here.
-            }
-            
-            std::unique_ptr<BaseExpression> const& UnaryExpression::getChild() const {
-                return child;
-            }
-            
-            BaseExpression* UnaryExpression::performSubstitution(std::map<std::string, std::reference_wrapper<BaseExpression>> const& substitution) {
-                BaseExpression* newChild = child->performSubstitution(substitution);
-                
-                // Only update the child if it changed, because otherwise the child gets destroyed.
-                if (newChild != child.get()) {
-                    child = std::unique_ptr<BaseExpression>(newChild);
-                }
-                
-                return this;
-            }
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
diff --git a/src/ir/expressions/UnaryExpression.h b/src/ir/expressions/UnaryExpression.h
deleted file mode 100644
index cfc685455..000000000
--- a/src/ir/expressions/UnaryExpression.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * UnaryExpression.h
- *
- *  Created on: 27.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_EXPRESSIONS_UNARYEXPRESSION_H_
-#define STORM_IR_EXPRESSIONS_UNARYEXPRESSION_H_
-
-#include "BaseExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            /*!
-             * A class representing a generic unary expression.
-             */
-            class UnaryExpression : public BaseExpression {
-            public:
-                /*!
-                 * Constructs a unary expression with the given type and child.
-                 * @param type The type of the unary expression.
-                 * @param right The child of the unary expression.
-                 */
-                UnaryExpression(ReturnType type, std::unique_ptr<BaseExpression>&& child);
-                
-                /*!
-                 * Copy-constructs from the given expression.
-                 *
-                 * @param unaryExpression The expression to copy.
-                 */
-                UnaryExpression(UnaryExpression const& unaryExpression);
-                
-                /*!
-                 * Retrieves the child of the expression node.
-                 *
-                 * @return The child of the expression node.
-                 */
-                std::unique_ptr<BaseExpression> const& getChild() const;
-
-            protected:
-                virtual BaseExpression* performSubstitution(std::map<std::string, std::reference_wrapper<BaseExpression>> const& substitution) override;
-                
-            private:
-                // The left child of the unary expression.
-                std::unique_ptr<BaseExpression> child;
-            };
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_EXPRESSIONS_UNARYEXPRESSION_H_ */
diff --git a/src/ir/expressions/UnaryNumericalFunctionExpression.cpp b/src/ir/expressions/UnaryNumericalFunctionExpression.cpp
deleted file mode 100644
index 6b4b1fbb2..000000000
--- a/src/ir/expressions/UnaryNumericalFunctionExpression.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * UnaryFunctionExpression.h
- *
- *  Created on: 03.01.2013
- *      Author: Christian Dehnert
- */
-
-#include <cmath>
-
-#include "UnaryNumericalFunctionExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            UnaryNumericalFunctionExpression::UnaryNumericalFunctionExpression(ReturnType type, std::unique_ptr<BaseExpression>&& child, FunctionType functionType) : UnaryExpression(type, std::move(child)), functionType(functionType) {
-                // Nothing to do here.
-            }
-            
-            UnaryNumericalFunctionExpression::UnaryNumericalFunctionExpression(UnaryNumericalFunctionExpression const& unaryNumericalFunctionExpression) : UnaryExpression(unaryNumericalFunctionExpression), functionType(unaryNumericalFunctionExpression.functionType) {
-                // Nothing to do here.
-            }
-            
-            std::unique_ptr<BaseExpression> UnaryNumericalFunctionExpression::clone() const {
-                return std::unique_ptr<BaseExpression>(new UnaryNumericalFunctionExpression(this->getType(), this->getChild()->clone(), functionType));
-            }
-            
-            std::unique_ptr<BaseExpression> UnaryNumericalFunctionExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const {
-                return std::unique_ptr<BaseExpression>(new UnaryNumericalFunctionExpression(this->getType(), this->getChild()->clone(renaming, variableState), this->functionType));
-            }
-            
-            int_fast64_t UnaryNumericalFunctionExpression::getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const {
-                if (this->getType() != int_) {
-                    BaseExpression::getValueAsInt(variableValues);
-                }
-                
-                int_fast64_t resultChild = this->getChild()->getValueAsInt(variableValues);
-                switch(functionType) {
-                    case MINUS: return -resultChild; break;
-                    case FLOOR: return static_cast<int_fast64_t>(std::floor(resultChild)); break;
-                    case CEIL: return static_cast<int_fast64_t>(std::ceil(resultChild)); break;
-                    default: throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: "
-                        << "Unknown numerical unary operator: '" << functionType << "'.";
-                }
-            }
-            
-            double UnaryNumericalFunctionExpression::getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const {
-                if (this->getType() != double_ && this->getType() != int_) {
-                    BaseExpression::getValueAsDouble(variableValues);
-                }
-                
-                double resultChild = this->getChild()->getValueAsDouble(variableValues);
-                switch(functionType) {
-                    case MINUS: return -resultChild; break;
-                    case FLOOR: return std::floor(resultChild); break;
-                    case CEIL: return std::ceil(resultChild); break;
-                    default: throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: "
-                        << "Unknown numerical unary operator: '" << functionType << "'.";
-                }
-            }
-            
-            UnaryNumericalFunctionExpression::FunctionType UnaryNumericalFunctionExpression::getFunctionType() const {
-                return functionType;
-            }
-            
-            void UnaryNumericalFunctionExpression::accept(ExpressionVisitor* visitor) {
-                visitor->visit(this);
-            }
-            
-            std::string UnaryNumericalFunctionExpression::toString() const {
-                std::stringstream result;
-                result << "(";
-                switch (functionType) {
-                    case MINUS: result << "-"; break;
-                    case FLOOR: result << "floor("; break;
-                    case CEIL: result << "ceil("; break;
-                }
-                result << this->getChild()->toString() << ")";
-                
-                return result.str();
-            }
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
-
diff --git a/src/ir/expressions/UnaryNumericalFunctionExpression.h b/src/ir/expressions/UnaryNumericalFunctionExpression.h
deleted file mode 100644
index bcb942378..000000000
--- a/src/ir/expressions/UnaryNumericalFunctionExpression.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * UnaryFunctionExpression.h
- *
- *  Created on: 03.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_EXPRESSIONS_UNARYFUNCTIONEXPRESSION_H_
-#define STORM_IR_EXPRESSIONS_UNARYFUNCTIONEXPRESSION_H_
-
-#include "UnaryExpression.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            /*!
-             * A class representing a unary function expression of numerical type.
-             */
-            class UnaryNumericalFunctionExpression : public UnaryExpression {
-            public:
-                /*!
-                 * An enum type specifying the different functions applicable.
-                 */
-                enum FunctionType {MINUS, FLOOR, CEIL};
-                
-                /*!
-                 * Creates a unary numerical function expression tree node with the given child and function type.
-                 *
-                 * @param child The child of the node.
-                 * @param functionType The operator that is to be applied to the two children.
-                 */
-                UnaryNumericalFunctionExpression(ReturnType type, std::unique_ptr<BaseExpression>&& child, FunctionType functionType);
-                
-                /*!
-                 * Copy-constructs from the given expression.
-                 *
-                 * @param unaryNumericalFunctionExpression The expression to copy.
-                 */
-                UnaryNumericalFunctionExpression(UnaryNumericalFunctionExpression const& unaryNumericalFunctionExpression);
-                
-                virtual std::unique_ptr<BaseExpression> clone() const override;
-                
-                virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override;
-                
-                virtual int_fast64_t getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override;
-                
-                virtual double getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override;
-                
-                /*!
-                 * Retrieves the operator that is associated with this node.
-                 *
-                 * @param The operator that is associated with this node.
-                 */
-                FunctionType getFunctionType() const;
-                
-                virtual void accept(ExpressionVisitor* visitor) override;
-                
-                virtual std::string toString() const override;
-                
-            private:
-                // The operator that is associated with this node.
-                FunctionType functionType;
-            };
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_EXPRESSIONS_UNARYFUNCTIONEXPRESSION_H_ */
diff --git a/src/ir/expressions/VariableExpression.cpp b/src/ir/expressions/VariableExpression.cpp
deleted file mode 100644
index 9bf09a734..000000000
--- a/src/ir/expressions/VariableExpression.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * VariableExpression.cpp
- *
- *  Created on: 10.06.2013
- *      Author: Christian Dehnert
- */
-
-#include "VariableExpression.h"
-#include "src/parser/prismparser/VariableState.h"
-#include "src/exceptions/ExpressionEvaluationException.h"
-
-namespace storm {
-    namespace ir {
-        namespace expressions {
-            
-            VariableExpression::VariableExpression(ReturnType type, std::string const& variableName) : BaseExpression(type), globalIndex(0), variableName(variableName) {
-                // Nothing to do here.
-            }
-            
-            VariableExpression::VariableExpression(ReturnType type, uint_fast64_t globalIndex, std::string const& variableName)
-            : BaseExpression(type), globalIndex(globalIndex), variableName(variableName) {
-                // Nothing to do here.
-            }
-            
-            VariableExpression::VariableExpression(VariableExpression const& variableExpression) : BaseExpression(variableExpression), globalIndex(variableExpression.globalIndex), variableName(variableExpression.variableName) {
-                // Nothing to do here.
-            }
-            
-            std::unique_ptr<BaseExpression> VariableExpression::clone() const {
-                return std::unique_ptr<BaseExpression>(new VariableExpression(*this));
-            }
-            
-            std::unique_ptr<BaseExpression> VariableExpression::clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const {
-                // Perform the proper cloning.
-                auto renamingPair = renaming.find(this->variableName);
-                if (renamingPair != renaming.end()) {
-                    if (this->getType() == int_) {
-                        return variableState.getIntegerVariableExpression(renamingPair->second)->clone();
-                    } else {
-                        return variableState.getBooleanVariableExpression(renamingPair->second)->clone();
-                    }
-                } else {
-                    if (this->getType() == int_) {
-                        return variableState.getIntegerVariableExpression(this->variableName)->clone();
-                    } else {
-                        return variableState.getBooleanVariableExpression(this->variableName)->clone();
-                    }
-                }
-            }
-            
-            BaseExpression* VariableExpression::performSubstitution(std::map<std::string, std::reference_wrapper<BaseExpression>> const& substitution) {
-                // If the name of the variable is a key of the map, we need to replace it.
-                auto substitutionIterator = substitution.find(variableName);
-                
-                if (substitutionIterator != substitution.end()) {
-                    std::unique_ptr<BaseExpression> expressionClone = substitutionIterator->second.get().clone();
-                    BaseExpression* rawPointer = expressionClone.release();
-                    return rawPointer;
-                } else {
-                    // Otherwise, we don't need to replace anything.
-                    return this;
-                }
-            }
-            
-            void VariableExpression::accept(ExpressionVisitor* visitor) {
-                visitor->visit(this);
-            }
-            
-            std::string VariableExpression::toString() const {
-                return this->variableName;
-            }
-            
-            int_fast64_t VariableExpression::getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const {
-                if (this->getType() != int_) {
-                    BaseExpression::getValueAsInt(variableValues);
-                }
-                
-                if (variableValues != nullptr) {
-                    return variableValues->second[globalIndex];
-                } else {
-                    throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression involving variables without variable values.";
-                }
-            }
-            
-            bool VariableExpression::getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const {
-                if (this->getType() != bool_) {
-                    BaseExpression::getValueAsBool(variableValues);
-                }
-                
-                if (variableValues != nullptr) {
-                    return variableValues->first[globalIndex];
-                } else {
-                    throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression involving variables without variable values.";
-                }
-            }
-            
-            double VariableExpression::getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const {
-                if (this->getType() != double_ && this->getType() != int_) {
-                    BaseExpression::getValueAsDouble(variableValues);
-                }
-                
-                // Because only int variables can deliver a double value, we only need to check them.
-                if (variableValues != nullptr) {
-                    return static_cast<double>(variableValues->second[globalIndex]);
-                } else {
-                    throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression with variable '" << variableName << "' of type double.";
-                }
-            }
-            
-            std::string const& VariableExpression::getVariableName() const {
-                return variableName;
-            }
-            
-            uint_fast64_t VariableExpression::getGlobalVariableIndex() const {
-                return this->globalIndex;
-            }
-            
-        } // namespace expressions
-    } // namespace ir
-} // namespace storm
diff --git a/src/ir/expressions/VariableExpression.h b/src/ir/expressions/VariableExpression.h
deleted file mode 100644
index 99358d377..000000000
--- a/src/ir/expressions/VariableExpression.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * VariableExpression.h
- *
- *  Created on: 03.01.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_IR_EXPRESSIONS_VARIABLEEXPRESSION_H_
-#define STORM_IR_EXPRESSIONS_VARIABLEEXPRESSION_H_
-
-#include "BaseExpression.h"
-
-namespace storm {
-	
-    // Forward-declare VariableState.
-	namespace parser {
-		namespace prismparser {
-			class VariableState;
-		} // namespace prismparser
-	} // namespace parser
-    
-	namespace ir {
-		namespace expressions {
-			
-            /*!
-             * A class representing a variable in the expression tree.
-             */
-			class VariableExpression : public BaseExpression {
-			public:
-                /*!
-                 * Creates a variable expression of the given type with the given name. As this variable has no indices
-                 * it is only meant as a dummy and needs to be replaced with a "full" variable expression.
-                 *
-                 * @param type The type of the variable.
-                 * @param variableName The name of the variable.
-                 */
-				VariableExpression(ReturnType type, std::string const& variableName);
-				
-                /*!
-                 * Creates a variable expression of the given type with the given name and indices.
-                 *
-                 * @param type The type of the variable.
-                 * @param globalIndex The global (i.e. program-wide) index of the variable.
-                 * @param variableName The name of the variable.
-                 */
-				VariableExpression(ReturnType type, uint_fast64_t globalIndex, std::string const& variableName);
-                
-                /*!
-                 * Copy-constructs from the given expression.
-                 *
-                 * @param variableExpression The expression to copy.
-                 */
-                VariableExpression(VariableExpression const& variableExpression);
-                
-                virtual std::unique_ptr<BaseExpression> clone() const override;
-                
-				virtual std::unique_ptr<BaseExpression> clone(std::map<std::string, std::string> const& renaming, storm::parser::prism::VariableState const& variableState) const override;
-				            
-				virtual void accept(ExpressionVisitor* visitor) override;
-				
-				virtual std::string toString() const override;
-				
-				virtual int_fast64_t getValueAsInt(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override;
-				
-				virtual bool getValueAsBool(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override;
-				
-				virtual double getValueAsDouble(std::pair<std::vector<bool>, std::vector<int_fast64_t>> const* variableValues) const override;
-				
-                /*!
-                 * Retrieves the name of the variable.
-                 *
-                 * @return The name of the variable.
-                 */
-				std::string const& getVariableName() const;
-				
-                /*!
-                 * Retrieves the global (i.e. program-wide) index of the variable.
-                 *
-                 * @return The global index of the variable.
-                 */
-				uint_fast64_t getGlobalVariableIndex() const;
-				            
-            protected:
-                virtual BaseExpression* performSubstitution(std::map<std::string, std::reference_wrapper<BaseExpression>> const& substitution) override;
-                
-			private:
-                // The global index of the variable.
-				uint_fast64_t globalIndex;
-                
-                // The name of the variable.
-				std::string variableName;
-			};
-			
-		} // namespace expressions
-	} // namespace ir
-} // namespace storm
-
-#endif /* STORM_IR_EXPRESSIONS_VARIABLEEXPRESSION_H_ */
diff --git a/src/parser/PrismParser.cpp b/src/parser/PrismParser.cpp
index 587c91dc8..6039c2c11 100644
--- a/src/parser/PrismParser.cpp
+++ b/src/parser/PrismParser.cpp
@@ -1,128 +1,636 @@
-/*
- * PrismParser.cpp
- *
- *  Created on: 11.01.2013
- *      Author: chris
- */
-
-#include "PrismParser.h"
-
-#include "src/utility/OsDetection.h"
-
-#include "src/parser/prismparser/PrismGrammar.h"
-
-// If the parser fails due to ill-formed data, this exception is thrown.
+#include "src/parser/PrismParser.h"
+#include "src/exceptions/InvalidArgumentException.h"
 #include "src/exceptions/WrongFormatException.h"
 
-// Needed for file IO.
-#include <fstream>
-#include <iomanip>
-#include <limits>
-
-#include "log4cplus/logger.h"
-#include "log4cplus/loggingmacros.h"
-extern log4cplus::Logger logger;
-
-
 namespace storm {
-namespace parser {
-
-/*!
- * Opens the given file for parsing, invokes the helper function to parse the actual content and
- * closes the file properly, even if an exception is thrown in the parser. In this case, the
- * exception is passed on to the caller.
- */
-storm::ir::Program PrismParserFromFile(std::string const& filename) {
-	// Open file and initialize result.
-	std::ifstream inputFileStream(filename, std::ios::in);
-	storm::ir::Program result;
-
-	// Now try to parse the contents of the file.
-	try {
-		result = PrismParser(inputFileStream, filename);
-	} catch(std::exception& e) {
-		// In case of an exception properly close the file before passing exception.
-		inputFileStream.close();
-		throw e;
-	}
-
-	// Close the stream in case everything went smoothly and return result.
-	inputFileStream.close();
-	return result;
-}
-
-/*!
- * Passes iterators to the input stream to the Boost spirit parser and thereby parses the input.
- * If the parser throws an expectation failure exception, i.e. expected input different than the one
- * provided, this is caught and displayed properly before the exception is passed on.
- */
-storm::ir::Program PrismParser(std::istream& inputStream, std::string const& filename) {
-	// Prepare iterators to input.
-	// TODO: Right now, this parses the whole contents of the file into a string first.
-	// While this is usually not necessary, because there exist adapters that make an input stream
-	// iterable in both directions without storing it into a string, using the corresponding
-	// Boost classes gives an awful output under valgrind and is thus disabled for the time being.
-	std::string fileContent((std::istreambuf_iterator<char>(inputStream)), (std::istreambuf_iterator<char>()));
-	BaseIteratorType stringIteratorBegin = fileContent.begin();
-	BaseIteratorType stringIteratorEnd = fileContent.end();
-	PositionIteratorType positionIteratorBegin(stringIteratorBegin, stringIteratorEnd, filename);
-	PositionIteratorType positionIteratorBegin2(stringIteratorBegin, stringIteratorEnd, filename);
-	PositionIteratorType positionIteratorEnd;
-
-	// Prepare resulting intermediate representation of input.
-	storm::ir::Program result;
-
-	// In order to instantiate the grammar, we have to pass the type of the skipping parser.
-	// As this is more complex, we let Boost figure out the actual type for us.
-	prism::PrismGrammar grammar;
-	try {
-		// Now parse the content using phrase_parse in order to be able to supply a skipping parser.
-		// First run.
-		LOG4CPLUS_INFO(logger, "Start parsing...");
-		qi::phrase_parse(positionIteratorBegin, positionIteratorEnd, grammar, boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol, result);
-		grammar.prepareForSecondRun();
-		result = storm::ir::Program();
-		LOG4CPLUS_INFO(logger, "Start second parsing run...");
-		// Second run.
-		qi::phrase_parse(positionIteratorBegin2, positionIteratorEnd, grammar, boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol, result);
-		LOG4CPLUS_INFO(logger, "Finished parsing, here is the parsed program:" << std::endl << result.toString());
-		// Reset grammars.
-		grammar.resetGrammars();
-	} catch(const qi::expectation_failure<PositionIteratorType>& e) {
-		// If the parser expected content different than the one provided, display information
-		// about the location of the error.
-		const boost::spirit::classic::file_position_base<std::string>& pos = e.first.get_position();
-
-		// Construct the error message including a caret display of the position in the
-		// erroneous line.
-		std::stringstream msg;
-		std::string line = e.first.get_currentline();
-		while (line.find('\t') != std::string::npos) line.replace(line.find('\t'),1," ");
-		msg << pos.file << ", line " << pos.line << ", column " << pos.column
-				<< ": parse error: expected " << e.what_ << std::endl << "\t"
-				<< line << std::endl << "\t";
-		int i = 0;
-		for (i = 1; i < pos.column; ++i) {
-			msg << "-";
-		}
-		msg << "^";
-		for (; i < 80; ++i) {
-			msg << "-";
-		}
-		msg << std::endl;
-
-		std::cerr << msg.str();
-		
-		// Reset grammars in any case.
-		grammar.resetGrammars();
-
-		// Now propagate exception.
-		throw storm::exceptions::WrongFormatException() << msg.str();
-	}
-
-	return result;
-}
-
-} // namespace parser
-
+    namespace parser {
+        storm::prism::Program PrismParser::parse(std::string const& filename, bool typeCheck) {
+            // Open file and initialize result.
+            std::ifstream inputFileStream(filename, std::ios::in);
+            LOG_THROW(inputFileStream.good(), storm::exceptions::WrongFormatException, "Unable to read from file " << filename << ".");
+            
+            storm::prism::Program result;
+            
+            // Now try to parse the contents of the file.
+            try {
+                std::string fileContent((std::istreambuf_iterator<char>(inputFileStream)), (std::istreambuf_iterator<char>()));
+                result = parseFromString(fileContent, filename, typeCheck);
+            } catch(std::exception& e) {
+                // In case of an exception properly close the file before passing exception.
+                inputFileStream.close();
+                throw e;
+            }
+            
+            // Close the stream in case everything went smoothly and return result.
+            inputFileStream.close();
+            return result;
+        }
+        
+        storm::prism::Program PrismParser::parseFromString(std::string const& input, std::string const& filename, bool typeCheck) {
+            PositionIteratorType first(input.begin());
+            PositionIteratorType iter = first;
+            PositionIteratorType last(input.end());
+            
+            // Create empty result;
+            storm::prism::Program result;
+            
+            // Create grammar.
+            storm::parser::PrismParser grammar(filename, first);
+            try {
+                // Now parse the content using phrase_parse in order to be able to supply a skipping parser.
+                bool succeeded = qi::phrase_parse(iter, last, grammar, boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol, result);
+                LOG_THROW(succeeded,  storm::exceptions::WrongFormatException, "Parsing failed in first pass.");
+                if (typeCheck) {
+                    first = PositionIteratorType(input.begin());
+                    iter = first;
+                    last = PositionIteratorType(input.end());
+                    grammar.moveToSecondRun();
+                    succeeded = qi::phrase_parse(iter, last, grammar, boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol, result);
+                    LOG_THROW(succeeded,  storm::exceptions::WrongFormatException, "Parsing failed in second pass.");
+                }
+            } catch (qi::expectation_failure<PositionIteratorType> const& e) {
+                // If the parser expected content different than the one provided, display information about the location of the error.
+                std::size_t lineNumber = boost::spirit::get_line(e.first);
+                
+                // Now propagate exception.
+                LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << lineNumber << " of file " << filename << ".");
+            }
+            
+            return result;
+        }
+        
+        PrismParser::PrismParser(std::string const& filename, Iterator first) : PrismParser::base_type(start), secondRun(false), allowDoubleLiteralsFlag(true), filename(filename), annotate(first) {
+            // Parse simple identifier.
+            identifier %= qi::as_string[qi::raw[qi::lexeme[((qi::alpha | qi::char_('_')) >> *(qi::alnum | qi::char_('_')))]]][qi::_pass = phoenix::bind(&PrismParser::isValidIdentifier, phoenix::ref(*this), qi::_1)];
+            identifier.name("identifier");
+            
+            floorCeilExpression = ((qi::lit("floor")[qi::_a = true] | qi::lit("ceil")[qi::_a = false]) >> qi::lit("(") >> plusExpression >> qi::lit(")"))[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&PrismParser::createFloorExpression, phoenix::ref(*this), qi::_1)] .else_ [qi::_val = phoenix::bind(&PrismParser::createCeilExpression, phoenix::ref(*this), qi::_1)]];
+            floorCeilExpression.name("floor/ceil expression");
+            
+            minMaxExpression = ((qi::lit("min")[qi::_a = true] | qi::lit("max")[qi::_a = false]) >> qi::lit("(") >> plusExpression >> qi::lit(",") >> plusExpression >> qi::lit(")"))[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&PrismParser::createMinimumExpression, phoenix::ref(*this), qi::_1, qi::_2)] .else_ [qi::_val = phoenix::bind(&PrismParser::createMaximumExpression, phoenix::ref(*this), qi::_1, qi::_2)]];
+            minMaxExpression.name("min/max expression");
+            
+            identifierExpression = identifier[qi::_val = phoenix::bind(&PrismParser::getIdentifierExpression, phoenix::ref(*this), qi::_1)];
+            identifierExpression.name("identifier expression");
+            
+            literalExpression = qi::lit("true")[qi::_val = phoenix::bind(&PrismParser::createTrueExpression, phoenix::ref(*this))] | qi::lit("false")[qi::_val = phoenix::bind(&PrismParser::createFalseExpression, phoenix::ref(*this))] | strict_double[qi::_val = phoenix::bind(&PrismParser::createDoubleLiteralExpression, phoenix::ref(*this), qi::_1, qi::_pass)] | qi::int_[qi::_val = phoenix::bind(&PrismParser::createIntegerLiteralExpression, phoenix::ref(*this), qi::_1)];
+            literalExpression.name("literal expression");
+            
+            atomicExpression = minMaxExpression | floorCeilExpression | qi::lit("(") >> expression >> qi::lit(")") | literalExpression | identifierExpression;
+            atomicExpression.name("atomic expression");
+            
+            unaryExpression = atomicExpression[qi::_val = qi::_1] | (qi::lit("!") >> atomicExpression)[qi::_val = phoenix::bind(&PrismParser::createNotExpression, phoenix::ref(*this), qi::_1)] | (qi::lit("-") >> atomicExpression)[qi::_val = phoenix::bind(&PrismParser::createMinusExpression, phoenix::ref(*this), qi::_1)];
+            unaryExpression.name("unary expression");
+            
+            multiplicationExpression = unaryExpression[qi::_val = qi::_1] >> *((qi::lit("*")[qi::_a = true] | qi::lit("/")[qi::_a = false]) >> unaryExpression[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&PrismParser::createMultExpression, phoenix::ref(*this), qi::_val, qi::_1)] .else_ [qi::_val = phoenix::bind(&PrismParser::createDivExpression, phoenix::ref(*this), qi::_val, qi::_1)]]);
+            multiplicationExpression.name("multiplication expression");
+            
+            plusExpression = multiplicationExpression[qi::_val = qi::_1] >> *((qi::lit("+")[qi::_a = true] | qi::lit("-")[qi::_a = false]) >> multiplicationExpression)[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&PrismParser::createPlusExpression, phoenix::ref(*this), qi::_val, qi::_1)] .else_ [qi::_val = phoenix::bind(&PrismParser::createMinusExpression, phoenix::ref(*this), qi::_val, qi::_1)]];
+            plusExpression.name("plus expression");
+            
+            relativeExpression = (plusExpression >> qi::lit(">=") >> plusExpression)[qi::_val = phoenix::bind(&PrismParser::createGreaterOrEqualExpression, phoenix::ref(*this), qi::_1, qi::_2)] | (plusExpression >> qi::lit(">") >> plusExpression)[qi::_val = phoenix::bind(&PrismParser::createGreaterExpression, phoenix::ref(*this), qi::_1, qi::_2)] | (plusExpression >> qi::lit("<=") >> plusExpression)[qi::_val = phoenix::bind(&PrismParser::createLessOrEqualExpression, phoenix::ref(*this), qi::_1, qi::_2)] | (plusExpression >> qi::lit("<") >> plusExpression)[qi::_val = phoenix::bind(&PrismParser::createLessExpression, phoenix::ref(*this), qi::_1, qi::_2)] | (plusExpression >> qi::lit("=") >> plusExpression)[qi::_val = phoenix::bind(&PrismParser::createEqualsExpression, phoenix::ref(*this), qi::_1, qi::_2)] | (plusExpression >> qi::lit("!=") >> plusExpression)[qi::_val = phoenix::bind(&PrismParser::createNotEqualsExpression, phoenix::ref(*this), qi::_1, qi::_2)] | plusExpression[qi::_val = qi::_1];
+            relativeExpression.name("relative expression");
+            
+            andExpression = relativeExpression[qi::_val = qi::_1] >> *(qi::lit("&") >> relativeExpression)[qi::_val = phoenix::bind(&PrismParser::createAndExpression, phoenix::ref(*this), qi::_val, qi::_1)];
+            andExpression.name("and expression");
+            
+            orExpression = andExpression[qi::_val = qi::_1] >> *(qi::lit("|") >> andExpression)[qi::_val = phoenix::bind(&PrismParser::createOrExpression, phoenix::ref(*this), qi::_val, qi::_1)];
+            orExpression.name("or expression");
+            
+            iteExpression = orExpression[qi::_val = qi::_1] >> -(qi::lit("?") > orExpression > qi::lit(":") > orExpression)[qi::_val = phoenix::bind(&PrismParser::createIteExpression, phoenix::ref(*this), qi::_val, qi::_1, qi::_2)];
+            iteExpression.name("if-then-else expression");
+            
+            expression %= iteExpression;
+            expression.name("expression");
+            
+            modelTypeDefinition %= modelType_;
+            modelTypeDefinition.name("model type");
+            
+            undefinedBooleanConstantDefinition = ((qi::lit("const") >> qi::lit("bool")) > identifier > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createUndefinedBooleanConstant, phoenix::ref(*this), qi::_1)];
+            undefinedBooleanConstantDefinition.name("undefined boolean constant declaration");
+            
+            undefinedIntegerConstantDefinition = ((qi::lit("const") >> qi::lit("int")) > identifier > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createUndefinedIntegerConstant, phoenix::ref(*this), qi::_1)];
+            undefinedIntegerConstantDefinition.name("undefined integer constant declaration");
+            
+            undefinedDoubleConstantDefinition = ((qi::lit("const") >> qi::lit("double")) > identifier > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createUndefinedDoubleConstant, phoenix::ref(*this), qi::_1)];
+            undefinedDoubleConstantDefinition.name("undefined double constant definition");
+            
+            undefinedConstantDefinition = (undefinedBooleanConstantDefinition | undefinedIntegerConstantDefinition | undefinedDoubleConstantDefinition);
+            undefinedConstantDefinition.name("undefined constant definition");
+            
+            definedBooleanConstantDefinition = ((qi::lit("const") >> qi::lit("bool") >> identifier >> qi::lit("=")) > expression > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createDefinedBooleanConstant, phoenix::ref(*this), qi::_1, qi::_2)];
+            definedBooleanConstantDefinition.name("defined boolean constant declaration");
+            
+            definedIntegerConstantDefinition = ((qi::lit("const") >> qi::lit("int") >> identifier >> qi::lit("=")) > expression >> qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createDefinedIntegerConstant, phoenix::ref(*this), qi::_1, qi::_2)];
+            definedIntegerConstantDefinition.name("defined integer constant declaration");
+            
+            definedDoubleConstantDefinition = ((qi::lit("const") >> qi::lit("double") >> identifier >> qi::lit("=")) > expression > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createDefinedDoubleConstant, phoenix::ref(*this), qi::_1, qi::_2)];
+            definedDoubleConstantDefinition.name("defined double constant declaration");
+            
+            definedConstantDefinition %= (definedBooleanConstantDefinition | definedIntegerConstantDefinition | definedDoubleConstantDefinition);
+            definedConstantDefinition.name("defined constant definition");
+            
+            formulaDefinition = (qi::lit("formula") > identifier > qi::lit("=") > expression > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createFormula, phoenix::ref(*this), qi::_1, qi::_2)];
+            formulaDefinition.name("formula definition");
+            
+            booleanVariableDefinition = ((identifier >> qi::lit(":") >> qi::lit("bool")) > ((qi::lit("init") > expression) | qi::attr(storm::expressions::Expression::createFalse())) > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createBooleanVariable, phoenix::ref(*this), qi::_1, qi::_2)];
+            booleanVariableDefinition.name("boolean variable definition");
+            
+            integerVariableDefinition = ((identifier >> qi::lit(":") >> qi::lit("[")[phoenix::bind(&PrismParser::allowDoubleLiterals, phoenix::ref(*this), false)]) > expression[qi::_a = qi::_1] > qi::lit("..") > expression > qi::lit("]")[phoenix::bind(&PrismParser::allowDoubleLiterals, phoenix::ref(*this), true)] > -(qi::lit("init") > expression[qi::_a = qi::_1]) > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createIntegerVariable, phoenix::ref(*this), qi::_1, qi::_2, qi::_3, qi::_a)];
+            integerVariableDefinition.name("integer variable definition");
+            
+            variableDefinition = (booleanVariableDefinition[phoenix::push_back(qi::_r1, qi::_1)] | integerVariableDefinition[phoenix::push_back(qi::_r2, qi::_1)]);
+            variableDefinition.name("variable declaration");
+            
+            globalVariableDefinition = (qi::lit("global") > (booleanVariableDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::globalBooleanVariables, qi::_r1), qi::_1)] | integerVariableDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::globalIntegerVariables, qi::_r1), qi::_1)]));
+            globalVariableDefinition.name("global variable declaration list");
+            
+            programHeader = modelTypeDefinition[phoenix::bind(&GlobalProgramInformation::modelType, qi::_r1) = qi::_1]
+            >   *(definedConstantDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::constants, qi::_r1), qi::_1)] | undefinedConstantDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::constants, qi::_r1), qi::_1)])
+            >   *(formulaDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::formulas, qi::_r1), qi::_1)])
+            >   *(globalVariableDefinition(qi::_r1));
+            programHeader.name("program header");
+            
+            stateRewardDefinition = (expression > qi::lit(":") > plusExpression >> qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createStateReward, phoenix::ref(*this), qi::_1, qi::_2)];
+            stateRewardDefinition.name("state reward definition");
+            
+            transitionRewardDefinition = (qi::lit("[") > -(identifier[qi::_a = qi::_1]) > qi::lit("]") > expression > qi::lit(":") > plusExpression > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createTransitionReward, phoenix::ref(*this), qi::_a, qi::_2, qi::_3)];
+            transitionRewardDefinition.name("transition reward definition");
+            
+            rewardModelDefinition = (qi::lit("rewards") > -(qi::lit("\"") > identifier[qi::_a = qi::_1] > qi::lit("\""))
+                                     > +(   stateRewardDefinition[phoenix::push_back(qi::_b, qi::_1)]
+                                         |   transitionRewardDefinition[phoenix::push_back(qi::_c, qi::_1)]
+                                         )
+                                     >> qi::lit("endrewards"))[qi::_val = phoenix::bind(&PrismParser::createRewardModel, phoenix::ref(*this), qi::_a, qi::_b, qi::_c)];
+            rewardModelDefinition.name("reward model definition");
+            
+            initialStatesConstruct = (qi::lit("init") > expression > qi::lit("endinit"))[qi::_pass = phoenix::bind(&PrismParser::addInitialStatesExpression, phoenix::ref(*this), qi::_1, qi::_r1)];
+            initialStatesConstruct.name("initial construct");
+            
+            labelDefinition = (qi::lit("label") > -qi::lit("\"") > identifier > -qi::lit("\"") > qi::lit("=") > expression >> qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createLabel, phoenix::ref(*this), qi::_1, qi::_2)];
+            labelDefinition.name("label definition");
+            
+            assignmentDefinition = (qi::lit("(") > identifier > qi::lit("'") > qi::lit("=") > expression > qi::lit(")"))[qi::_val = phoenix::bind(&PrismParser::createAssignment, phoenix::ref(*this), qi::_1, qi::_2)];
+            assignmentDefinition.name("assignment");
+            
+            assignmentDefinitionList %= +assignmentDefinition % "&";
+            assignmentDefinitionList.name("assignment list");
+            
+            updateDefinition = (((plusExpression > qi::lit(":")) | qi::attr(storm::expressions::Expression::createDoubleLiteral(1))) >> assignmentDefinitionList)[qi::_val = phoenix::bind(&PrismParser::createUpdate, phoenix::ref(*this), qi::_1, qi::_2, qi::_r1)];
+            updateDefinition.name("update");
+            
+            updateListDefinition %= +updateDefinition(qi::_r1) % "+";
+            updateListDefinition.name("update list");
+            
+            commandDefinition = (qi::lit("[") > -(identifier[qi::_a = qi::_1]) > qi::lit("]") > expression > qi::lit("->") > updateListDefinition(qi::_r1) > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createCommand, phoenix::ref(*this), qi::_a, qi::_2, qi::_3, 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.name("module definition");
+            
+            moduleRenaming = ((qi::lit("module") >> identifier >> qi::lit("=")) > identifier > qi::lit("[")
+                              > ((identifier > qi::lit("=") > identifier)[phoenix::insert(qi::_a, phoenix::construct<std::pair<std::string,std::string>>(qi::_1, qi::_2))] % ",") > qi::lit("]")
+                              > qi::lit("endmodule"))[qi::_val = phoenix::bind(&PrismParser::createRenamedModule, phoenix::ref(*this), qi::_1, qi::_2, qi::_a, qi::_r1)];
+            moduleRenaming.name("module definition via renaming");
+            
+            moduleDefinitionList %= +(moduleRenaming(qi::_r1) | moduleDefinition(qi::_r1))[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::modules, qi::_r1), qi::_1)];
+            moduleDefinitionList.name("module list");
+            
+            start = (qi::eps > programHeader(qi::_a) > moduleDefinitionList(qi::_a) > *(initialStatesConstruct(qi::_a) | rewardModelDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::rewardModels, qi::_a), qi::_1)] | labelDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::labels, qi::_a), qi::_1)] | formulaDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::formulas, qi::_a), qi::_1)]) > qi::eoi)[qi::_val = phoenix::bind(&PrismParser::createProgram, phoenix::ref(*this), qi::_a)];
+            start.name("probabilistic program");
+            
+            // Enable error reporting.
+            qi::on_error<qi::fail>(expression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
+            qi::on_error<qi::fail>(iteExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
+            qi::on_error<qi::fail>(orExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
+            qi::on_error<qi::fail>(andExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
+            qi::on_error<qi::fail>(relativeExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
+            qi::on_error<qi::fail>(plusExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
+            qi::on_error<qi::fail>(multiplicationExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
+            qi::on_error<qi::fail>(unaryExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
+            qi::on_error<qi::fail>(atomicExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
+            qi::on_error<qi::fail>(literalExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
+            qi::on_error<qi::fail>(identifierExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
+            qi::on_error<qi::fail>(minMaxExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
+            qi::on_error<qi::fail>(floorCeilExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4));
+            
+            // Enable location tracking for important entities.
+            auto setLocationInfoFunction = this->annotate(qi::_val, qi::_1, qi::_3);
+            qi::on_success(undefinedBooleanConstantDefinition, setLocationInfoFunction);
+            qi::on_success(undefinedIntegerConstantDefinition, setLocationInfoFunction);
+            qi::on_success(undefinedDoubleConstantDefinition, setLocationInfoFunction);
+            qi::on_success(definedBooleanConstantDefinition, setLocationInfoFunction);
+            qi::on_success(definedIntegerConstantDefinition, setLocationInfoFunction);
+            qi::on_success(definedDoubleConstantDefinition, setLocationInfoFunction);
+            qi::on_success(booleanVariableDefinition, setLocationInfoFunction);
+            qi::on_success(integerVariableDefinition, setLocationInfoFunction);
+            qi::on_success(moduleDefinition, setLocationInfoFunction);
+            qi::on_success(moduleRenaming, setLocationInfoFunction);
+            qi::on_success(formulaDefinition, setLocationInfoFunction);
+            qi::on_success(rewardModelDefinition, setLocationInfoFunction);
+            qi::on_success(labelDefinition, setLocationInfoFunction);
+            qi::on_success(commandDefinition, setLocationInfoFunction);
+            qi::on_success(updateDefinition, setLocationInfoFunction);
+            qi::on_success(assignmentDefinition, setLocationInfoFunction);
+        }
+        
+        void PrismParser::moveToSecondRun() {
+            this->secondRun = true;
+        }
+        
+        void PrismParser::allowDoubleLiterals(bool flag) {
+            this->allowDoubleLiteralsFlag = flag;
+        }
+        
+        std::string const& PrismParser::getFilename() const {
+            return this->filename;
+        }
+        
+        bool PrismParser::isValidIdentifier(std::string const& identifier) {
+            if (this->keywords_.find(identifier) != nullptr) {
+                return false;
+            }
+            return true;
+        }
+        
+        bool PrismParser::addInitialStatesExpression(storm::expressions::Expression initialStatesExpression, GlobalProgramInformation& globalProgramInformation) {
+            LOG_THROW(!globalProgramInformation.hasInitialStatesExpression, storm::exceptions::InvalidArgumentException, "Program must not define two initial constructs.");
+            if (globalProgramInformation.hasInitialStatesExpression) {
+                return false;
+            }
+            globalProgramInformation.hasInitialStatesExpression = true;
+            globalProgramInformation.initialStatesExpression = initialStatesExpression;
+            return true;
+        }
+        
+        storm::expressions::Expression PrismParser::createIteExpression(storm::expressions::Expression e1, storm::expressions::Expression e2, storm::expressions::Expression e3) const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return e1.ite(e2, e3);
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createOrExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return e1 || e2;
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createAndExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return e1 && e2;
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createGreaterExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return e1 > e2;
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createGreaterOrEqualExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return e1 >= e2;
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createLessExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return e1 < e2;
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createLessOrEqualExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return e1 <= e2;
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createEqualsExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return e1 == e2;
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createNotEqualsExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return e1 != e2;
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createPlusExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return e1 + e2;
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createMinusExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return e1 - e2;
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createMultExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return e1 * e2;
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createDivExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return e1 / e2;
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createNotExpression(storm::expressions::Expression e1) const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return !e1;
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createMinusExpression(storm::expressions::Expression e1) const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return -e1;
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createTrueExpression() const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return storm::expressions::Expression::createTrue();
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createFalseExpression() const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return storm::expressions::Expression::createFalse();
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createDoubleLiteralExpression(double value, bool& pass) const {
+            // If we are not supposed to accept double expressions, we reject it by setting pass to false.
+            if (!this->allowDoubleLiteralsFlag) {
+                pass = false;
+            }
+            
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return storm::expressions::Expression::createDoubleLiteral(value);
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createIntegerLiteralExpression(int value) const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return storm::expressions::Expression::createIntegerLiteral(static_cast<int_fast64_t>(value));
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createMinimumExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return storm::expressions::Expression::minimum(e1, e2);
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createMaximumExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return storm::expressions::Expression::maximum(e1, e2);
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createFloorExpression(storm::expressions::Expression e1) const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return e1.floor();
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::createCeilExpression(storm::expressions::Expression e1) const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                return e1.ceil();
+            }
+        }
+        
+        storm::expressions::Expression PrismParser::getIdentifierExpression(std::string const& identifier) const {
+            if (!this->secondRun) {
+                return storm::expressions::Expression::createFalse();
+            } else {
+                storm::expressions::Expression const* expression = this->identifiers_.find(identifier);
+                LOG_THROW(expression != nullptr, storm::exceptions::WrongFormatException, "Undeclared identifier '" << identifier << "'.");
+                return *expression;
+            }
+        }
+        
+        storm::prism::Constant PrismParser::createUndefinedBooleanConstant(std::string const& newConstant) const {
+            this->identifiers_.add(newConstant, storm::expressions::Expression::createBooleanConstant(newConstant));
+            return storm::prism::Constant(storm::expressions::ExpressionReturnType::Bool, newConstant, this->getFilename());
+        }
+        
+        storm::prism::Constant PrismParser::createUndefinedIntegerConstant(std::string const& newConstant) const {
+            this->identifiers_.add(newConstant, storm::expressions::Expression::createIntegerConstant(newConstant));
+            return storm::prism::Constant(storm::expressions::ExpressionReturnType::Int, newConstant, this->getFilename());
+        }
+        
+        storm::prism::Constant PrismParser::createUndefinedDoubleConstant(std::string const& newConstant) const {
+            this->identifiers_.add(newConstant, storm::expressions::Expression::createDoubleConstant(newConstant));
+            return storm::prism::Constant(storm::expressions::ExpressionReturnType::Double, newConstant, this->getFilename());
+        }
+        
+        storm::prism::Constant PrismParser::createDefinedBooleanConstant(std::string const& newConstant, storm::expressions::Expression expression) const {
+            this->identifiers_.add(newConstant, storm::expressions::Expression::createBooleanConstant(newConstant));
+            return storm::prism::Constant(storm::expressions::ExpressionReturnType::Bool, newConstant, expression, this->getFilename());
+        }
+        
+        storm::prism::Constant PrismParser::createDefinedIntegerConstant(std::string const& newConstant, storm::expressions::Expression expression) const {
+            this->identifiers_.add(newConstant, storm::expressions::Expression::createIntegerConstant(newConstant));
+            return storm::prism::Constant(storm::expressions::ExpressionReturnType::Int, newConstant, expression, this->getFilename());
+        }
+        
+        storm::prism::Constant PrismParser::createDefinedDoubleConstant(std::string const& newConstant, storm::expressions::Expression expression) const {
+            this->identifiers_.add(newConstant, storm::expressions::Expression::createDoubleConstant(newConstant));
+            return storm::prism::Constant(storm::expressions::ExpressionReturnType::Double, newConstant, expression, this->getFilename());
+        }
+        
+        storm::prism::Formula PrismParser::createFormula(std::string const& formulaName, storm::expressions::Expression expression) const {
+            if (this->secondRun) {
+                this->identifiers_.add(formulaName, expression);
+            }
+            return storm::prism::Formula(formulaName, expression, this->getFilename());
+        }
+        
+        storm::prism::Label PrismParser::createLabel(std::string const& labelName, storm::expressions::Expression expression) const {
+            return storm::prism::Label(labelName, expression, this->getFilename());
+        }
+        
+        storm::prism::RewardModel PrismParser::createRewardModel(std::string const& rewardModelName, std::vector<storm::prism::StateReward> const& stateRewards, std::vector<storm::prism::TransitionReward> const& transitionRewards) const {
+            return storm::prism::RewardModel(rewardModelName, stateRewards, transitionRewards, this->getFilename());
+        }
+        
+        storm::prism::StateReward PrismParser::createStateReward(storm::expressions::Expression statePredicateExpression, storm::expressions::Expression rewardValueExpression) const {
+            return storm::prism::StateReward(statePredicateExpression, rewardValueExpression, this->getFilename());
+        }
+        
+        storm::prism::TransitionReward PrismParser::createTransitionReward(std::string const& actionName, storm::expressions::Expression statePredicateExpression, storm::expressions::Expression rewardValueExpression) const {
+            return storm::prism::TransitionReward(actionName, statePredicateExpression, rewardValueExpression, this->getFilename());
+        }
+        
+        storm::prism::Assignment PrismParser::createAssignment(std::string const& variableName, storm::expressions::Expression assignedExpression) const {
+            return storm::prism::Assignment(variableName, assignedExpression, this->getFilename());
+        }
+        
+        storm::prism::Update PrismParser::createUpdate(storm::expressions::Expression likelihoodExpression, std::vector<storm::prism::Assignment> const& assignments, GlobalProgramInformation& globalProgramInformation) const {
+            ++globalProgramInformation.currentUpdateIndex;
+            return storm::prism::Update(globalProgramInformation.currentUpdateIndex - 1, likelihoodExpression, assignments, this->getFilename());
+        }
+        
+        storm::prism::Command PrismParser::createCommand(std::string const& actionName, storm::expressions::Expression guardExpression, std::vector<storm::prism::Update> const& updates, GlobalProgramInformation& globalProgramInformation) const {
+            ++globalProgramInformation.currentCommandIndex;
+            return storm::prism::Command(globalProgramInformation.currentCommandIndex - 1, actionName, guardExpression, updates, this->getFilename());
+        }
+        
+        storm::prism::BooleanVariable PrismParser::createBooleanVariable(std::string const& variableName, storm::expressions::Expression initialValueExpression) const {
+            this->identifiers_.add(variableName, storm::expressions::Expression::createBooleanVariable(variableName));
+            return storm::prism::BooleanVariable(variableName, initialValueExpression, this->getFilename());
+        }
+        
+        storm::prism::IntegerVariable PrismParser::createIntegerVariable(std::string const& variableName, storm::expressions::Expression lowerBoundExpression, storm::expressions::Expression upperBoundExpression, storm::expressions::Expression initialValueExpression) const {
+            this->identifiers_.add(variableName, storm::expressions::Expression::createIntegerVariable(variableName));
+            return storm::prism::IntegerVariable(variableName, lowerBoundExpression, upperBoundExpression, initialValueExpression, this->getFilename());
+        }
+        
+        storm::prism::Module PrismParser::createModule(std::string const& moduleName, std::vector<storm::prism::BooleanVariable> const& booleanVariables, std::vector<storm::prism::IntegerVariable> const& integerVariables, std::vector<storm::prism::Command> const& commands, GlobalProgramInformation& globalProgramInformation) const {
+            globalProgramInformation.moduleToIndexMap[moduleName] = globalProgramInformation.modules.size();
+            return storm::prism::Module(moduleName, booleanVariables, integerVariables, commands, this->getFilename());
+        }
+        
+        storm::prism::Module PrismParser::createRenamedModule(std::string const& newModuleName, std::string const& oldModuleName, std::map<std::string, std::string> const& renaming, GlobalProgramInformation& globalProgramInformation) const {
+            // Check whether the module to rename actually exists.
+            auto const& moduleIndexPair = globalProgramInformation.moduleToIndexMap.find(oldModuleName);
+            LOG_THROW(moduleIndexPair != globalProgramInformation.moduleToIndexMap.end(), storm::exceptions::WrongFormatException, "No module named '" << oldModuleName << "' to rename.");
+            storm::prism::Module const& moduleToRename = globalProgramInformation.modules[moduleIndexPair->second];
+            
+            if (!this->secondRun) {
+                // Register all (renamed) variables for later use.
+                for (auto const& variable : moduleToRename.getBooleanVariables()) {
+                    auto const& renamingPair = renaming.find(variable.getName());
+                    LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException, "Boolean variable '" << variable.getName() << " was not renamed.");
+                    this->identifiers_.add(renamingPair->second, storm::expressions::Expression::createBooleanVariable(renamingPair->second));
+                }
+                for (auto const& variable : moduleToRename.getIntegerVariables()) {
+                    auto const& renamingPair = renaming.find(variable.getName());
+                    LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException, "Integer variable '" << variable.getName() << " was not renamed.");
+                    this->identifiers_.add(renamingPair->second, storm::expressions::Expression::createIntegerVariable(renamingPair->second));
+                }
+                
+                // Return a dummy module in the first pass.
+                return storm::prism::Module();
+            } else {
+                // Add a mapping from the new module name to its (future) index.
+                globalProgramInformation.moduleToIndexMap[newModuleName] = globalProgramInformation.modules.size();
+                
+                // Create a mapping from identifiers to the expressions they need to be replaced with.
+                std::map<std::string, storm::expressions::Expression> expressionRenaming;
+                for (auto const& namePair : renaming) {
+                    storm::expressions::Expression const* substitutedExpression = this->identifiers_.find(namePair.second);
+                    // If the mapped-to-value is an expression, we need to replace it.
+                    if (substitutedExpression != nullptr) {
+                        expressionRenaming.emplace(namePair.first, *substitutedExpression);
+                    }
+                }
+                
+                // Rename the boolean variables.
+                std::vector<storm::prism::BooleanVariable> booleanVariables;
+                for (auto const& variable : moduleToRename.getBooleanVariables()) {
+                    auto const& renamingPair = renaming.find(variable.getName());
+                    LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException, "Boolean variable '" << variable.getName() << " was not renamed.");
+                    
+                    booleanVariables.push_back(storm::prism::BooleanVariable(renamingPair->second, variable.getInitialValueExpression().substitute<std::map>(expressionRenaming), this->getFilename(), get_line(qi::_1)));
+                }
+                
+                // Rename the integer variables.
+                std::vector<storm::prism::IntegerVariable> integerVariables;
+                for (auto const& variable : moduleToRename.getIntegerVariables()) {
+                    auto const& renamingPair = renaming.find(variable.getName());
+                    LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException, "Integer variable '" << variable.getName() << " was not renamed.");
+                    
+                    integerVariables.push_back(storm::prism::IntegerVariable(renamingPair->second, variable.getLowerBoundExpression().substitute<std::map>(expressionRenaming), variable.getUpperBoundExpression().substitute<std::map>(expressionRenaming), variable.getInitialValueExpression().substitute<std::map>(expressionRenaming), this->getFilename(), get_line(qi::_1)));
+                }
+                
+                // Rename commands.
+                std::vector<storm::prism::Command> commands;
+                for (auto const& command : moduleToRename.getCommands()) {
+                    std::vector<storm::prism::Update> updates;
+                    for (auto const& update : command.getUpdates()) {
+                        std::vector<storm::prism::Assignment> assignments;
+                        for (auto const& assignment : update.getAssignments()) {
+                            auto const& renamingPair = renaming.find(assignment.getVariableName());
+                            if (renamingPair != renaming.end()) {
+                                assignments.emplace_back(renamingPair->second, assignment.getExpression().substitute<std::map>(expressionRenaming), this->getFilename(), get_line(qi::_1));
+                            } else {
+                                assignments.emplace_back(assignment.getVariableName(), assignment.getExpression().substitute<std::map>(expressionRenaming), this->getFilename(), get_line(qi::_1));
+                            }
+                        }
+                        updates.emplace_back(globalProgramInformation.currentUpdateIndex, update.getLikelihoodExpression().substitute<std::map>(expressionRenaming), assignments, this->getFilename(), get_line(qi::_1));
+                        ++globalProgramInformation.currentUpdateIndex;
+                    }
+                    
+                    std::string newActionName = command.getActionName();
+                    auto const& renamingPair = renaming.find(command.getActionName());
+                    if (renamingPair != renaming.end()) {
+                        newActionName = renamingPair->second;
+                    }
+                    
+                    commands.emplace_back(globalProgramInformation.currentCommandIndex, newActionName, command.getGuardExpression().substitute<std::map>(expressionRenaming), updates, this->getFilename(), get_line(qi::_1));
+                    ++globalProgramInformation.currentCommandIndex;
+                }
+                
+                return storm::prism::Module(newModuleName, booleanVariables, integerVariables, commands, this->getFilename());
+            }
+        }
+        
+        storm::prism::Program PrismParser::createProgram(GlobalProgramInformation const& globalProgramInformation) const {
+            return storm::prism::Program(globalProgramInformation.modelType, globalProgramInformation.constants, globalProgramInformation.globalBooleanVariables, globalProgramInformation.globalIntegerVariables, globalProgramInformation.formulas, globalProgramInformation.modules, globalProgramInformation.rewardModels, globalProgramInformation.hasInitialStatesExpression, globalProgramInformation.initialStatesExpression, globalProgramInformation.labels, this->getFilename());
+        }
+    } // namespace parser
 } // namespace storm
diff --git a/src/parser/PrismParser.h b/src/parser/PrismParser.h
index da8ad0941..3f8f17b65 100644
--- a/src/parser/PrismParser.h
+++ b/src/parser/PrismParser.h
@@ -1,49 +1,320 @@
-/* * PrismParser.h
- *
- *  Created on: Jan 3, 2013
- *      Author: Christian Dehnert
- */
-
 #ifndef STORM_PARSER_PRISMPARSER_H_
-#define STORM_PARSER_PRISMPARSER_H_
-
-// All classes of the intermediate representation are used.
-#include "src/ir/IR.h"
+#define	STORM_PARSER_PRISMPARSER_H_
 
-// Used for file input.
-#include <istream>
+// Include files for file input.
+#include <fstream>
 #include <memory>
+#include <iomanip>
 
-namespace storm {
-
-namespace parser {
+// Include boost spirit.
+#define BOOST_SPIRIT_USE_PHOENIX_V3
+#include <boost/typeof/typeof.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix.hpp>
+#include <boost/spirit/include/support_line_pos_iterator.hpp>
+#include <boost/spirit/home/classic/iterator/position_iterator.hpp>
 
-using namespace storm::ir;
-using namespace storm::ir::expressions;
+namespace qi = boost::spirit::qi;
+namespace phoenix = boost::phoenix;
 
-/*
- * This functions parse the format of the PRISM model checker into an intermediate representation.
- */
+typedef std::string::const_iterator BaseIteratorType;
+typedef boost::spirit::line_pos_iterator<BaseIteratorType> PositionIteratorType;
+typedef PositionIteratorType Iterator;
+typedef BOOST_TYPEOF(boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol) Skipper;
+typedef BOOST_TYPEOF(qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol | boost::spirit::ascii::space) Skipper2;
 
-/*!
- * Parses the given file into the intermediate representation assuming it complies with the
- * PRISM syntax.
- * @param filename the name of the file to parse.
- * @return a shared pointer to the intermediate representation of the PRISM file.
- */
-storm::ir::Program PrismParserFromFile(std::string const& filename);
+#include "src/storage/prism/Program.h"
+#include "src/storage/expressions/Expression.h"
+#include "src/exceptions/ExceptionMacros.h"
 
-/*!
- * Parses the given input stream into the intermediate representation assuming it complies with
- * the PRISM syntax.
- * @param inputStream the input stream to parse.
- * @param filename the name of the file the input stream belongs to. Used for diagnostics.
- * @return a shared pointer to the intermediate representation of the PRISM file.
- */
-storm::ir::Program PrismParser(std::istream& inputStream, std::string const& filename);
-
-} // namespace parser
+namespace storm {
+    namespace parser {
+        class GlobalProgramInformation {
+        public:
+            // Default construct the header information.
+            GlobalProgramInformation() = default;
+            
+            // Members for all essential information that needs to be collected.
+            storm::prism::Program::ModelType modelType;
+            std::vector<storm::prism::Constant> constants;
+            std::vector<storm::prism::Formula> formulas;
+            std::vector<storm::prism::BooleanVariable> globalBooleanVariables;
+            std::vector<storm::prism::IntegerVariable> globalIntegerVariables;
+            std::map<std::string, uint_fast64_t> moduleToIndexMap;
+            std::vector<storm::prism::Module> modules;
+            std::vector<storm::prism::RewardModel> rewardModels;
+            std::vector<storm::prism::Label> labels;
+            storm::expressions::Expression initialStatesExpression;
+            bool hasInitialStatesExpression;
+            
+            // Counters to provide unique indexing for commands and updates.
+            uint_fast64_t currentCommandIndex;
+            uint_fast64_t currentUpdateIndex;
+        };
 
+        class PrismParser : public qi::grammar<Iterator, storm::prism::Program(), qi::locals<GlobalProgramInformation>, Skipper> {
+        public:
+            /*!
+             * Parses the given file into the PRISM storage classes assuming it complies with the PRISM syntax.
+             *
+             * @param filename the name of the file to parse.
+             * @param typeCheck Sets whether the expressions are generated and therefore typechecked.
+             * @return The resulting PRISM program.
+             */
+            static storm::prism::Program parse(std::string const& filename, bool typeCheck = true);
+            
+            /*!
+             * Parses the given input stream into the PRISM storage classes assuming it complies with the PRISM syntax.
+             *
+             * @param input The input string to parse.
+             * @param filename The name of the file from which the input was read.
+             * @param typeCheck Sets whether the expressions are generated and therefore typechecked.
+             * @return The resulting PRISM program.
+             */
+            static storm::prism::Program parseFromString(std::string const& input, std::string const& filename, bool typeCheck = true);
+            
+        private:
+            struct modelTypeStruct : qi::symbols<char, storm::prism::Program::ModelType> {
+                modelTypeStruct() {
+                    add
+                    ("dtmc", storm::prism::Program::ModelType::DTMC)
+                    ("ctmc", storm::prism::Program::ModelType::CTMC)
+                    ("mdp", storm::prism::Program::ModelType::MDP)
+                    ("ctmdp", storm::prism::Program::ModelType::CTMDP)
+                    ("ma", storm::prism::Program::ModelType::MA);
+                }
+            };
+            
+            struct keywordsStruct : qi::symbols<char, bool> {
+                keywordsStruct() {
+                    add
+                    ("dtmc", 1)
+                    ("ctmc", 2)
+                    ("mdp", 3)
+                    ("ctmdp", 4)
+                    ("ma", 5)
+                    ("const", 6)
+                    ("int", 7)
+                    ("bool", 8)
+                    ("module", 9)
+                    ("endmodule", 10)
+                    ("rewards", 11)
+                    ("endrewards", 12)
+                    ("true", 13)
+                    ("min", 14)
+                    ("max", 15)
+                    ("floor", 16)
+                    ("ceil", 17)
+                    ("init", 18)
+                    ("endinit", 19);
+                }
+            };
+            
+            // Functor used for displaying error information.
+            struct ErrorHandler {
+                typedef qi::error_handler_result result_type;
+                
+                template<typename T1, typename T2, typename T3, typename T4>
+                qi::error_handler_result operator()(T1 b, T2 e, T3 where, T4 const& what) const {
+                    //                    LOG4CPLUS_ERROR(logger, "Error: expecting " << what << " in line " << get_line(where) << " at column " << get_column(b, where, 4) << ".");
+                    std::cerr << "Error: expecting " << what << " in line " << get_line(where) << "." << std::endl;
+                    T3 end(where);
+                    while (end != e && *end != '\r' && *end != '\n') {
+                        ++end;
+                    }
+                    std::cerr << "Error: expecting " << what << " in line " << get_line(where) << ": \n" << std::string(get_line_start(b, where), end) << " ... \n" << std::setw(std::distance(b, where)) << '^' << "---- here\n";
+                    return qi::fail;
+                }
+            };
+            
+            // Functor used for annotating entities with line number information.
+            class PositionAnnotation {
+            public:
+                typedef void result_type;
+                
+                PositionAnnotation(Iterator first) : first(first) {
+                    // Intentionally left empty.
+                }
+                
+                template<typename Entity, typename First, typename Last>
+                result_type operator()(Entity& entity, First f, Last l) const {
+                    entity.setLineNumber(get_line(f));
+                }
+            private:
+                std::string filename;
+                Iterator const first;
+            };
+            
+            /*!
+             * Creates a grammar for the given filename and the iterator to the first input to parse.
+             *
+             * @param filename The filename that is to be read. This is used for proper error reporting.
+             * @param first The iterator to the beginning of the input.
+             */
+            PrismParser(std::string const& filename, Iterator first);
+            
+            /*!
+             * Sets an internal flag that indicates the second run is now taking place.
+             */
+            void moveToSecondRun();
+            
+            // A flag that stores whether the grammar is currently doing the second run.
+            bool secondRun;
+            
+            /*!
+             * Sets whether doubles literals are allowed in the parsed expression.
+             *
+             * @param flag Indicates whether to allow or forbid double literals in the parsed expression.
+             */
+            void allowDoubleLiterals(bool flag);
+            
+            // A flag that stores wether to allow or forbid double literals in parsed expressions.
+            bool allowDoubleLiteralsFlag;
+            
+            // The name of the file being parsed.
+            std::string filename;
+            
+            /*!
+             * Retrieves the name of the file currently being parsed.
+             *
+             * @return The name of the file currently being parsed.
+             */
+            std::string const& getFilename() const;
+            
+            // A function used for annotating the entities with their position.
+            phoenix::function<ErrorHandler> handler;
+            phoenix::function<PositionAnnotation> annotate;
+            
+            // The starting point of the grammar.
+            qi::rule<Iterator, storm::prism::Program(), qi::locals<GlobalProgramInformation>, Skipper> start;
+            
+            // Rules for model type.
+            qi::rule<Iterator, storm::prism::Program::ModelType(), Skipper> modelTypeDefinition;
+            
+            // Rules for parsing the program header.
+            qi::rule<Iterator, qi::unused_type(GlobalProgramInformation&), Skipper> programHeader;
+            qi::rule<Iterator, storm::prism::Constant(), Skipper> undefinedConstantDefinition;
+            qi::rule<Iterator, storm::prism::Constant(), Skipper> undefinedBooleanConstantDefinition;
+            qi::rule<Iterator, storm::prism::Constant(), Skipper> undefinedIntegerConstantDefinition;
+            qi::rule<Iterator, storm::prism::Constant(), Skipper> undefinedDoubleConstantDefinition;
+            qi::rule<Iterator, storm::prism::Constant(), Skipper> definedConstantDefinition;
+            qi::rule<Iterator, storm::prism::Constant(), Skipper> definedBooleanConstantDefinition;
+            qi::rule<Iterator, storm::prism::Constant(), Skipper> definedIntegerConstantDefinition;
+            qi::rule<Iterator, storm::prism::Constant(), Skipper> definedDoubleConstantDefinition;
+            
+            // Rules for global variable definitions.
+            qi::rule<Iterator, qi::unused_type(GlobalProgramInformation&), Skipper> globalVariableDefinition;
+            qi::rule<Iterator, qi::unused_type(GlobalProgramInformation&), Skipper> globalBooleanVariableDefinition;
+            qi::rule<Iterator, qi::unused_type(GlobalProgramInformation&), Skipper> globalIntegerVariableDefinition;
+            
+            // Rules for modules definition.
+            qi::rule<Iterator, std::vector<storm::prism::Module>(GlobalProgramInformation&), Skipper> moduleDefinitionList;
+            qi::rule<Iterator, storm::prism::Module(GlobalProgramInformation&), qi::locals<std::vector<storm::prism::BooleanVariable>, std::vector<storm::prism::IntegerVariable>>, Skipper> moduleDefinition;
+            qi::rule<Iterator, storm::prism::Module(GlobalProgramInformation&), qi::locals<std::map<std::string, std::string>>, Skipper> moduleRenaming;
+            
+            // Rules for variable definitions.
+            qi::rule<Iterator, qi::unused_type(std::vector<storm::prism::BooleanVariable>&, std::vector<storm::prism::IntegerVariable>&), Skipper> variableDefinition;
+            qi::rule<Iterator, storm::prism::BooleanVariable(), Skipper> booleanVariableDefinition;
+            qi::rule<Iterator, storm::prism::IntegerVariable(), qi::locals<storm::expressions::Expression>, Skipper> integerVariableDefinition;
+            
+            // Rules for command definitions.
+            qi::rule<Iterator, storm::prism::Command(GlobalProgramInformation&), qi::locals<std::string>, Skipper> commandDefinition;
+            qi::rule<Iterator, std::vector<storm::prism::Update>(GlobalProgramInformation&), Skipper> updateListDefinition;
+            qi::rule<Iterator, storm::prism::Update(GlobalProgramInformation&), Skipper> updateDefinition;
+            qi::rule<Iterator, std::vector<storm::prism::Assignment>(), Skipper> assignmentDefinitionList;
+            qi::rule<Iterator, storm::prism::Assignment(), Skipper> assignmentDefinition;
+            
+            // Rules for reward definitions.
+            qi::rule<Iterator, storm::prism::RewardModel(), qi::locals<std::string, std::vector<storm::prism::StateReward>, std::vector<storm::prism::TransitionReward>>, Skipper> rewardModelDefinition;
+            qi::rule<Iterator, storm::prism::StateReward(), Skipper> stateRewardDefinition;
+            qi::rule<Iterator, storm::prism::TransitionReward(), qi::locals<std::string>, Skipper> transitionRewardDefinition;
+            
+            // Rules for initial states expression.
+            qi::rule<Iterator, qi::unused_type(GlobalProgramInformation&), Skipper> initialStatesConstruct;
+            
+            // Rules for label definitions.
+            qi::rule<Iterator, storm::prism::Label(), Skipper> labelDefinition;
+            
+            // Rules for formula definitions.
+            qi::rule<Iterator, storm::prism::Formula(), Skipper> formulaDefinition;
+            
+            // Rules for identifier parsing.
+            qi::rule<Iterator, std::string(), Skipper> identifier;
+            
+            // Rules for parsing a composed expression.
+            qi::rule<Iterator, storm::expressions::Expression(), Skipper> expression;
+            qi::rule<Iterator, storm::expressions::Expression(), Skipper> iteExpression;
+            qi::rule<Iterator, storm::expressions::Expression(), Skipper> orExpression;
+            qi::rule<Iterator, storm::expressions::Expression(), Skipper> andExpression;
+            qi::rule<Iterator, storm::expressions::Expression(), Skipper> relativeExpression;
+            qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> plusExpression;
+            qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> multiplicationExpression;
+            qi::rule<Iterator, storm::expressions::Expression(), Skipper> unaryExpression;
+            qi::rule<Iterator, storm::expressions::Expression(), Skipper> atomicExpression;
+            qi::rule<Iterator, storm::expressions::Expression(), Skipper> literalExpression;
+            qi::rule<Iterator, storm::expressions::Expression(), Skipper> identifierExpression;
+            qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> minMaxExpression;
+            qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> floorCeilExpression;
+            
+            // Parser that is used to recognize doubles only (as opposed to Spirit's double_ parser).
+            boost::spirit::qi::real_parser<double, boost::spirit::qi::strict_real_policies<double>> strict_double;
+            
+            // Parsers that recognize special keywords and model types.
+            storm::parser::PrismParser::keywordsStruct keywords_;
+            storm::parser::PrismParser::modelTypeStruct modelType_;
+            qi::symbols<char, storm::expressions::Expression> identifiers_;
+            
+            // Helper methods used in the grammar.
+            bool isValidIdentifier(std::string const& identifier);
+            bool addInitialStatesExpression(storm::expressions::Expression initialStatesExpression, GlobalProgramInformation& globalProgramInformation);
+            
+            storm::expressions::Expression createIteExpression(storm::expressions::Expression e1, storm::expressions::Expression e2, storm::expressions::Expression e3) const;
+            storm::expressions::Expression createOrExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;
+            storm::expressions::Expression createAndExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;
+            storm::expressions::Expression createGreaterExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;
+            storm::expressions::Expression createGreaterOrEqualExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;
+            storm::expressions::Expression createLessExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;
+            storm::expressions::Expression createLessOrEqualExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;
+            storm::expressions::Expression createEqualsExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;
+            storm::expressions::Expression createNotEqualsExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;
+            storm::expressions::Expression createPlusExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;
+            storm::expressions::Expression createMinusExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;
+            storm::expressions::Expression createMultExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;
+            storm::expressions::Expression createDivExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;
+            storm::expressions::Expression createNotExpression(storm::expressions::Expression e1) const;
+            storm::expressions::Expression createMinusExpression(storm::expressions::Expression e1) const;
+            storm::expressions::Expression createTrueExpression() const;
+            storm::expressions::Expression createFalseExpression() const;
+            storm::expressions::Expression createDoubleLiteralExpression(double value, bool& pass) const;
+            storm::expressions::Expression createIntegerLiteralExpression(int value) const;
+            storm::expressions::Expression createMinimumExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;
+            storm::expressions::Expression createMaximumExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const;
+            storm::expressions::Expression createFloorExpression(storm::expressions::Expression e1) const;
+            storm::expressions::Expression createCeilExpression(storm::expressions::Expression e1) const;
+            storm::expressions::Expression getIdentifierExpression(std::string const& identifier) const;
+            
+            storm::prism::Constant createUndefinedBooleanConstant(std::string const& newConstant) const;
+            storm::prism::Constant createUndefinedIntegerConstant(std::string const& newConstant) const;
+            storm::prism::Constant createUndefinedDoubleConstant(std::string const& newConstant) const;
+            storm::prism::Constant createDefinedBooleanConstant(std::string const& newConstant, storm::expressions::Expression expression) const;
+            storm::prism::Constant createDefinedIntegerConstant(std::string const& newConstant, storm::expressions::Expression expression) const;
+            storm::prism::Constant createDefinedDoubleConstant(std::string const& newConstant, storm::expressions::Expression expression) const;
+            storm::prism::Formula createFormula(std::string const& formulaName, storm::expressions::Expression expression) const;
+            storm::prism::Label createLabel(std::string const& labelName, storm::expressions::Expression expression) const;
+            storm::prism::RewardModel createRewardModel(std::string const& rewardModelName, std::vector<storm::prism::StateReward> const& stateRewards, std::vector<storm::prism::TransitionReward> const& transitionRewards) const;
+            storm::prism::StateReward createStateReward(storm::expressions::Expression statePredicateExpression, storm::expressions::Expression rewardValueExpression) const;
+            storm::prism::TransitionReward createTransitionReward(std::string const& actionName, storm::expressions::Expression statePredicateExpression, storm::expressions::Expression rewardValueExpression) const;
+            storm::prism::Assignment createAssignment(std::string const& variableName, storm::expressions::Expression assignedExpression) const;
+            storm::prism::Update createUpdate(storm::expressions::Expression likelihoodExpression, std::vector<storm::prism::Assignment> const& assignments, GlobalProgramInformation& globalProgramInformation) const;
+            storm::prism::Command createCommand(std::string const& actionName, storm::expressions::Expression guardExpression, std::vector<storm::prism::Update> const& updates, GlobalProgramInformation& globalProgramInformation) const;
+            storm::prism::BooleanVariable createBooleanVariable(std::string const& variableName, storm::expressions::Expression initialValueExpression) const;
+            storm::prism::IntegerVariable createIntegerVariable(std::string const& variableName, storm::expressions::Expression lowerBoundExpression, storm::expressions::Expression upperBoundExpression, storm::expressions::Expression initialValueExpression) const;
+            storm::prism::Module createModule(std::string const& moduleName, std::vector<storm::prism::BooleanVariable> const& booleanVariables, std::vector<storm::prism::IntegerVariable> const& integerVariables, std::vector<storm::prism::Command> const& commands, GlobalProgramInformation& globalProgramInformation) const;
+            storm::prism::Module createRenamedModule(std::string const& newModuleName, std::string const& oldModuleName, std::map<std::string, std::string> const& renaming, GlobalProgramInformation& globalProgramInformation) const;
+            storm::prism::Program createProgram(GlobalProgramInformation const& globalProgramInformation) const;
+        };
+    } // namespace parser
 } // namespace storm
 
-#endif /* STORM_PARSER_PRISMPARSER_H_ */
+#endif	/* STORM_PARSER_PRISMPARSER_H_ */
+
diff --git a/src/parser/prismparser/BaseGrammar.h b/src/parser/prismparser/BaseGrammar.h
deleted file mode 100644
index 7cac493c3..000000000
--- a/src/parser/prismparser/BaseGrammar.h
+++ /dev/null
@@ -1,253 +0,0 @@
-/* 
- * File:   Keywords.h
- * Author: nafur
- *
- * Created on April 10, 2013, 6:03 PM
- */
-
-#ifndef BASEGRAMMAR_H
-#define	BASEGRAMMAR_H
-
-#include "Includes.h"
-
-#include "VariableState.h"
-
-namespace storm {
-namespace parser {
-namespace prism {
-
-	/*!
-	 * This is the base class for all expression grammars.
-	 * It takes care of implementing a singleton, stores a VariableState and implements some common helper routines.
-	 */
-	template <typename T>
-	class BaseGrammar {
-	public:
-		/*!
-		 * Constructor.
-		 */
-		BaseGrammar(std::shared_ptr<VariableState> const& state) : state(state) {}
-
-		/*!
-		 * Create and return a new instance of class T, usually the subclass.
-		 * @param state VariableState to be given to the constructor.
-		 * @returns Instance of class T.
-		 */
-		static T& instance(std::shared_ptr<VariableState> const& state = nullptr) {
-			if (BaseGrammar::instanceObject == nullptr) {
-				BaseGrammar::instanceObject = std::shared_ptr<T>(new T(state));
-				if (!state->firstRun) BaseGrammar::instanceObject->secondRun();
-			}
-			return *BaseGrammar::instanceObject;
-		}
-
-		/*!
-		 * Clear the cached instance.
-		 */
-		static void resetInstance() {
-			BaseGrammar::instanceObject = nullptr;
-		}
-
-		/*!
-		 * Notify the cached object, that we will begin with the second parsing run.
-		 */
-		static void secondRun() {
-			if (BaseGrammar::instanceObject != nullptr) {
-				BaseGrammar::instanceObject->prepareSecondRun();
-			}
-		}
-
-		/*!
-		 * Create a new boolean literal with the given value.
-		 * @param value Value of the literal.
-		 * @returns Boolean literal.
-		 */
-		std::shared_ptr<BaseExpression> createBoolLiteral(bool value) {
-			return std::shared_ptr<BaseExpression>(new BooleanLiteralExpression(value));
-		}
-		/*!
-		 * Create a new double literal with the given value.
-		 * @param value Value of the literal.
-		 * @returns Double literal.
-		 */
-		std::shared_ptr<BaseExpression> createDoubleLiteral(double value) {
-			return std::shared_ptr<BaseExpression>(new DoubleLiteralExpression(value));
-		}
-		/*!
-		 * Create a new integer literal with the given value.
-		 * @param value Value of the literal.
-		 * @returns Integer literal.
-		 */
-		std::shared_ptr<BaseExpression> createIntLiteral(int_fast64_t value) {
-			return std::shared_ptr<BaseExpression>(new IntegerLiteralExpression(value));
-		}
-		
-		/*!
-		 * Create a new plus expression. If addition is true, it will be an addition, otherwise a subtraction.
-		 * @param left Left operand.
-		 * @param addition Flag for addition or subtraction.
-		 * @param right Right operand.
-		 * @param type Return type.
-		 * @returns Plus expression.
-		 */
-		std::shared_ptr<BaseExpression> createPlus(std::shared_ptr<BaseExpression> const& left, bool addition, std::shared_ptr<BaseExpression> const& right, BaseExpression::ReturnType type) {
-			if (addition) {
-				return std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(type, left->clone(), right->clone(), BinaryNumericalFunctionExpression::PLUS));
-			} else {
-				return std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(type, left->clone(), right->clone(), BinaryNumericalFunctionExpression::MINUS));
-			}
-		}
-		/*!
-		 * Create a new double plus expression. If addition is true, it will be an addition, otherwise a subtraction.
-		 * @param left Left operand.
-		 * @param addition Flag for addition or subtraction.
-		 * @param right Right operand.
-		 * @returns Double plus expression.
-		 */
-		std::shared_ptr<BaseExpression> createDoublePlus(std::shared_ptr<BaseExpression> const& left, bool addition, std::shared_ptr<BaseExpression> const& right) {
-			return this->createPlus(left, addition, right, BaseExpression::double_);
-		}
-		/*!
-		 * Create a new integer plus expression. If addition is true, it will be an addition, otherwise a subtraction.
-		 * @param left Left operand.
-		 * @param addition Flag for addition or subtraction.
-		 * @param right Right operand.
-		 * @returns Integer plus expression.
-		 */
-		std::shared_ptr<BaseExpression> createIntPlus(std::shared_ptr<BaseExpression> const& left, bool addition, std::shared_ptr<BaseExpression> const& right) {
-			return this->createPlus(left, addition, right, BaseExpression::int_);
-		}
-
-		/*!
-		 * Create a new integer multiplication expression.
-		 * @param left Left operand.
-		 * @param right Right operand.
-		 * @returns Integer multiplication expression.
-		 */
-		std::shared_ptr<BaseExpression> createIntMult(std::shared_ptr<BaseExpression> const& left, std::shared_ptr<BaseExpression> const& right) {
-			return std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(BaseExpression::int_, left->clone(), right->clone(), BinaryNumericalFunctionExpression::TIMES));
-		}
-        
-		/*!
-		 * Create a new integer multiplication expression. If multiplication is true, it will be an multiplication, otherwise a division.
-		 * @param left Left operand.
-		 * @param addition Flag for multiplication or division.
-		 * @param right Right operand.
-		 * @returns Integer multiplication expression.
-		 */
-		std::shared_ptr<BaseExpression> createDoubleMult(std::shared_ptr<BaseExpression> const& left, bool multiplication, std::shared_ptr<BaseExpression> const& right) {
-			if (multiplication) {
-				return std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(BaseExpression::double_, left->clone(), right->clone(), BinaryNumericalFunctionExpression::TIMES));
-			} else {
-				return std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(BaseExpression::double_, left->clone(), right->clone(), BinaryNumericalFunctionExpression::DIVIDE));
-			}
-		}
-        
-        /*!
-         * Creates an integer min/max expression.
-         *
-         * @param min Indicates whether the expression is min or max.
-         * @param left The left operand.
-         * @param right The right operand.
-         * @return An integer min/max expression.
-         */
-        std::shared_ptr<BaseExpression> createIntMinMax(bool min, std::shared_ptr<BaseExpression> const& left, std::shared_ptr<BaseExpression> const& right) {
-            if (min) {
-                return std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(BaseExpression::int_, left->clone(), right->clone(), BinaryNumericalFunctionExpression::MIN));
-            } else {
-                return std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(BaseExpression::int_, left->clone(), right->clone(), BinaryNumericalFunctionExpression::MAX));
-            }
-        }
-        
-        /*!
-         * Creates an integer floor/ceil expression.
-         *
-         * @param floor Indicates whether the expression is a floor expression.
-         * @param operand The argument of the floor/ceil operation.
-         * @return An integer floor/ceil expression.
-         */
-        std::shared_ptr<BaseExpression> createIntFloorCeil(bool floor, std::shared_ptr<BaseExpression> const& operand) {
-            if (floor) {
-                return std::shared_ptr<BaseExpression>(new UnaryNumericalFunctionExpression(BaseExpression::int_, operand->clone(), UnaryNumericalFunctionExpression::FLOOR));
-            } else {
-                return std::shared_ptr<BaseExpression>(new UnaryNumericalFunctionExpression(BaseExpression::int_, operand->clone(), UnaryNumericalFunctionExpression::CEIL));
-            }
-        }
-        
-		/*!
-		 * Create a new binary relation expression.
-		 * @param left Left operand.
-		 * @param relationType Type of binary relation.
-		 * @param right Right operand.
-		 * @returns Binary relation expression.
-		 */
-		std::shared_ptr<BaseExpression> createRelation(std::shared_ptr<BaseExpression> const& left, BinaryRelationExpression::RelationType relationType, std::shared_ptr<BaseExpression> const& right) {
-			return std::shared_ptr<BaseExpression>(new BinaryRelationExpression(left->clone(), right->clone(), relationType));
-		}
-		/*!
-		 * Create a new negation expression.
-		 * @param child Expression to be negated.
-		 * @returns Negation expression.
-		 */
-		std::shared_ptr<BaseExpression> createNot(std::shared_ptr<BaseExpression> const& child) {
-			return std::shared_ptr<UnaryBooleanFunctionExpression>(new UnaryBooleanFunctionExpression(child->clone(), UnaryBooleanFunctionExpression::NOT));
-		}
-		/*!
-		 * Create a new And expression.
-		 * @param left Left operand.
-		 * @param right Right operand.
-		 * @returns And expression.
-		 */
-		std::shared_ptr<BaseExpression> createAnd(std::shared_ptr<BaseExpression> const& left, std::shared_ptr<BaseExpression> const& right) {
-			return std::shared_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(left->clone(), right->clone(), BinaryBooleanFunctionExpression::AND));
-		}
-		/*!
-		 * Create a new Or expression.
-		 * @param left Left operand.
-		 * @param right Right operand.
-		 * @returns Or expression.
-		 */
-		std::shared_ptr<BaseExpression> createOr(std::shared_ptr<BaseExpression> const& left, std::shared_ptr<BaseExpression> const& right) {
-			return std::shared_ptr<BinaryBooleanFunctionExpression>(new BinaryBooleanFunctionExpression(left->clone(), right->clone(), BinaryBooleanFunctionExpression::OR));
-		}
-		/*!
-		 * Retrieve boolean variable by name.
-		 * @param name Variable name.
-		 * @returns Boolean variable.
-		 */
-		std::shared_ptr<BaseExpression> getBoolVariable(std::string const& name) {
-			return std::shared_ptr<BaseExpression>(new VariableExpression(*state->getBooleanVariableExpression(name)));
-		}
-		/*!
-		 * Retrieve integer variable by name.
-		 * @param name Variable name.
-		 * @returns Integer variable.
-		 */
-		std::shared_ptr<BaseExpression> getIntVariable(std::string const& name) {
-			return std::shared_ptr<BaseExpression>(new VariableExpression(*state->getIntegerVariableExpression(name)));
-		}
-
-		/*!
-		 * Base method to switch to second run. This does nothing.
-		 * Any subclass that needs to do something in order to proceed to the second run should override this method.
-		 */
-		virtual void prepareSecondRun() {}
-        
-	protected:
-		/*!
-		 * Pointer to variable state.
-		 */
-		std::shared_ptr<VariableState> state;
-
-	private:
-		static std::shared_ptr<T> instanceObject;
-		static bool inSecondRun;
-	};
-
-	template <typename T>
-	std::shared_ptr<T> BaseGrammar<T>::instanceObject;
-}
-}
-}
-#endif	/* BASEGRAMMAR_H */
-
diff --git a/src/parser/prismparser/BooleanExpressionGrammar.cpp b/src/parser/prismparser/BooleanExpressionGrammar.cpp
deleted file mode 100644
index a7d9366f8..000000000
--- a/src/parser/prismparser/BooleanExpressionGrammar.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-#include "BooleanExpressionGrammar.h"
-
-#include "IntegerExpressionGrammar.h"
-#include "ConstBooleanExpressionGrammar.h"
-
-namespace storm {
-    namespace parser {
-        namespace prism {
-            
-            BooleanExpressionGrammar::BooleanExpressionGrammar(std::shared_ptr<VariableState> const& state)
-            : BooleanExpressionGrammar::base_type(booleanExpression), BaseGrammar(state) {
-                
-                booleanExpression %= orExpression;
-                booleanExpression.name("boolean expression");
-                
-                orExpression = andExpression[qi::_val = qi::_1] >> *(qi::lit("|") >> andExpression)[qi::_val = phoenix::bind(&BaseGrammar::createOr, this, qi::_val, qi::_1)];
-                orExpression.name("boolean expression");
-                
-                andExpression = notExpression[qi::_val = qi::_1] >> *(qi::lit("&") >> notExpression)[qi::_val = phoenix::bind(&BaseGrammar::createAnd, this, qi::_val, qi::_1)];
-                andExpression.name("boolean expression");
-                
-                notExpression = atomicBooleanExpression[qi::_val = qi::_1] | (qi::lit("!") >> atomicBooleanExpression)[qi::_val = phoenix::bind(&BaseGrammar::createNot, this, qi::_1)];
-                notExpression.name("boolean expression");
-                
-                atomicBooleanExpression %= (relativeExpression | booleanVariableExpression | this->state->constantBooleanFormulas_ | this->state->booleanFormulas_ | qi::lit("(") >> booleanExpression >> qi::lit(")") | ConstBooleanExpressionGrammar::instance(this->state));
-                atomicBooleanExpression.name("boolean expression");
-                
-                relativeExpression = (IntegerExpressionGrammar::instance(this->state) >> relations_ >> IntegerExpressionGrammar::instance(this->state))[qi::_val = phoenix::bind(&BaseGrammar::createRelation, this, qi::_1, qi::_2, qi::_3)];
-                relativeExpression.name("relative expression");
-                
-                booleanVariableExpression = IdentifierGrammar::instance(this->state)[qi::_val = phoenix::bind(&BaseGrammar::getBoolVariable, this, qi::_1)];
-                booleanVariableExpression.name("boolean variable");
-            }
-            
-            void BooleanExpressionGrammar::prepareSecondRun() {
-                booleanVariableExpression %= this->state->booleanVariables_;
-                booleanVariableExpression.name("boolean variable");
-            }
-            
-        } // namespace prism
-    } // namespace parser
-} // namespace storm
diff --git a/src/parser/prismparser/BooleanExpressionGrammar.h b/src/parser/prismparser/BooleanExpressionGrammar.h
deleted file mode 100644
index 909219fa3..000000000
--- a/src/parser/prismparser/BooleanExpressionGrammar.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* 
- * File:   BooleanExpressionGrammar.h
- * Author: nafur
- *
- * Created on April 10, 2013, 6:27 PM
- */
-
-#ifndef BOOLEANEXPRESSIONGRAMMAR_H
-#define	BOOLEANEXPRESSIONGRAMMAR_H
-
-#include "Includes.h"
-#include "VariableState.h"
-#include "IdentifierGrammars.h"
-#include "Tokens.h"
-
-#include <iostream>
-
-namespace storm {
-namespace parser {
-namespace prism {
-
-/*!
- * This grammar parses (non constant) boolean expressions as used in prism models.
- */
-class BooleanExpressionGrammar : public qi::grammar<Iterator, std::shared_ptr<BaseExpression>(), Skipper, Unused>, public BaseGrammar<BooleanExpressionGrammar> {
-public:
-	BooleanExpressionGrammar(std::shared_ptr<VariableState> const& state);
-	/*!
-	 * Switch to second run.
-	 * Variable names may be any valid identifier in the first run, but only defined variables in the second run.
-	 */
-	virtual void prepareSecondRun();
-	
-private:
-	qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper, Unused> booleanExpression;
-	qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> orExpression;
-	qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> andExpression;
-	qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> notExpression;
-	qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> atomicBooleanExpression;
-	qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> relativeExpression;
-	qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> booleanVariableExpression;
-
-	/*!
-	 * Parser relation operators.
-	 */
-	storm::parser::prism::relationalOperatorStruct relations_;
-};
-
-
-}
-}
-}
-
-#endif	/* BOOLEANEXPRESSIONGRAMMAR_H */
diff --git a/src/parser/prismparser/ConstBooleanExpressionGrammar.cpp b/src/parser/prismparser/ConstBooleanExpressionGrammar.cpp
deleted file mode 100644
index a5ce0567d..000000000
--- a/src/parser/prismparser/ConstBooleanExpressionGrammar.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#include "ConstBooleanExpressionGrammar.h"
-
-#include "ConstIntegerExpressionGrammar.h"
-
-namespace storm {
-namespace parser {
-namespace prism {
-
-	ConstBooleanExpressionGrammar::ConstBooleanExpressionGrammar(std::shared_ptr<VariableState> const& state)
-		: ConstBooleanExpressionGrammar::base_type(constantBooleanExpression), BaseGrammar(state) {
-
-		constantBooleanExpression %= constantOrExpression;
-		constantBooleanExpression.name("constant boolean expression");
-		
-		constantOrExpression = constantAndExpression[qi::_val = qi::_1] >> *(qi::lit("|") >> constantAndExpression)[qi::_val = phoenix::bind(&BaseGrammar::createOr, this, qi::_val, qi::_1)];
-		constantOrExpression.name("constant boolean expression");
-
-		constantAndExpression = constantNotExpression[qi::_val = qi::_1] >> *(qi::lit("&") >> constantNotExpression)[qi::_val = phoenix::bind(&BaseGrammar::createAnd, this, qi::_val, qi::_1)];
-		constantAndExpression.name("constant boolean expression");
-
-		constantNotExpression = constantAtomicBooleanExpression[qi::_val = qi::_1] | (qi::lit("!") >> constantAtomicBooleanExpression)[qi::_val = phoenix::bind(&BaseGrammar::createNot, this, qi::_1)];
-		constantNotExpression.name("constant boolean expression");
-
-		constantAtomicBooleanExpression %= (constantRelativeExpression | this->state->constantBooleanFormulas_ | qi::lit("(") >> constantBooleanExpression >> qi::lit(")") | booleanLiteralExpression | booleanConstantExpression);
-		constantAtomicBooleanExpression.name("constant boolean expression");
-
-		constantRelativeExpression = (ConstIntegerExpressionGrammar::instance(this->state) >> relations_ >> ConstIntegerExpressionGrammar::instance(this->state))[qi::_val = phoenix::bind(&BaseGrammar::createRelation, this, qi::_1, qi::_2, qi::_3)];
-		constantRelativeExpression.name("constant boolean expression");
-		
-		booleanConstantExpression %= (this->state->booleanConstants_ | booleanLiteralExpression);
-		booleanConstantExpression.name("boolean constant or literal");
-
-		booleanLiteralExpression = qi::bool_[qi::_val = phoenix::bind(&BaseGrammar::createBoolLiteral, this, qi::_1)];
-		booleanLiteralExpression.name("boolean literal");
-	}
-}
-}
-}
diff --git a/src/parser/prismparser/ConstBooleanExpressionGrammar.h b/src/parser/prismparser/ConstBooleanExpressionGrammar.h
deleted file mode 100644
index 8fea3ce95..000000000
--- a/src/parser/prismparser/ConstBooleanExpressionGrammar.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* 
- * File:   ConstBooleanExpressionGrammar.h
- * Author: nafur
- *
- * Created on April 10, 2013, 6:34 PM
- */
-
-#ifndef CONSTBOOLEANEXPRESSIONGRAMMAR_H
-#define	CONSTBOOLEANEXPRESSIONGRAMMAR_H
-
-#include "Includes.h"
-#include "VariableState.h"
-#include "IdentifierGrammars.h"
-#include "Tokens.h"
-
-namespace storm {
-namespace parser {
-namespace prism {
-
-/*!
- * This grammar parses constant boolean expression as used in prism models.
- */
-class ConstBooleanExpressionGrammar : public qi::grammar<Iterator, std::shared_ptr<BaseExpression>(), Skipper, Unused>, public BaseGrammar<ConstBooleanExpressionGrammar> {
-public:
-	ConstBooleanExpressionGrammar(std::shared_ptr<VariableState> const& state);
-
-
-private:
-	qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper, Unused> constantBooleanExpression;
-	qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> constantOrExpression;
-	qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> constantAndExpression;
-	qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> constantNotExpression;
-	qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> constantAtomicBooleanExpression;
-	qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> constantRelativeExpression;
-	qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> booleanConstantExpression;
-	qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> booleanLiteralExpression;
-
-	storm::parser::prism::relationalOperatorStruct relations_;
-};
-
-
-}
-}
-}
-
-#endif	/* CONSTBOOLEANEXPRESSIONGRAMMAR_H */
-
diff --git a/src/parser/prismparser/ConstDoubleExpressionGrammar.cpp b/src/parser/prismparser/ConstDoubleExpressionGrammar.cpp
deleted file mode 100644
index 18cd5ae31..000000000
--- a/src/parser/prismparser/ConstDoubleExpressionGrammar.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-#include "ConstDoubleExpressionGrammar.h"
-
-namespace storm {
-namespace parser {
-namespace prism {
-
-ConstDoubleExpressionGrammar::ConstDoubleExpressionGrammar(std::shared_ptr<VariableState> const& state)
-	: ConstDoubleExpressionGrammar::base_type(constantDoubleExpression), BaseGrammar(state) {
-
-	constantDoubleExpression %= constantDoublePlusExpression;
-	constantDoubleExpression.name("constant double expression");
-
-	constantDoublePlusExpression %= constantDoubleMultExpression[qi::_val = qi::_1] >> *((qi::lit("+")[qi::_a = true] | qi::lit("-")[qi::_a = false]) >> constantDoubleMultExpression)
-			[qi::_val = phoenix::bind(&BaseGrammar::createDoublePlus, this, qi::_val, qi::_a, qi::_1)];
-	constantDoublePlusExpression.name("constant double expression");
-
-	constantDoubleMultExpression %= constantAtomicDoubleExpression[qi::_val = qi::_1] >> *((qi::lit("*")[qi::_a = true] | qi::lit("/")[qi::_a = false]) >> constantAtomicDoubleExpression)
-			[qi::_val = phoenix::bind(&BaseGrammar::createDoubleMult, this, qi::_val, qi::_a, qi::_1)];
-	constantDoubleMultExpression.name("constant double expression");
-
-	constantAtomicDoubleExpression %= (qi::lit("(") >> constantDoubleExpression >> qi::lit(")") | this->state->constantDoubleFormulas_ | this->state->constantIntegerFormulas_ | doubleConstantExpression);
-	constantAtomicDoubleExpression.name("constant double expression");
-
-	doubleConstantExpression %= (this->state->doubleConstants_ | this->state->integerConstants_ | doubleLiteralExpression);
-	doubleConstantExpression.name("double constant or literal");
-
-	doubleLiteralExpression = qi::double_[qi::_val = phoenix::bind(&BaseGrammar::createDoubleLiteral, this, qi::_1)];
-	doubleLiteralExpression.name("double literal");
-}
-
-
-}
-}
-}
diff --git a/src/parser/prismparser/ConstDoubleExpressionGrammar.h b/src/parser/prismparser/ConstDoubleExpressionGrammar.h
deleted file mode 100644
index 41c503731..000000000
--- a/src/parser/prismparser/ConstDoubleExpressionGrammar.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 
- * File:   ConstDoubleExpressionGrammar.h
- * Author: nafur
- *
- * Created on April 10, 2013, 7:04 PM
- */
-
-#ifndef CONSTDOUBLEEXPRESSIONGRAMMAR_H
-#define	CONSTDOUBLEEXPRESSIONGRAMMAR_H
-
-#include "Includes.h"
-#include "VariableState.h"
-#include "IdentifierGrammars.h"
-
-namespace storm {
-    namespace parser {
-        namespace prism {
-            
-            /*!
-             * This grammar parses constant double expressions as used in prism models.
-             */
-            class ConstDoubleExpressionGrammar : public qi::grammar<Iterator, std::shared_ptr<BaseExpression>(), Skipper, Unused>, public BaseGrammar<ConstDoubleExpressionGrammar> {
-            public:
-                ConstDoubleExpressionGrammar(std::shared_ptr<VariableState> const& state);
-                
-            private:
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper, Unused> constantDoubleExpression;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), qi::locals<bool>, Skipper> constantDoublePlusExpression;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), qi::locals<bool>, Skipper> constantDoubleMultExpression;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> constantAtomicDoubleExpression;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> doubleConstantExpression;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> doubleLiteralExpression;
-            };
-            
-            
-        }
-    }
-}
-
-#endif	/* CONSTDOUBLEEXPRESSIONGRAMMAR_H */
-
diff --git a/src/parser/prismparser/ConstIntegerExpressionGrammar.cpp b/src/parser/prismparser/ConstIntegerExpressionGrammar.cpp
deleted file mode 100644
index 9ebebebc7..000000000
--- a/src/parser/prismparser/ConstIntegerExpressionGrammar.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-#include "ConstIntegerExpressionGrammar.h"
-
-namespace storm {
-    namespace parser {
-        namespace prism {
-            
-            
-            ConstIntegerExpressionGrammar::ConstIntegerExpressionGrammar(std::shared_ptr<VariableState> const& state)
-            : ConstIntegerExpressionGrammar::base_type(constantIntegerExpression), BaseGrammar(state) {
-                
-                constantIntegerExpression %= constantIntegerPlusExpression;
-                constantIntegerExpression.name("constant integer expression");
-                
-                constantIntegerPlusExpression = constantIntegerMultExpression[qi::_val = qi::_1] >> *((qi::lit("+")[qi::_a = true] | qi::lit("-")[qi::_a = false]) >> constantIntegerMultExpression)
-                [qi::_val = phoenix::bind(&BaseGrammar::createIntPlus, this, qi::_val, qi::_a, qi::_1)];
-                constantIntegerPlusExpression.name("constant integer expression");
-                
-                constantIntegerMultExpression %= constantAtomicIntegerExpression[qi::_val = qi::_1] >> *(qi::lit("*") >> constantAtomicIntegerExpression)
-                [qi::_val = phoenix::bind(&BaseGrammar::createIntMult, this, qi::_val, qi::_1)];
-                constantIntegerMultExpression.name("constant integer expression");
-                
-                constantAtomicIntegerExpression %= (constantIntegerMinMaxExpression | constantIntegerFloorCeilExpression | this->state->constantIntegerFormulas_ | qi::lit("(") >> constantIntegerExpression >> qi::lit(")") | integerConstantExpression);
-                constantAtomicIntegerExpression.name("constant integer expression");
-                
-                constantIntegerMinMaxExpression = ((qi::lit("min")[qi::_a = true] | qi::lit("max")[qi::_a = false]) >> qi::lit("(") >> constantIntegerExpression >> qi::lit(",") >> constantIntegerExpression >> qi::lit(")"))[qi::_val = phoenix::bind(&BaseGrammar::createIntMinMax, this, qi::_a, qi::_1, qi::_2)];
-                constantIntegerMinMaxExpression.name("integer min/max expression");
-                
-                constantIntegerFloorCeilExpression = ((qi::lit("floor")[qi::_a = true] | qi::lit("ceil")[qi::_a = false]) >> qi::lit("(") >> constantIntegerExpression >> qi::lit(")"))[qi::_val = phoenix::bind(&BaseGrammar::createIntFloorCeil, this, qi::_a, qi::_1)];
-                constantIntegerFloorCeilExpression.name("integer floor/ceil expression");
-                
-                integerConstantExpression %= (this->state->integerConstants_ | integerLiteralExpression);
-                integerConstantExpression.name("integer constant or literal");
-                
-                integerLiteralExpression = qi::int_[qi::_val = phoenix::bind(&BaseGrammar::createIntLiteral, this, qi::_1)];
-                integerLiteralExpression.name("integer literal");
-                
-            }
-            
-        } // namespace prism
-    } // namespace parser
-} // namespace storm
diff --git a/src/parser/prismparser/ConstIntegerExpressionGrammar.h b/src/parser/prismparser/ConstIntegerExpressionGrammar.h
deleted file mode 100644
index 2b6a08cae..000000000
--- a/src/parser/prismparser/ConstIntegerExpressionGrammar.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* 
- * File:   ConstIntegerExpressionGrammar.h
- * Author: nafur
- *
- * Created on April 10, 2013, 6:02 PM
- */
-
-#ifndef CONSTINTEGEREXPRESSIONGRAMMAR_H
-#define	CONSTINTEGEREXPRESSIONGRAMMAR_H
-
-#include "Includes.h"
-#include "VariableState.h"
-#include "IdentifierGrammars.h"
-
-namespace storm {
-    namespace parser {
-        namespace prism {
-            
-            /*!
-             * This grammar parses constant integer expressions as used in prism models.
-             */
-            class ConstIntegerExpressionGrammar : public qi::grammar<Iterator, std::shared_ptr<BaseExpression>(), Skipper, Unused>, public BaseGrammar<ConstIntegerExpressionGrammar> {
-            public:
-                ConstIntegerExpressionGrammar(std::shared_ptr<VariableState> const& state);
-                
-            private:
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper, Unused> constantIntegerExpression;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), qi::locals<bool>, Skipper> constantIntegerPlusExpression;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> constantIntegerMultExpression;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> constantAtomicIntegerExpression;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> integerConstantExpression;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> integerLiteralExpression;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), qi::locals<bool>, Skipper> constantIntegerMinMaxExpression;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), qi::locals<bool>, Skipper> constantIntegerFloorCeilExpression;
-            };
-            
-            
-        }
-    }
-}
-
-#endif	/* CONSTINTEGEREXPRESSIONGRAMMAR_H */
diff --git a/src/parser/prismparser/IdentifierGrammars.cpp b/src/parser/prismparser/IdentifierGrammars.cpp
deleted file mode 100644
index ec6f14931..000000000
--- a/src/parser/prismparser/IdentifierGrammars.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "IdentifierGrammars.h"
-
-namespace storm {
-    namespace parser {
-        namespace prism {
-            
-            IdentifierGrammar::IdentifierGrammar(std::shared_ptr<VariableState> const& state)
-            : IdentifierGrammar::base_type(identifierName), BaseGrammar(state) {
-                
-                identifierName %= qi::as_string[qi::raw[qi::lexeme[((qi::alpha | qi::char_('_')) >> *(qi::alnum | qi::char_('_')))]]][ qi::_pass = phoenix::bind(&VariableState::isIdentifier, this->state.get(), qi::_1) ];
-                identifierName.name("identifier");
-            }
-            
-            FreeIdentifierGrammar::FreeIdentifierGrammar(std::shared_ptr<VariableState> const& state)
-            : FreeIdentifierGrammar::base_type(freeIdentifierName), BaseGrammar(state) {
-                
-                freeIdentifierName %= qi::as_string[qi::raw[qi::lexeme[((qi::alpha | qi::char_('_')) >> *(qi::alnum | qi::char_('_')))]]][ qi::_pass = phoenix::bind(&VariableState::isFreeIdentifier, this->state.get(), qi::_1) ];
-                freeIdentifierName.name("identifier");
-            }
-            
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/parser/prismparser/IdentifierGrammars.h b/src/parser/prismparser/IdentifierGrammars.h
deleted file mode 100644
index ccb14bbc1..000000000
--- a/src/parser/prismparser/IdentifierGrammars.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* 
- * File:   Keywords.h
- * Author: nafur
- *
- * Created on April 10, 2013, 6:03 PM
- */
-
-#ifndef IDENTIFIERGRAMMARS_H
-#define	IDENTIFIERGRAMMARS_H
-
-#include "Includes.h"
-#include "BaseGrammar.h"
-#include "VariableState.h"
-
-namespace storm {
-    namespace parser {
-        namespace prism {
-            
-            /*!
-             * This grammar parses a (possibly used) identifier as used in a prism models.
-             */
-            class IdentifierGrammar : public qi::grammar<Iterator, std::string(), Skipper, Unused>, public BaseGrammar<IdentifierGrammar> {
-            public:
-                IdentifierGrammar(std::shared_ptr<VariableState> const& state);
-            private:
-                qi::rule<Iterator, std::string(), Skipper> identifierName;
-            };
-            
-            /*!
-             * This grammar parses an used identifier as used in a prism models.
-             */
-            class FreeIdentifierGrammar : public qi::grammar<Iterator, std::string(), Skipper, Unused>, public BaseGrammar<IdentifierGrammar>  {
-            public:
-                FreeIdentifierGrammar(std::shared_ptr<VariableState> const& state);
-            private:
-                qi::rule<Iterator, std::string(), Skipper> freeIdentifierName;
-            };
-        }
-    }
-}
-#endif	/* IDENTIFIERGRAMMARS_H */
-
diff --git a/src/parser/prismparser/Includes.h b/src/parser/prismparser/Includes.h
deleted file mode 100644
index 49a720dad..000000000
--- a/src/parser/prismparser/Includes.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 
- * File:   Includes
- * Author: Gereon Kremer
- *
- * Created on April 10, 2013, 4:46 PM
- */
-
-#ifndef BOOSTINCLUDES_H
-#define	BOOSTINCLUDES_H
-
-// Used for Boost spirit.
-#include <boost/typeof/typeof.hpp>
-#include <boost/spirit/include/qi.hpp>
-#include <boost/spirit/include/phoenix.hpp>
-
-// Include headers for spirit iterators. Needed for diagnostics and input stream iteration.
-#include <boost/spirit/include/classic_position_iterator.hpp>
-#include <boost/spirit/include/support_multi_pass.hpp>
-
-namespace qi = boost::spirit::qi;
-namespace phoenix = boost::phoenix;
-
-typedef std::string::const_iterator BaseIteratorType;
-typedef boost::spirit::classic::position_iterator2<BaseIteratorType> PositionIteratorType;
-typedef PositionIteratorType Iterator;
-typedef BOOST_TYPEOF(boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol) Skipper;
-typedef BOOST_TYPEOF(qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol | boost::spirit::ascii::space) Skipper2;
-typedef boost::spirit::unused_type Unused;
-
-#include "src/ir/IR.h"
-using namespace storm::ir;
-using namespace storm::ir::expressions;
-
-#include "log4cplus/logger.h"
-#include "log4cplus/loggingmacros.h"
-extern log4cplus::Logger logger;
-
-#endif	/* BOOSTINCLUDES_H */
-
diff --git a/src/parser/prismparser/IntegerExpressionGrammar.cpp b/src/parser/prismparser/IntegerExpressionGrammar.cpp
deleted file mode 100644
index 3bcfd4d4f..000000000
--- a/src/parser/prismparser/IntegerExpressionGrammar.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-#include "IntegerExpressionGrammar.h"
-
-#include "IdentifierGrammars.h"
-#include "ConstIntegerExpressionGrammar.h"
-
-namespace storm {
-    namespace parser {
-        namespace prism {
-            
-            IntegerExpressionGrammar::IntegerExpressionGrammar(std::shared_ptr<VariableState> const& state)
-            : IntegerExpressionGrammar::base_type(integerExpression), BaseGrammar(state) {
-                
-                integerExpression %= integerPlusExpression;
-                integerExpression.name("integer expression");
-                
-                integerPlusExpression = integerMultExpression[qi::_val = qi::_1] >> *((qi::lit("+")[qi::_a = true] | qi::lit("-")[qi::_a = false]) >> integerMultExpression)[qi::_val = phoenix::bind(&BaseGrammar::createIntPlus, this, qi::_val, qi::_a, qi::_1)];
-                integerPlusExpression.name("integer expression");
-                
-                integerMultExpression %= atomicIntegerExpression[qi::_val = qi::_1] >> *(qi::lit("*") >> atomicIntegerExpression[qi::_val = phoenix::bind(&BaseGrammar::createIntMult, this, qi::_val, qi::_1)]);
-                integerMultExpression.name("integer expression");
-                
-                atomicIntegerExpression %= (integerMinMaxExpression | integerFloorCeilExpression | this->state->constantIntegerFormulas_ | this->state->integerFormulas_ | qi::lit("(") >> integerExpression >> qi::lit(")") | integerVariableExpression | ConstIntegerExpressionGrammar::instance(this->state));
-                atomicIntegerExpression.name("integer expression");
-                
-                integerMinMaxExpression = ((qi::lit("min")[qi::_a = true] | qi::lit("max")[qi::_a = false]) >> qi::lit("(") >> integerExpression >> qi::lit(",") >> integerExpression >> qi::lit(")"))[qi::_val = phoenix::bind(&BaseGrammar::createIntMinMax, this, qi::_a, qi::_1, qi::_2)];
-                integerMinMaxExpression.name("integer min/max expression");
-                
-                integerFloorCeilExpression = ((qi::lit("floor")[qi::_a = true] | qi::lit("ceil")[qi::_a = false]) >> qi::lit("(") >> integerExpression >> qi::lit(")"))[qi::_val = phoenix::bind(&BaseGrammar::createIntFloorCeil, this, qi::_a, qi::_1)];
-                integerFloorCeilExpression.name("integer floor/ceil expression");
-                
-                integerVariableExpression = IdentifierGrammar::instance(this->state)[qi::_val = phoenix::bind(&BaseGrammar::getIntVariable, this, qi::_1)];
-                integerVariableExpression.name("integer variable");
-            }
-            
-            void IntegerExpressionGrammar::prepareSecondRun() {
-                integerVariableExpression %= this->state->integerVariables_;
-                integerVariableExpression.name("integer variable");
-            }
-            
-        }
-    }
-}
diff --git a/src/parser/prismparser/IntegerExpressionGrammar.h b/src/parser/prismparser/IntegerExpressionGrammar.h
deleted file mode 100644
index 7531ef36e..000000000
--- a/src/parser/prismparser/IntegerExpressionGrammar.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* 
- * File:   IntegerExpressionGrammar.h
- * Author: nafur
- *
- * Created on April 10, 2013, 4:39 PM
- */
-
-#ifndef INTEGEREXPRESSIONGRAMMAR_H
-#define	INTEGEREXPRESSIONGRAMMAR_H
-
-#include "src/ir/IR.h"
-#include "VariableState.h"
-#include "Includes.h"
-#include "IdentifierGrammars.h"
-
-#include <memory>
-
-namespace storm {
-    namespace parser {
-        namespace prism {
-            
-            /*!
-             * This grammar parses a (non constant) integer expressions as used in prism models.
-             */
-            class IntegerExpressionGrammar : public qi::grammar<Iterator, std::shared_ptr<BaseExpression>(), Skipper, Unused>, public BaseGrammar<IntegerExpressionGrammar> {
-            public:
-                IntegerExpressionGrammar(std::shared_ptr<VariableState> const& state);
-                
-                /*!
-                 * Switch to second run.
-                 * Variable names may be any valid identifier in the first run, but only defined variables in the second run.
-                 */
-                virtual void prepareSecondRun();
-                
-            private:
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper, Unused> integerExpression;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), qi::locals<bool>, Skipper> integerPlusExpression;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> integerMultExpression;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> atomicIntegerExpression;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> integerVariableExpression;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), qi::locals<bool>, Skipper> integerMinMaxExpression;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), qi::locals<bool>, Skipper> integerFloorCeilExpression;
-            };
-            
-        }
-    }
-}
-
-#endif	/* INTEGEREXPRESSIONGRAMMAR_H */
-
diff --git a/src/parser/prismparser/PrismGrammar.cpp b/src/parser/prismparser/PrismGrammar.cpp
deleted file mode 100644
index b6de4f0f4..000000000
--- a/src/parser/prismparser/PrismGrammar.cpp
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * PrismGrammar.cpp
- *
- *  Created on: 11.01.2013
- *      Author: chris
- */
-
-// Needed for file IO.
-#include <fstream>
-#include <iomanip>
-#include <limits>
-
-#include "PrismGrammar.h"
-
-#include "src/utility/OsDetection.h"
-
-#include "src/parser/prismparser/Includes.h"
-#include "src/parser/prismparser/BooleanExpressionGrammar.h"
-#include "src/parser/prismparser/ConstBooleanExpressionGrammar.h"
-#include "src/parser/prismparser/ConstDoubleExpressionGrammar.h"
-#include "src/parser/prismparser/ConstIntegerExpressionGrammar.h"
-#include "src/parser/prismparser/IntegerExpressionGrammar.h"
-#include "src/parser/prismparser/IdentifierGrammars.h"
-#include "src/parser/prismparser/VariableState.h"
-#include "src/exceptions/InvalidArgumentException.h"
-
-#include "log4cplus/logger.h"
-#include "log4cplus/loggingmacros.h"
-extern log4cplus::Logger logger;
-
-// Some typedefs and namespace definitions to reduce code size.
-typedef std::string::const_iterator BaseIteratorType;
-typedef boost::spirit::classic::position_iterator2<BaseIteratorType> PositionIteratorType;
-namespace qi = boost::spirit::qi;
-namespace phoenix = boost::phoenix;
-
-namespace storm {
-    namespace parser {
-        namespace prism {
-            
-            void PrismGrammar::addLabel(std::string const& name, std::shared_ptr<BaseExpression> const& value, std::map<std::string, std::unique_ptr<BaseExpression>>& nameToExpressionMap) {
-                this->state->labelNames_.add(name, name);
-                nameToExpressionMap[name] = value->clone();
-            }
-            
-            void PrismGrammar::addIntegerAssignment(std::string const& variable, std::shared_ptr<BaseExpression> const& value, std::map<std::string, Assignment>& variableToAssignmentMap) {
-                this->state->assignedIntegerVariables_.add(variable, variable);
-                variableToAssignmentMap[variable] = Assignment(variable, value->clone());
-            }
-            
-            void PrismGrammar::addBooleanAssignment(std::string const& variable, std::shared_ptr<BaseExpression> const& value, std::map<std::string, Assignment>& variableToAssigmentMap) {
-                this->state->assignedBooleanVariables_.add(variable, variable);
-                variableToAssigmentMap[variable] = Assignment(variable, value->clone());
-            }
-            
-            void PrismGrammar::addUndefinedBooleanConstant(std::string const& name, std::map<std::string, std::unique_ptr<BooleanConstantExpression>>& nameToExpressionMap) {
-                this->state->booleanConstants_.add(name, std::shared_ptr<BaseExpression>(new BooleanConstantExpression(name)));
-                this->state->allConstantNames_.add(name, name);
-                nameToExpressionMap.emplace(name, std::unique_ptr<BooleanConstantExpression>(new BooleanConstantExpression(dynamic_cast<BooleanConstantExpression&>(*this->state->booleanConstants_.at(name)))));
-            }
-            
-            void PrismGrammar::addUndefinedIntegerConstant(std::string const& name, std::map<std::string, std::unique_ptr<IntegerConstantExpression>>& nameToExpressionMap) {
-                this->state->integerConstants_.add(name, std::shared_ptr<BaseExpression>(new IntegerConstantExpression(name)));
-                this->state->allConstantNames_.add(name, name);
-                nameToExpressionMap.emplace(name, std::unique_ptr<IntegerConstantExpression>(new IntegerConstantExpression(dynamic_cast<IntegerConstantExpression&>(*this->state->integerConstants_.at(name)))));
-            }
-            
-            void PrismGrammar::addUndefinedDoubleConstant(std::string const& name, std::map<std::string, std::unique_ptr<DoubleConstantExpression>>& nameToExpressionMap) {
-                this->state->doubleConstants_.add(name, std::shared_ptr<BaseExpression>(new DoubleConstantExpression(name)));
-                this->state->allConstantNames_.add(name, name);
-                nameToExpressionMap.emplace(name, std::unique_ptr<DoubleConstantExpression>(new DoubleConstantExpression(dynamic_cast<DoubleConstantExpression&>(*this->state->doubleConstants_.at(name)))));
-            }
-            
-            Module PrismGrammar::renameModule(std::string const& newName, std::string const& oldName, std::map<std::string, std::string> const& renaming) {
-                this->state->moduleNames_.add(newName, newName);
-                Module* old = this->moduleMap_.find(oldName);
-                if (old == nullptr) {
-                    LOG4CPLUS_ERROR(logger, "Renaming module failed: module " << oldName << " does not exist.");
-                    throw storm::exceptions::InvalidArgumentException() << "Renaming module failed: module " << oldName << " does not exist.";
-                }
-                Module res(*old, newName, renaming, *this->state);
-                this->moduleMap_.at(newName) = res;
-                return res;
-            }
-            
-            Module PrismGrammar::createModule(std::string const& name, std::vector<BooleanVariable> const& bools, std::vector<IntegerVariable> const& ints, std::map<std::string, uint_fast64_t> const& boolids, std::map<std::string, uint_fast64_t> const& intids, std::vector<storm::ir::Command> const& commands) {
-                this->state->moduleNames_.add(name, name);
-                Module res(name, bools, ints, boolids, intids, commands);
-                this->moduleMap_.at(name) = res;
-                return res;
-            }
-            
-            void PrismGrammar::createIntegerVariable(std::string const& name, std::shared_ptr<BaseExpression> const& lower, std::shared_ptr<BaseExpression> const& upper, std::shared_ptr<BaseExpression> const& init, std::vector<IntegerVariable>& vars, std::map<std::string, uint_fast64_t>& varids, bool isGlobalVariable) {
-                uint_fast64_t id = this->state->addIntegerVariable(name);
-                uint_fast64_t newLocalIndex = this->state->nextLocalIntegerVariableIndex;
-                vars.emplace_back(newLocalIndex, id, name, lower != nullptr ? lower->clone() : nullptr, upper != nullptr ? upper->clone() : nullptr, init != nullptr ? init->clone() : nullptr);
-                varids[name] = newLocalIndex;
-                ++this->state->nextLocalIntegerVariableIndex;
-                this->state->localIntegerVariables_.add(name, name);
-                if (isGlobalVariable) {
-                    this->state->globalIntegerVariables_.add(name, name);
-                }
-            }
-            
-            void PrismGrammar::createBooleanVariable(std::string const& name, std::shared_ptr<BaseExpression> const& init, std::vector<BooleanVariable>& vars, std::map<std::string, uint_fast64_t>& varids, bool isGlobalVariable) {
-                uint_fast64_t id = this->state->addBooleanVariable(name);
-                uint_fast64_t newLocalIndex = this->state->nextLocalBooleanVariableIndex;
-                vars.emplace_back(newLocalIndex, id, name, init != nullptr ? init->clone() : nullptr);
-                varids[name] = newLocalIndex;
-                ++this->state->nextLocalBooleanVariableIndex;
-                this->state->localBooleanVariables_.add(name, name);
-                if (isGlobalVariable) {
-                    this->state->globalBooleanVariables_.add(name, name);
-                }
-            }
-            
-            StateReward createStateReward(std::shared_ptr<BaseExpression> const& guard, std::shared_ptr<BaseExpression> const& reward) {
-                return StateReward(guard->clone(), reward->clone());
-            }
-            TransitionReward createTransitionReward(std::string const& label, std::shared_ptr<BaseExpression> const& guard, std::shared_ptr<BaseExpression> const& reward) {
-                return TransitionReward(label, guard->clone(), reward->clone());
-            }
-            void createRewardModel(std::string const& name, std::vector<StateReward>& stateRewards, std::vector<TransitionReward>& transitionRewards, std::map<std::string, RewardModel>& mapping) {
-                mapping[name] = RewardModel(name, stateRewards, transitionRewards);
-            }
-            Update PrismGrammar::createUpdate(std::shared_ptr<BaseExpression> const& likelihood, std::map<std::string, Assignment> const& bools, std::map<std::string, Assignment> const& ints) {
-                this->state->nextGlobalUpdateIndex++;
-                return Update(this->state->getNextGlobalUpdateIndex() - 1, likelihood != nullptr ? likelihood->clone() : nullptr, bools, ints);
-            }
-            Command PrismGrammar::createCommand(std::string const& label, std::shared_ptr<BaseExpression> const& guard, std::vector<Update> const& updates) {
-                this->state->nextGlobalCommandIndex++;
-                return Command(this->state->getNextGlobalCommandIndex() - 1, label, guard->clone(), updates);
-            }
-            Program createProgram(
-                                  Program::ModelType modelType,
-                                  std::map<std::string, std::unique_ptr<BooleanConstantExpression>> const& undefBoolConst,
-                                  std::map<std::string, std::unique_ptr<IntegerConstantExpression>> const& undefIntConst,
-                                  std::map<std::string, std::unique_ptr<DoubleConstantExpression>> const& undefDoubleConst,
-                                  GlobalVariableInformation const& globalVariableInformation,
-                                  std::vector<Module> const& modules,
-                                  std::map<std::string, RewardModel> const& rewards,
-                                  std::map<std::string, std::unique_ptr<BaseExpression>> const& labels) {
-                return Program(modelType, undefBoolConst, undefIntConst, undefDoubleConst,
-                               globalVariableInformation.booleanVariables, globalVariableInformation.integerVariables,
-                               globalVariableInformation.booleanVariableToIndexMap,
-                               globalVariableInformation.integerVariableToIndexMap, modules, rewards, labels);
-            }
-            
-            PrismGrammar::PrismGrammar() : PrismGrammar::base_type(start), state(new VariableState()) {
-                
-                labelDefinition = (qi::lit("label") >> -qi::lit("\"") >> FreeIdentifierGrammar::instance(this->state) >> -qi::lit("\"") >> qi::lit("=") >> BooleanExpressionGrammar::instance(this->state) >> qi::lit(";"))
-                [phoenix::bind(&PrismGrammar::addLabel, this, qi::_1, qi::_2, qi::_r1)];
-                labelDefinition.name("label declaration");
-                labelDefinitionList %= *labelDefinition(qi::_r1);
-                labelDefinitionList.name("label declaration list");
-                
-                // This block defines all entities that are needed for parsing a reward model.
-                stateRewardDefinition = (BooleanExpressionGrammar::instance(this->state) > qi::lit(":") > ConstDoubleExpressionGrammar::instance(this->state) >> qi::lit(";"))[qi::_val = phoenix::bind(&createStateReward, qi::_1, qi::_2)];
-                stateRewardDefinition.name("state reward definition");
-                transitionRewardDefinition = (qi::lit("[") > -(commandName[qi::_a = qi::_1]) > qi::lit("]") > BooleanExpressionGrammar::instance(this->state) > qi::lit(":") > ConstDoubleExpressionGrammar::instance(this->state) > qi::lit(";"))[qi::_val = phoenix::bind(&createTransitionReward, qi::_a, qi::_2, qi::_3)];
-                transitionRewardDefinition.name("transition reward definition");
-                rewardDefinition = (qi::lit("rewards") > qi::lit("\"") > FreeIdentifierGrammar::instance(this->state) > qi::lit("\"") > +(stateRewardDefinition[phoenix::push_back(qi::_a, qi::_1)] | transitionRewardDefinition[phoenix::push_back(qi::_b, qi::_1)]) >> qi::lit("endrewards"))
-                [phoenix::bind(&createRewardModel, qi::_1, qi::_a, qi::_b, qi::_r1)];
-                rewardDefinition.name("reward definition");
-                rewardDefinitionList = *rewardDefinition(qi::_r1);
-                rewardDefinitionList.name("reward definition list");
-                
-                commandName %= this->state->commandNames_;
-                commandName.name("command name");
-                unassignedLocalBooleanVariableName %= (this->state->localBooleanVariables_ | this->state->globalBooleanVariables_) - this->state->assignedBooleanVariables_;
-                unassignedLocalBooleanVariableName.name("unassigned local/global boolean variable");
-                unassignedLocalIntegerVariableName %= (this->state->localIntegerVariables_ | this->state->globalIntegerVariables_) - this->state->assignedIntegerVariables_;
-                unassignedLocalIntegerVariableName.name("unassigned local/global integer variable");
-                
-                // This block defines all entities that are needed for parsing a single command.
-                assignmentDefinition =
-                (qi::lit("(") >> unassignedLocalIntegerVariableName > qi::lit("'") > qi::lit("=") > IntegerExpressionGrammar::instance(this->state) > qi::lit(")"))[phoenix::bind(&PrismGrammar::addIntegerAssignment, this, qi::_1, qi::_2, qi::_r2)] |
-                (qi::lit("(") >> unassignedLocalBooleanVariableName > qi::lit("'") > qi::lit("=") > BooleanExpressionGrammar::instance(this->state) > qi::lit(")"))[phoenix::bind(&PrismGrammar::addBooleanAssignment, this, qi::_1, qi::_2, qi::_r1)];
-                assignmentDefinition.name("assignment");
-                assignmentDefinitionList = assignmentDefinition(qi::_r1, qi::_r2) % "&";
-                assignmentDefinitionList.name("assignment list");
-                updateDefinition = (((ConstDoubleExpressionGrammar::instance(this->state) >> qi::lit(":"))
-                                     | qi::attr(std::shared_ptr<BaseExpression>(new storm::ir::expressions::DoubleLiteralExpression(1))))[phoenix::clear(phoenix::ref(this->state->assignedBooleanVariables_)), phoenix::clear(phoenix::ref(this->state->assignedIntegerVariables_))]
-                                    >> assignmentDefinitionList(qi::_a, qi::_b))[qi::_val = phoenix::bind(&PrismGrammar::createUpdate, this, qi::_1, qi::_a, qi::_b)];
-                updateDefinition.name("update");
-                updateListDefinition = +updateDefinition % "+";
-                updateListDefinition.name("update list");
-                commandDefinition = (
-                                     qi::lit("[") > -(
-                                                      (FreeIdentifierGrammar::instance(this->state)[phoenix::bind(this->state->commandNames_.add, qi::_1, qi::_1)] | commandName)[qi::_a = qi::_1]
-                                                      ) > qi::lit("]") > BooleanExpressionGrammar::instance(this->state) > qi::lit("->") > updateListDefinition > qi::lit(";")
-                                     )[qi::_val = phoenix::bind(&PrismGrammar::createCommand, this, qi::_a, qi::_2, qi::_3)];
-                commandDefinition.name("command");
-                
-                // This block defines all entities that are needed for parsing variable definitions.
-                booleanVariableDefinition = (FreeIdentifierGrammar::instance(this->state) >> qi::lit(":") >> qi::lit("bool") > -(qi::lit("init") > ConstBooleanExpressionGrammar::instance(this->state)[qi::_b = phoenix::construct<std::shared_ptr<BaseExpression>>(qi::_1)]) > qi::lit(";"))
-                [phoenix::bind(&PrismGrammar::createBooleanVariable, this, qi::_1, qi::_b, qi::_r1, qi::_r2, qi::_r3)];
-                booleanVariableDefinition.name("boolean variable declaration");
-                
-                integerVariableDefinition = (FreeIdentifierGrammar::instance(this->state) >> qi::lit(":") >> qi::lit("[") > ConstIntegerExpressionGrammar::instance(this->state) > qi::lit("..") > ConstIntegerExpressionGrammar::instance(this->state) > qi::lit("]") > -(qi::lit("init") > ConstIntegerExpressionGrammar::instance(this->state)[qi::_b = phoenix::construct<std::shared_ptr<BaseExpression>>(qi::_1)]) > qi::lit(";"))
-                [phoenix::bind(&PrismGrammar::createIntegerVariable, this, qi::_1, qi::_2, qi::_3, qi::_b, qi::_r1, qi::_r2, qi::_r3)];
-                integerVariableDefinition.name("integer variable declaration");
-                variableDefinition = (booleanVariableDefinition(qi::_r1, qi::_r3, false) | integerVariableDefinition(qi::_r2, qi::_r4, false));
-                variableDefinition.name("variable declaration");
-                
-                // This block defines all entities that are needed for parsing a module.
-                moduleDefinition = (qi::lit("module") >> FreeIdentifierGrammar::instance(this->state)[phoenix::bind(&VariableState::clearLocalVariables, *this->state)]
-                                    >> *(variableDefinition(qi::_a, qi::_b, qi::_c, qi::_d)) >> +commandDefinition > qi::lit("endmodule"))
-                [qi::_val = phoenix::bind(&PrismGrammar::createModule, this, qi::_1, qi::_a, qi::_b, qi::_c, qi::_d, qi::_2)];
-                
-                moduleDefinition.name("module");
-                moduleRenaming = (qi::lit("module")	>> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=")
-                                  > this->state->moduleNames_ > qi::lit("[") > *(
-                                                                                 (IdentifierGrammar::instance(this->state) > qi::lit("=") > IdentifierGrammar::instance(this->state) >> -qi::lit(","))[phoenix::insert(qi::_a, phoenix::construct<std::pair<std::string,std::string>>(qi::_1, qi::_2))]
-                                                                                 ) > qi::lit("]") > qi::lit("endmodule"))
-                [qi::_val = phoenix::bind(&PrismGrammar::renameModule, this, qi::_1, qi::_2, qi::_a)];
-                moduleRenaming.name("renamed module");
-                moduleDefinitionList %= +(moduleDefinition | moduleRenaming);
-                moduleDefinitionList.name("module list");
-                
-                // This block defines all entities that are needed for parsing global variable definitions.
-                globalVariableDefinitionList = *(qi::lit("global") > (booleanVariableDefinition(bind(&GlobalVariableInformation::booleanVariables, qi::_r1), bind(&GlobalVariableInformation::booleanVariableToIndexMap, qi::_r1), true) | integerVariableDefinition(bind(&GlobalVariableInformation::integerVariables, qi::_r1), bind(&GlobalVariableInformation::integerVariableToIndexMap, qi::_r1), true)));
-                globalVariableDefinitionList.name("global variable declaration list");
-                
-                // This block defines all entities that are needed for parsing constant definitions.
-                definedBooleanConstantDefinition = (qi::lit("const") >> qi::lit("bool") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") > ConstBooleanExpressionGrammar::instance(this->state) > qi::lit(";"))[phoenix::bind(this->state->booleanConstants_.add, qi::_1, qi::_2), phoenix::bind(this->state->allConstantNames_.add, qi::_1, qi::_1), qi::_val = qi::_2];
-                definedBooleanConstantDefinition.name("defined boolean constant declaration");
-                definedIntegerConstantDefinition = (qi::lit("const") >> qi::lit("int") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") >> ConstIntegerExpressionGrammar::instance(this->state) >> qi::lit(";"))[phoenix::bind(this->state->integerConstants_.add, qi::_1, qi::_2), phoenix::bind(this->state->allConstantNames_.add, qi::_1, qi::_1), qi::_val = qi::_2];
-                definedIntegerConstantDefinition.name("defined integer constant declaration");
-                definedDoubleConstantDefinition = (qi::lit("const") >> qi::lit("double") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") > ConstDoubleExpressionGrammar::instance(this->state) > qi::lit(";"))[phoenix::bind(this->state->doubleConstants_.add, qi::_1, qi::_2), phoenix::bind(this->state->allConstantNames_.add, qi::_1, qi::_1), qi::_val = qi::_2];
-                definedDoubleConstantDefinition.name("defined double constant declaration");
-                undefinedBooleanConstantDefinition = (qi::lit("const") >> qi::lit("bool") > FreeIdentifierGrammar::instance(this->state) > qi::lit(";"))[phoenix::bind(&PrismGrammar::addUndefinedBooleanConstant, this, qi::_1, qi::_r1)];
-                undefinedBooleanConstantDefinition.name("undefined boolean constant declaration");
-                undefinedIntegerConstantDefinition = (qi::lit("const") >> qi::lit("int") > FreeIdentifierGrammar::instance(this->state) > qi::lit(";"))[phoenix::bind(&PrismGrammar::addUndefinedIntegerConstant, this, qi::_1, qi::_r1)]; 
-                undefinedIntegerConstantDefinition.name("undefined integer constant declaration");
-                undefinedDoubleConstantDefinition = (qi::lit("const") >> qi::lit("double") > FreeIdentifierGrammar::instance(this->state) > qi::lit(";"))[phoenix::bind(&PrismGrammar::addUndefinedDoubleConstant, this, qi::_1, qi::_r1)];
-                undefinedDoubleConstantDefinition.name("undefined double constant declaration");
-                definedConstantDefinition %= (definedBooleanConstantDefinition | definedIntegerConstantDefinition | definedDoubleConstantDefinition);
-                definedConstantDefinition.name("defined constant declaration");
-                undefinedConstantDefinition = (undefinedBooleanConstantDefinition(qi::_r1) | undefinedIntegerConstantDefinition(qi::_r2) | undefinedDoubleConstantDefinition(qi::_r3));
-                undefinedConstantDefinition.name("undefined constant declaration");
-                constantDefinitionList = *(definedConstantDefinition | undefinedConstantDefinition(qi::_r1, qi::_r2, qi::_r3));
-                constantDefinitionList.name("constant declaration list");
-                
-                constantBooleanFormulaDefinition = (qi::lit("formula") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") >> ConstBooleanExpressionGrammar::instance(this->state) >> qi::lit(";"))[phoenix::bind(this->state->constantBooleanFormulas_.add, qi::_1, qi::_2)];
-                constantBooleanFormulaDefinition.name("constant boolean formula definition");
-                booleanFormulaDefinition = (qi::lit("formula") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") >> BooleanExpressionGrammar::instance(this->state) >> qi::lit(";"))[phoenix::bind(this->state->booleanFormulas_.add, qi::_1, qi::_2)];
-                booleanFormulaDefinition.name("boolean formula definition");
-                constantIntegerFormulaDefinition = (qi::lit("formula") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") >> ConstIntegerExpressionGrammar::instance(this->state) >> qi::lit(";"))[phoenix::bind(this->state->constantIntegerFormulas_.add, qi::_1, qi::_2)];
-                constantIntegerFormulaDefinition.name("constant integer formula definition");
-                integerFormulaDefinition = (qi::lit("formula") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") >> IntegerExpressionGrammar::instance(this->state) >> qi::lit(";"))[phoenix::bind(this->state->integerFormulas_.add, qi::_1, qi::_2)];
-                integerFormulaDefinition.name("integer formula definition");
-                constantDoubleFormulaDefinition = (qi::lit("formula") >> FreeIdentifierGrammar::instance(this->state) >> qi::lit("=") >> ConstDoubleExpressionGrammar::instance(this->state) >> qi::lit(";"))[phoenix::bind(this->state->constantDoubleFormulas_.add, qi::_1, qi::_2)];
-                constantDoubleFormulaDefinition.name("constant double formula definition");
-                formulaDefinition = constantBooleanFormulaDefinition | booleanFormulaDefinition | constantIntegerFormulaDefinition | integerFormulaDefinition | constantDoubleFormulaDefinition;
-                formulaDefinition.name("formula definition");
-                formulaDefinitionList = *formulaDefinition;
-                formulaDefinitionList.name("formula definition list");
-
-                // This block defines all entities that are needed for parsing a program.
-                modelTypeDefinition = modelType_;
-                modelTypeDefinition.name("model type");
-                start = (qi::eps >
-                         modelTypeDefinition >
-                         constantDefinitionList(qi::_a, qi::_b, qi::_c) >
-                         formulaDefinitionList >
-                         globalVariableDefinitionList(qi::_d) >
-                         moduleDefinitionList >
-                         rewardDefinitionList(qi::_e) >
-                         labelDefinitionList(qi::_f))[qi::_val = phoenix::bind(&createProgram, qi::_1, qi::_a, qi::_b, qi::_c, qi::_d, qi::_2, qi::_e, qi::_f)];
-                start.name("probabilistic program declaration");
-            }
-            
-            void PrismGrammar::prepareForSecondRun() {
-                LOG4CPLUS_INFO(logger, "Preparing parser for second run.");
-                this->state->prepareForSecondRun();
-                BooleanExpressionGrammar::secondRun();
-                ConstBooleanExpressionGrammar::secondRun();
-                ConstDoubleExpressionGrammar::secondRun();
-                ConstIntegerExpressionGrammar::secondRun();
-                IntegerExpressionGrammar::secondRun();
-            }
-            
-            void PrismGrammar::resetGrammars() {
-                LOG4CPLUS_INFO(logger, "Resetting grammars.");
-                BooleanExpressionGrammar::resetInstance();
-                ConstBooleanExpressionGrammar::resetInstance();
-                ConstDoubleExpressionGrammar::resetInstance();
-                ConstIntegerExpressionGrammar::resetInstance();
-                IntegerExpressionGrammar::resetInstance();
-            }
-            
-        } // namespace prism
-    } // namespace parser
-} // namespace storm
diff --git a/src/parser/prismparser/PrismGrammar.h b/src/parser/prismparser/PrismGrammar.h
deleted file mode 100644
index 57ba55c5b..000000000
--- a/src/parser/prismparser/PrismGrammar.h
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * File:   PrismGrammar.h
- * Author: nafur
- *
- * Created on April 30, 2013, 5:20 PM
- */
-
-#ifndef STORM_PARSER_PRISMPARSER_PRISMGRAMMAR_H
-#define	STORM_PARSER_PRISMPARSER_PRISMGRAMMAR_H
-
-// All classes of the intermediate representation are used.
-#include "src/ir/IR.h"
-#include "src/parser/prismparser/Includes.h"
-#include "src/parser/prismparser/Tokens.h"
-#include "src/parser/prismparser/IdentifierGrammars.h"
-#include "src/parser/prismparser/VariableState.h"
-#include "src/parser/prismparser/ConstBooleanExpressionGrammar.h"
-#include "src/parser/prismparser/ConstDoubleExpressionGrammar.h"
-#include "src/parser/prismparser/ConstIntegerExpressionGrammar.h"
-#include "src/parser/prismparser/BooleanExpressionGrammar.h"
-#include "src/parser/prismparser/IntegerExpressionGrammar.h"
-
-// Used for file input.
-#include <istream>
-#include <memory>
-
-namespace storm {
-    namespace parser {
-        namespace prism {
-            
-            using namespace storm::ir;
-            using namespace storm::ir::expressions;
-            
-            struct GlobalVariableInformation {
-                std::vector<BooleanVariable> booleanVariables;
-                std::vector<IntegerVariable> integerVariables;
-                std::map<std::string, uint_fast64_t> booleanVariableToIndexMap;
-                std::map<std::string, uint_fast64_t> integerVariableToIndexMap;
-            };
-            
-            /*!
-             * The Boost spirit grammar for the PRISM language. Returns the intermediate representation of
-             * the input that complies with the PRISM syntax.
-             */
-            class PrismGrammar : public qi::grammar<
-            Iterator,
-            Program(),
-            qi::locals<
-            std::map<std::string, std::unique_ptr<BooleanConstantExpression>>,
-            std::map<std::string, std::unique_ptr<IntegerConstantExpression>>,
-            std::map<std::string, std::unique_ptr<DoubleConstantExpression>>,
-            GlobalVariableInformation,
-            std::map<std::string, RewardModel>,
-            std::map<std::string, std::unique_ptr<BaseExpression>>
-            >,
-            Skipper> {
-            public:
-                /*!
-                 * Default constructor that creates an empty and functional grammar.
-                 */
-                PrismGrammar();
-                
-                /*!
-                 * Puts all sub-grammars into the mode for performing the second run. A two-run model was chosen
-                 * because modules can involve variables that are only declared afterwards, so the first run
-                 * creates all variables and the second one tries to parse the full model.
-                 */
-                void prepareForSecondRun();
-                
-                /*!
-                 * Resets all sub-grammars, i.e. puts them into an initial state.
-                 */
-                void resetGrammars();
-                
-            private:
-                
-                std::shared_ptr<storm::parser::prism::VariableState> state;
-                struct qi::symbols<char, Module> moduleMap_;
-                
-                // The starting point of the grammar.
-                qi::rule<
-                Iterator,
-                Program(),
-                qi::locals<
-				std::map<std::string, std::unique_ptr<BooleanConstantExpression>>,
-				std::map<std::string, std::unique_ptr<IntegerConstantExpression>>,
-				std::map<std::string, std::unique_ptr<DoubleConstantExpression>>,
-                GlobalVariableInformation,
-				std::map<std::string, RewardModel>,
-				std::map<std::string, std::unique_ptr<BaseExpression>>
-                >,
-                Skipper> start;
-                qi::rule<Iterator, Program::ModelType(), Skipper> modelTypeDefinition;
-                qi::rule<Iterator, qi::unused_type(std::map<std::string, std::unique_ptr<BooleanConstantExpression>>&, std::map<std::string, std::unique_ptr<IntegerConstantExpression>>&, std::map<std::string, std::unique_ptr<DoubleConstantExpression>>&), Skipper> constantDefinitionList;
-                qi::rule<Iterator, std::vector<Module>(), Skipper> moduleDefinitionList;
-                
-                // Rules for global variable definitions
-                qi::rule<Iterator, qi::unused_type(GlobalVariableInformation&), Skipper> globalVariableDefinitionList;
-                
-                // Rules for module definition.
-                qi::rule<Iterator, Module(), qi::locals<std::vector<BooleanVariable>, std::vector<IntegerVariable>, std::map<std::string, uint_fast64_t>, std::map<std::string, uint_fast64_t>>, Skipper> moduleDefinition;
-                qi::rule<Iterator, Module(), qi::locals<std::map<std::string, std::string>>, Skipper> moduleRenaming;
-                
-                // Rules for variable definitions.
-                qi::rule<Iterator, qi::unused_type(std::vector<BooleanVariable>&, std::vector<IntegerVariable>&, std::map<std::string, uint_fast64_t>&, std::map<std::string, uint_fast64_t>&), Skipper> variableDefinition;
-                qi::rule<Iterator, qi::unused_type(std::vector<BooleanVariable>&, std::map<std::string, uint_fast64_t>&, bool), qi::locals<uint_fast64_t, std::shared_ptr<BaseExpression>>, Skipper> booleanVariableDefinition;
-                qi::rule<Iterator, qi::unused_type(std::vector<IntegerVariable>&, std::map<std::string, uint_fast64_t>&, bool), qi::locals<uint_fast64_t, std::shared_ptr<BaseExpression>>, Skipper> integerVariableDefinition;
-                
-                // Rules for command definitions.
-                qi::rule<Iterator, Command(), qi::locals<std::string>, Skipper> commandDefinition;
-                qi::rule<Iterator, std::vector<Update>(), Skipper> updateListDefinition;
-                qi::rule<Iterator, Update(), qi::locals<std::map<std::string, Assignment>, std::map<std::string, Assignment>>, Skipper> updateDefinition;
-                qi::rule<Iterator, qi::unused_type(std::map<std::string, Assignment>&, std::map<std::string, Assignment>&), Skipper> assignmentDefinitionList;
-                qi::rule<Iterator, qi::unused_type(std::map<std::string, Assignment>&, std::map<std::string, Assignment>&), Skipper> assignmentDefinition;
-                
-                // Rules for variable/command names.
-                qi::rule<Iterator, std::string(), Skipper> commandName;
-                qi::rule<Iterator, std::string(), Skipper> unassignedLocalBooleanVariableName;
-                qi::rule<Iterator, std::string(), Skipper> unassignedLocalIntegerVariableName;
-                
-                // Rules for reward definitions.
-                qi::rule<Iterator, qi::unused_type(std::map<std::string, RewardModel>&), Skipper> rewardDefinitionList;
-                qi::rule<Iterator, qi::unused_type(std::map<std::string, RewardModel>&), qi::locals<std::vector<StateReward>, std::vector<TransitionReward>>, Skipper> rewardDefinition;
-                qi::rule<Iterator, StateReward(), Skipper> stateRewardDefinition;
-                qi::rule<Iterator, TransitionReward(), qi::locals<std::string>, Skipper> transitionRewardDefinition;
-                
-                // Rules for label definitions.
-                qi::rule<Iterator, qi::unused_type(std::map<std::string, std::unique_ptr<BaseExpression>>&), Skipper> labelDefinitionList;
-                qi::rule<Iterator, qi::unused_type(std::map<std::string, std::unique_ptr<BaseExpression>>&), Skipper> labelDefinition;
-                
-                // Rules for constant definitions.
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> constantDefinition;
-                qi::rule<Iterator, qi::unused_type(std::map<std::string, std::unique_ptr<BooleanConstantExpression>>&, std::map<std::string, std::unique_ptr<IntegerConstantExpression>>&, std::map<std::string, std::unique_ptr<DoubleConstantExpression>>&), Skipper> undefinedConstantDefinition;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> definedConstantDefinition;
-                qi::rule<Iterator, qi::unused_type(std::map<std::string, std::unique_ptr<BooleanConstantExpression>>&), Skipper> undefinedBooleanConstantDefinition;
-                qi::rule<Iterator, qi::unused_type(std::map<std::string, std::unique_ptr<IntegerConstantExpression>>&), Skipper> undefinedIntegerConstantDefinition;
-                qi::rule<Iterator, qi::unused_type(std::map<std::string, std::unique_ptr<DoubleConstantExpression>>&), Skipper> undefinedDoubleConstantDefinition;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> definedBooleanConstantDefinition;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> definedIntegerConstantDefinition;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> definedDoubleConstantDefinition;
-                
-                // Rules for formula definitions.
-                qi::rule<Iterator, qi::unused_type(), Skipper> formulaDefinitionList;
-                qi::rule<Iterator, qi::unused_type(), Skipper> formulaDefinition;
-                qi::rule<Iterator, qi::unused_type(), Skipper> constantIntegerFormulaDefinition;
-                qi::rule<Iterator, qi::unused_type(), Skipper> integerFormulaDefinition;
-                qi::rule<Iterator, qi::unused_type(), Skipper> constantDoubleFormulaDefinition;
-                qi::rule<Iterator, qi::unused_type(), Skipper> constantBooleanFormulaDefinition;
-                qi::rule<Iterator, qi::unused_type(), Skipper> booleanFormulaDefinition;
-
-                // Rules for variable recognition.
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), Skipper> booleanVariableCreatorExpression;
-                qi::rule<Iterator, std::shared_ptr<BaseExpression>(), qi::locals<std::shared_ptr<BaseExpression>>, Skipper> integerVariableCreatorExpression;
-                
-                storm::parser::prism::keywordsStruct keywords_;
-                storm::parser::prism::modelTypeStruct modelType_;
-                storm::parser::prism::relationalOperatorStruct relations_;
-                
-                /*!
-                 * Adds a label with the given name and expression to the given label-to-expression map.
-                 *
-                 * @param name The name of the label.
-                 * @param expression The expression associated with the label.
-                 * @param nameToExpressionMap The map to which the label is added.
-                 */
-                void addLabel(std::string const& name, std::shared_ptr<BaseExpression> const& value, std::map<std::string, std::unique_ptr<BaseExpression>>& nameToExpressionMap);
-                
-                /*!
-                 * Adds a boolean assignment for the given variable with the given expression and adds it to the
-                 * provided variable-to-assignment map.
-                 *
-                 * @param variable The name of the variable that the assignment targets.
-                 * @param expression The expression that is assigned to the variable.
-                 * @param variableToAssignmentMap The map to which the assignment is added.
-                 */
-                void addBooleanAssignment(std::string const& variable, std::shared_ptr<BaseExpression> const& expression, std::map<std::string, Assignment>& variableToAssignmentMap);
-                
-                /*!
-                 * Adds a boolean assignment for the given variable with the given expression and adds it to the
-                 * provided variable-to-assignment map.
-                 *
-                 * @param variable The name of the variable that the assignment targets.
-                 * @param expression The expression that is assigned to the variable.
-                 * @param variableToAssignmentMap The map to which the assignment is added.
-                 */
-                void addIntegerAssignment(std::string const& variable, std::shared_ptr<BaseExpression> const& expression, std::map<std::string, Assignment>& variableToAssignmentMap);
-                
-                void addUndefinedBooleanConstant(std::string const& name, std::map<std::string, std::unique_ptr<BooleanConstantExpression>>& nameToExpressionMap);
-
-                void addUndefinedIntegerConstant(std::string const& name, std::map<std::string, std::unique_ptr<IntegerConstantExpression>>& nameToExpressionMap);
-
-                void addUndefinedDoubleConstant(std::string const& name, std::map<std::string, std::unique_ptr<DoubleConstantExpression>>& nameToExpressionMap);
-
-                /*!
-                 * Creates a module by renaming, i.e. takes the module given by the old name, creates a new module
-                 * with the given name which renames all identifiers according to the given mapping.
-                 *
-                 * @param name The name of the new module.
-                 * @param oldName The name of the module that is to be copied (modulo renaming).
-                 * @param renaming A mapping from identifiers to their new names.
-                 */
-                Module renameModule(std::string const& name, std::string const& oldName, std::map<std::string, std::string> const& renaming);
-                
-                /*!
-                 * Creates a new module with the given name, boolean and integer variables and commands.
-                 *
-                 * @param name The name of the module to create.
-                 * @param booleanVariables The boolean variables of the module.
-                 * @param integerVariables The integer variables of the module.
-                 * @param booleanVariableToLocalIndexMap A mapping of boolean variables to module-local indices.
-                 * @param integerVariableToLocalIndexMap A mapping of boolean variables to module-local indices.
-                 * @param commands The commands associated with this module.
-                 */
-                Module createModule(std::string const& name, std::vector<BooleanVariable> const& booleanVariables, std::vector<IntegerVariable> const& integerVariables, std::map<std::string, uint_fast64_t> const& booleanVariableToLocalIndexMap, std::map<std::string, uint_fast64_t> const& integerVariableToLocalIndexMap, std::vector<storm::ir::Command> const& commands);
-                
-                /*!
-                 * Creates an integer variable with the given name, domain and initial value and adds it to the
-                 * provided list of integer variables and the given mappings.
-                 *
-                 * @param name The name of the integer variable.
-                 * @param lower The expression that defines the lower bound of the domain.
-                 * @param upper The expression that defines the upper bound of the domain.
-                 * @param init The expression that defines the initial value of the variable.
-                 * @param integerVariableToGlobalIndexMap A mapping of integer variables to global indices.
-                 * @param isGlobalVariable A flag indicating whether the variable is supposed to be global or not.
-                 */
-                void createIntegerVariable(std::string const& name, std::shared_ptr<BaseExpression> const& lower, std::shared_ptr<BaseExpression> const& upper, std::shared_ptr<BaseExpression> const& init, std::vector<IntegerVariable>& integerVariables, std::map<std::string, uint_fast64_t>& integerVariableToGlobalIndexMap, bool isGlobalVariable);
-                
-                /*!
-                 * Creates an boolean variable with the given name and initial value and adds it to the
-                 * provided list of boolean variables and the given mappings.
-                 *
-                 * @param name The name of the boolean variable.
-                 * @param init The expression that defines the initial value of the variable.
-                 * @param booleanVariableToGlobalIndexMap A mapping of boolean variables to global indices.
-                 * @param isGlobalVariable A flag indicating whether the variable is supposed to be global or not.
-                 */
-                void createBooleanVariable(std::string const& name, std::shared_ptr<BaseExpression> const& init, std::vector<BooleanVariable>& booleanVariables, std::map<std::string, uint_fast64_t>& booleanVariableToGlobalIndexMap, bool isGlobalVariable);
-                
-                /*!
-                 * Creates a command with the given label, guard and updates.
-                 *
-                 * @param label The label of the command.
-                 * @param guard The guard of the command.
-                 * @param updates The updates associated with the command.
-                 */
-                Command createCommand(std::string const& label, std::shared_ptr<BaseExpression> const& guard, std::vector<Update> const& updates);
-                
-                /*!
-                 * Creates an update with the given likelihood and the given assignments to boolean and integer variables, respectively.
-                 *
-                 * @param likelihood The likelihood of this update being executed.
-                 * @param booleanAssignments The assignments to boolean variables this update involves.
-                 * @param integerAssignments The assignments to integer variables this update involves.
-                 */
-                Update createUpdate(std::shared_ptr<BaseExpression> const& likelihood, std::map<std::string, Assignment> const& booleanAssignments, std::map<std::string, Assignment> const& integerAssignments);
-                
-            };
-            
-            
-        } // namespace prism
-    } // namespace parser
-} // namespace storm
-
-
-#endif	/* STORM_PARSER_PRISMPARSER_PRISMGRAMMAR_H */
-
diff --git a/src/parser/prismparser/Tokens.h b/src/parser/prismparser/Tokens.h
deleted file mode 100644
index bbf7e8418..000000000
--- a/src/parser/prismparser/Tokens.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* 
- * File:   Tokens.h
- * Author: nafur
- *
- * Created on April 19, 2013, 11:17 PM
- */
-
-#ifndef TOKENS_H
-#define	TOKENS_H
-
-namespace storm {
-namespace parser {
-namespace prism {
-
-	/*!
-	 * A structure mapping the textual representation of a model type to the model type
-	 * representation of the intermediate representation.
-	 */
-	struct modelTypeStruct : qi::symbols<char, Program::ModelType> {
-		modelTypeStruct() {
-			add
-				("dtmc", Program::ModelType::DTMC)
-				("ctmc", Program::ModelType::CTMC)
-				("mdp", Program::ModelType::MDP)
-				("ctmdp", Program::ModelType::CTMDP)
-			;
-		}
-	};
-
-
-	/*!
-	 * A structure defining the keywords that are not allowed to be chosen as identifiers.
-	 */
-	struct keywordsStruct : qi::symbols<char, unsigned> {
-		keywordsStruct() {
-			add
-				("dtmc", 1)
-				("ctmc", 2)
-				("mdp", 3)
-				("ctmdp", 4)
-				("const", 5)
-				("int", 6)
-				("bool", 7)
-				("module", 8)
-				("endmodule", 9)
-				("rewards", 10)
-				("endrewards", 11)
-				("true", 12)
-				("false", 13)
-			;
-		}
-	};
-	
-	/*!
-	 * A structure mapping the textual representation of a binary relation to the representation
-	 * of the intermediate representation.
-	 */
-	struct relationalOperatorStruct : qi::symbols<char, BinaryRelationExpression::RelationType> {
-		relationalOperatorStruct() {
-			add
-				("=", BinaryRelationExpression::EQUAL)
-				("!=", BinaryRelationExpression::NOT_EQUAL)
-				("<", BinaryRelationExpression::LESS)
-				("<=", BinaryRelationExpression::LESS_OR_EQUAL)
-				(">", BinaryRelationExpression::GREATER)
-				(">=", BinaryRelationExpression::GREATER_OR_EQUAL)
-			;
-		}
-	};
-}
-}
-}
-
-#endif	/* TOKENS_H */
-
diff --git a/src/parser/prismparser/VariableState.cpp b/src/parser/prismparser/VariableState.cpp
deleted file mode 100644
index 244a3f17e..000000000
--- a/src/parser/prismparser/VariableState.cpp
+++ /dev/null
@@ -1,191 +0,0 @@
-#include "VariableState.h"
-#include "src/exceptions/InvalidArgumentException.h"
-
-namespace storm {
-    namespace parser {
-        namespace prism {
-            
-            using namespace storm::ir;
-            using namespace storm::ir::expressions;
-            
-            template<typename T>
-            struct SymbolDump {
-                SymbolDump(std::ostream& out) : out(out) {}
-                void operator() (std::basic_string<char> s, T elem) {
-                    this->out << "\t" << s << " -> " << elem << std::endl;
-                }
-            private:
-                std::ostream& out;
-            };
-            template<typename T>
-            std::ostream& operator<<(std::ostream& out, qi::symbols<char, T>& symbols) {
-                out << "Dumping symbol table" << std::endl;
-                SymbolDump<T> dump(out);
-                symbols.for_each(dump);
-                return out;
-            }
-            std::ostream& operator<<(std::ostream& out, VariableState::variableNamesStruct& symbols) {
-                SymbolDump<std::string> dump(out);
-                symbols.for_each(dump);
-                return out;
-            }
-            
-            
-            VariableState::VariableState(bool firstRun)	: firstRun(firstRun), keywords(), nextLocalBooleanVariableIndex(0), nextLocalIntegerVariableIndex(0), nextGlobalBooleanVariableIndex(0), nextGlobalIntegerVariableIndex(0), nextGlobalCommandIndex(0), nextGlobalUpdateIndex(0) {
-                // Nothing to do here.
-            }
-            
-            uint_fast64_t VariableState::getNextLocalBooleanVariableIndex() const {
-                return this->nextLocalBooleanVariableIndex;
-            }
-            
-            uint_fast64_t VariableState::getNextLocalIntegerVariableIndex() const {
-                return this->nextLocalIntegerVariableIndex;
-            }
-            
-            uint_fast64_t VariableState::getNextGlobalBooleanVariableIndex() const {
-                return this->nextGlobalBooleanVariableIndex;
-            }
-            
-            uint_fast64_t VariableState::getNextGlobalIntegerVariableIndex() const {
-                return this->nextGlobalIntegerVariableIndex;
-            }
-            
-            uint_fast64_t VariableState::getNextGlobalCommandIndex() const {
-                return this->nextGlobalCommandIndex;
-            }
-            
-            uint_fast64_t VariableState::getNextGlobalUpdateIndex() const {
-                return this->nextGlobalUpdateIndex;
-            }
-            
-            uint_fast64_t VariableState::addBooleanVariable(std::string const& name) {
-                if (firstRun) {
-                    LOG4CPLUS_TRACE(logger, "Adding boolean variable " << name << " with new id " << this->nextGlobalBooleanVariableIndex << ".");
-                    this->booleanVariables_.add(name, std::shared_ptr<VariableExpression>(new VariableExpression(storm::ir::expressions::BaseExpression::bool_, this->nextGlobalBooleanVariableIndex, name)));
-                    this->booleanVariableNames_.add(name, name);
-                    ++this->nextGlobalBooleanVariableIndex;
-                    ++this->nextLocalBooleanVariableIndex;
-                    return this->nextGlobalBooleanVariableIndex - 1;
-                } else {
-                    std::shared_ptr<VariableExpression> variableExpression = this->booleanVariables_.at(name);
-                    if (variableExpression != nullptr) {
-                        return variableExpression->getGlobalVariableIndex();
-                    } else {
-                        LOG4CPLUS_ERROR(logger, "Boolean variable " << name << " does not exist.");
-                        throw storm::exceptions::InvalidArgumentException() << "Boolean variable " << name << " does not exist.";
-                    }
-                }
-            }
-            
-            uint_fast64_t VariableState::addIntegerVariable(std::string const& name) {
-                if (firstRun) {
-                    LOG4CPLUS_TRACE(logger, "Adding integer variable " << name << " with new id " << this->nextGlobalIntegerVariableIndex << ".");
-                    this->integerVariables_.add(name, std::shared_ptr<VariableExpression>(new VariableExpression(storm::ir::expressions::BaseExpression::int_, this->nextGlobalIntegerVariableIndex, name)));
-                    this->integerVariableNames_.add(name, name);
-                    ++this->nextGlobalIntegerVariableIndex;
-                    ++this->nextLocalIntegerVariableIndex;
-                    return this->nextGlobalIntegerVariableIndex - 1;
-                } else {
-                    std::shared_ptr<VariableExpression> variableExpression = this->integerVariables_.at(name);
-                    if (variableExpression != nullptr) {
-                        return variableExpression->getGlobalVariableIndex();
-                    } else {
-                        LOG4CPLUS_ERROR(logger, "Integer variable " << name << " does not exist.");
-                        throw storm::exceptions::InvalidArgumentException() << "Integer variable " << name << " does not exist.";
-                    }
-                }
-            }
-            
-            std::shared_ptr<VariableExpression> VariableState::getBooleanVariableExpression(std::string const& name) const {
-                std::shared_ptr<VariableExpression> const* variableExpression = this->booleanVariables_.find(name);
-                if (variableExpression != nullptr) {
-                    return *variableExpression;
-                } else {
-                    if (firstRun) {
-                        LOG4CPLUS_TRACE(logger, "Trying to retrieve boolean variable " << name << " that was not yet created; returning dummy instead.");
-                        return std::shared_ptr<VariableExpression>(new VariableExpression(BaseExpression::bool_, name));
-                    } else {
-                        LOG4CPLUS_ERROR(logger, "Boolean variable " << name << " does not exist.");
-                        throw storm::exceptions::InvalidArgumentException() << "Boolean variable " << name << " does not exist.";
-                    }
-                }
-            }
-            
-            std::shared_ptr<VariableExpression> VariableState::getIntegerVariableExpression(std::string const& name) const {
-                std::shared_ptr<VariableExpression> const* variableExpression = this->integerVariables_.find(name);
-                if (variableExpression != nullptr) {
-                    return *variableExpression;
-                } else {
-                    if (firstRun) {
-                        LOG4CPLUS_TRACE(logger, "Trying to retrieve integer variable " << name << " that was not yet created; returning dummy instead.");
-                        return std::shared_ptr<VariableExpression>(new VariableExpression(BaseExpression::int_, name));
-                    } else {
-                        LOG4CPLUS_ERROR(logger, "Integer variable " << name << " does not exist.");
-                        throw storm::exceptions::InvalidArgumentException() << "Integer variable " << name << " does not exist.";
-                    }
-                }
-            }
-            
-            std::shared_ptr<VariableExpression> VariableState::getVariableExpression(std::string const& name) const {
-                std::shared_ptr<VariableExpression> const* variableExpression = this->integerVariables_.find(name);
-                if (variableExpression != nullptr) {
-                    return *variableExpression;
-                }
-                
-                variableExpression = this->booleanVariables_.find(name);
-                if (variableExpression != nullptr) {
-                    return *variableExpression;
-                }
-                LOG4CPLUS_ERROR(logger, "Variable " << name << " does not exist.");
-                throw storm::exceptions::InvalidArgumentException() << "Variable " << name << " does not exist.";
-            }
-            
-            void VariableState::clearLocalVariables() {
-                this->localBooleanVariables_.clear();
-                this->localIntegerVariables_.clear();
-                this->nextLocalBooleanVariableIndex = 0;
-                this->nextLocalIntegerVariableIndex = 0;
-            }
-            
-            bool VariableState::isFreeIdentifier(std::string const& identifier) const {
-            	if (this->booleanVariableNames_.find(identifier) != nullptr) return false;
-                if (this->integerVariableNames_.find(identifier) != nullptr) return false;
-                if (this->allConstantNames_.find(identifier) != nullptr) return false;
-                if (this->labelNames_.find(identifier) != nullptr) return false;
-                if (this->moduleNames_.find(identifier) != nullptr) return false;
-                if (this->keywords.find(identifier) != nullptr) return false;
-                if (this->booleanFormulas_.find(identifier) != nullptr) return false;
-                if (this->integerFormulas_.find(identifier) != nullptr) return false;
-                if (this->doubleFormulas_.find(identifier) != nullptr) return false;
-                if (this->constantBooleanFormulas_.find(identifier) != nullptr) return false;
-                if (this->constantIntegerFormulas_.find(identifier) != nullptr) return false;
-                if (this->constantDoubleFormulas_.find(identifier) != nullptr) return false;
-                return true;
-            }
-            
-            bool VariableState::isIdentifier(std::string const& identifier) const {
-                if (this->allConstantNames_.find(identifier) != nullptr) return false;
-                if (this->keywords.find(identifier) != nullptr) return false;
-                return true;
-            }
-            
-            void VariableState::prepareForSecondRun() {
-                integerConstants_.clear();
-                booleanConstants_.clear();
-                doubleConstants_.clear();
-                allConstantNames_.clear();
-                constantBooleanFormulas_.clear();
-                booleanFormulas_.clear();
-                constantIntegerFormulas_.clear();
-                integerFormulas_.clear();
-                constantDoubleFormulas_.clear();
-                doubleFormulas_.clear();
-                this->firstRun = false;
-                nextGlobalCommandIndex = 0;
-                nextGlobalUpdateIndex = 0;
-            }
-            
-        } // namespace prism
-    } // namespace parser
-} // namespace storm
diff --git a/src/parser/prismparser/VariableState.h b/src/parser/prismparser/VariableState.h
deleted file mode 100644
index 6dc7170a4..000000000
--- a/src/parser/prismparser/VariableState.h
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * File:   VariableState.h
- * Author: nafur
- *
- * Created on April 10, 2013, 4:43 PM
- */
-
-#ifndef STORM_PARSER_PRISMPARSER_VARIABLESTATE_H
-#define	STORM_PARSER_PRISMPARSER_VARIABLESTATE_H
-
-#include <iostream>
-
-#include "src/ir/IR.h"
-#include "Includes.h"
-#include "Tokens.h"
-
-namespace storm {
-    namespace parser {
-        namespace prism {
-            
-            using namespace storm::ir;
-            using namespace storm::ir::expressions;
-            
-            template<typename T>
-            std::ostream& operator<<(std::ostream& out, qi::symbols<char, T>& symbols);
-            
-            /*!
-             * This class contains the internal state that is needed for parsing a PRISM model.
-             */
-            class VariableState {
-            public:
-                /*!
-                 * Creates a new variable state object. By default, this object will be set to a state in which
-                 * it is ready for performing a first run on some input. The first run creates all variables
-                 * while the second one checks for the correct usage of variables in expressions.
-                 *
-                 * @param firstRun If set, this object will be in a state ready for performing the first run. If
-                 * set to false, this object will assume that it has all variable data already.
-                 */
-                VariableState(bool firstRun = true);
-                
-                /*!
-                 * Indicator, if we are still in the first run.
-                 */
-                bool firstRun;
-                
-                /*!
-                 * A parser for all reserved keywords.
-                 */
-                keywordsStruct keywords;
-                
-                /*!
-                 * Internal counter for the local index of the next new boolean variable.
-                 */
-                uint_fast64_t nextLocalBooleanVariableIndex;
-                
-                /*!
-                 * Retrieves the next free local index for a boolean variable.
-                 *
-                 * @return The next free local index for a boolean variable.
-                 */
-                uint_fast64_t getNextLocalBooleanVariableIndex() const;
-                
-                /*!
-                 * Internal counter for the local index of the next new integer variable.
-                 */
-                uint_fast64_t nextLocalIntegerVariableIndex;
-                
-                /*!
-                 * Retrieves the next free global index for a integer variable.
-                 *
-                 * @return The next free global index for a integer variable.
-                 */
-                uint_fast64_t getNextLocalIntegerVariableIndex() const;
-                
-                /*!
-                 * Internal counter for the index of the next new boolean variable.
-                 */
-                uint_fast64_t nextGlobalBooleanVariableIndex;
-                
-                /*!
-                 * Retrieves the next free global index for a boolean variable.
-                 *
-                 * @return The next free global index for a boolean variable.
-                 */
-                uint_fast64_t getNextGlobalBooleanVariableIndex() const;
-                
-                /*!
-                 * Internal counter for the index of the next new integer variable.
-                 */
-                uint_fast64_t nextGlobalIntegerVariableIndex;
-                
-                /*!
-                 * Retrieves the next free global index for a integer variable.
-                 *
-                 * @return The next free global index for a integer variable.
-                 */
-                uint_fast64_t getNextGlobalIntegerVariableIndex() const;
-                
-                /*!
-                 * Internal counter for the index of the next command.
-                 */
-                uint_fast64_t nextGlobalCommandIndex;
-                
-                /*!
-                 * Retrieves the next free global index for a command.
-                 *
-                 * @return The next free global index for a command.
-                 */
-                uint_fast64_t getNextGlobalCommandIndex() const;
-                
-                /*!
-                 * Internal counter for the index of the next update.
-                 */
-                uint_fast64_t nextGlobalUpdateIndex;
-                
-                /*!
-                 * Retrieves the next free global index for an update.
-                 *
-                 * @return The next free global index for an update.
-                 */
-                uint_fast64_t getNextGlobalUpdateIndex() const;
-                
-                // Structures mapping variable and constant names to the corresponding expression nodes of
-                // the intermediate representation.
-                struct qi::symbols<char, std::shared_ptr<VariableExpression>> integerVariables_, booleanVariables_;
-                struct qi::symbols<char, std::shared_ptr<BaseExpression>> integerConstants_, booleanConstants_, doubleConstants_, booleanFormulas_, constantBooleanFormulas_, integerFormulas_, constantIntegerFormulas_, doubleFormulas_, constantDoubleFormulas_;
-                
-                // A structure representing the identity function over identifier names.
-                struct variableNamesStruct : qi::symbols<char, std::string> { }
-                integerVariableNames_, booleanVariableNames_, commandNames_, labelNames_, allConstantNames_, moduleNames_,
-                localBooleanVariables_, localIntegerVariables_, assignedBooleanVariables_, assignedIntegerVariables_,
-                globalBooleanVariables_, globalIntegerVariables_;
-                
-                /*!
-                 * Adds a new boolean variable with the given name.
-                 *
-                 * @param name The name of the variable.
-                 * @return The global index of the variable.
-                 */
-                uint_fast64_t addBooleanVariable(std::string const& name);
-                
-                /*!
-                 * Adds a new integer variable with the given name.
-                 *
-                 * @param name The name of the variable.
-                 * @return The global index of the variable.
-                 */
-                uint_fast64_t addIntegerVariable(std::string const& name);
-                
-                /*!
-                 * Retrieves the variable expression for the boolean variable with the given name.
-                 *
-                 * @param name The name of the boolean variable for which to retrieve the variable expression.
-                 * @return The variable expression for the boolean variable with the given name.
-                 */
-                std::shared_ptr<VariableExpression> getBooleanVariableExpression(std::string const& name) const;
-                
-                /*!
-                 * Retrieves the variable expression for the integer variable with the given name.
-                 *
-                 * @param name The name of the integer variable for which to retrieve the variable expression.
-                 * @return The variable expression for the integer variable with the given name.
-                 */
-                std::shared_ptr<VariableExpression> getIntegerVariableExpression(std::string const& name) const;
-                
-                /*!
-                 * Retrieve the variable expression for the variable with the given name.
-                 *
-                 * @param name The name of the variable for which to retrieve the variable expression.
-                 * @return The variable expression for the variable with the given name.
-                 */
-                std::shared_ptr<VariableExpression> getVariableExpression(std::string const& name) const;
-                
-                /*!
-                 * Clears all local variables.
-                 */
-                void clearLocalVariables();
-                
-                /*!
-                 * Check if the given string is a free identifier.
-                 *
-                 * @param identifier A string to be checked.
-                 * @return True iff the given string is a free identifier.
-                 */
-                bool isFreeIdentifier(std::string const& identifier) const;
-                
-                /*!
-                 * Check if given string is a valid identifier.
-                 *
-                 * @param identifier A string to be checked.
-                 * @return True iff the given string is an identifier.
-                 */
-                bool isIdentifier(std::string const& identifier) const;
-                
-                /*!
-                 * Prepare state to proceed to second parser run. Currently, this clears the constants.
-                 */
-                void prepareForSecondRun();
-            };
-            
-        } // namespace prism
-    } // namespace parser
-} // namespace storm
-
-#endif	/* STORM_PARSER_PRISMPARSER_VARIABLESTATE_H */
-
diff --git a/src/solver/GurobiLpSolver.cpp b/src/solver/GurobiLpSolver.cpp
index c06233942..75a0d5a7e 100644
--- a/src/solver/GurobiLpSolver.cpp
+++ b/src/solver/GurobiLpSolver.cpp
@@ -1,6 +1,7 @@
 #include "src/solver/GurobiLpSolver.h"
 
 #ifdef STORM_HAVE_GUROBI
+#include <numeric>
 
 #include "src/exceptions/InvalidStateException.h"
 #include "src/settings/Settings.h"
@@ -162,12 +163,29 @@ namespace storm {
                 throw storm::exceptions::InvalidStateException() << "Sizes of variable indices vector and coefficients vector do not match.";
             }
             
-            // Convert the uint vector to ints for proper input to Gurobi.
-            std::vector<int> variablesCopy(variables.begin(), variables.end());
+            // As Gurobi requires the indices to be unique, we now explicitly make them unique. For this, we sort the
+            // variables and coefficients and eliminated duplicates by adding the coefficients.
             
-            // Copy the coefficients, because Gurobi does not take the coefficients as const values. The alternative to this would be casting
-            // away the constness, which gives undefined behaviour if Gurobi actually modifies something.
-            std::vector<double> coefficientsCopy(coefficients);
+            // We start by sorting both vectors.
+            std::vector<uint_fast64_t> sortedVariables(variables);
+			std::vector<double> sortedCoefficients(coefficients);
+            std::vector<uint_fast64_t> permutation(variables.size());
+            std::iota(permutation.begin(), permutation.end(), 0);
+            std::sort(permutation.begin(), permutation.end(), [&] (uint_fast64_t i, uint_fast64_t j) { return variables[i] < variables[j]; } );
+            std::transform(permutation.begin(), permutation.end(), sortedVariables.begin(), [&] (uint_fast64_t i) { return variables[i]; } );
+            std::transform(permutation.begin(), permutation.end(), sortedCoefficients.begin(), [&] (uint_fast64_t i) { return coefficients[i]; } );
+            
+            // Now we perform the duplicate elimination step.
+            std::vector<int> uniqueVariables;
+            std::vector<double> uniqueCoefficients;
+			for (uint_fast64_t i = 0; i < sortedVariables.size(); ++i) {
+				if (!uniqueVariables.empty() && uniqueVariables.back() == sortedVariables[i]) {
+					uniqueCoefficients.back() += sortedCoefficients[i];
+                } else {
+					uniqueVariables.push_back(static_cast<int>(sortedVariables[i]));
+					uniqueCoefficients.push_back(sortedCoefficients[i]);
+                }
+            }
             
             bool strictBound = boundType == LESS || boundType == GREATER;
             char sense = boundType == LESS || boundType == LESS_EQUAL ? GRB_LESS_EQUAL : boundType == EQUAL ? GRB_EQUAL : GRB_GREATER_EQUAL;
@@ -181,7 +199,7 @@ namespace storm {
                     rightHandSideValue += storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble();
                 }
             }
-            int error = GRBaddconstr(model, variablesCopy.size(), variablesCopy.data(), coefficientsCopy.data(), sense, rightHandSideValue, name == "" ? nullptr : name.c_str());
+            int error = GRBaddconstr(model, uniqueVariables.size(), uniqueVariables.data(), uniqueCoefficients.data(), sense, rightHandSideValue, name == "" ? nullptr : name.c_str());
             
             if (error) {
                 LOG4CPLUS_ERROR(logger, "Unable to assert Gurobi constraint (" << GRBgeterrormsg(env) << ", error code " << error << ").");
diff --git a/src/storage/dd/CuddDd.cpp b/src/storage/dd/CuddDd.cpp
index eba51a557..0e163c5f7 100644
--- a/src/storage/dd/CuddDd.cpp
+++ b/src/storage/dd/CuddDd.cpp
@@ -7,22 +7,26 @@
 
 namespace storm {
     namespace dd {
-        Dd<CUDD>::Dd(std::shared_ptr<DdManager<CUDD>> ddManager, ADD cuddAdd, std::set<std::string> const& containedMetaVariableNames) : ddManager(ddManager), cuddAdd(cuddAdd), containedMetaVariableNames(containedMetaVariableNames) {
+        Dd<DdType::CUDD>::Dd(std::shared_ptr<DdManager<DdType::CUDD>> ddManager, ADD cuddAdd, std::set<std::string> const& containedMetaVariableNames) : ddManager(ddManager), cuddAdd(cuddAdd), containedMetaVariableNames(containedMetaVariableNames) {
             // Intentionally left empty.
         }
         
-        bool Dd<CUDD>::operator==(Dd<CUDD> const& other) const {
-            return this->getCuddAdd() == other.getCuddAdd();
+        bool Dd<DdType::CUDD>::operator==(Dd<DdType::CUDD> const& other) const {
+            return this->cuddAdd == other.getCuddAdd();
         }
         
-        Dd<CUDD> Dd<CUDD>::operator+(Dd<CUDD> const& other) const {
-            Dd<CUDD> result(*this);
+        bool Dd<DdType::CUDD>::operator!=(Dd<DdType::CUDD> const& other) const {
+            return this->cuddAdd != other.getCuddAdd();
+        }
+        
+        Dd<DdType::CUDD> Dd<DdType::CUDD>::operator+(Dd<DdType::CUDD> const& other) const {
+            Dd<DdType::CUDD> result(*this);
             result += other;
             return result;
         }
         
-        Dd<CUDD>& Dd<CUDD>::operator+=(Dd<CUDD> const& other) {
-            this->getCuddAdd() += other.getCuddAdd();
+        Dd<DdType::CUDD>& Dd<DdType::CUDD>::operator+=(Dd<DdType::CUDD> const& other) {
+            this->cuddAdd += other.getCuddAdd();
             
             // Join the variable sets of the two participating DDs.
             this->getContainedMetaVariableNames().insert(other.getContainedMetaVariableNames().begin(), other.getContainedMetaVariableNames().end());
@@ -30,14 +34,14 @@ namespace storm {
             return *this;
         }
         
-        Dd<CUDD> Dd<CUDD>::operator*(Dd<CUDD> const& other) const {
-            Dd<CUDD> result(*this);
+        Dd<DdType::CUDD> Dd<DdType::CUDD>::operator*(Dd<DdType::CUDD> const& other) const {
+            Dd<DdType::CUDD> result(*this);
             result *= other;
             return result;
         }
         
-        Dd<CUDD>& Dd<CUDD>::operator*=(Dd<CUDD> const& other) {
-            this->getCuddAdd() *= other.getCuddAdd();
+        Dd<DdType::CUDD>& Dd<DdType::CUDD>::operator*=(Dd<DdType::CUDD> const& other) {
+            this->cuddAdd *= other.getCuddAdd();
             
             // Join the variable sets of the two participating DDs.
             this->getContainedMetaVariableNames().insert(other.getContainedMetaVariableNames().begin(), other.getContainedMetaVariableNames().end());
@@ -45,14 +49,14 @@ namespace storm {
             return *this;
         }
         
-        Dd<CUDD> Dd<CUDD>::operator-(Dd<CUDD> const& other) const {
-            Dd<CUDD> result(*this);
+        Dd<DdType::CUDD> Dd<DdType::CUDD>::operator-(Dd<DdType::CUDD> const& other) const {
+            Dd<DdType::CUDD> result(*this);
             result -= other;
             return result;
         }
         
-        Dd<CUDD>& Dd<CUDD>::operator-=(Dd<CUDD> const& other) {
-            this->getCuddAdd() -= other.getCuddAdd();
+        Dd<DdType::CUDD>& Dd<DdType::CUDD>::operator-=(Dd<DdType::CUDD> const& other) {
+            this->cuddAdd -= other.getCuddAdd();
             
             // Join the variable sets of the two participating DDs.
             this->getContainedMetaVariableNames().insert(other.getContainedMetaVariableNames().begin(), other.getContainedMetaVariableNames().end());
@@ -60,14 +64,14 @@ namespace storm {
             return *this;
         }
         
-        Dd<CUDD> Dd<CUDD>::operator/(Dd<CUDD> const& other) const {
-            Dd<CUDD> result(*this);
+        Dd<DdType::CUDD> Dd<DdType::CUDD>::operator/(Dd<DdType::CUDD> const& other) const {
+            Dd<DdType::CUDD> result(*this);
             result /= other;
             return result;
         }
         
-        Dd<CUDD>& Dd<CUDD>::operator/=(Dd<CUDD> const& other) {
-            this->getCuddAdd().Divide(other.getCuddAdd());
+        Dd<DdType::CUDD>& Dd<DdType::CUDD>::operator/=(Dd<DdType::CUDD> const& other) {
+            this->cuddAdd = this->cuddAdd.Divide(other.getCuddAdd());
             
             // Join the variable sets of the two participating DDs.
             this->getContainedMetaVariableNames().insert(other.getContainedMetaVariableNames().begin(), other.getContainedMetaVariableNames().end());
@@ -75,55 +79,55 @@ namespace storm {
             return *this;
         }
         
-        Dd<CUDD> Dd<CUDD>::operator~() const {
-            Dd<CUDD> result(*this);
+        Dd<DdType::CUDD> Dd<DdType::CUDD>::operator~() const {
+            Dd<DdType::CUDD> result(*this);
             result.complement();
             return result;
         }
         
-        Dd<CUDD>& Dd<CUDD>::complement() {
-            this->getCuddAdd() = ~this->getCuddAdd();
+        Dd<DdType::CUDD>& Dd<DdType::CUDD>::complement() {
+            this->cuddAdd = ~this->cuddAdd;
             return *this;
         }
         
-        Dd<CUDD> Dd<CUDD>::equals(Dd<CUDD> const& other) const {
-            Dd<CUDD> result(*this);
-            result.getCuddAdd().Equals(other.getCuddAdd());
+        Dd<DdType::CUDD> Dd<DdType::CUDD>::equals(Dd<DdType::CUDD> const& other) const {
+            Dd<DdType::CUDD> result(*this);
+            result.cuddAdd = result.cuddAdd.Equals(other.getCuddAdd());
             return result;
         }
         
-        Dd<CUDD> Dd<CUDD>::notEquals(Dd<CUDD> const& other) const {
-            Dd<CUDD> result(*this);
-            result.getCuddAdd().NotEquals(other.getCuddAdd());
+        Dd<DdType::CUDD> Dd<DdType::CUDD>::notEquals(Dd<DdType::CUDD> const& other) const {
+            Dd<DdType::CUDD> result(*this);
+            result.cuddAdd = result.cuddAdd.NotEquals(other.getCuddAdd());
             return result;
         }
         
-        Dd<CUDD> Dd<CUDD>::less(Dd<CUDD> const& other) const {
-            Dd<CUDD> result(*this);
-            result.getCuddAdd().LessThan(other.getCuddAdd());
+        Dd<DdType::CUDD> Dd<DdType::CUDD>::less(Dd<DdType::CUDD> const& other) const {
+            Dd<DdType::CUDD> result(*this);
+            result.cuddAdd = result.cuddAdd.LessThan(other.getCuddAdd());
             return result;
         }
         
-        Dd<CUDD> Dd<CUDD>::lessOrEqual(Dd<CUDD> const& other) const {
-            Dd<CUDD> result(*this);
-            result.getCuddAdd().LessThanOrEqual(other.getCuddAdd());
+        Dd<DdType::CUDD> Dd<DdType::CUDD>::lessOrEqual(Dd<DdType::CUDD> const& other) const {
+            Dd<DdType::CUDD> result(*this);
+            result.cuddAdd = result.cuddAdd.LessThanOrEqual(other.getCuddAdd());
             return result;
         }
         
-        Dd<CUDD> Dd<CUDD>::greater(Dd<CUDD> const& other) const {
-            Dd<CUDD> result(*this);
-            result.getCuddAdd().GreaterThan(other.getCuddAdd());
+        Dd<DdType::CUDD> Dd<DdType::CUDD>::greater(Dd<DdType::CUDD> const& other) const {
+            Dd<DdType::CUDD> result(*this);
+            result.cuddAdd = result.cuddAdd.GreaterThan(other.getCuddAdd());
             return result;
         }
         
-        Dd<CUDD> Dd<CUDD>::greaterOrEqual(Dd<CUDD> const& other) const {
-            Dd<CUDD> result(*this);
-            result.getCuddAdd().GreaterThanOrEqual(other.getCuddAdd());
+        Dd<DdType::CUDD> Dd<DdType::CUDD>::greaterOrEqual(Dd<DdType::CUDD> const& other) const {
+            Dd<DdType::CUDD> result(*this);
+            result.cuddAdd = result.cuddAdd.GreaterThanOrEqual(other.getCuddAdd());
             return result;
         }
         
-        void Dd<CUDD>::existsAbstract(std::set<std::string> const& metaVariableNames) {
-            Dd<CUDD> cubeDd(this->getDdManager()->getOne());
+        void Dd<DdType::CUDD>::existsAbstract(std::set<std::string> const& metaVariableNames) {
+            Dd<DdType::CUDD> cubeDd(this->getDdManager()->getOne());
             
             for (auto const& metaVariableName : metaVariableNames) {
                 // First check whether the DD contains the meta variable and erase it, if this is the case.
@@ -132,15 +136,15 @@ namespace storm {
                 }
                 this->getContainedMetaVariableNames().erase(metaVariableName);
                 
-                DdMetaVariable<CUDD> const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName);
+                DdMetaVariable<DdType::CUDD> const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName);
                 cubeDd *= metaVariable.getCube();
             }
             
-            this->getCuddAdd().OrAbstract(cubeDd.getCuddAdd());
+            this->cuddAdd = this->cuddAdd.OrAbstract(cubeDd.getCuddAdd());
         }
         
-        void Dd<CUDD>::sumAbstract(std::set<std::string> const& metaVariableNames) {
-            Dd<CUDD> cubeDd(this->getDdManager()->getOne());
+        void Dd<DdType::CUDD>::sumAbstract(std::set<std::string> const& metaVariableNames) {
+            Dd<DdType::CUDD> cubeDd(this->getDdManager()->getOne());
             
             for (auto const& metaVariableName : metaVariableNames) {
                 // First check whether the DD contains the meta variable and erase it, if this is the case.
@@ -149,15 +153,15 @@ namespace storm {
                 }
                 this->getContainedMetaVariableNames().erase(metaVariableName);
                 
-                DdMetaVariable<CUDD> const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName);
+                DdMetaVariable<DdType::CUDD> const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName);
                 cubeDd *= metaVariable.getCube();
             }
             
-            this->getCuddAdd().ExistAbstract(cubeDd.getCuddAdd());
+            this->cuddAdd = this->cuddAdd.ExistAbstract(cubeDd.getCuddAdd());
         }
         
-        void Dd<CUDD>::minAbstract(std::set<std::string> const& metaVariableNames) {
-            Dd<CUDD> cubeDd(this->getDdManager()->getOne());
+        void Dd<DdType::CUDD>::minAbstract(std::set<std::string> const& metaVariableNames) {
+            Dd<DdType::CUDD> cubeDd(this->getDdManager()->getOne());
             
             for (auto const& metaVariableName : metaVariableNames) {
                 // First check whether the DD contains the meta variable and erase it, if this is the case.
@@ -166,15 +170,15 @@ namespace storm {
                 }
                 this->getContainedMetaVariableNames().erase(metaVariableName);
                 
-                DdMetaVariable<CUDD> const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName);
+                DdMetaVariable<DdType::CUDD> const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName);
                 cubeDd *= metaVariable.getCube();
             }
             
-            this->getCuddAdd().Minimum(cubeDd.getCuddAdd());
+            this->cuddAdd = this->cuddAdd.MinAbstract(cubeDd.getCuddAdd());
         }
         
-        void Dd<CUDD>::maxAbstract(std::set<std::string> const& metaVariableNames) {
-            Dd<CUDD> cubeDd(this->getDdManager()->getOne());
+        void Dd<DdType::CUDD>::maxAbstract(std::set<std::string> const& metaVariableNames) {
+            Dd<DdType::CUDD> cubeDd(this->getDdManager()->getOne());
             
             for (auto const& metaVariableName : metaVariableNames) {
                 // First check whether the DD contains the meta variable and erase it, if this is the case.
@@ -183,19 +187,19 @@ namespace storm {
                 }
                 this->getContainedMetaVariableNames().erase(metaVariableName);
                 
-                DdMetaVariable<CUDD> const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName);
+                DdMetaVariable<DdType::CUDD> const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName);
                 cubeDd *= metaVariable.getCube();
             }
             
-            this->getCuddAdd().Maximum(cubeDd.getCuddAdd());
+            this->cuddAdd = this->cuddAdd.MaxAbstract(cubeDd.getCuddAdd());
         }
         
-        void Dd<CUDD>::swapVariables(std::vector<std::pair<std::string, std::string>> const& metaVariablePairs) {
+        void Dd<DdType::CUDD>::swapVariables(std::vector<std::pair<std::string, std::string>> const& metaVariablePairs) {
             std::vector<ADD> from;
             std::vector<ADD> to;
             for (auto const& metaVariablePair : metaVariablePairs) {
-                DdMetaVariable<CUDD> const& variable1 = this->getDdManager()->getMetaVariable(metaVariablePair.first);
-                DdMetaVariable<CUDD> const& variable2 = this->getDdManager()->getMetaVariable(metaVariablePair.second);
+                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()) {
@@ -223,10 +227,10 @@ namespace storm {
             }
             
             // Finally, call CUDD to swap the variables.
-            this->getCuddAdd().SwapVariables(from, to);
+            this->cuddAdd = this->cuddAdd.SwapVariables(from, to);
         }
         
-        Dd<CUDD> Dd<CUDD>::multiplyMatrix(Dd<CUDD> const& otherMatrix, std::set<std::string> const& summationMetaVariableNames) {
+        Dd<DdType::CUDD> Dd<DdType::CUDD>::multiplyMatrix(Dd<DdType::CUDD> const& otherMatrix, std::set<std::string> const& summationMetaVariableNames) {
             std::vector<ADD> summationDdVariables;
             
             // Create the CUDD summation variables.
@@ -241,11 +245,10 @@ namespace storm {
             std::set<std::string> containedMetaVariableNames;
             std::set_difference(unionOfMetaVariableNames.begin(), unionOfMetaVariableNames.end(), summationMetaVariableNames.begin(), summationMetaVariableNames.end(), std::inserter(containedMetaVariableNames, containedMetaVariableNames.begin()));
             
-            return Dd<CUDD>(this->getDdManager(), this->getCuddAdd().MatrixMultiply(otherMatrix.getCuddAdd(), summationDdVariables), containedMetaVariableNames);
+            return Dd<DdType::CUDD>(this->getDdManager(), this->cuddAdd.MatrixMultiply(otherMatrix.getCuddAdd(), summationDdVariables), containedMetaVariableNames);
         }
-
         
-        uint_fast64_t Dd<CUDD>::getNonZeroCount() const {
+        uint_fast64_t Dd<DdType::CUDD>::getNonZeroCount() const {
             std::size_t numberOfDdVariables = 0;
             for (auto const& metaVariableName : this->containedMetaVariableNames) {
                 numberOfDdVariables += this->getDdManager()->getMetaVariable(metaVariableName).getNumberOfDdVariables();
@@ -253,60 +256,85 @@ namespace storm {
             return static_cast<uint_fast64_t>(this->cuddAdd.CountMinterm(static_cast<int>(numberOfDdVariables)));
         }
         
-        uint_fast64_t Dd<CUDD>::getLeafCount() const {
+        uint_fast64_t Dd<DdType::CUDD>::getLeafCount() const {
             return static_cast<uint_fast64_t>(this->cuddAdd.CountLeaves());
         }
         
-        uint_fast64_t Dd<CUDD>::getNodeCount() const {
+        uint_fast64_t Dd<DdType::CUDD>::getNodeCount() const {
             return static_cast<uint_fast64_t>(this->cuddAdd.nodeCount());
         }
         
-        double Dd<CUDD>::getMin() const {
-            ADD constantMinAdd = this->getCuddAdd().FindMin();
+        double Dd<DdType::CUDD>::getMin() const {
+            ADD constantMinAdd = this->cuddAdd.FindMin();
             return static_cast<double>(Cudd_V(constantMinAdd.getNode()));
         }
         
-        double Dd<CUDD>::getMax() const {
-            ADD constantMaxAdd = this->getCuddAdd().FindMax();
+        double Dd<DdType::CUDD>::getMax() const {
+            ADD constantMaxAdd = this->cuddAdd.FindMax();
             return static_cast<double>(Cudd_V(constantMaxAdd.getNode()));
         }
         
-        void Dd<CUDD>::setValue(std::string const& metaVariableName, int_fast64_t variableValue, double targetValue) {
-            std::unordered_map<std::string, int_fast64_t> metaVariableNameToValueMap;
+        void Dd<DdType::CUDD>::setValue(std::string const& metaVariableName, int_fast64_t variableValue, double targetValue) {
+            std::map<std::string, int_fast64_t> metaVariableNameToValueMap;
             metaVariableNameToValueMap.emplace(metaVariableName, variableValue);
             this->setValue(metaVariableNameToValueMap, targetValue);
         }
         
-        void Dd<CUDD>::setValue(std::string const& metaVariableName1, int_fast64_t variableValue1, std::string const& metaVariableName2, int_fast64_t variableValue2, double targetValue) {
-            std::unordered_map<std::string, int_fast64_t> metaVariableNameToValueMap;
+        void Dd<DdType::CUDD>::setValue(std::string const& metaVariableName1, int_fast64_t variableValue1, std::string const& metaVariableName2, int_fast64_t variableValue2, double targetValue) {
+            std::map<std::string, int_fast64_t> metaVariableNameToValueMap;
             metaVariableNameToValueMap.emplace(metaVariableName1, variableValue1);
             metaVariableNameToValueMap.emplace(metaVariableName2, variableValue2);
             this->setValue(metaVariableNameToValueMap, targetValue);
         }
         
-        void Dd<CUDD>::setValue(std::unordered_map<std::string, int_fast64_t> const& metaVariableNameToValueMap, double targetValue) {
-            Dd<CUDD> valueEncoding(this->getDdManager()->getOne());
+        void Dd<DdType::CUDD>::setValue(std::map<std::string, int_fast64_t> const& metaVariableNameToValueMap, double targetValue) {
+            Dd<DdType::CUDD> valueEncoding(this->getDdManager()->getOne());
+            for (auto const& nameValuePair : metaVariableNameToValueMap) {
+                valueEncoding *= this->getDdManager()->getEncoding(nameValuePair.first, nameValuePair.second);
+                // Also record that the DD now contains the meta variable.
+                this->addContainedMetaVariable(nameValuePair.first);
+            }
+            
+            this->cuddAdd = valueEncoding.getCuddAdd().Ite(this->getDdManager()->getConstant(targetValue).getCuddAdd(), this->cuddAdd);
+        }
+        
+        double Dd<DdType::CUDD>::getValue(std::map<std::string, int_fast64_t> const& metaVariableNameToValueMap) const {
+            std::set<std::string> remainingMetaVariables(this->getContainedMetaVariableNames());
+            Dd<DdType::CUDD> valueEncoding(this->getDdManager()->getOne());
             for (auto const& nameValuePair : metaVariableNameToValueMap) {
                 valueEncoding *= this->getDdManager()->getEncoding(nameValuePair.first, nameValuePair.second);
+                if (this->containsMetaVariable(nameValuePair.first)) {
+                    remainingMetaVariables.erase(nameValuePair.first);
+                }
+            }
+            
+            if (!remainingMetaVariables.empty()) {
+                throw storm::exceptions::InvalidArgumentException() << "Cannot evaluate function for which not all inputs were given.";
             }
             
-            this->getCuddAdd() = valueEncoding.getCuddAdd().Ite(this->getDdManager()->getConstant(targetValue).getCuddAdd(), this->cuddAdd);
+            Dd<DdType::CUDD> value = *this * valueEncoding;
+            value.sumAbstract(this->getContainedMetaVariableNames());
+            return static_cast<double>(Cudd_V(value.getCuddAdd().getNode()));
         }
         
-        bool Dd<CUDD>::isOne() const {
+        bool Dd<DdType::CUDD>::isOne() const {
             return *this == this->getDdManager()->getOne();
         }
         
-        bool Dd<CUDD>::isZero() const {
+        bool Dd<DdType::CUDD>::isZero() const {
             return *this == this->getDdManager()->getZero();
         }
         
-        bool Dd<CUDD>::containsMetaVariable(std::string const& metaVariableName) const {
+        bool Dd<DdType::CUDD>::isConstant() const {
+            return Cudd_IsConstant(this->cuddAdd.getNode());
+        }
+        
+        bool Dd<DdType::CUDD>::containsMetaVariable(std::string const& metaVariableName) const {
             auto const& metaVariable = containedMetaVariableNames.find(metaVariableName);
             return metaVariable != containedMetaVariableNames.end();
         }
         
-        bool Dd<CUDD>::containsMetaVariables(std::set<std::string> metaVariableNames) const {
+        bool Dd<DdType::CUDD>::containsMetaVariables(std::set<std::string> metaVariableNames) const {
             for (auto const& metaVariableName : metaVariableNames) {
                 auto const& metaVariable = containedMetaVariableNames.find(metaVariableName);
                 
@@ -317,38 +345,49 @@ namespace storm {
             return true;
         }
         
-        std::set<std::string> const& Dd<CUDD>::getContainedMetaVariableNames() const {
+        std::set<std::string> const& Dd<DdType::CUDD>::getContainedMetaVariableNames() const {
             return this->containedMetaVariableNames;
         }
         
-        std::set<std::string>& Dd<CUDD>::getContainedMetaVariableNames() {
+        std::set<std::string>& Dd<DdType::CUDD>::getContainedMetaVariableNames() {
             return this->containedMetaVariableNames;
         }
         
-        void Dd<CUDD>::exportToDot(std::string const& filename) const {
-            FILE* filePointer = fopen(filename.c_str() , "w");
-            this->getDdManager()->getCuddManager().DumpDot({this->cuddAdd}, nullptr, nullptr, filePointer);
-            fclose(filePointer);
+        void Dd<DdType::CUDD>::exportToDot(std::string const& filename) const {
+			std::vector<ADD> cuddAddVector = { this->cuddAdd };
+			if (filename.empty()) {
+				this->getDdManager()->getCuddManager().DumpDot(cuddAddVector);
+            } else {
+                FILE* filePointer = fopen(filename.c_str() , "w");
+				this->getDdManager()->getCuddManager().DumpDot(cuddAddVector, nullptr, nullptr, filePointer);
+                fclose(filePointer);
+            }
         }
         
-        ADD Dd<CUDD>::getCuddAdd() {
+        ADD Dd<DdType::CUDD>::getCuddAdd() {
             return this->cuddAdd;
         }
         
-        ADD const& Dd<CUDD>::getCuddAdd() const {
+        ADD const& Dd<DdType::CUDD>::getCuddAdd() const {
             return this->cuddAdd;
         }
         
-        void Dd<CUDD>::addContainedMetaVariable(std::string const& metaVariableName) {
+        void Dd<DdType::CUDD>::addContainedMetaVariable(std::string const& metaVariableName) {
             this->getContainedMetaVariableNames().insert(metaVariableName);
         }
 
-        void Dd<CUDD>::removeContainedMetaVariable(std::string const& metaVariableName) {
+        void Dd<DdType::CUDD>::removeContainedMetaVariable(std::string const& metaVariableName) {
             this->getContainedMetaVariableNames().erase(metaVariableName);
         }
         
-        std::shared_ptr<DdManager<CUDD>> Dd<CUDD>::getDdManager() const {
+        std::shared_ptr<DdManager<DdType::CUDD>> Dd<DdType::CUDD>::getDdManager() const {
             return this->ddManager;
         }
+        
+        std::ostream & operator<<(std::ostream& out, const Dd<DdType::CUDD>& dd) {
+            dd.exportToDot();
+            return out;
+        }
+
     }
 }
\ No newline at end of file
diff --git a/src/storage/dd/CuddDd.h b/src/storage/dd/CuddDd.h
index 1f8339fe6..6da2dc9c3 100644
--- a/src/storage/dd/CuddDd.h
+++ b/src/storage/dd/CuddDd.h
@@ -1,9 +1,10 @@
 #ifndef STORM_STORAGE_DD_CUDDDD_H_
 #define STORM_STORAGE_DD_CUDDDD_H_
 
-#include <unordered_map>
+#include <map>
 #include <set>
 #include <memory>
+#include <iostream>
 
 #include "src/storage/dd/Dd.h"
 #include "src/utility/OsDetection.h"
@@ -17,26 +18,35 @@ namespace storm {
         template<DdType Type> class DdManager;
         
         template<>
-        class Dd<CUDD> {
+        class Dd<DdType::CUDD> {
         public:
             // Declare the DdManager class as friend so it can access the internals of a DD.
-            friend class DdManager<CUDD>;
+            friend class DdManager<DdType::CUDD>;
             
             // Instantiate all copy/move constructors/assignments with the default implementation.
             Dd() = default;
-            Dd(Dd<CUDD> const& other) = default;
-			Dd& operator=(Dd<CUDD> const& other) = default;
+            Dd(Dd<DdType::CUDD> const& other) = default;
+			Dd& operator=(Dd<DdType::CUDD> const& other) = default;
 #ifndef WINDOWS
-            Dd(Dd<CUDD>&& other) = default;
-            Dd& operator=(Dd<CUDD>&& other) = default;
+            Dd(Dd<DdType::CUDD>&& other) = default;
+            Dd& operator=(Dd<DdType::CUDD>&& other) = default;
 #endif
             
             /*!
              * Retrieves whether the two DDs represent the same function.
              *
              * @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<CUDD> const& other) const;
+            bool operator==(Dd<DdType::CUDD> const& other) const;
+            
+            /*!
+             * Retrieves whether the two DDs represent different functions.
+             *
+             * @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;
             
             /*!
              * Adds the two DDs.
@@ -44,7 +54,7 @@ namespace storm {
              * @param other The DD to add to the current one.
              * @return The result of the addition.
              */
-            Dd<CUDD> operator+(Dd<CUDD> const& other) const;
+            Dd<DdType::CUDD> operator+(Dd<DdType::CUDD> const& other) const;
             
             /*!
              * Adds the given DD to the current one.
@@ -52,7 +62,7 @@ namespace storm {
              * @param other The DD to add to the current one.
              * @return A reference to the current DD after the operation.
              */
-            Dd<CUDD>& operator+=(Dd<CUDD> const& other);
+            Dd<DdType::CUDD>& operator+=(Dd<DdType::CUDD> const& other);
             
             /*!
              * Multiplies the two DDs.
@@ -60,7 +70,7 @@ namespace storm {
              * @param other The DD to multiply with the current one.
              * @return The result of the multiplication.
              */
-            Dd<CUDD> operator*(Dd<CUDD> const& other) const;
+            Dd<DdType::CUDD> operator*(Dd<DdType::CUDD> const& other) const;
             
             /*!
              * Multiplies the given DD with the current one and assigns the result to the current DD.
@@ -68,7 +78,7 @@ namespace storm {
              * @param other The DD to multiply with the current one.
              * @return A reference to the current DD after the operation.
              */
-            Dd<CUDD>& operator*=(Dd<CUDD> const& other);
+            Dd<DdType::CUDD>& operator*=(Dd<DdType::CUDD> const& other);
             
             /*!
              * Subtracts the given DD from the current one.
@@ -76,7 +86,7 @@ namespace storm {
              * @param other The DD to subtract from the current one.
              * @return The result of the subtraction.
              */
-            Dd<CUDD> operator-(Dd<CUDD> const& other) const;
+            Dd<DdType::CUDD> operator-(Dd<DdType::CUDD> const& other) const;
             
             /*!
              * Subtracts the given DD from the current one and assigns the result to the current DD.
@@ -84,7 +94,7 @@ namespace storm {
              * @param other The DD to subtract from the current one.
              * @return A reference to the current DD after the operation.
              */
-            Dd<CUDD>& operator-=(Dd<CUDD> const& other);
+            Dd<DdType::CUDD>& operator-=(Dd<DdType::CUDD> const& other);
             
             /*!
              * Divides the current DD by the given one.
@@ -92,7 +102,7 @@ namespace storm {
              * @param other The DD by which to divide the current one.
              * @return The result of the division.
              */
-            Dd<CUDD> operator/(Dd<CUDD> const& other) const;
+            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.
@@ -100,14 +110,14 @@ namespace storm {
              * @param other The DD by which to divide the current one.
              * @return A reference to the current DD after the operation.
              */
-            Dd<CUDD>& operator/=(Dd<CUDD> const& other);
+            Dd<DdType::CUDD>& operator/=(Dd<DdType::CUDD> const& other);
             
             /*!
              * Subtracts the DD from the constant zero function.
              *
              * @return The resulting function represented as a DD.
              */
-            Dd<CUDD> minus() const;
+            Dd<DdType::CUDD> minus() const;
             
             /*!
              * Retrieves the logical complement of the current DD. The result will map all encodings with a value
@@ -115,7 +125,7 @@ namespace storm {
              *
              * @return The logical complement of the current DD.
              */
-            Dd<CUDD> operator~() const;
+            Dd<DdType::CUDD> operator~() const;
             
             /*!
              * Logically complements the current DD. The result will map all encodings with a value
@@ -123,7 +133,7 @@ namespace storm {
              *
              * @return A reference to the current DD after the operation.
              */
-            Dd<CUDD>& complement();
+            Dd<DdType::CUDD>& complement();
             
             /*!
              * Retrieves the function that maps all evaluations to one that have an identical function values.
@@ -131,7 +141,7 @@ namespace storm {
              * @param other The DD with which to perform the operation.
              * @return The resulting function represented as a DD.
              */
-            Dd<CUDD> equals(Dd<CUDD> const& other) const;
+            Dd<DdType::CUDD> equals(Dd<DdType::CUDD> const& other) const;
             
             /*!
              * Retrieves the function that maps all evaluations to one that have distinct function values.
@@ -139,7 +149,7 @@ namespace storm {
              * @param other The DD with which to perform the operation.
              * @return The resulting function represented as a DD.
              */
-            Dd<CUDD> notEquals(Dd<CUDD> const& other) const;
+            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
@@ -148,7 +158,7 @@ namespace storm {
              * @param other The DD with which to perform the operation.
              * @return The resulting function represented as a DD.
              */
-            Dd<CUDD> less(Dd<CUDD> const& other) const;
+            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
@@ -157,7 +167,7 @@ namespace storm {
              * @param other The DD with which to perform the operation.
              * @return The resulting function represented as a DD.
              */
-            Dd<CUDD> lessOrEqual(Dd<CUDD> const& other) const;
+            Dd<DdType::CUDD> lessOrEqual(Dd<DdType::CUDD> const& other) const;
             
             /*!
              * Retrieves the function that maps all evaluations to one whose function value in the first DD are greater
@@ -166,7 +176,7 @@ namespace storm {
              * @param other The DD with which to perform the operation.
              * @return The resulting function represented as a DD.
              */
-            Dd<CUDD> greater(Dd<CUDD> const& other) const;
+            Dd<DdType::CUDD> greater(Dd<DdType::CUDD> const& other) const;
             
             /*!
              * Retrieves the function that maps all evaluations to one whose function value in the first DD are greater
@@ -175,7 +185,7 @@ namespace storm {
              * @param other The DD with which to perform the operation.
              * @return The resulting function represented as a DD.
              */
-            Dd<CUDD> greaterOrEqual(Dd<CUDD> const& other) const;
+            Dd<DdType::CUDD> greaterOrEqual(Dd<DdType::CUDD> const& other) const;
             
             /*!
              * Existentially abstracts from the given meta variables.
@@ -222,7 +232,7 @@ namespace storm {
              * matrix multiplication.
              * @return A DD representing the result of the matrix-matrix multiplication.
              */
-            Dd<CUDD> multiplyMatrix(Dd<CUDD> const& otherMatrix, std::set<std::string> const& summationMetaVariableNames);
+            Dd<DdType::CUDD> multiplyMatrix(Dd<DdType::CUDD> const& otherMatrix, std::set<std::string> const& summationMetaVariableNames);
             
             /*!
              * Retrieves the number of encodings that are mapped to a non-zero value.
@@ -294,7 +304,16 @@ namespace storm {
              * have. All values must be within the range of the respective meta variable.
              * @param targetValue The new function value of the modified encodings.
              */
-            void setValue(std::unordered_map<std::string, int_fast64_t> const& metaVariableNameToValueMap, double targetValue);
+            void setValue(std::map<std::string, int_fast64_t> const& metaVariableNameToValueMap = std::map<std::string, int_fast64_t>(), double targetValue = 0);
+            
+            /*!
+             * Retrieves the value of the function when all meta variables are assigned the values of the given mapping.
+             * Note that the mapping must specify values for all meta variables contained in the DD.
+             *
+             * @param metaVariableNameToValueMap A mapping of meta variable names to their values.
+             * @return The value of the function evaluated with the given input.
+             */
+            double getValue(std::map<std::string, int_fast64_t> const& metaVariableNameToValueMap = std::map<std::string, int_fast64_t>()) const;
             
             /*!
              * Retrieves whether this DD represents the constant one function.
@@ -310,6 +329,13 @@ namespace storm {
              */
             bool isZero() const;
             
+            /*!
+             * Retrieves whether this DD represents a constant function.
+             *
+             * @return True if this DD represents a constants function.
+             */
+            bool isConstant() const;
+            
             /*!
              * Retrieves whether the given meta variable is contained in the DD.
              *
@@ -345,20 +371,21 @@ namespace storm {
              *
              * @param filename The name of the file to which the DD is to be exported.
              */
-            void exportToDot(std::string const& filename) const;
+            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<CUDD>> getDdManager() const;
+            std::shared_ptr<DdManager<DdType::CUDD>> getDdManager() const;
             
+            friend std::ostream & operator<<(std::ostream& out, const Dd<DdType::CUDD>& dd);
         private:
             /*!
-             * Retrieves the CUDD ADD object associated with this DD.
+             * Retrieves a reference to the CUDD ADD object associated with this DD.
              *
-             * @return The CUDD ADD object assoicated with this DD.
+             * @return The CUDD ADD object associated with this DD.
              */
             ADD getCuddAdd();
             
@@ -390,10 +417,10 @@ namespace storm {
              * @param cuddAdd The CUDD ADD to store.
              * @param
              */
-            Dd(std::shared_ptr<DdManager<CUDD>> ddManager, ADD cuddAdd, std::set<std::string> const& containedMetaVariableNames = std::set<std::string>());
+            Dd(std::shared_ptr<DdManager<DdType::CUDD>> ddManager, ADD cuddAdd, std::set<std::string> const& containedMetaVariableNames = std::set<std::string>());
             
             // A pointer to the manager responsible for this DD.
-            std::shared_ptr<DdManager<CUDD>> ddManager;
+            std::shared_ptr<DdManager<DdType::CUDD>> ddManager;
             
             // The ADD created by CUDD.
             ADD cuddAdd;
diff --git a/src/storage/dd/CuddDdManager.cpp b/src/storage/dd/CuddDdManager.cpp
index dd6ce4f4f..9843b5c92 100644
--- a/src/storage/dd/CuddDdManager.cpp
+++ b/src/storage/dd/CuddDdManager.cpp
@@ -4,34 +4,47 @@
 #include "src/storage/dd/CuddDdManager.h"
 #include "src/exceptions/InvalidArgumentException.h"
 
-#include <iostream>
-
 namespace storm {
     namespace dd {
-        DdManager<CUDD>::DdManager() : metaVariableMap(), cuddManager() {
+        DdManager<DdType::CUDD>::DdManager() : metaVariableMap(), cuddManager() {
             // Intentionally left empty.
         }
         
-        Dd<CUDD> DdManager<CUDD>::getOne() {
-            return Dd<CUDD>(this->shared_from_this(), cuddManager.addOne());
+        Dd<DdType::CUDD> DdManager<DdType::CUDD>::getOne() {
+            return Dd<DdType::CUDD>(this->shared_from_this(), cuddManager.addOne());
         }
         
-        Dd<CUDD> DdManager<CUDD>::getZero() {
-            return Dd<CUDD>(this->shared_from_this(), cuddManager.addZero());
+        Dd<DdType::CUDD> DdManager<DdType::CUDD>::getZero() {
+            return Dd<DdType::CUDD>(this->shared_from_this(), cuddManager.addZero());
         }
         
-        Dd<CUDD> DdManager<CUDD>::getConstant(double value) {
-            return Dd<CUDD>(this->shared_from_this(), cuddManager.constant(value));
+        Dd<DdType::CUDD> DdManager<DdType::CUDD>::getConstant(double value) {
+            return Dd<DdType::CUDD>(this->shared_from_this(), cuddManager.constant(value));
         }
         
-        Dd<CUDD> DdManager<CUDD>::getEncoding(std::string const& metaVariableName, int_fast64_t value) {
-            std::vector<Dd<CUDD>> ddVariables = this->getMetaVariable(metaVariableName).getDdVariables();
+        Dd<DdType::CUDD> DdManager<DdType::CUDD>::getEncoding(std::string const& metaVariableName, int_fast64_t value) {
+            // Check whether the meta variable exists.
+            if (!this->hasMetaVariable(metaVariableName)) {
+                throw storm::exceptions::InvalidArgumentException() << "Unknown meta variable name '" << metaVariableName << "'.";
+            }
+            
+            DdMetaVariable<DdType::CUDD> const& metaVariable = this->getMetaVariable(metaVariableName);
+            
+            // Check whether the value is legal for this meta variable.
+            if (value < metaVariable.getLow() || value > metaVariable.getHigh()) {
+                throw storm::exceptions::InvalidArgumentException() << "Illegal value " << value << " for meta variable '" << metaVariableName << "'.";
+            }
+            
+            // 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();
 
-            Dd<CUDD> result;
+            Dd<DdType::CUDD> result;
             if (value & (1ull << (ddVariables.size() - 1))) {
                 result = ddVariables[0];
             } else {
-                result = ddVariables[0];
+                result = ~ddVariables[0];
             }
             
             for (std::size_t i = 1; i < ddVariables.size(); ++i) {
@@ -41,21 +54,42 @@ namespace storm {
                     result *= ~ddVariables[i];
                 }
             }
+                        
+            return result;
+        }
+        
+        Dd<DdType::CUDD> DdManager<DdType::CUDD>::getRange(std::string const& metaVariableName) {
+            // Check whether the meta variable exists.
+            if (!this->hasMetaVariable(metaVariableName)) {
+                throw storm::exceptions::InvalidArgumentException() << "Unknown meta variable name '" << metaVariableName << "'.";
+            }
+
+            storm::dd::DdMetaVariable<DdType::CUDD> const& metaVariable = this->getMetaVariable(metaVariableName);
+            
+            Dd<DdType::CUDD> result = this->getZero();
             
+            for (int_fast64_t value = metaVariable.getLow(); value <= metaVariable.getHigh(); ++value) {
+                result.setValue(metaVariableName, value, static_cast<double>(1));
+            }
             return result;
         }
         
-        Dd<CUDD> DdManager<CUDD>::getRange(std::string const metaVariableName) {
-            storm::dd::DdMetaVariable<CUDD> const& metaVariable = this->getMetaVariable(metaVariableName);
+        Dd<DdType::CUDD> DdManager<DdType::CUDD>::getIdentity(std::string const& metaVariableName) {
+            // Check whether the meta variable exists.
+            if (!this->hasMetaVariable(metaVariableName)) {
+                throw storm::exceptions::InvalidArgumentException() << "Unknown meta variable name '" << metaVariableName << "'.";
+            }
+            
+            storm::dd::DdMetaVariable<DdType::CUDD> const& metaVariable = this->getMetaVariable(metaVariableName);
             
-            Dd<CUDD> result = this->getZero();
+            Dd<DdType::CUDD> result = this->getZero();
             for (int_fast64_t value = metaVariable.getLow(); value <= metaVariable.getHigh(); ++value) {
-                result.setValue(metaVariableName, value - metaVariable.getLow(), static_cast<double>(value));
+                result.setValue(metaVariableName, value, static_cast<double>(value));
             }
             return result;
         }
 
-        void DdManager<CUDD>::addMetaVariable(std::string const& name, int_fast64_t low, int_fast64_t high) {
+        void DdManager<DdType::CUDD>::addMetaVariable(std::string const& name, int_fast64_t low, int_fast64_t high) {
             // Check whether a meta variable already exists.
             if (this->hasMetaVariable(name)) {
                 throw storm::exceptions::InvalidArgumentException() << "A meta variable '" << name << "' already exists.";
@@ -68,15 +102,15 @@ namespace storm {
             
             std::size_t numberOfBits = static_cast<std::size_t>(std::ceil(std::log2(high - low + 1)));
             
-            std::vector<Dd<CUDD>> variables;
+            std::vector<Dd<DdType::CUDD>> variables;
             for (std::size_t i = 0; i < numberOfBits; ++i) {
-                variables.emplace_back(Dd<CUDD>(this->shared_from_this(), cuddManager.addVar(), {name}));
+                variables.emplace_back(Dd<DdType::CUDD>(this->shared_from_this(), cuddManager.addVar(), {name}));
             }
             
-            metaVariableMap.emplace(name, DdMetaVariable<CUDD>(name, low, high, variables, this->shared_from_this()));
+            metaVariableMap.emplace(name, DdMetaVariable<DdType::CUDD>(name, low, high, variables, this->shared_from_this()));
         }
         
-        void DdManager<CUDD>::addMetaVariablesInterleaved(std::vector<std::string> const& names, int_fast64_t low, int_fast64_t high) {
+        void DdManager<DdType::CUDD>::addMetaVariablesInterleaved(std::vector<std::string> const& names, int_fast64_t low, int_fast64_t high) {
             // Make sure that at least one meta variable is added.
             if (names.size() == 0) {
                 throw storm::exceptions::InvalidArgumentException() << "Illegal to add zero meta variables.";
@@ -103,30 +137,30 @@ namespace storm {
             
             // Add the variables in interleaved order.
             std::size_t numberOfBits = static_cast<std::size_t>(std::ceil(std::log2(high - low + 1)));
-            std::vector<std::vector<Dd<CUDD>>> variables(names.size());
+            std::vector<std::vector<Dd<DdType::CUDD>>> variables(names.size());
             for (uint_fast64_t bit = 0; bit < numberOfBits; ++bit) {
                 for (uint_fast64_t i = 0; i < names.size(); ++i) {
-                    variables[i].emplace_back(Dd<CUDD>(this->shared_from_this(), cuddManager.addVar(), {names[i]}));
+                    variables[i].emplace_back(Dd<DdType::CUDD>(this->shared_from_this(), cuddManager.addVar(), {names[i]}));
                 }
             }
             
             // Now add the meta variables.
             for (uint_fast64_t i = 0; i < names.size(); ++i) {
-                metaVariableMap.emplace(names[i], DdMetaVariable<CUDD>(names[i], low, high, variables[i], this->shared_from_this()));
+                metaVariableMap.emplace(names[i], DdMetaVariable<DdType::CUDD>(names[i], low, high, variables[i], this->shared_from_this()));
             }
         }
         
-        DdMetaVariable<CUDD> const& DdManager<CUDD>::getMetaVariable(std::string const& metaVariableName) const {
+        DdMetaVariable<DdType::CUDD> const& DdManager<DdType::CUDD>::getMetaVariable(std::string const& metaVariableName) const {
             auto const& nameVariablePair = metaVariableMap.find(metaVariableName);
             
             if (!this->hasMetaVariable(metaVariableName)) {
-                throw storm::exceptions::InvalidArgumentException() << "Unknown meta variable name.";
+                throw storm::exceptions::InvalidArgumentException() << "Unknown meta variable name '" << metaVariableName << "'.";
             }
             
             return nameVariablePair->second;
         }
         
-        std::set<std::string> DdManager<CUDD>::getAllMetaVariableNames() const {
+        std::set<std::string> DdManager<DdType::CUDD>::getAllMetaVariableNames() const {
             std::set<std::string> result;
             for (auto const& nameValuePair : metaVariableMap) {
                 result.insert(nameValuePair.first);
@@ -134,15 +168,15 @@ namespace storm {
             return result;
         }
         
-        std::size_t DdManager<CUDD>::getNumberOfMetaVariables() const {
+        std::size_t DdManager<DdType::CUDD>::getNumberOfMetaVariables() const {
             return this->metaVariableMap.size();
         }
         
-        bool DdManager<CUDD>::hasMetaVariable(std::string const& metaVariableName) const {
+        bool DdManager<DdType::CUDD>::hasMetaVariable(std::string const& metaVariableName) const {
             return this->metaVariableMap.find(metaVariableName) != this->metaVariableMap.end();
         }
         
-        Cudd& DdManager<CUDD>::getCuddManager() {
+        Cudd& DdManager<DdType::CUDD>::getCuddManager() {
             return this->cuddManager;
         }
     }
diff --git a/src/storage/dd/CuddDdManager.h b/src/storage/dd/CuddDdManager.h
index 1d0d32a99..ca3f9c2c3 100644
--- a/src/storage/dd/CuddDdManager.h
+++ b/src/storage/dd/CuddDdManager.h
@@ -14,10 +14,10 @@
 namespace storm {
     namespace dd {
         template<>
-        class DdManager<CUDD> : public std::enable_shared_from_this<DdManager<CUDD>> {
+        class DdManager<DdType::CUDD> : public std::enable_shared_from_this<DdManager<DdType::CUDD>> {
         public:
             // To break the cylic dependencies, we need to forward-declare the other DD-related classes.
-            friend class Dd<CUDD>;
+            friend class Dd<DdType::CUDD>;
             
             /*!
              * Creates an empty manager without any meta variables.
@@ -25,11 +25,11 @@ namespace storm {
             DdManager();
             
             // Explictly forbid copying a DdManager, but allow moving it.
-            DdManager(DdManager<CUDD> const& other) = delete;
-			DdManager<CUDD>& operator=(DdManager<CUDD> const& other) = delete;
+            DdManager(DdManager<DdType::CUDD> const& other) = delete;
+			DdManager<DdType::CUDD>& operator=(DdManager<DdType::CUDD> const& other) = delete;
 #ifndef WINDOWS
-            DdManager(DdManager<CUDD>&& other) = default;
-            DdManager<CUDD>& operator=(DdManager<CUDD>&& other) = default;
+            DdManager(DdManager<DdType::CUDD>&& other) = default;
+            DdManager<DdType::CUDD>& operator=(DdManager<DdType::CUDD>&& other) = default;
 #endif
             
             /*!
@@ -37,21 +37,21 @@ namespace storm {
              *
              * @return A DD representing the constant one function.
              */
-            Dd<CUDD> getOne();
+            Dd<DdType::CUDD> getOne();
             
             /*!
              * Retrieves a DD representing the constant zero function.
              *
              * @return A DD representing the constant zero function.
              */
-            Dd<CUDD> getZero();
+            Dd<DdType::CUDD> getZero();
             
             /*!
              * Retrieves a DD representing the constant function with the given value.
              *
              * @return A DD representing the constant function with the given value.
              */
-            Dd<CUDD> getConstant(double value);
+            Dd<DdType::CUDD> getConstant(double value);
             
             /*!
              * Retrieves the DD representing the function that maps all inputs which have the given meta variable equal
@@ -62,16 +62,25 @@ namespace storm {
              * @return The DD representing the function that maps all inputs which have the given meta variable equal
              * to the given value one.
              */
-            Dd<CUDD> getEncoding(std::string const& metaVariableName, int_fast64_t value);
+            Dd<DdType::CUDD> getEncoding(std::string const& metaVariableName, int_fast64_t value);
             
             /*!
              * Retrieves the DD 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 metaVariableName The name of the meta variable whose range to retrieve.
-             * @return The range of the meta variable
+             * @return The range of the meta variable.
              */
-            Dd<CUDD> getRange(std::string const metaVariableName);
+            Dd<DdType::CUDD> getRange(std::string const& metaVariableName);
+
+            /*!
+             * Retrieves the DD 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 metaVariableName The name of the meta variable whose identity to retrieve.
+             * @return The identity of the meta variable.
+             */
+            Dd<DdType::CUDD> getIdentity(std::string const& metaVariableName);
             
             /*!
              * Adds a meta variable with the given name and range.
@@ -97,7 +106,7 @@ namespace storm {
              * @param metaVariableName The name of the meta variable to retrieve.
              * @return The meta variable with the given name.
              */
-            DdMetaVariable<CUDD> const& getMetaVariable(std::string const& metaVariableName) const;
+            DdMetaVariable<DdType::CUDD> const& getMetaVariable(std::string const& metaVariableName) const;
             
             /*!
              * Retrieves the names of all meta variables that have been added to the manager.
@@ -130,7 +139,7 @@ namespace storm {
             Cudd& getCuddManager();
             
             // A mapping from variable names to the meta variable information.
-            std::unordered_map<std::string, DdMetaVariable<CUDD>> metaVariableMap;
+            std::unordered_map<std::string, DdMetaVariable<DdType::CUDD>> metaVariableMap;
             
             // The manager responsible for the DDs created/modified with this DdManager.
             Cudd cuddManager;
diff --git a/src/storage/dd/DdMetaVariable.cpp b/src/storage/dd/DdMetaVariable.cpp
index 7671289fc..9132eab03 100644
--- a/src/storage/dd/DdMetaVariable.cpp
+++ b/src/storage/dd/DdMetaVariable.cpp
@@ -47,6 +47,6 @@ namespace storm {
         }
         
         // Explicitly instantiate DdMetaVariable.
-        template class DdMetaVariable<CUDD>;
+        template class DdMetaVariable<DdType::CUDD>;
     }
 }
\ No newline at end of file
diff --git a/src/storage/dd/DdType.h b/src/storage/dd/DdType.h
index 327832ec5..feb2fe70a 100644
--- a/src/storage/dd/DdType.h
+++ b/src/storage/dd/DdType.h
@@ -3,7 +3,7 @@
 
 namespace storm {
     namespace dd {
-        enum DdType {
+        enum class DdType {
             CUDD
         };
     }
diff --git a/src/storage/expressions/BaseExpression.cpp b/src/storage/expressions/BaseExpression.cpp
new file mode 100644
index 000000000..b9734a9ad
--- /dev/null
+++ b/src/storage/expressions/BaseExpression.cpp
@@ -0,0 +1,65 @@
+#include "src/storage/expressions/BaseExpression.h"
+#include "src/exceptions/ExceptionMacros.h"
+#include "src/exceptions/InvalidTypeException.h"
+
+namespace storm {
+    namespace expressions {        
+        BaseExpression::BaseExpression(ExpressionReturnType returnType) : returnType(returnType) {
+            // Intentionally left empty.
+        }
+
+        ExpressionReturnType BaseExpression::getReturnType() const {
+            return this->returnType;
+        }
+        
+        bool BaseExpression::hasIntegralReturnType() const {
+            return this->getReturnType() == ExpressionReturnType::Int;
+        }
+        
+        bool BaseExpression::hasNumericalReturnType() const {
+            return this->getReturnType() == ExpressionReturnType::Double || this->getReturnType() == ExpressionReturnType::Int;
+        }
+        
+        bool BaseExpression::hasBooleanReturnType() const {
+            return this->getReturnType() == ExpressionReturnType::Bool;
+        }
+        
+        int_fast64_t BaseExpression::evaluateAsInt(Valuation const* valuation) const {
+            LOG_THROW(false, storm::exceptions::InvalidTypeException, "Unable to evaluate expression as integer.");
+        }
+        
+        bool BaseExpression::evaluateAsBool(Valuation const* valuation) const {
+            LOG_THROW(false, storm::exceptions::InvalidTypeException, "Unable to evaluate expression as boolean.");
+        }
+        
+        double BaseExpression::evaluateAsDouble(Valuation const* valuation) const {
+            LOG_THROW(false, storm::exceptions::InvalidTypeException, "Unable to evaluate expression as double.");
+        }
+        
+        bool BaseExpression::isConstant() const {
+            return false;
+        }
+
+        bool BaseExpression::isTrue() const {
+            return false;
+        }
+
+        bool BaseExpression::isFalse() const {
+            return false;
+        }
+        
+        std::shared_ptr<BaseExpression const> BaseExpression::getSharedPointer() const {
+            return this->shared_from_this();
+        }
+        
+        std::ostream& operator<<(std::ostream& stream, ExpressionReturnType const& enumValue) {
+            stream << static_cast<std::underlying_type<ExpressionReturnType>::type>(enumValue);
+            return stream;
+        }
+        
+        std::ostream& operator<<(std::ostream& stream, BaseExpression const& expression) {
+            expression.printToStream(stream);
+            return stream;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/expressions/BaseExpression.h b/src/storage/expressions/BaseExpression.h
new file mode 100644
index 000000000..fb3df4514
--- /dev/null
+++ b/src/storage/expressions/BaseExpression.h
@@ -0,0 +1,176 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_BASEEXPRESSION_H_
+#define STORM_STORAGE_EXPRESSIONS_BASEEXPRESSION_H_
+
+#include <cstdint>
+#include <memory>
+#include <set>
+#include <iostream>
+
+#include "src/storage/expressions/Valuation.h"
+#include "src/storage/expressions/ExpressionVisitor.h"
+#include "src/exceptions/InvalidArgumentException.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace expressions {
+        /*!
+         * Each node in an expression tree has a uniquely defined type from this enum.
+         */
+        enum class ExpressionReturnType {Undefined, Bool, Int, Double};
+        
+        std::ostream& operator<<(std::ostream& stream, ExpressionReturnType const& enumValue);
+        
+        /*!
+         * The base class of all expression classes.
+         */
+        class BaseExpression : public std::enable_shared_from_this<BaseExpression> {
+        public:
+            /*!
+             * Constructs a base expression with the given return type.
+             *
+             * @param returnType The return type of the expression.
+             */
+            BaseExpression(ExpressionReturnType returnType);
+            
+            // Create default versions of constructors and assignments.
+            BaseExpression(BaseExpression const&) = default;
+            BaseExpression& operator=(BaseExpression const&) = default;
+#ifndef WINDOWS
+            BaseExpression(BaseExpression&&) = default;
+            BaseExpression& operator=(BaseExpression&&) = default;
+#endif
+            
+            // Make the destructor virtual (to allow destruction via base class pointer) and default it.
+            virtual ~BaseExpression() = default;
+            
+            /*!
+             * Evaluates the expression under the valuation of unknowns (variables and constants) given by the
+             * valuation and returns the resulting boolean value. If the return type of the expression is not a boolean
+             * an exception is thrown.
+             *
+             * @param valuation The valuation of unknowns under which to evaluate the expression.
+             * @return The boolean value of the expression under the given valuation.
+             */
+            virtual bool evaluateAsBool(Valuation const* valuation = nullptr) const;
+
+            /*!
+             * Evaluates the expression under the valuation of unknowns (variables and constants) given by the
+             * valuation and returns the resulting integer value. If the return type of the expression is not an integer
+             * an exception is thrown.
+             *
+             * @param valuation The valuation of unknowns under which to evaluate the expression.
+             * @return The integer value of the expression under the given valuation.
+             */
+            virtual int_fast64_t evaluateAsInt(Valuation const* valuation = nullptr) const;
+            
+            /*!
+             * Evaluates the expression under the valuation of unknowns (variables and constants) given by the
+             * valuation and returns the resulting double value. If the return type of the expression is not a double
+             * an exception is thrown.
+             *
+             * @param valuation The valuation of unknowns under which to evaluate the expression.
+             * @return The double value of the expression under the given valuation.
+             */
+            virtual double evaluateAsDouble(Valuation const* valuation = nullptr) const;
+
+            /*!
+             * Retrieves whether the expression is constant, i.e., contains no variables or undefined constants.
+             *
+             * @return True iff the expression is constant.
+             */
+            virtual bool isConstant() const;
+            
+            /*!
+             * Checks if the expression is equal to the boolean literal true.
+             *
+             * @return True iff the expression is equal to the boolean literal true.
+             */
+            virtual bool isTrue() const;
+            
+            /*!
+             * Checks if the expression is equal to the boolean literal false.
+             *
+             * @return True iff the expression is equal to the boolean literal false.
+             */
+            virtual bool isFalse() const;
+            
+            /*!
+             * Retrieves the set of all variables that appear in the expression.
+             *
+             * @return The set of all variables that appear in the expression.
+             */
+            virtual std::set<std::string> getVariables() const = 0;
+            
+            /*!
+             * Retrieves the set of all constants that appear in the expression.
+             *
+             * @return The set of all constants that appear in the expression.
+             */
+            virtual std::set<std::string> getConstants() const = 0;
+            
+            /*!
+             * Simplifies the expression according to some simple rules.
+             *
+             * @return A pointer to the simplified expression.
+             */
+            virtual std::shared_ptr<BaseExpression const> simplify() const = 0;
+            
+            /*!
+             * Accepts the given visitor by calling its visit method.
+             *
+             * @param visitor The visitor that is to be accepted.
+             */
+            virtual void accept(ExpressionVisitor* visitor) const = 0;
+            
+            /*!
+             * Retrieves whether the expression has a numerical return type, i.e., integer or double.
+             *
+             * @return True iff the expression has a numerical return type.
+             */
+            bool hasNumericalReturnType() const;
+            
+            /*!
+             * Retrieves whether the expression has an integral return type, i.e., integer.
+             *
+             * @return True iff the expression has an integral return type.
+             */
+            bool hasIntegralReturnType() const;
+            
+            /*!
+             * Retrieves whether the expression has a boolean return type.
+             *
+             * @return True iff the expression has a boolean return type.
+             */
+            bool hasBooleanReturnType() const;
+            
+            /*!
+             * Retrieves a shared pointer to this expression.
+             *
+             * @return A shared pointer to this expression.
+             */
+            std::shared_ptr<BaseExpression const> getSharedPointer() const;
+            
+            /*!
+             * Retrieves the return type of the expression.
+             *
+             * @return The return type of the expression.
+             */
+            ExpressionReturnType getReturnType() const;
+            
+            friend std::ostream& operator<<(std::ostream& stream, BaseExpression const& expression);
+        protected:
+            /*!
+             * Prints the expression to the given stream.
+             *
+             * @param stream The stream to which to write the expression.
+             */
+            virtual void printToStream(std::ostream& stream) const = 0;
+            
+        private:
+            // The return type of this expression.
+            ExpressionReturnType returnType;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_BASEEXPRESSION_H_ */
\ No newline at end of file
diff --git a/src/storage/expressions/BinaryBooleanFunctionExpression.cpp b/src/storage/expressions/BinaryBooleanFunctionExpression.cpp
new file mode 100644
index 000000000..9f5e5edeb
--- /dev/null
+++ b/src/storage/expressions/BinaryBooleanFunctionExpression.cpp
@@ -0,0 +1,97 @@
+#include "src/storage/expressions/BinaryBooleanFunctionExpression.h"
+#include "src/storage/expressions/BooleanLiteralExpression.h"
+#include "src/exceptions/ExceptionMacros.h"
+#include "src/exceptions/InvalidTypeException.h"
+
+namespace storm {
+    namespace expressions {
+        BinaryBooleanFunctionExpression::BinaryBooleanFunctionExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& firstOperand, std::shared_ptr<BaseExpression const> const& secondOperand, OperatorType operatorType) : BinaryExpression(returnType, firstOperand, secondOperand), operatorType(operatorType) {
+            // Intentionally left empty.
+        }
+        
+        BinaryBooleanFunctionExpression::OperatorType BinaryBooleanFunctionExpression::getOperatorType() const {
+            return this->operatorType;
+        }
+        
+        bool BinaryBooleanFunctionExpression::evaluateAsBool(Valuation const* valuation) const {
+            LOG_THROW(this->hasBooleanReturnType(), storm::exceptions::InvalidTypeException, "Unable to evaluate expression as boolean.");
+            
+            bool firstOperandEvaluation = this->getFirstOperand()->evaluateAsBool(valuation);
+            bool secondOperandEvaluation = this->getSecondOperand()->evaluateAsBool(valuation);
+            
+            bool result;
+            switch (this->getOperatorType()) {
+                case OperatorType::And: result = firstOperandEvaluation && secondOperandEvaluation; break;
+                case OperatorType::Or: result = firstOperandEvaluation || secondOperandEvaluation; break;
+                case OperatorType::Implies: result = !firstOperandEvaluation || secondOperandEvaluation; break;
+                case OperatorType::Iff: result = (firstOperandEvaluation && secondOperandEvaluation) || (!firstOperandEvaluation && !secondOperandEvaluation); break;
+            }
+            
+            return result;
+        }
+        
+        std::shared_ptr<BaseExpression const> BinaryBooleanFunctionExpression::simplify() const {
+            std::shared_ptr<BaseExpression const> firstOperandSimplified = this->getFirstOperand()->simplify();
+            std::shared_ptr<BaseExpression const> secondOperandSimplified = this->getSecondOperand()->simplify();
+            
+            switch (this->getOperatorType()) {
+                case OperatorType::And: if (firstOperandSimplified->isTrue()) {
+                    return secondOperandSimplified;
+                } else if (firstOperandSimplified->isFalse()) {
+                    return firstOperandSimplified;
+                } else if (secondOperandSimplified->isTrue()) {
+                    return firstOperandSimplified;
+                } else if (secondOperandSimplified->isFalse()) {
+                    return secondOperandSimplified;
+                }
+                break;
+                case OperatorType::Or: if (firstOperandSimplified->isTrue()) {
+                    return firstOperandSimplified;
+                } else if (firstOperandSimplified->isFalse()) {
+                    return secondOperandSimplified;
+                } else if (secondOperandSimplified->isTrue()) {
+                    return secondOperandSimplified;
+                } else if (secondOperandSimplified->isFalse()) {
+                    return firstOperandSimplified;
+                }
+                break;
+                case OperatorType::Implies: if (firstOperandSimplified->isTrue()) {
+                    return secondOperandSimplified;
+                } else if (firstOperandSimplified->isFalse()) {
+                    return std::shared_ptr<BaseExpression>(new BooleanLiteralExpression(true));
+                } else if (secondOperandSimplified->isTrue()) {
+                    return std::shared_ptr<BaseExpression>(new BooleanLiteralExpression(true));
+                }
+                break;
+                case OperatorType::Iff: if (firstOperandSimplified->isTrue() && secondOperandSimplified->isTrue()) {
+                    return std::shared_ptr<BaseExpression>(new BooleanLiteralExpression(true));
+                } else if (firstOperandSimplified->isFalse() && secondOperandSimplified->isFalse()) {
+                    return std::shared_ptr<BaseExpression>(new BooleanLiteralExpression(true));
+                }
+                break;
+            }
+            
+            // If the two successors remain unchanged, we can return a shared_ptr to this very object.
+            if (firstOperandSimplified.get() == this->getFirstOperand().get() && secondOperandSimplified.get() == this->getSecondOperand().get()) {
+                return this->shared_from_this();
+            } else {
+                return std::shared_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(this->getReturnType(), firstOperandSimplified, secondOperandSimplified, this->getOperatorType()));
+            }
+        }
+        
+        void BinaryBooleanFunctionExpression::accept(ExpressionVisitor* visitor) const {
+            visitor->visit(this);
+        }
+        
+        void BinaryBooleanFunctionExpression::printToStream(std::ostream& stream) const {
+            stream << "(" << *this->getFirstOperand();
+            switch (this->getOperatorType()) {
+                case OperatorType::And: stream << " & "; break;
+                case OperatorType::Or: stream << " | "; break;
+                case OperatorType::Implies: stream << " => "; break;
+                case OperatorType::Iff: stream << " <=> "; break;
+            }
+            stream << *this->getSecondOperand() << ")";
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/expressions/BinaryBooleanFunctionExpression.h b/src/storage/expressions/BinaryBooleanFunctionExpression.h
new file mode 100644
index 000000000..7a05a1ab5
--- /dev/null
+++ b/src/storage/expressions/BinaryBooleanFunctionExpression.h
@@ -0,0 +1,58 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_BINARYBOOLEANFUNCTIONEXPRESSION_H_
+#define STORM_STORAGE_EXPRESSIONS_BINARYBOOLEANFUNCTIONEXPRESSION_H_
+
+#include "src/storage/expressions/BinaryExpression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace expressions {
+        class BinaryBooleanFunctionExpression : public BinaryExpression {
+        public:
+            /*!
+             * An enum type specifying the different operators applicable.
+             */
+            enum class OperatorType {And, Or, Implies, Iff};
+            
+            /*!
+             * Creates a binary boolean function expression with the given return type, operands and operator.
+             *
+             * @param returnType The return type of the expression.
+             * @param firstOperand The first operand of the expression.
+             * @param secondOperand The second operand of the expression.
+             * @param functionType The operator of the expression.
+             */
+            BinaryBooleanFunctionExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& firstOperand, std::shared_ptr<BaseExpression const> const& secondOperand, OperatorType operatorType);
+            
+            // Instantiate constructors and assignments with their default implementations.
+            BinaryBooleanFunctionExpression(BinaryBooleanFunctionExpression const& other) = default;
+            BinaryBooleanFunctionExpression& operator=(BinaryBooleanFunctionExpression const& other) = default;
+#ifndef WINDOWS
+            BinaryBooleanFunctionExpression(BinaryBooleanFunctionExpression&&) = default;
+            BinaryBooleanFunctionExpression& operator=(BinaryBooleanFunctionExpression&&) = default;
+#endif
+            virtual ~BinaryBooleanFunctionExpression() = default;
+            
+            // Override base class methods.
+            virtual bool evaluateAsBool(Valuation const* valuation = nullptr) const override;
+            virtual std::shared_ptr<BaseExpression const> simplify() const override;
+            virtual void accept(ExpressionVisitor* visitor) const override;
+
+            /*!
+             * Retrieves the operator associated with the expression.
+             *
+             * @return The operator associated with the expression.
+             */
+            OperatorType getOperatorType() const;
+            
+        protected:
+            // Override base class method.
+            virtual void printToStream(std::ostream& stream) const override;
+
+        private:
+            // The operator of the expression.
+            OperatorType operatorType;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_BINARYBOOLEANFUNCTIONEXPRESSION_H_ */
\ No newline at end of file
diff --git a/src/storage/expressions/BinaryExpression.cpp b/src/storage/expressions/BinaryExpression.cpp
new file mode 100644
index 000000000..cfd18447c
--- /dev/null
+++ b/src/storage/expressions/BinaryExpression.cpp
@@ -0,0 +1,35 @@
+#include "src/storage/expressions/BinaryExpression.h"
+
+namespace storm {
+    namespace expressions {
+        BinaryExpression::BinaryExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& firstOperand, std::shared_ptr<BaseExpression const> const& secondOperand) : BaseExpression(returnType), firstOperand(firstOperand), secondOperand(secondOperand) {
+            // Intentionally left empty.
+        }
+                
+        bool BinaryExpression::isConstant() const {
+            return this->getFirstOperand()->isConstant() && this->getSecondOperand()->isConstant();
+        }
+        
+        std::set<std::string> BinaryExpression::getVariables() const {
+            std::set<std::string> firstVariableSet = this->getFirstOperand()->getVariables();
+            std::set<std::string> secondVariableSet = this->getSecondOperand()->getVariables();
+            firstVariableSet.insert(secondVariableSet.begin(), secondVariableSet.end());
+            return firstVariableSet;
+        }
+        
+        std::set<std::string> BinaryExpression::getConstants() const {
+            std::set<std::string> firstConstantSet = this->getFirstOperand()->getVariables();
+            std::set<std::string> secondConstantSet = this->getSecondOperand()->getVariables();
+            firstConstantSet.insert(secondConstantSet.begin(), secondConstantSet.end());
+            return firstConstantSet;
+        }
+        
+        std::shared_ptr<BaseExpression const> const& BinaryExpression::getFirstOperand() const {
+            return this->firstOperand;
+        }
+        
+        std::shared_ptr<BaseExpression const> const& BinaryExpression::getSecondOperand() const {
+            return this->secondOperand;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/expressions/BinaryExpression.h b/src/storage/expressions/BinaryExpression.h
new file mode 100644
index 000000000..640297a91
--- /dev/null
+++ b/src/storage/expressions/BinaryExpression.h
@@ -0,0 +1,61 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_BINARYEXPRESSION_H_
+#define STORM_STORAGE_EXPRESSIONS_BINARYEXPRESSION_H_
+
+#include "src/storage/expressions/BaseExpression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace expressions {
+        /*!
+         * The base class of all binary expressions.
+         */
+        class BinaryExpression : public BaseExpression {
+        public:
+            /*!
+             * Constructs a binary expression with the given return type and operands.
+             *
+             * @param returnType The return type of the expression.
+             * @param firstOperand The first operand of the expression.
+             * @param secondOperand The second operand of the expression.
+             */
+            BinaryExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& firstOperand, std::shared_ptr<BaseExpression const> const& secondOperand);
+            
+            // Instantiate constructors and assignments with their default implementations.
+            BinaryExpression(BinaryExpression const& other) = default;
+            BinaryExpression& operator=(BinaryExpression const& other) = default;
+#ifndef WINDOWS
+            BinaryExpression(BinaryExpression&&) = default;
+            BinaryExpression& operator=(BinaryExpression&&) = default;
+#endif
+            virtual ~BinaryExpression() = default;
+
+            // Override base class methods.
+            virtual bool isConstant() const override;
+            virtual std::set<std::string> getVariables() const override;
+            virtual std::set<std::string> getConstants() const override;
+            
+            /*!
+             * Retrieves the first operand of the expression.
+             *
+             * @return The first operand of the expression.
+             */
+            std::shared_ptr<BaseExpression const> const& getFirstOperand() const;
+            
+            /*!
+             * Retrieves the second operand of the expression.
+             *
+             * @return The second operand of the expression.
+             */
+            std::shared_ptr<BaseExpression const> const& getSecondOperand() const;
+
+        private:
+            // The first operand of the expression.
+            std::shared_ptr<BaseExpression const> firstOperand;
+            
+            // The second operand of the expression.
+            std::shared_ptr<BaseExpression const> secondOperand;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_BINARYEXPRESSION_H_ */
\ No newline at end of file
diff --git a/src/storage/expressions/BinaryNumericalFunctionExpression.cpp b/src/storage/expressions/BinaryNumericalFunctionExpression.cpp
new file mode 100644
index 000000000..225bea963
--- /dev/null
+++ b/src/storage/expressions/BinaryNumericalFunctionExpression.cpp
@@ -0,0 +1,75 @@
+#include <algorithm>
+
+#include "src/storage/expressions/BinaryNumericalFunctionExpression.h"
+#include "src/exceptions/ExceptionMacros.h"
+#include "src/exceptions/InvalidTypeException.h"
+
+namespace storm {
+    namespace expressions {
+        BinaryNumericalFunctionExpression::BinaryNumericalFunctionExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& firstOperand, std::shared_ptr<BaseExpression const> const& secondOperand, OperatorType operatorType) : BinaryExpression(returnType, firstOperand, secondOperand), operatorType(operatorType) {
+            // Intentionally left empty.
+        }
+        
+        BinaryNumericalFunctionExpression::OperatorType BinaryNumericalFunctionExpression::getOperatorType() const {
+            return this->operatorType;
+        }
+        
+        int_fast64_t BinaryNumericalFunctionExpression::evaluateAsInt(Valuation const* valuation) const {
+            LOG_THROW(this->hasIntegralReturnType(), storm::exceptions::InvalidTypeException, "Unable to evaluate expression as integer.");
+            
+            int_fast64_t firstOperandEvaluation = this->getFirstOperand()->evaluateAsInt(valuation);
+            int_fast64_t secondOperandEvaluation = this->getSecondOperand()->evaluateAsInt(valuation);
+            switch (this->getOperatorType()) {
+                case OperatorType::Plus: return firstOperandEvaluation + secondOperandEvaluation; break;
+                case OperatorType::Minus: return firstOperandEvaluation - secondOperandEvaluation; break;
+                case OperatorType::Times: return firstOperandEvaluation * secondOperandEvaluation; break;
+                case OperatorType::Divide: return firstOperandEvaluation / secondOperandEvaluation; break;
+                case OperatorType::Min: return std::min(firstOperandEvaluation, secondOperandEvaluation); break;
+                case OperatorType::Max: return std::max(firstOperandEvaluation, secondOperandEvaluation); break;
+            }
+        }
+        
+        double BinaryNumericalFunctionExpression::evaluateAsDouble(Valuation const* valuation) const {
+            LOG_THROW(this->hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Unable to evaluate expression as double.");
+            
+            double firstOperandEvaluation = this->getFirstOperand()->evaluateAsDouble(valuation);
+            double secondOperandEvaluation = this->getSecondOperand()->evaluateAsDouble(valuation);
+            switch (this->getOperatorType()) {
+                case OperatorType::Plus: return static_cast<double>(firstOperandEvaluation + secondOperandEvaluation); break;
+                case OperatorType::Minus: return static_cast<double>(firstOperandEvaluation - secondOperandEvaluation); break;
+                case OperatorType::Times: return static_cast<double>(firstOperandEvaluation * secondOperandEvaluation); break;
+                case OperatorType::Divide: return static_cast<double>(firstOperandEvaluation / secondOperandEvaluation); break;
+                case OperatorType::Min: return static_cast<double>(std::min(firstOperandEvaluation, secondOperandEvaluation)); break;
+                case OperatorType::Max: return static_cast<double>(std::max(firstOperandEvaluation, secondOperandEvaluation)); break;
+            }
+        }
+        
+        std::shared_ptr<BaseExpression const> BinaryNumericalFunctionExpression::simplify() const {
+            std::shared_ptr<BaseExpression const> firstOperandSimplified = this->getFirstOperand()->simplify();
+            std::shared_ptr<BaseExpression const> secondOperandSimplified = this->getSecondOperand()->simplify();
+            
+            if (firstOperandSimplified.get() == this->getFirstOperand().get() && secondOperandSimplified.get() == this->getSecondOperand().get()) {
+                return this->shared_from_this();
+            } else {
+                return std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(this->getReturnType(), firstOperandSimplified, secondOperandSimplified, this->getOperatorType()));
+            }
+        }
+        
+        void BinaryNumericalFunctionExpression::accept(ExpressionVisitor* visitor) const {
+            visitor->visit(this);
+        }
+        
+        void BinaryNumericalFunctionExpression::printToStream(std::ostream& stream) const {
+            stream << "(";
+            switch (this->getOperatorType()) {
+                case OperatorType::Plus: stream << *this->getFirstOperand() << " + " << *this->getSecondOperand(); break;
+                case OperatorType::Minus: stream << *this->getFirstOperand() << " - " << *this->getSecondOperand(); break;
+                case OperatorType::Times: stream << *this->getFirstOperand() << " * " << *this->getSecondOperand(); break;
+                case OperatorType::Divide: stream << *this->getFirstOperand() << " / " << *this->getSecondOperand(); break;
+                case OperatorType::Min: stream << "min(" << *this->getFirstOperand() << ", " << *this->getSecondOperand() << ")"; break;
+                case OperatorType::Max: stream << "max(" << *this->getFirstOperand() << ", " << *this->getSecondOperand() << ")"; break;
+            }
+            stream << ")";
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/expressions/BinaryNumericalFunctionExpression.h b/src/storage/expressions/BinaryNumericalFunctionExpression.h
new file mode 100644
index 000000000..4e8573a4c
--- /dev/null
+++ b/src/storage/expressions/BinaryNumericalFunctionExpression.h
@@ -0,0 +1,59 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_BINARYNUMERICALFUNCTIONEXPRESSION_H_
+#define STORM_STORAGE_EXPRESSIONS_BINARYNUMERICALFUNCTIONEXPRESSION_H_
+
+#include "src/storage/expressions/BinaryExpression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace expressions {
+        class BinaryNumericalFunctionExpression : public BinaryExpression {
+        public:
+            /*!
+             * An enum type specifying the different operators applicable.
+             */
+            enum class OperatorType {Plus, Minus, Times, Divide, Min, Max};
+            
+            /*!
+             * Constructs a binary numerical function expression with the given return type, operands and operator.
+             *
+             * @param returnType The return type of the expression.
+             * @param firstOperand The first operand of the expression.
+             * @param secondOperand The second operand of the expression.
+             * @param functionType The operator of the expression.
+             */
+            BinaryNumericalFunctionExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& firstOperand, std::shared_ptr<BaseExpression const> const& secondOperand, OperatorType operatorType);
+            
+            // Instantiate constructors and assignments with their default implementations.
+            BinaryNumericalFunctionExpression(BinaryNumericalFunctionExpression const& other) = default;
+            BinaryNumericalFunctionExpression& operator=(BinaryNumericalFunctionExpression const& other) = default;
+#ifndef WINDOWS
+            BinaryNumericalFunctionExpression(BinaryNumericalFunctionExpression&&) = default;
+            BinaryNumericalFunctionExpression& operator=(BinaryNumericalFunctionExpression&&) = default;
+#endif
+            virtual ~BinaryNumericalFunctionExpression() = default;
+            
+            // Override base class methods.
+            virtual int_fast64_t evaluateAsInt(Valuation const* valuation = nullptr) const override;
+            virtual double evaluateAsDouble(Valuation const* valuation = nullptr) const override;
+            virtual std::shared_ptr<BaseExpression const> simplify() const override;
+            virtual void accept(ExpressionVisitor* visitor) const override;
+
+            /*!
+             * Retrieves the operator associated with the expression.
+             *
+             * @return The operator associated with the expression.
+             */
+            OperatorType getOperatorType() const;
+            
+        protected:
+            // Override base class method.
+            virtual void printToStream(std::ostream& stream) const override;
+
+        private:
+            // The operator of the expression.
+            OperatorType operatorType;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_BINARYNUMERICALFUNCTIONEXPRESSION_H_ */
\ No newline at end of file
diff --git a/src/storage/expressions/BinaryRelationExpression.cpp b/src/storage/expressions/BinaryRelationExpression.cpp
new file mode 100644
index 000000000..7e48c2286
--- /dev/null
+++ b/src/storage/expressions/BinaryRelationExpression.cpp
@@ -0,0 +1,59 @@
+#include "src/storage/expressions/BinaryRelationExpression.h"
+
+#include "src/exceptions/ExceptionMacros.h"
+#include "src/exceptions/InvalidTypeException.h"
+
+namespace storm {
+    namespace expressions {
+        BinaryRelationExpression::BinaryRelationExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& firstOperand, std::shared_ptr<BaseExpression const> const& secondOperand, RelationType relationType) : BinaryExpression(returnType, firstOperand, secondOperand), relationType(relationType) {
+            // Intentionally left empty.
+        }
+                
+        bool BinaryRelationExpression::evaluateAsBool(Valuation const* valuation) const {
+            LOG_THROW(this->hasBooleanReturnType(), storm::exceptions::InvalidTypeException, "Unable to evaluate expression as boolean.");
+
+            double firstOperandEvaluated = this->getFirstOperand()->evaluateAsDouble(valuation);
+            double secondOperandEvaluated = this->getSecondOperand()->evaluateAsDouble(valuation);
+            switch (this->getRelationType()) {
+                case RelationType::Equal: return firstOperandEvaluated == secondOperandEvaluated; break;
+                case RelationType::NotEqual: return firstOperandEvaluated != secondOperandEvaluated; break;
+                case RelationType::Greater: return firstOperandEvaluated > secondOperandEvaluated; break;
+                case RelationType::GreaterOrEqual: return firstOperandEvaluated >= secondOperandEvaluated; break;
+                case RelationType::Less: return firstOperandEvaluated < secondOperandEvaluated; break;
+                case RelationType::LessOrEqual: return firstOperandEvaluated <= secondOperandEvaluated; break;
+            }
+        }
+        
+        std::shared_ptr<BaseExpression const> BinaryRelationExpression::simplify() const {
+            std::shared_ptr<BaseExpression const> firstOperandSimplified = this->getFirstOperand()->simplify();
+            std::shared_ptr<BaseExpression const> secondOperandSimplified = this->getSecondOperand()->simplify();
+            
+            if (firstOperandSimplified.get() == this->getFirstOperand().get() && secondOperandSimplified.get() == this->getSecondOperand().get()) {
+                return this->shared_from_this();
+            } else {
+                return std::shared_ptr<BaseExpression>(new BinaryRelationExpression(this->getReturnType(), firstOperandSimplified, secondOperandSimplified, this->getRelationType()));
+            }
+        }
+        
+        void BinaryRelationExpression::accept(ExpressionVisitor* visitor) const {
+            visitor->visit(this);
+        }
+        
+        BinaryRelationExpression::RelationType BinaryRelationExpression::getRelationType() const {
+            return this->relationType;
+        }
+        
+        void BinaryRelationExpression::printToStream(std::ostream& stream) const {
+            stream << "(" << *this->getFirstOperand();
+            switch (this->getRelationType()) {
+                case RelationType::Equal: stream << " = "; break;
+                case RelationType::NotEqual: stream << " != "; break;
+                case RelationType::Greater: stream << " > "; break;
+                case RelationType::GreaterOrEqual: stream << " >= "; break;
+                case RelationType::Less: stream << " < "; break;
+                case RelationType::LessOrEqual: stream << " <= "; break;
+            }
+            stream << *this->getSecondOperand() << ")";
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/expressions/BinaryRelationExpression.h b/src/storage/expressions/BinaryRelationExpression.h
new file mode 100644
index 000000000..b88ef71f9
--- /dev/null
+++ b/src/storage/expressions/BinaryRelationExpression.h
@@ -0,0 +1,58 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_BINARYRELATIONEXPRESSION_H_
+#define STORM_STORAGE_EXPRESSIONS_BINARYRELATIONEXPRESSION_H_
+
+#include "src/storage/expressions/BinaryExpression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace expressions {
+        class BinaryRelationExpression : public BinaryExpression {
+        public:
+            /*!
+             * An enum type specifying the different relations applicable.
+             */
+            enum class RelationType {Equal, NotEqual, Less, LessOrEqual, Greater, GreaterOrEqual};
+            
+            /*!
+             * Creates a binary relation expression with the given return type, operands and relation type.
+             *
+             * @param returnType The return type of the expression.
+             * @param firstOperand The first operand of the expression.
+             * @param secondOperand The second operand of the expression.
+             * @param relationType The operator of the expression.
+             */
+            BinaryRelationExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& firstOperand, std::shared_ptr<BaseExpression const> const& secondOperand, RelationType relationType);
+            
+            // Instantiate constructors and assignments with their default implementations.
+            BinaryRelationExpression(BinaryRelationExpression const& other) = default;
+            BinaryRelationExpression& operator=(BinaryRelationExpression const& other) = default;
+#ifndef WINDOWS
+            BinaryRelationExpression(BinaryRelationExpression&&) = default;
+            BinaryRelationExpression& operator=(BinaryRelationExpression&&) = default;
+#endif
+            virtual ~BinaryRelationExpression() = default;
+            
+            // Override base class methods.
+            virtual bool evaluateAsBool(Valuation const* valuation = nullptr) const override;
+            virtual std::shared_ptr<BaseExpression const> simplify() const override;
+            virtual void accept(ExpressionVisitor* visitor) const override;
+
+            /*!
+             * Retrieves the relation associated with the expression.
+             *
+             * @return The relation associated with the expression.
+             */
+            RelationType getRelationType() const;
+            
+        protected:
+            // Override base class method.
+            virtual void printToStream(std::ostream& stream) const override;
+
+        private:
+            // The relation type of the expression.
+            RelationType relationType;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_BINARYRELATIONEXPRESSION_H_ */
\ No newline at end of file
diff --git a/src/storage/expressions/BooleanConstantExpression.cpp b/src/storage/expressions/BooleanConstantExpression.cpp
new file mode 100644
index 000000000..de87dab48
--- /dev/null
+++ b/src/storage/expressions/BooleanConstantExpression.cpp
@@ -0,0 +1,23 @@
+#include "src/storage/expressions/BooleanConstantExpression.h"
+#include "src/exceptions/ExceptionMacros.h"
+
+namespace storm {
+    namespace expressions {
+        BooleanConstantExpression::BooleanConstantExpression(std::string const& constantName) : ConstantExpression(ExpressionReturnType::Bool, constantName) {
+            // Intentionally left empty.
+        }
+                
+        bool BooleanConstantExpression::evaluateAsBool(Valuation const* valuation) const {
+            LOG_ASSERT(valuation != nullptr, "Evaluating expressions with unknowns without valuation.");
+            return valuation->getBooleanValue(this->getConstantName());
+        }
+        
+        void BooleanConstantExpression::accept(ExpressionVisitor* visitor) const {
+            visitor->visit(this);
+        }
+        
+        std::shared_ptr<BaseExpression const> BooleanConstantExpression::simplify() const {
+            return this->shared_from_this();
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/expressions/BooleanConstantExpression.h b/src/storage/expressions/BooleanConstantExpression.h
new file mode 100644
index 000000000..dd204d7a5
--- /dev/null
+++ b/src/storage/expressions/BooleanConstantExpression.h
@@ -0,0 +1,35 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_BOOLEANCONSTANTEXPRESSION_H_
+#define STORM_STORAGE_EXPRESSIONS_BOOLEANCONSTANTEXPRESSION_H_
+
+#include "src/storage/expressions/ConstantExpression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace expressions {
+        class BooleanConstantExpression : public ConstantExpression {
+        public:
+            /*!
+             * Creates a boolean constant expression with the given constant name.
+             *
+             * @param constantName The name of the boolean constant associated with this expression.
+             */
+            BooleanConstantExpression(std::string const& constantName);
+            
+            // Instantiate constructors and assignments with their default implementations.
+            BooleanConstantExpression(BooleanConstantExpression const& other) = default;
+            BooleanConstantExpression& operator=(BooleanConstantExpression const& other) = default;
+#ifndef WINDOWS
+            BooleanConstantExpression(BooleanConstantExpression&&) = default;
+            BooleanConstantExpression& operator=(BooleanConstantExpression&&) = default;
+#endif
+            virtual ~BooleanConstantExpression() = default;
+            
+            // Override base class methods.
+            virtual bool evaluateAsBool(Valuation const* valuation = nullptr) const override;
+            virtual void accept(ExpressionVisitor* visitor) const override;
+            virtual std::shared_ptr<BaseExpression const> simplify() const override;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_BOOLEANCONSTANTEXPRESSION_H_ */
diff --git a/src/storage/expressions/BooleanLiteralExpression.cpp b/src/storage/expressions/BooleanLiteralExpression.cpp
new file mode 100644
index 000000000..6ef15fe83
--- /dev/null
+++ b/src/storage/expressions/BooleanLiteralExpression.cpp
@@ -0,0 +1,49 @@
+#include "src/storage/expressions/BooleanLiteralExpression.h"
+
+namespace storm {
+    namespace expressions {
+        BooleanLiteralExpression::BooleanLiteralExpression(bool value) : BaseExpression(ExpressionReturnType::Bool), value(value) {
+            // Intentionally left empty.
+        }
+        
+        bool BooleanLiteralExpression::evaluateAsBool(Valuation const* valuation) const {
+            return this->getValue();
+        }
+        
+        bool BooleanLiteralExpression::isConstant() const {
+            return true;
+        }
+        
+        bool BooleanLiteralExpression::isTrue() const {
+            return this->getValue() == true;
+        }
+        
+        bool BooleanLiteralExpression::isFalse() const {
+            return this->getValue() == false;
+        }
+        
+        std::set<std::string> BooleanLiteralExpression::getVariables() const {
+            return std::set<std::string>();
+        }
+        
+        std::set<std::string> BooleanLiteralExpression::getConstants() const {
+            return std::set<std::string>();
+        }
+        
+        std::shared_ptr<BaseExpression const> BooleanLiteralExpression::simplify() const {
+            return this->shared_from_this();
+        }
+        
+        void BooleanLiteralExpression::accept(ExpressionVisitor* visitor) const {
+            visitor->visit(this);
+        }
+        
+        bool BooleanLiteralExpression::getValue() const {
+            return this->value;
+        }
+        
+        void BooleanLiteralExpression::printToStream(std::ostream& stream) const {
+            stream << (this->getValue() ? "true" : "false");
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/expressions/BooleanLiteralExpression.h b/src/storage/expressions/BooleanLiteralExpression.h
new file mode 100644
index 000000000..6c0413236
--- /dev/null
+++ b/src/storage/expressions/BooleanLiteralExpression.h
@@ -0,0 +1,55 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_BOOLEANLITERALEXPRESSION_H_
+#define STORM_STORAGE_EXPRESSIONS_BOOLEANLITERALEXPRESSION_H_
+
+#include "src/storage/expressions/BaseExpression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace expressions {
+        class BooleanLiteralExpression : public BaseExpression {
+        public:
+            /*!
+             * Creates a boolean literal expression with the given value.
+             *
+             * @param value The value of the boolean literal.
+             */
+            BooleanLiteralExpression(bool value);
+            
+            // Instantiate constructors and assignments with their default implementations.
+            BooleanLiteralExpression(BooleanLiteralExpression const& other) = default;
+            BooleanLiteralExpression& operator=(BooleanLiteralExpression const& other) = default;
+#ifndef WINDOWS
+            BooleanLiteralExpression(BooleanLiteralExpression&&) = default;
+            BooleanLiteralExpression& operator=(BooleanLiteralExpression&&) = default;
+#endif
+            virtual ~BooleanLiteralExpression() = default;
+
+            // Override base class methods.
+            virtual bool evaluateAsBool(Valuation const* valuation = nullptr) const override;
+            virtual bool isConstant() const override;
+            virtual bool isTrue() const override;
+            virtual bool isFalse() const override;
+            virtual std::set<std::string> getVariables() const override;
+            virtual std::set<std::string> getConstants() const override;
+            virtual std::shared_ptr<BaseExpression const> simplify() const override;
+            virtual void accept(ExpressionVisitor* visitor) const override;
+            
+            /*!
+             * Retrieves the value of the boolean literal.
+             *
+             * @return The value of the boolean literal.
+             */
+            bool getValue() const;
+            
+        protected:
+            // Override base class method.
+            virtual void printToStream(std::ostream& stream) const override;
+            
+        private:
+            // The value of the boolean literal.
+            bool value;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_BOOLEANLITERALEXPRESSION_H_ */
\ No newline at end of file
diff --git a/src/storage/expressions/ConstantExpression.cpp b/src/storage/expressions/ConstantExpression.cpp
new file mode 100644
index 000000000..d09a75573
--- /dev/null
+++ b/src/storage/expressions/ConstantExpression.cpp
@@ -0,0 +1,25 @@
+#include "src/storage/expressions/ConstantExpression.h"
+
+namespace storm {
+    namespace expressions {
+        ConstantExpression::ConstantExpression(ExpressionReturnType returnType, std::string const& constantName) : BaseExpression(returnType), constantName(constantName) {
+            // Intentionally left empty.
+        }
+        
+        std::set<std::string> ConstantExpression::getVariables() const {
+            return std::set<std::string>();
+        }
+        
+        std::set<std::string> ConstantExpression::getConstants() const {
+            return {this->getConstantName()};
+        }
+        
+        std::string const& ConstantExpression::getConstantName() const {
+            return this->constantName;
+        }
+        
+        void ConstantExpression::printToStream(std::ostream& stream) const {
+            stream << this->getConstantName();
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/expressions/ConstantExpression.h b/src/storage/expressions/ConstantExpression.h
new file mode 100644
index 000000000..50f00c235
--- /dev/null
+++ b/src/storage/expressions/ConstantExpression.h
@@ -0,0 +1,50 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_CONSTANTEXPRESSION_H_
+#define STORM_STORAGE_EXPRESSIONS_CONSTANTEXPRESSION_H_
+
+#include "src/storage/expressions/BaseExpression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace expressions {
+        class ConstantExpression : public BaseExpression {
+        public:
+            /*!
+             * Creates a constant expression with the given return type and constant name.
+             *
+             * @param returnType The return type of the expression.
+             * @param constantName The name of the constant associated with this expression.
+             */
+            ConstantExpression(ExpressionReturnType returnType, std::string const& constantName);
+            
+            // Instantiate constructors and assignments with their default implementations.
+            ConstantExpression(ConstantExpression const& other) = default;
+            ConstantExpression& operator=(ConstantExpression const& other) = default;
+#ifndef WINDOWS
+            ConstantExpression(ConstantExpression&&) = default;
+            ConstantExpression& operator=(ConstantExpression&&) = default;
+#endif
+            virtual ~ConstantExpression() = default;
+            
+            // Override base class methods.
+            virtual std::set<std::string> getVariables() const override;
+            virtual std::set<std::string> getConstants() const override;
+            
+            /*!
+             * Retrieves the name of the constant.
+             *
+             * @return The name of the constant.
+             */
+            std::string const& getConstantName() const;
+
+        protected:
+            // Override base class method.
+            virtual void printToStream(std::ostream& stream) const override;
+            
+        private:
+            // The name of the constant.
+            std::string constantName;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_CONSTANTEXPRESSION_H_ */
diff --git a/src/storage/expressions/DoubleConstantExpression.cpp b/src/storage/expressions/DoubleConstantExpression.cpp
new file mode 100644
index 000000000..e7d541975
--- /dev/null
+++ b/src/storage/expressions/DoubleConstantExpression.cpp
@@ -0,0 +1,23 @@
+#include "src/storage/expressions/DoubleConstantExpression.h"
+#include "src/exceptions/ExceptionMacros.h"
+
+namespace storm {
+    namespace expressions {
+        DoubleConstantExpression::DoubleConstantExpression(std::string const& constantName) : ConstantExpression(ExpressionReturnType::Double, constantName) {
+            // Intentionally left empty.
+        }
+        
+        double DoubleConstantExpression::evaluateAsDouble(Valuation const* valuation) const {
+            LOG_ASSERT(valuation != nullptr, "Evaluating expressions with unknowns without valuation.");
+            return valuation->getDoubleValue(this->getConstantName());
+        }
+        
+        std::shared_ptr<BaseExpression const> DoubleConstantExpression::simplify() const {
+            return this->shared_from_this();
+        }
+        
+        void DoubleConstantExpression::accept(ExpressionVisitor* visitor) const {
+            visitor->visit(this);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/expressions/DoubleConstantExpression.h b/src/storage/expressions/DoubleConstantExpression.h
new file mode 100644
index 000000000..b271bf6db
--- /dev/null
+++ b/src/storage/expressions/DoubleConstantExpression.h
@@ -0,0 +1,35 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_DOUBLECONSTANTEXPRESSION_H_
+#define STORM_STORAGE_EXPRESSIONS_DOUBLECONSTANTEXPRESSION_H_
+
+#include "src/storage/expressions/ConstantExpression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace expressions {
+        class DoubleConstantExpression : public ConstantExpression {
+        public:
+            /*!
+             * Creates a double constant expression with the given constant name.
+             *
+             * @param constantName The name of the double constant associated with this expression.
+             */
+            DoubleConstantExpression(std::string const& constantName);
+            
+            // Instantiate constructors and assignments with their default implementations.
+            DoubleConstantExpression(DoubleConstantExpression const& other) = default;
+            DoubleConstantExpression& operator=(DoubleConstantExpression const& other) = default;
+#ifndef WINDOWS
+            DoubleConstantExpression(DoubleConstantExpression&&) = default;
+            DoubleConstantExpression& operator=(DoubleConstantExpression&&) = default;
+#endif
+            virtual ~DoubleConstantExpression() = default;
+            
+            // Override base class methods.
+            virtual double evaluateAsDouble(Valuation const* valuation = nullptr) const override;
+            virtual void accept(ExpressionVisitor* visitor) const override;
+            virtual std::shared_ptr<BaseExpression const> simplify() const override;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_DOUBLECONSTANTEXPRESSION_H_ */
diff --git a/src/storage/expressions/DoubleLiteralExpression.cpp b/src/storage/expressions/DoubleLiteralExpression.cpp
new file mode 100644
index 000000000..642a1817f
--- /dev/null
+++ b/src/storage/expressions/DoubleLiteralExpression.cpp
@@ -0,0 +1,41 @@
+#include "src/storage/expressions/DoubleLiteralExpression.h"
+
+namespace storm {
+    namespace expressions {
+        DoubleLiteralExpression::DoubleLiteralExpression(double value) : BaseExpression(ExpressionReturnType::Double), value(value) {
+            // Intentionally left empty.
+        }
+        
+        double DoubleLiteralExpression::evaluateAsDouble(Valuation const* valuation) const {
+            return this->getValue();
+        }
+        
+        bool DoubleLiteralExpression::isConstant() const {
+            return true;
+        }
+        
+        std::set<std::string> DoubleLiteralExpression::getVariables() const {
+            return std::set<std::string>();
+        }
+        
+        std::set<std::string> DoubleLiteralExpression::getConstants() const {
+            return std::set<std::string>();
+        }
+        
+        std::shared_ptr<BaseExpression const> DoubleLiteralExpression::simplify() const {
+            return this->shared_from_this();
+        }
+        
+        void DoubleLiteralExpression::accept(ExpressionVisitor* visitor) const {
+            visitor->visit(this);
+        }
+        
+        double DoubleLiteralExpression::getValue() const {
+            return this->value;
+        }
+        
+        void DoubleLiteralExpression::printToStream(std::ostream& stream) const {
+            stream << this->getValue();
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/expressions/DoubleLiteralExpression.h b/src/storage/expressions/DoubleLiteralExpression.h
new file mode 100644
index 000000000..e4bc28b81
--- /dev/null
+++ b/src/storage/expressions/DoubleLiteralExpression.h
@@ -0,0 +1,53 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_DOUBLELITERALEXPRESSION_H_
+#define STORM_STORAGE_EXPRESSIONS_DOUBLELITERALEXPRESSION_H_
+
+#include "src/storage/expressions/BaseExpression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace expressions {
+        class DoubleLiteralExpression : public BaseExpression {
+        public:
+            /*!
+             * Creates an double literal expression with the given value.
+             *
+             * @param value The value of the double literal.
+             */
+            DoubleLiteralExpression(double value);
+            
+            // Instantiate constructors and assignments with their default implementations.
+            DoubleLiteralExpression(DoubleLiteralExpression const& other) = default;
+            DoubleLiteralExpression& operator=(DoubleLiteralExpression const& other) = default;
+#ifndef WINDOWS
+            DoubleLiteralExpression(DoubleLiteralExpression&&) = default;
+            DoubleLiteralExpression& operator=(DoubleLiteralExpression&&) = default;
+#endif
+            virtual ~DoubleLiteralExpression() = default;
+            
+            // Override base class methods.
+            virtual double evaluateAsDouble(Valuation const* valuation = nullptr) const override;
+            virtual bool isConstant() const override;
+            virtual std::set<std::string> getVariables() const override;
+            virtual std::set<std::string> getConstants() const override;
+            virtual std::shared_ptr<BaseExpression const> simplify() const override;
+            virtual void accept(ExpressionVisitor* visitor) const override;
+
+            /*!
+             * Retrieves the value of the double literal.
+             *
+             * @return The value of the double literal.
+             */
+            double getValue() const;
+            
+        protected:
+            // Override base class method.
+            virtual void printToStream(std::ostream& stream) const override;
+            
+        private:
+            // The value of the double literal.
+            double value;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_DOUBLELITERALEXPRESSION_H_ */
\ No newline at end of file
diff --git a/src/storage/expressions/Expression.cpp b/src/storage/expressions/Expression.cpp
new file mode 100644
index 000000000..7eb94966b
--- /dev/null
+++ b/src/storage/expressions/Expression.cpp
@@ -0,0 +1,260 @@
+#include <map>
+#include <unordered_map>
+
+#include "src/storage/expressions/Expression.h"
+#include "src/storage/expressions/SubstitutionVisitor.h"
+#include "src/storage/expressions/IdentifierSubstitutionVisitor.h"
+#include "src/exceptions/InvalidTypeException.h"
+#include "src/exceptions/ExceptionMacros.h"
+
+#include "src/storage/expressions/IfThenElseExpression.h"
+#include "src/storage/expressions/BinaryBooleanFunctionExpression.h"
+#include "src/storage/expressions/BinaryNumericalFunctionExpression.h"
+#include "src/storage/expressions/BinaryRelationExpression.h"
+#include "src/storage/expressions/BooleanConstantExpression.h"
+#include "src/storage/expressions/IntegerConstantExpression.h"
+#include "src/storage/expressions/DoubleConstantExpression.h"
+#include "src/storage/expressions/BooleanLiteralExpression.h"
+#include "src/storage/expressions/IntegerLiteralExpression.h"
+#include "src/storage/expressions/DoubleLiteralExpression.h"
+#include "src/storage/expressions/VariableExpression.h"
+#include "src/storage/expressions/UnaryBooleanFunctionExpression.h"
+#include "src/storage/expressions/UnaryNumericalFunctionExpression.h"
+
+namespace storm {
+    namespace expressions {
+        Expression::Expression(std::shared_ptr<BaseExpression const> const& expressionPtr) : expressionPtr(expressionPtr) {
+            // Intentionally left empty.
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        Expression Expression::substitute(MapType<std::string, Expression> const& identifierToExpressionMap) const {
+            return SubstitutionVisitor<MapType>(identifierToExpressionMap).substitute(this->getBaseExpressionPointer().get());
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        Expression Expression::substitute(MapType<std::string, std::string> const& identifierToIdentifierMap) const {
+            return IdentifierSubstitutionVisitor<MapType>(identifierToIdentifierMap).substitute(this->getBaseExpressionPointer().get());
+        }
+        
+        bool Expression::evaluateAsBool(Valuation const* valuation) const {
+            return this->getBaseExpression().evaluateAsBool(valuation);
+        }
+        
+        int_fast64_t Expression::evaluateAsInt(Valuation const* valuation) const {
+            return this->getBaseExpression().evaluateAsInt(valuation);
+        }
+        
+        double Expression::evaluateAsDouble(Valuation const* valuation) const {
+            return this->getBaseExpression().evaluateAsDouble(valuation);
+        }
+        
+        Expression Expression::simplify() {
+            return Expression(this->getBaseExpression().simplify());
+        }
+        
+        bool Expression::isConstant() const {
+            return this->getBaseExpression().isConstant();
+        }
+        
+        bool Expression::isTrue() const {
+            return this->getBaseExpression().isTrue();
+        }
+        
+        bool Expression::isFalse() const {
+            return this->getBaseExpression().isFalse();
+        }
+        
+        std::set<std::string> Expression::getVariables() const {
+            return this->getBaseExpression().getVariables();
+        }
+        
+        std::set<std::string> Expression::getConstants() const {
+            return this->getBaseExpression().getConstants();
+        }
+        
+        BaseExpression const& Expression::getBaseExpression() const {
+            return *this->expressionPtr;
+        }
+        
+        std::shared_ptr<BaseExpression const> const& Expression::getBaseExpressionPointer() const {
+            return this->expressionPtr;
+        }
+        
+        ExpressionReturnType Expression::getReturnType() const {
+            return this->getBaseExpression().getReturnType();
+        }
+        
+        bool Expression::hasNumericalReturnType() const {
+            return this->getReturnType() == ExpressionReturnType::Int || this->getReturnType() == ExpressionReturnType::Double;
+        }
+        
+        bool Expression::hasBooleanReturnType() const {
+            return this->getReturnType() == ExpressionReturnType::Bool;
+        }
+        
+        Expression Expression::createBooleanLiteral(bool value) {
+            return Expression(std::shared_ptr<BaseExpression>(new BooleanLiteralExpression(value)));
+        }
+        
+        Expression Expression::createTrue() {
+            return createBooleanLiteral(true);
+        }
+        
+        Expression Expression::createFalse() {
+            return createBooleanLiteral(false);
+        }
+        
+        Expression Expression::createIntegerLiteral(int_fast64_t value) {
+            return Expression(std::shared_ptr<BaseExpression>(new IntegerLiteralExpression(value)));
+        }
+        
+        Expression Expression::createDoubleLiteral(double value) {
+            return Expression(std::shared_ptr<BaseExpression>(new DoubleLiteralExpression(value)));
+        }
+        
+        Expression Expression::createBooleanVariable(std::string const& variableName) {
+            return Expression(std::shared_ptr<BaseExpression>(new VariableExpression(ExpressionReturnType::Bool, variableName)));
+        }
+        
+        Expression Expression::createIntegerVariable(std::string const& variableName) {
+            return Expression(std::shared_ptr<BaseExpression>(new VariableExpression(ExpressionReturnType::Int, variableName)));
+        }
+        
+        Expression Expression::createDoubleVariable(std::string const& variableName) {
+            return Expression(std::shared_ptr<BaseExpression>(new VariableExpression(ExpressionReturnType::Double, variableName)));
+        }
+        
+        Expression Expression::createUndefinedVariable(std::string const& variableName) {
+            return Expression(std::shared_ptr<BaseExpression>(new VariableExpression(ExpressionReturnType::Undefined, variableName)));
+        }
+        
+        Expression Expression::createBooleanConstant(std::string const& constantName) {
+            return Expression(std::shared_ptr<BaseExpression>(new BooleanConstantExpression(constantName)));
+        }
+        
+        Expression Expression::createIntegerConstant(std::string const& constantName) {
+            return Expression(std::shared_ptr<BaseExpression>(new IntegerConstantExpression(constantName)));
+        }
+        
+        Expression Expression::createDoubleConstant(std::string const& constantName) {
+            return Expression(std::shared_ptr<BaseExpression>(new DoubleConstantExpression(constantName)));
+        }
+        
+        Expression Expression::operator+(Expression const& other) const {
+            LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '+' requires numerical operands.");
+            return Expression(std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(this->getReturnType() == ExpressionReturnType::Int && other.getReturnType() == ExpressionReturnType::Int ? ExpressionReturnType::Int : ExpressionReturnType::Double, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryNumericalFunctionExpression::OperatorType::Plus)));
+        }
+        
+        Expression Expression::operator-(Expression const& other) const {
+            LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '-' requires numerical operands.");
+            return Expression(std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(this->getReturnType() == ExpressionReturnType::Int && other.getReturnType() == ExpressionReturnType::Int ? ExpressionReturnType::Int : ExpressionReturnType::Double, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryNumericalFunctionExpression::OperatorType::Minus)));
+        }
+        
+        Expression Expression::operator-() const {
+            LOG_THROW(this->hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '-' requires numerical operand.");
+            return Expression(std::shared_ptr<BaseExpression>(new UnaryNumericalFunctionExpression(this->getReturnType(), this->getBaseExpressionPointer(), UnaryNumericalFunctionExpression::OperatorType::Minus)));
+        }
+        
+        Expression Expression::operator*(Expression const& other) const {
+            LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '*' requires numerical operands.");
+            return Expression(std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(this->getReturnType() == ExpressionReturnType::Int && other.getReturnType() == ExpressionReturnType::Int ? ExpressionReturnType::Int : ExpressionReturnType::Double, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryNumericalFunctionExpression::OperatorType::Times)));
+        }
+        
+        Expression Expression::operator/(Expression const& other) const {
+            LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '/' requires numerical operands.");
+            return Expression(std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(this->getReturnType() == ExpressionReturnType::Int && other.getReturnType() == ExpressionReturnType::Int ? ExpressionReturnType::Int : ExpressionReturnType::Double, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryNumericalFunctionExpression::OperatorType::Divide)));
+        }
+        
+        Expression Expression::operator&&(Expression const& other) const {
+            LOG_THROW(this->hasBooleanReturnType() && other.hasBooleanReturnType(), storm::exceptions::InvalidTypeException, "Operator '&&' requires boolean operands.");
+            return Expression(std::shared_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryBooleanFunctionExpression::OperatorType::And)));
+        }
+        
+        Expression Expression::operator||(Expression const& other) const {
+            LOG_THROW(this->hasBooleanReturnType() && other.hasBooleanReturnType(), storm::exceptions::InvalidTypeException, "Operator '||' requires numerical operands.");
+            return Expression(std::shared_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryBooleanFunctionExpression::OperatorType::Or)));
+        }
+        
+        Expression Expression::operator!() const {
+            LOG_THROW(this->hasBooleanReturnType(), storm::exceptions::InvalidTypeException, "Operator '!' requires boolean operand.");
+            return Expression(std::shared_ptr<BaseExpression>(new UnaryBooleanFunctionExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), UnaryBooleanFunctionExpression::OperatorType::Not)));
+        }
+        
+        Expression Expression::operator==(Expression const& other) const {
+            LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '==' requires numerical operands.");
+            return Expression(std::shared_ptr<BaseExpression>(new BinaryRelationExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryRelationExpression::RelationType::Equal)));
+        }
+        
+        Expression Expression::operator!=(Expression const& other) const {
+            LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '!=' requires numerical operands.");
+            return Expression(std::shared_ptr<BaseExpression>(new BinaryRelationExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryRelationExpression::RelationType::NotEqual)));
+        }
+        
+        Expression Expression::operator>(Expression const& other) const {
+            LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '>' requires numerical operands.");
+            return Expression(std::shared_ptr<BaseExpression>(new BinaryRelationExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryRelationExpression::RelationType::Greater)));
+        }
+        
+        Expression Expression::operator>=(Expression const& other) const {
+            LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '>=' requires numerical operands.");
+            return Expression(std::shared_ptr<BaseExpression>(new BinaryRelationExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryRelationExpression::RelationType::GreaterOrEqual)));
+        }
+        
+        Expression Expression::operator<(Expression const& other) const {
+            LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '<' requires numerical operands.");
+            return Expression(std::shared_ptr<BaseExpression>(new BinaryRelationExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryRelationExpression::RelationType::Less)));
+        }
+        
+        Expression Expression::operator<=(Expression const& other) const {
+            LOG_THROW(this->hasNumericalReturnType() && other.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator '<=' requires numerical operands.");
+            return Expression(std::shared_ptr<BaseExpression>(new BinaryRelationExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryRelationExpression::RelationType::LessOrEqual)));
+        }
+        
+        Expression Expression::minimum(Expression const& lhs, Expression const& rhs) {
+            LOG_THROW(lhs.hasNumericalReturnType() && rhs.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator 'min' requires numerical operands.");
+            return Expression(std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(lhs.getReturnType() == ExpressionReturnType::Int && rhs.getReturnType() == ExpressionReturnType::Int ? ExpressionReturnType::Int : ExpressionReturnType::Double, lhs.getBaseExpressionPointer(), rhs.getBaseExpressionPointer(), BinaryNumericalFunctionExpression::OperatorType::Min)));
+        }
+        
+        Expression Expression::maximum(Expression const& lhs, Expression const& rhs) {
+            LOG_THROW(lhs.hasNumericalReturnType() && rhs.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator 'max' requires numerical operands.");
+            return Expression(std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(lhs.getReturnType() == ExpressionReturnType::Int && rhs.getReturnType() == ExpressionReturnType::Int ? ExpressionReturnType::Int : ExpressionReturnType::Double, lhs.getBaseExpressionPointer(), rhs.getBaseExpressionPointer(), BinaryNumericalFunctionExpression::OperatorType::Max)));
+        }
+        
+        Expression Expression::ite(Expression const& thenExpression, Expression const& elseExpression) {
+            LOG_THROW(this->hasBooleanReturnType(), storm::exceptions::InvalidTypeException, "Condition of if-then-else operator must be of boolean type.");
+            LOG_THROW(thenExpression.hasBooleanReturnType() && elseExpression.hasBooleanReturnType() || thenExpression.hasNumericalReturnType() && elseExpression.hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "'then' and 'else' expression of if-then-else operator must have equal return type.");
+            return Expression(std::shared_ptr<BaseExpression>(new IfThenElseExpression(thenExpression.hasBooleanReturnType() && elseExpression.hasBooleanReturnType() ? ExpressionReturnType::Bool : (thenExpression.getReturnType() == ExpressionReturnType::Int && elseExpression.getReturnType() == ExpressionReturnType::Int ? ExpressionReturnType::Int : ExpressionReturnType::Double), this->getBaseExpressionPointer(), thenExpression.getBaseExpressionPointer(), elseExpression.getBaseExpressionPointer())));
+        }
+        
+        Expression Expression::implies(Expression const& other) const {
+            LOG_THROW(this->hasBooleanReturnType() && other.hasBooleanReturnType(), storm::exceptions::InvalidTypeException, "Operator '&&' requires boolean operands.");
+            return Expression(std::shared_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryBooleanFunctionExpression::OperatorType::Implies)));
+        }
+        
+        Expression Expression::iff(Expression const& other) const {
+            LOG_THROW(this->hasBooleanReturnType() && other.hasBooleanReturnType(), storm::exceptions::InvalidTypeException, "Operator '&&' requires boolean operands.");
+            return Expression(std::shared_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(ExpressionReturnType::Bool, this->getBaseExpressionPointer(), other.getBaseExpressionPointer(), BinaryBooleanFunctionExpression::OperatorType::Iff)));
+        }
+        
+        Expression Expression::floor() const {
+            LOG_THROW(this->hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator 'floor' requires numerical operand.");
+            return Expression(std::shared_ptr<BaseExpression>(new UnaryNumericalFunctionExpression(ExpressionReturnType::Int, this->getBaseExpressionPointer(), UnaryNumericalFunctionExpression::OperatorType::Floor)));
+        }
+        
+        Expression Expression::ceil() const {
+            LOG_THROW(this->hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Operator 'ceil' requires numerical operand.");
+            return Expression(std::shared_ptr<BaseExpression>(new UnaryNumericalFunctionExpression(ExpressionReturnType::Int, this->getBaseExpressionPointer(), UnaryNumericalFunctionExpression::OperatorType::Ceil)));
+        }
+        
+        template Expression Expression::substitute<std::map>(std::map<std::string, storm::expressions::Expression> const&) const;
+        template Expression Expression::substitute<std::unordered_map>(std::unordered_map<std::string, storm::expressions::Expression> const&) const;
+        template Expression Expression::substitute<std::map>(std::map<std::string, std::string> const&) const;
+        template Expression Expression::substitute<std::unordered_map>(std::unordered_map<std::string, std::string> const&) const;
+        
+        std::ostream& operator<<(std::ostream& stream, Expression const& expression) {
+            stream << expression.getBaseExpression();
+            return stream;
+        }
+    }
+}
diff --git a/src/storage/expressions/Expression.h b/src/storage/expressions/Expression.h
new file mode 100644
index 000000000..ea7d99572
--- /dev/null
+++ b/src/storage/expressions/Expression.h
@@ -0,0 +1,209 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_EXPRESSION_H_
+#define STORM_STORAGE_EXPRESSIONS_EXPRESSION_H_
+
+#include <memory>
+
+#include "src/storage/expressions/BaseExpression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace expressions {
+        class Expression {
+        public:
+            Expression() = default;
+            
+            /*!
+             * Creates an expression with the given underlying base expression.
+             *
+             * @param expressionPtr A pointer to the underlying base expression.
+             */
+            Expression(std::shared_ptr<BaseExpression const> const& expressionPtr);
+            
+            // Instantiate constructors and assignments with their default implementations.
+            Expression(Expression const& other) = default;
+            Expression& operator=(Expression const& other) = default;
+#ifndef WINDOWS
+            Expression(Expression&&) = default;
+            Expression& operator=(Expression&&) = default;
+#endif
+            
+            // Static factory methods to create atomic expression parts.
+            static Expression createBooleanLiteral(bool value);
+            static Expression createTrue();
+            static Expression createFalse();
+            static Expression createIntegerLiteral(int_fast64_t value);
+            static Expression createDoubleLiteral(double value);
+            static Expression createBooleanVariable(std::string const& variableName);
+            static Expression createIntegerVariable(std::string const& variableName);
+            static Expression createDoubleVariable(std::string const& variableName);
+            static Expression createUndefinedVariable(std::string const& variableName);
+            static Expression createBooleanConstant(std::string const& constantName);
+            static Expression createIntegerConstant(std::string const& constantName);
+            static Expression createDoubleConstant(std::string const& constantName);
+            
+            // Provide operator overloads to conveniently construct new expressions from other expressions.
+            Expression operator+(Expression const& other) const;
+            Expression operator-(Expression const& other) const;
+            Expression operator-() const;
+            Expression operator*(Expression const& other) const;
+            Expression operator/(Expression const& other) const;
+            Expression operator&&(Expression const& other) const;
+            Expression operator||(Expression const& other) const;
+            Expression operator!() const;
+            Expression operator==(Expression const& other) const;
+            Expression operator!=(Expression const& other) const;
+            Expression operator>(Expression const& other) const;
+            Expression operator>=(Expression const& other) const;
+            Expression operator<(Expression const& other) const;
+            Expression operator<=(Expression const& other) const;
+            
+            Expression ite(Expression const& thenExpression, Expression const& elseExpression);
+            Expression implies(Expression const& other) const;
+            Expression iff(Expression const& other) const;
+            
+            Expression floor() const;
+            Expression ceil() const;
+
+            static Expression minimum(Expression const& lhs, Expression const& rhs);
+            static Expression maximum(Expression const& lhs, Expression const& rhs);
+            
+            /*!
+             * Substitutes all occurrences of identifiers according to the given map. Note that this substitution is
+             * done simultaneously, i.e., identifiers appearing in the expressions that were "plugged in" are not
+             * substituted.
+             *
+             * @param identifierToExpressionMap A mapping from identifiers to the expression they are substituted with.
+             * @return An expression in which all identifiers in the key set of the mapping are replaced by the
+             * expression they are mapped to.
+             */
+            template<template<typename... Arguments> class MapType>
+            Expression substitute(MapType<std::string, Expression> const& identifierToExpressionMap) const;
+            
+            /*!
+             * Substitutes all occurrences of identifiers with different names given by a mapping.
+             *
+             * @param identifierToIdentifierMap A mapping from identifiers to identifiers they are substituted with.
+             * @return An expression in which all identifiers in the key set of the mapping are replaced by the
+             * identifiers they are mapped to.
+             */
+            template<template<typename... Arguments> class MapType>
+            Expression substitute(MapType<std::string, std::string> const& identifierToIdentifierMap) const;
+            
+            /*!
+             * Evaluates the expression under the valuation of unknowns (variables and constants) given by the
+             * valuation and returns the resulting boolean value. If the return type of the expression is not a boolean
+             * an exception is thrown.
+             *
+             * @param valuation The valuation of unknowns under which to evaluate the expression.
+             * @return The boolean value of the expression under the given valuation.
+             */
+            bool evaluateAsBool(Valuation const* valuation = nullptr) const;
+            
+            /*!
+             * Evaluates the expression under the valuation of unknowns (variables and constants) given by the
+             * valuation and returns the resulting integer value. If the return type of the expression is not an integer
+             * an exception is thrown.
+             *
+             * @param valuation The valuation of unknowns under which to evaluate the expression.
+             * @return The integer value of the expression under the given valuation.
+             */
+            int_fast64_t evaluateAsInt(Valuation const* valuation = nullptr) const;
+            
+            /*!
+             * Evaluates the expression under the valuation of unknowns (variables and constants) given by the
+             * valuation and returns the resulting double value. If the return type of the expression is not a double
+             * an exception is thrown.
+             *
+             * @param valuation The valuation of unknowns under which to evaluate the expression.
+             * @return The double value of the expression under the given valuation.
+             */
+            double evaluateAsDouble(Valuation const* valuation = nullptr) const;
+            
+            /*!
+             * Simplifies the expression according to some basic rules.
+             *
+             * @return The simplified expression.
+             */
+            Expression simplify();
+            
+            /*!
+             * Retrieves whether the expression is constant, i.e., contains no variables or undefined constants.
+             *
+             * @return True iff the expression is constant.
+             */
+            bool isConstant() const;
+            
+            /*!
+             * Checks if the expression is equal to the boolean literal true.
+             *
+             * @return True iff the expression is equal to the boolean literal true.
+             */
+            bool isTrue() const;
+            
+            /*!
+             * Checks if the expression is equal to the boolean literal false.
+             *
+             * @return True iff the expression is equal to the boolean literal false.
+             */
+            bool isFalse() const;
+            
+            /*!
+             * Retrieves the set of all variables that appear in the expression.
+             *
+             * @return The set of all variables that appear in the expression.
+             */
+            std::set<std::string> getVariables() const;
+            
+            /*!
+             * Retrieves the set of all constants that appear in the expression.
+             *
+             * @return The set of all constants that appear in the expression.
+             */
+            std::set<std::string> getConstants() const;
+            
+            /*!
+             * Retrieves the base expression underlying this expression object. Note that prior to calling this, the
+             * expression object must be properly initialized.
+             *
+             * @return A reference to the underlying base expression.
+             */
+            BaseExpression const& getBaseExpression() const;
+            
+            /*!
+             * Retrieves a pointer to the base expression underlying this expression object.
+             *
+             * @return A pointer to the underlying base expression.
+             */
+            std::shared_ptr<BaseExpression const> const& getBaseExpressionPointer() const;
+
+            /*!
+             * Retrieves the return type of the expression.
+             *
+             * @return The return type of the expression.
+             */
+            ExpressionReturnType getReturnType() const;
+            
+            /*!
+             * Retrieves whether the expression has a numerical return type, i.e., integer or double.
+             *
+             * @return True iff the expression has a numerical return type.
+             */
+            bool hasNumericalReturnType() const;
+            
+            /*!
+             * Retrieves whether the expression has a boolean return type.
+             *
+             * @return True iff the expression has a boolean return type.
+             */
+            bool hasBooleanReturnType() const;
+            
+            friend std::ostream& operator<<(std::ostream& stream, Expression const& expression);
+
+        private:
+            // A pointer to the underlying base expression.
+            std::shared_ptr<BaseExpression const> expressionPtr;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_EXPRESSION_H_ */
\ No newline at end of file
diff --git a/src/storage/expressions/ExpressionVisitor.h b/src/storage/expressions/ExpressionVisitor.h
new file mode 100644
index 000000000..928e6297c
--- /dev/null
+++ b/src/storage/expressions/ExpressionVisitor.h
@@ -0,0 +1,41 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_EXPRESSIONVISITOR_H_
+#define STORM_STORAGE_EXPRESSIONS_EXPRESSIONVISITOR_H_
+
+namespace storm {
+    namespace expressions {
+        // Forward-declare all expression classes.
+        class IfThenElseExpression;
+        class BinaryBooleanFunctionExpression;
+        class BinaryNumericalFunctionExpression;
+        class BinaryRelationExpression;
+        class BooleanConstantExpression;
+        class DoubleConstantExpression;
+        class IntegerConstantExpression;
+        class IntegerConstantExpression;
+        class VariableExpression;
+        class UnaryBooleanFunctionExpression;
+        class UnaryNumericalFunctionExpression;
+        class BooleanLiteralExpression;
+        class IntegerLiteralExpression;
+        class DoubleLiteralExpression;
+        
+        class ExpressionVisitor {
+        public:
+            virtual void visit(IfThenElseExpression const* expression) = 0;
+            virtual void visit(BinaryBooleanFunctionExpression const* expression) = 0;
+            virtual void visit(BinaryNumericalFunctionExpression const* expression) = 0;
+            virtual void visit(BinaryRelationExpression const* expression) = 0;
+            virtual void visit(BooleanConstantExpression const* expression) = 0;
+            virtual void visit(DoubleConstantExpression const* expression) = 0;
+            virtual void visit(IntegerConstantExpression const* expression) = 0;
+            virtual void visit(VariableExpression const* expression) = 0;
+            virtual void visit(UnaryBooleanFunctionExpression const* expression) = 0;
+            virtual void visit(UnaryNumericalFunctionExpression const* expression) = 0;
+            virtual void visit(BooleanLiteralExpression const* expression) = 0;
+            virtual void visit(IntegerLiteralExpression const* expression) = 0;
+            virtual void visit(DoubleLiteralExpression const* expression) = 0;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_EXPRESSIONVISITOR_H_ */
\ No newline at end of file
diff --git a/src/storage/expressions/Expressions.h b/src/storage/expressions/Expressions.h
new file mode 100644
index 000000000..df8bbd8ed
--- /dev/null
+++ b/src/storage/expressions/Expressions.h
@@ -0,0 +1,14 @@
+#include "src/storage/expressions/IfThenElseExpression.h"
+#include "src/storage/expressions/BinaryBooleanFunctionExpression.h"
+#include "src/storage/expressions/BinaryNumericalFunctionExpression.h"
+#include "src/storage/expressions/BinaryRelationExpression.h"
+#include "src/storage/expressions/BooleanConstantExpression.h"
+#include "src/storage/expressions/BooleanLiteralExpression.h"
+#include "src/storage/expressions/DoubleConstantExpression.h"
+#include "src/storage/expressions/DoubleLiteralExpression.h"
+#include "src/storage/expressions/IntegerConstantExpression.h"
+#include "src/storage/expressions/IntegerLiteralExpression.h"
+#include "src/storage/expressions/UnaryBooleanFunctionExpression.h"
+#include "src/storage/expressions/UnaryNumericalFunctionExpression.h"
+#include "src/storage/expressions/VariableExpression.h"
+#include "src/storage/expressions/Expression.h"
\ No newline at end of file
diff --git a/src/storage/expressions/IdentifierSubstitutionVisitor.cpp b/src/storage/expressions/IdentifierSubstitutionVisitor.cpp
new file mode 100644
index 000000000..17161775a
--- /dev/null
+++ b/src/storage/expressions/IdentifierSubstitutionVisitor.cpp
@@ -0,0 +1,200 @@
+#include <map>
+#include <unordered_map>
+
+#include "src/storage/expressions/IdentifierSubstitutionVisitor.h"
+
+#include "src/storage/expressions/IfThenElseExpression.h"
+#include "src/storage/expressions/BinaryBooleanFunctionExpression.h"
+#include "src/storage/expressions/BinaryNumericalFunctionExpression.h"
+#include "src/storage/expressions/BinaryRelationExpression.h"
+#include "src/storage/expressions/BooleanConstantExpression.h"
+#include "src/storage/expressions/IntegerConstantExpression.h"
+#include "src/storage/expressions/DoubleConstantExpression.h"
+#include "src/storage/expressions/BooleanLiteralExpression.h"
+#include "src/storage/expressions/IntegerLiteralExpression.h"
+#include "src/storage/expressions/DoubleLiteralExpression.h"
+#include "src/storage/expressions/VariableExpression.h"
+#include "src/storage/expressions/UnaryBooleanFunctionExpression.h"
+#include "src/storage/expressions/UnaryNumericalFunctionExpression.h"
+
+namespace storm {
+    namespace expressions  {
+        template<template<typename... Arguments> class MapType>
+        IdentifierSubstitutionVisitor<MapType>::IdentifierSubstitutionVisitor(MapType<std::string, std::string> const& identifierToIdentifierMap) : identifierToIdentifierMap(identifierToIdentifierMap) {
+            // Intentionally left empty.
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        Expression IdentifierSubstitutionVisitor<MapType>::substitute(BaseExpression const* expression) {
+            expression->accept(this);
+            return Expression(this->expressionStack.top());
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void IdentifierSubstitutionVisitor<MapType>::visit(IfThenElseExpression const* expression) {
+            expression->getCondition()->accept(this);
+            std::shared_ptr<BaseExpression const> conditionExpression = expressionStack.top();
+            expressionStack.pop();
+            
+            expression->getThenExpression()->accept(this);
+            std::shared_ptr<BaseExpression const> thenExpression = expressionStack.top();
+            expressionStack.pop();
+            
+            expression->getElseExpression()->accept(this);
+            std::shared_ptr<BaseExpression const> elseExpression = expressionStack.top();
+            expressionStack.pop();
+            
+            // If the arguments did not change, we simply push the expression itself.
+            if (conditionExpression.get() == expression->getCondition().get() && thenExpression.get() == expression->getThenExpression().get() && elseExpression.get() == expression->getElseExpression().get()) {
+                this->expressionStack.push(expression->getSharedPointer());
+            } else {
+                this->expressionStack.push(std::shared_ptr<BaseExpression>(new IfThenElseExpression(expression->getReturnType(), conditionExpression, thenExpression, elseExpression)));
+            }
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void IdentifierSubstitutionVisitor<MapType>::visit(BinaryBooleanFunctionExpression const* expression) {
+            expression->getFirstOperand()->accept(this);
+            std::shared_ptr<BaseExpression const> firstExpression = expressionStack.top();
+            expressionStack.pop();
+            
+            expression->getSecondOperand()->accept(this);
+            std::shared_ptr<BaseExpression const> secondExpression = expressionStack.top();
+            expressionStack.pop();
+            
+            // If the arguments did not change, we simply push the expression itself.
+            if (firstExpression.get() == expression->getFirstOperand().get() && secondExpression.get() == expression->getSecondOperand().get()) {
+                this->expressionStack.push(expression->getSharedPointer());
+            } else {
+                this->expressionStack.push(std::shared_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(expression->getReturnType(), firstExpression, secondExpression, expression->getOperatorType())));
+            }
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void IdentifierSubstitutionVisitor<MapType>::visit(BinaryNumericalFunctionExpression const* expression) {
+            expression->getFirstOperand()->accept(this);
+            std::shared_ptr<BaseExpression const> firstExpression = expressionStack.top();
+            expressionStack.pop();
+            
+            expression->getSecondOperand()->accept(this);
+            std::shared_ptr<BaseExpression const> secondExpression = expressionStack.top();
+            expressionStack.pop();
+            
+            // If the arguments did not change, we simply push the expression itself.
+            if (firstExpression.get() == expression->getFirstOperand().get() && secondExpression.get() == expression->getSecondOperand().get()) {
+                this->expressionStack.push(expression->getSharedPointer());
+            } else {
+                this->expressionStack.push(std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(expression->getReturnType(), firstExpression, secondExpression, expression->getOperatorType())));
+            }
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void IdentifierSubstitutionVisitor<MapType>::visit(BinaryRelationExpression const* expression) {
+            expression->getFirstOperand()->accept(this);
+            std::shared_ptr<BaseExpression const> firstExpression = expressionStack.top();
+            expressionStack.pop();
+            
+            expression->getSecondOperand()->accept(this);
+            std::shared_ptr<BaseExpression const> secondExpression = expressionStack.top();
+            expressionStack.pop();
+            
+            // If the arguments did not change, we simply push the expression itself.
+            if (firstExpression.get() == expression->getFirstOperand().get() && secondExpression.get() == expression->getSecondOperand().get()) {
+                this->expressionStack.push(expression->getSharedPointer());
+            } else {
+                this->expressionStack.push(std::shared_ptr<BaseExpression>(new BinaryRelationExpression(expression->getReturnType(), firstExpression, secondExpression, expression->getRelationType())));
+            }
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void IdentifierSubstitutionVisitor<MapType>::visit(BooleanConstantExpression const* expression) {
+            // If the boolean constant is in the key set of the substitution, we need to replace it.
+            auto const& namePair = this->identifierToIdentifierMap.find(expression->getConstantName());
+            if (namePair != this->identifierToIdentifierMap.end()) {
+                this->expressionStack.push(std::shared_ptr<BaseExpression>(new BooleanConstantExpression(namePair->second)));
+            } else {
+                this->expressionStack.push(expression->getSharedPointer());
+            }
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void IdentifierSubstitutionVisitor<MapType>::visit(DoubleConstantExpression const* expression) {
+            // If the double constant is in the key set of the substitution, we need to replace it.
+            auto const& namePair = this->identifierToIdentifierMap.find(expression->getConstantName());
+            if (namePair != this->identifierToIdentifierMap.end()) {
+                this->expressionStack.push(std::shared_ptr<BaseExpression>(new DoubleConstantExpression(namePair->second)));
+            } else {
+                this->expressionStack.push(expression->getSharedPointer());
+            }
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void IdentifierSubstitutionVisitor<MapType>::visit(IntegerConstantExpression const* expression) {
+            // If the integer constant is in the key set of the substitution, we need to replace it.
+            auto const& namePair = this->identifierToIdentifierMap.find(expression->getConstantName());
+            if (namePair != this->identifierToIdentifierMap.end()) {
+                this->expressionStack.push(std::shared_ptr<BaseExpression>(new IntegerConstantExpression(namePair->second)));
+            } else {
+                this->expressionStack.push(expression->getSharedPointer());
+            }
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void IdentifierSubstitutionVisitor<MapType>::visit(VariableExpression const* expression) {
+            // If the variable is in the key set of the substitution, we need to replace it.
+            auto const& namePair = this->identifierToIdentifierMap.find(expression->getVariableName());
+            if (namePair != this->identifierToIdentifierMap.end()) {
+                this->expressionStack.push(std::shared_ptr<BaseExpression>(new VariableExpression(expression->getReturnType(), namePair->second)));
+            } else {
+                this->expressionStack.push(expression->getSharedPointer());
+            }
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void IdentifierSubstitutionVisitor<MapType>::visit(UnaryBooleanFunctionExpression const* expression) {
+            expression->getOperand()->accept(this);
+            std::shared_ptr<BaseExpression const> operandExpression = expressionStack.top();
+            expressionStack.pop();
+            
+            // If the argument did not change, we simply push the expression itself.
+            if (operandExpression.get() == expression->getOperand().get()) {
+                expressionStack.push(expression->getSharedPointer());
+            } else {
+                expressionStack.push(std::shared_ptr<BaseExpression>(new UnaryBooleanFunctionExpression(expression->getReturnType(), operandExpression, expression->getOperatorType())));
+            }
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void IdentifierSubstitutionVisitor<MapType>::visit(UnaryNumericalFunctionExpression const* expression) {
+            expression->getOperand()->accept(this);
+            std::shared_ptr<BaseExpression const> operandExpression = expressionStack.top();
+            expressionStack.pop();
+            
+            // If the argument did not change, we simply push the expression itself.
+            if (operandExpression.get() == expression->getOperand().get()) {
+                expressionStack.push(expression->getSharedPointer());
+            } else {
+                expressionStack.push(std::shared_ptr<BaseExpression>(new UnaryNumericalFunctionExpression(expression->getReturnType(), operandExpression, expression->getOperatorType())));
+            }
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void IdentifierSubstitutionVisitor<MapType>::visit(BooleanLiteralExpression const* expression) {
+            this->expressionStack.push(expression->getSharedPointer());
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void IdentifierSubstitutionVisitor<MapType>::visit(IntegerLiteralExpression const* expression) {
+            this->expressionStack.push(expression->getSharedPointer());
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void IdentifierSubstitutionVisitor<MapType>::visit(DoubleLiteralExpression const* expression) {
+            this->expressionStack.push(expression->getSharedPointer());
+        }
+        
+        // Explicitly instantiate the class with map and unordered_map.
+        template class IdentifierSubstitutionVisitor<std::map>;
+        template class IdentifierSubstitutionVisitor<std::unordered_map>;
+    }
+}
diff --git a/src/storage/expressions/IdentifierSubstitutionVisitor.h b/src/storage/expressions/IdentifierSubstitutionVisitor.h
new file mode 100644
index 000000000..6be7aa9ca
--- /dev/null
+++ b/src/storage/expressions/IdentifierSubstitutionVisitor.h
@@ -0,0 +1,55 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_IDENTIFIERSUBSTITUTIONVISITOR_H_
+#define STORM_STORAGE_EXPRESSIONS_IDENTIFIERSUBSTITUTIONVISITOR_H_
+
+#include <stack>
+
+#include "src/storage/expressions/Expression.h"
+#include "src/storage/expressions/ExpressionVisitor.h"
+
+namespace storm {
+    namespace expressions {
+        template<template<typename... Arguments> class MapType>
+        class IdentifierSubstitutionVisitor : public ExpressionVisitor {
+        public:
+            /*!
+             * Creates a new substitution visitor that uses the given map to replace identifiers.
+             *
+             * @param identifierToExpressionMap A mapping from identifiers to expressions.
+             */
+            IdentifierSubstitutionVisitor(MapType<std::string, std::string> const& identifierToExpressionMap);
+            
+            /*!
+             * Substitutes the identifiers in the given expression according to the previously given map and returns the
+             * resulting expression.
+             *
+             * @param expression The expression in which to substitute the identifiers.
+             * @return The expression in which all identifiers in the key set of the previously given mapping are
+             * substituted with the mapped-to expressions.
+             */
+            Expression substitute(BaseExpression const* expression);
+            
+            virtual void visit(IfThenElseExpression const* expression) override;
+            virtual void visit(BinaryBooleanFunctionExpression const* expression) override;
+            virtual void visit(BinaryNumericalFunctionExpression const* expression) override;
+            virtual void visit(BinaryRelationExpression const* expression) override;
+            virtual void visit(BooleanConstantExpression const* expression) override;
+            virtual void visit(DoubleConstantExpression const* expression) override;
+            virtual void visit(IntegerConstantExpression const* expression) override;
+            virtual void visit(VariableExpression const* expression) override;
+            virtual void visit(UnaryBooleanFunctionExpression const* expression) override;
+            virtual void visit(UnaryNumericalFunctionExpression const* expression) override;
+            virtual void visit(BooleanLiteralExpression const* expression) override;
+            virtual void visit(IntegerLiteralExpression const* expression) override;
+            virtual void visit(DoubleLiteralExpression const* expression) override;
+            
+        private:
+            // A stack of expression used to pass the results to the higher levels.
+            std::stack<std::shared_ptr<BaseExpression const>> expressionStack;
+            
+            // A mapping of identifier names to expressions with which they shall be replaced.
+            MapType<std::string, std::string> const& identifierToIdentifierMap;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_IDENTIFIERSUBSTITUTIONVISITOR_H_ */
\ No newline at end of file
diff --git a/src/storage/expressions/IfThenElseExpression.cpp b/src/storage/expressions/IfThenElseExpression.cpp
new file mode 100644
index 000000000..81ebca670
--- /dev/null
+++ b/src/storage/expressions/IfThenElseExpression.cpp
@@ -0,0 +1,96 @@
+#include "src/storage/expressions/IfThenElseExpression.h"
+
+namespace storm {
+    namespace expressions {
+        IfThenElseExpression::IfThenElseExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& condition, std::shared_ptr<BaseExpression const> const& thenExpression, std::shared_ptr<BaseExpression const> const& elseExpression) : BaseExpression(returnType), condition(condition), thenExpression(thenExpression), elseExpression(elseExpression) {
+            // Intentionally left empty.
+        }
+        
+        bool IfThenElseExpression::evaluateAsBool(Valuation const* valuation) const {
+            bool conditionValue = this->condition->evaluateAsBool(valuation);
+            if (conditionValue) {
+                return this->thenExpression->evaluateAsBool(valuation);
+            } else {
+                return this->elseExpression->evaluateAsBool(valuation);
+            }
+        }
+        
+        int_fast64_t IfThenElseExpression::evaluateAsInt(Valuation const* valuation) const {
+            bool conditionValue = this->condition->evaluateAsBool(valuation);
+            if (conditionValue) {
+                return this->thenExpression->evaluateAsInt(valuation);
+            } else {
+                return this->elseExpression->evaluateAsInt(valuation);
+            }
+        }
+        
+        double IfThenElseExpression::evaluateAsDouble(Valuation const* valuation) const {
+            bool conditionValue = this->condition->evaluateAsBool(valuation);
+            if (conditionValue) {
+                return this->thenExpression->evaluateAsDouble(valuation);
+            } else {
+                return this->elseExpression->evaluateAsDouble(valuation);
+            }
+        }
+        
+        bool IfThenElseExpression::isConstant() const {
+            return this->condition->isConstant() && this->thenExpression->isConstant() && this->elseExpression->isConstant();
+        }
+        
+        std::set<std::string> IfThenElseExpression::getVariables() const {
+            std::set<std::string> result = this->condition->getVariables();
+            std::set<std::string> tmp = this->thenExpression->getVariables();
+            result.insert(tmp.begin(), tmp.end());
+            tmp = this->elseExpression->getVariables();
+            result.insert(tmp.begin(), tmp.end());
+            return result;
+        }
+        
+        std::set<std::string> IfThenElseExpression::getConstants() const {
+            std::set<std::string> result = this->condition->getConstants();
+            std::set<std::string> tmp = this->thenExpression->getConstants();
+            result.insert(tmp.begin(), tmp.end());
+            tmp = this->elseExpression->getConstants();
+            result.insert(tmp.begin(), tmp.end());
+            return result;
+        }
+        
+        std::shared_ptr<BaseExpression const> IfThenElseExpression::simplify() const {
+            std::shared_ptr<BaseExpression const> conditionSimplified;
+            if (conditionSimplified->isTrue()) {
+                return this->thenExpression->simplify();
+            } else if (conditionSimplified->isFalse()) {
+                return this->elseExpression->simplify();
+            } else {
+                std::shared_ptr<BaseExpression const> thenExpressionSimplified = this->thenExpression->simplify();
+                std::shared_ptr<BaseExpression const> elseExpressionSimplified = this->elseExpression->simplify();
+                
+                if (conditionSimplified.get() == this->condition.get() && thenExpressionSimplified.get() == this->thenExpression.get() && elseExpressionSimplified.get() == this->elseExpression.get()) {
+                    return this->shared_from_this();
+                } else {
+                    return std::shared_ptr<BaseExpression>(new IfThenElseExpression(this->getReturnType(), conditionSimplified, thenExpressionSimplified, elseExpressionSimplified));
+                }
+            }
+        }
+        
+        void IfThenElseExpression::accept(ExpressionVisitor* visitor) const {
+            visitor->visit(this);
+        }
+        
+        std::shared_ptr<BaseExpression const> IfThenElseExpression::getCondition() const {
+            return this->condition;
+        }
+        
+        std::shared_ptr<BaseExpression const> IfThenElseExpression::getThenExpression() const {
+            return this->thenExpression;
+        }
+        
+        std::shared_ptr<BaseExpression const> IfThenElseExpression::getElseExpression() const {
+            return this->elseExpression;
+        }
+        
+        void IfThenElseExpression::printToStream(std::ostream& stream) const {
+            stream << "(" << *this->condition << " ? " << *this->thenExpression << " : " << *this->elseExpression << ")";
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/expressions/IfThenElseExpression.h b/src/storage/expressions/IfThenElseExpression.h
new file mode 100644
index 000000000..979cb08f0
--- /dev/null
+++ b/src/storage/expressions/IfThenElseExpression.h
@@ -0,0 +1,77 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_IFTHENELSEEXPRESSION_H_
+#define STORM_STORAGE_EXPRESSIONS_IFTHENELSEEXPRESSION_H_
+
+#include "src/storage/expressions/BaseExpression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace expressions {
+        class IfThenElseExpression : public BaseExpression {
+        public:
+            /*!
+             * Creates an if-then-else expression with the given return type, condition and operands.
+             *
+             * @param returnType The return type of the expression.
+             * @param thenExpression The expression evaluated if the condition evaluates true.
+             * @param elseExpression The expression evaluated if the condition evaluates false.
+             */
+            IfThenElseExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& condition, std::shared_ptr<BaseExpression const> const& thenExpression, std::shared_ptr<BaseExpression const> const& elseExpression);
+            
+            // Instantiate constructors and assignments with their default implementations.
+            IfThenElseExpression(IfThenElseExpression const& other) = default;
+            IfThenElseExpression& operator=(IfThenElseExpression const& other) = default;
+#ifndef WINDOWS
+            IfThenElseExpression(IfThenElseExpression&&) = default;
+            IfThenElseExpression& operator=(IfThenElseExpression&&) = default;
+#endif
+            virtual ~IfThenElseExpression() = default;
+            
+            // Override base class methods.
+            virtual bool evaluateAsBool(Valuation const* valuation = nullptr) const override;
+            virtual int_fast64_t evaluateAsInt(Valuation const* valuation = nullptr) const override;
+            virtual double evaluateAsDouble(Valuation const* valuation = nullptr) const override;
+            virtual bool isConstant() const override;
+            virtual std::set<std::string> getVariables() const override;
+            virtual std::set<std::string> getConstants() const override;
+            virtual std::shared_ptr<BaseExpression const> simplify() const override;
+            virtual void accept(ExpressionVisitor* visitor) const override;
+            
+            /*!
+             * Retrieves the condition expression of the if-then-else expression.
+             *
+             * @return The condition expression of the if-then-else expression.
+             */
+            std::shared_ptr<BaseExpression const> getCondition() const;
+
+            /*!
+             * Retrieves the then expression of the if-then-else expression.
+             *
+             * @return The then expression of the if-then-else expression.
+             */
+            std::shared_ptr<BaseExpression const> getThenExpression() const;
+
+            /*!
+             * Retrieves the else expression of the if-then-else expression.
+             *
+             * @return The else expression of the if-then-else expression.
+             */
+            std::shared_ptr<BaseExpression const> getElseExpression() const;
+
+        protected:
+            // Override base class method.
+            virtual void printToStream(std::ostream& stream) const override;
+            
+        private:
+            // The condition of the if-then-else.
+            std::shared_ptr<BaseExpression const> condition;
+            
+            // The return expression of the if-part.
+            std::shared_ptr<BaseExpression const> thenExpression;
+
+            // The return expression of the else-part.
+            std::shared_ptr<BaseExpression const> elseExpression;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_IFTHENELSEEXPRESSION_H_ */
\ No newline at end of file
diff --git a/src/storage/expressions/IntegerConstantExpression.cpp b/src/storage/expressions/IntegerConstantExpression.cpp
new file mode 100644
index 000000000..60ad8de89
--- /dev/null
+++ b/src/storage/expressions/IntegerConstantExpression.cpp
@@ -0,0 +1,27 @@
+#include "src/storage/expressions/IntegerConstantExpression.h"
+#include "src/exceptions/ExceptionMacros.h"
+
+namespace storm {
+    namespace expressions {
+        IntegerConstantExpression::IntegerConstantExpression(std::string const& constantName) : ConstantExpression(ExpressionReturnType::Int, constantName) {
+            // Intentionally left empty.
+        }
+        
+        int_fast64_t IntegerConstantExpression::evaluateAsInt(Valuation const* valuation) const {
+            LOG_ASSERT(valuation != nullptr, "Evaluating expressions with unknowns without valuation.");
+            return valuation->getIntegerValue(this->getConstantName());
+        }
+        
+        double IntegerConstantExpression::evaluateAsDouble(Valuation const* valuation) const {
+            return static_cast<double>(this->evaluateAsInt(valuation));
+        }
+        
+        std::shared_ptr<BaseExpression const> IntegerConstantExpression::simplify() const {
+            return this->shared_from_this();
+        }
+        
+        void IntegerConstantExpression::accept(ExpressionVisitor* visitor) const {
+            visitor->visit(this);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/expressions/IntegerConstantExpression.h b/src/storage/expressions/IntegerConstantExpression.h
new file mode 100644
index 000000000..fcf151ead
--- /dev/null
+++ b/src/storage/expressions/IntegerConstantExpression.h
@@ -0,0 +1,36 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_INTEGERCONSTANTEXPRESSION_H_
+#define STORM_STORAGE_EXPRESSIONS_INTEGERCONSTANTEXPRESSION_H_
+
+#include "src/storage/expressions/ConstantExpression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace expressions {
+        class IntegerConstantExpression : public ConstantExpression {
+        public:
+            /*!
+             * Creates an integer constant expression with the given constant name.
+             *
+             * @param constantName The name of the integer constant associated with this expression.
+             */
+            IntegerConstantExpression(std::string const& constantName);
+            
+            // Instantiate constructors and assignments with their default implementations.
+            IntegerConstantExpression(IntegerConstantExpression const& other) = default;
+            IntegerConstantExpression& operator=(IntegerConstantExpression const& other) = default;
+#ifndef WINDOWS
+            IntegerConstantExpression(IntegerConstantExpression&&) = default;
+            IntegerConstantExpression& operator=(IntegerConstantExpression&&) = default;
+#endif
+            virtual ~IntegerConstantExpression() = default;
+            
+            // Override base class methods.
+            virtual int_fast64_t evaluateAsInt(Valuation const* valuation = nullptr) const override;
+            virtual double evaluateAsDouble(Valuation const* valuation = nullptr) const override;
+            virtual std::shared_ptr<BaseExpression const> simplify() const override;
+            virtual void accept(ExpressionVisitor* visitor) const;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_INTEGERCONSTANTEXPRESSION_H_ */
diff --git a/src/storage/expressions/IntegerLiteralExpression.cpp b/src/storage/expressions/IntegerLiteralExpression.cpp
new file mode 100644
index 000000000..5e6404fc8
--- /dev/null
+++ b/src/storage/expressions/IntegerLiteralExpression.cpp
@@ -0,0 +1,45 @@
+#include "src/storage/expressions/IntegerLiteralExpression.h"
+
+namespace storm {
+    namespace expressions {
+        IntegerLiteralExpression::IntegerLiteralExpression(int_fast64_t value) : BaseExpression(ExpressionReturnType::Int), value(value) {
+            // Intentionally left empty.
+        }
+        
+        int_fast64_t IntegerLiteralExpression::evaluateAsInt(Valuation const* valuation) const {
+            return this->getValue();
+        }
+        
+        double IntegerLiteralExpression::evaluateAsDouble(Valuation const* valuation) const {
+            return static_cast<double>(this->evaluateAsInt(valuation));
+        }
+        
+        bool IntegerLiteralExpression::isConstant() const {
+            return true;
+        }
+        
+        std::set<std::string> IntegerLiteralExpression::getVariables() const {
+            return std::set<std::string>();
+        }
+        
+        std::set<std::string> IntegerLiteralExpression::getConstants() const {
+            return std::set<std::string>();
+        }
+        
+        std::shared_ptr<BaseExpression const> IntegerLiteralExpression::simplify() const {
+            return this->shared_from_this();
+        }
+        
+        void IntegerLiteralExpression::accept(ExpressionVisitor* visitor) const {
+            visitor->visit(this);
+        }
+        
+        int_fast64_t IntegerLiteralExpression::getValue() const {
+            return this->value;
+        }
+        
+        void IntegerLiteralExpression::printToStream(std::ostream& stream) const {
+            stream << this->getValue();
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/expressions/IntegerLiteralExpression.h b/src/storage/expressions/IntegerLiteralExpression.h
new file mode 100644
index 000000000..8d50fe688
--- /dev/null
+++ b/src/storage/expressions/IntegerLiteralExpression.h
@@ -0,0 +1,54 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_INTEGERLITERALEXPRESSION_H_
+#define STORM_STORAGE_EXPRESSIONS_INTEGERLITERALEXPRESSION_H_
+
+#include "src/storage/expressions/BaseExpression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace expressions {
+        class IntegerLiteralExpression : public BaseExpression {
+        public:
+            /*!
+             * Creates an integer literal expression with the given value.
+             *
+             * @param value The value of the integer literal.
+             */
+            IntegerLiteralExpression(int_fast64_t value);
+            
+            // Instantiate constructors and assignments with their default implementations.
+            IntegerLiteralExpression(IntegerLiteralExpression const& other) = default;
+            IntegerLiteralExpression& operator=(IntegerLiteralExpression const& other) = default;
+#ifndef WINDOWS
+            IntegerLiteralExpression(IntegerLiteralExpression&&) = default;
+            IntegerLiteralExpression& operator=(IntegerLiteralExpression&&) = default;
+#endif
+            virtual ~IntegerLiteralExpression() = default;
+            
+            // Override base class methods.
+            virtual int_fast64_t evaluateAsInt(Valuation const* valuation = nullptr) const override;
+            virtual double evaluateAsDouble(Valuation const* valuation = nullptr) const override;
+            virtual bool isConstant() const override;
+            virtual std::set<std::string> getVariables() const override;
+            virtual std::set<std::string> getConstants() const override;
+            virtual std::shared_ptr<BaseExpression const> simplify() const override;
+            virtual void accept(ExpressionVisitor* visitor) const override;
+            
+            /*!
+             * Retrieves the value of the integer literal.
+             *
+             * @return The value of the integer literal.
+             */
+            int_fast64_t getValue() const;
+            
+        protected:
+            // Override base class method.
+            virtual void printToStream(std::ostream& stream) const override;
+
+        private:
+            // The value of the integer literal.
+            int_fast64_t value;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_INTEGERLITERALEXPRESSION_H_ */
\ No newline at end of file
diff --git a/src/storage/expressions/SimpleValuation.cpp b/src/storage/expressions/SimpleValuation.cpp
new file mode 100644
index 000000000..fb6f0088c
--- /dev/null
+++ b/src/storage/expressions/SimpleValuation.cpp
@@ -0,0 +1,120 @@
+#include "src/storage/expressions/SimpleValuation.h"
+
+#include <boost/functional/hash.hpp>
+
+namespace storm {
+    namespace expressions {
+        SimpleValuation::SimpleValuation() : booleanIdentifierToIndexMap(new std::unordered_map<std::string, uint_fast64_t>()), integerIdentifierToIndexMap(new std::unordered_map<std::string, uint_fast64_t>()), doubleIdentifierToIndexMap(new std::unordered_map<std::string, uint_fast64_t>()), booleanValues(), integerValues(), doubleValues() {
+            // Intentionally left empty.
+        }
+        
+        bool SimpleValuation::operator==(SimpleValuation const& other) const {
+            return this->booleanIdentifierToIndexMap.get() == other.booleanIdentifierToIndexMap.get() && this->integerIdentifierToIndexMap.get() == other.integerIdentifierToIndexMap.get() && this->doubleIdentifierToIndexMap.get() == other.doubleIdentifierToIndexMap.get() && this->booleanValues == other.booleanValues && this->integerValues == other.integerValues && this->doubleValues == other.doubleValues;
+        }
+        
+        void SimpleValuation::addBooleanIdentifier(std::string const& name, bool initialValue) {
+            this->booleanIdentifierToIndexMap->emplace(name, this->booleanValues.size());
+            this->booleanValues.push_back(false);
+        }
+        
+        void SimpleValuation::addIntegerIdentifier(std::string const& name, int_fast64_t initialValue) {
+            this->integerIdentifierToIndexMap->emplace(name, this->integerValues.size());
+            this->integerValues.push_back(initialValue);
+        }
+        
+        void SimpleValuation::addDoubleIdentifier(std::string const& name, double initialValue) {
+            this->doubleIdentifierToIndexMap->emplace(name, this->doubleValues.size());
+            this->doubleValues.push_back(initialValue);
+        }
+        
+        void SimpleValuation::setBooleanValue(std::string const& name, bool value) {
+            this->booleanValues[this->booleanIdentifierToIndexMap->at(name)] = value;
+        }
+        
+        void SimpleValuation::setIntegerValue(std::string const& name, int_fast64_t value) {
+            this->integerValues[this->integerIdentifierToIndexMap->at(name)] = value;
+        }
+        
+        void SimpleValuation::setDoubleValue(std::string const& name, double value) {
+            this->doubleValues[this->doubleIdentifierToIndexMap->at(name)] = value;
+        }
+        
+        bool SimpleValuation::getBooleanValue(std::string const& name) const {
+            auto const& nameIndexPair = this->booleanIdentifierToIndexMap->find(name);
+            return this->booleanValues[nameIndexPair->second];
+        }
+        
+        int_fast64_t SimpleValuation::getIntegerValue(std::string const& name) const {
+            auto const& nameIndexPair = this->integerIdentifierToIndexMap->find(name);
+            return this->integerValues[nameIndexPair->second];
+        }
+        
+        double SimpleValuation::getDoubleValue(std::string const& name) const {
+            auto const& nameIndexPair = this->doubleIdentifierToIndexMap->find(name);
+            return this->doubleValues[nameIndexPair->second];
+        }
+        
+        std::ostream& operator<<(std::ostream& stream, SimpleValuation const& valuation) {
+            stream << "valuation { bool [";
+            if (!valuation.booleanValues.empty()) {
+                for (uint_fast64_t i = 0; i < valuation.booleanValues.size() - 1; ++i) {
+                    stream << valuation.booleanValues[i] << ", ";
+                }
+                stream << valuation.booleanValues.back();
+            }
+            stream << "] int [";
+            if (!valuation.integerValues.empty()) {
+                for (uint_fast64_t i = 0; i < valuation.integerValues.size() - 1; ++i) {
+                    stream << valuation.integerValues[i] << ", ";
+                }
+                stream << valuation.integerValues.back();
+            }
+            stream << "] double [";
+            if (!valuation.doubleValues.empty()) {
+                for (uint_fast64_t i = 0; i < valuation.doubleValues.size() - 1; ++i) {
+                    stream << valuation.doubleValues[i] << ", ";
+                }
+                stream << valuation.doubleValues.back();
+            }
+            stream << "] }";
+            
+            return stream;
+        }
+        
+        std::size_t SimpleValuationPointerHash::operator()(SimpleValuation* valuation) const {
+            size_t seed = 0;
+            for (auto const& value : valuation->booleanValues) {
+                boost::hash_combine<bool>(seed, value);
+            }
+            for (auto const& value : valuation->integerValues) {
+                boost::hash_combine<int_fast64_t>(seed, value);
+            }
+            for (auto const& value : valuation->doubleValues) {
+                boost::hash_combine<double>(seed, value);
+            }
+            return seed;
+        }
+        
+        bool SimpleValuationPointerCompare::operator()(SimpleValuation* valuation1, SimpleValuation* valuation2) const {
+            return *valuation1 == *valuation2;
+        }
+        
+        bool SimpleValuationPointerLess::operator()(SimpleValuation* valuation1, SimpleValuation* valuation2) const {
+            // Compare boolean variables.
+            bool less = valuation1->booleanValues < valuation2->booleanValues;
+            if (less) {
+                return true;
+            }
+            less = valuation1->integerValues < valuation2->integerValues;
+            if (less) {
+                return true;
+            }
+            less = valuation1->doubleValues < valuation2->doubleValues;
+            if (less) {
+                return true;
+            } else {
+                return false;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/expressions/SimpleValuation.h b/src/storage/expressions/SimpleValuation.h
new file mode 100644
index 000000000..35b74291b
--- /dev/null
+++ b/src/storage/expressions/SimpleValuation.h
@@ -0,0 +1,141 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_SIMPLEVALUATION_H_
+#define STORM_STORAGE_EXPRESSIONS_SIMPLEVALUATION_H_
+
+#include <memory>
+#include <vector>
+#include <unordered_map>
+#include <iostream>
+
+#include "src/storage/expressions/Valuation.h"
+
+namespace storm {
+    namespace expressions {
+        class SimpleValuation : public Valuation {
+        public:
+            friend class SimpleValuationPointerHash;
+            friend class SimpleValuationPointerLess;
+            
+            /*!
+             * Creates a simple valuation without any identifiers.
+            */
+            SimpleValuation();
+
+            // Instantiate some constructors and assignments with their default implementations.
+            SimpleValuation(SimpleValuation const&) = default;
+            SimpleValuation& operator=(SimpleValuation const&) = default;
+            SimpleValuation(SimpleValuation&&) = default;
+            SimpleValuation& operator=(SimpleValuation&&) = default;
+            virtual ~SimpleValuation() = default;
+
+            /*!
+             * Compares two simple valuations wrt. equality.
+             */
+            bool operator==(SimpleValuation const& other) const;
+            
+            /*!
+             * Adds a boolean identifier with the given name.
+             *
+             * @param name The name of the boolean identifier to add.
+             * @param initialValue The initial value of the identifier.
+             */
+            void addBooleanIdentifier(std::string const& name, bool initialValue = false);
+            
+            /*!
+             * Adds a integer identifier with the given name.
+             *
+             * @param name The name of the integer identifier to add.
+             * @param initialValue The initial value of the identifier.
+             */
+            void addIntegerIdentifier(std::string const& name, int_fast64_t initialValue = 0);
+
+            /*!
+             * Adds a double identifier with the given name.
+             *
+             * @param name The name of the double identifier to add.
+             * @param initialValue The initial value of the identifier.
+             */
+            void addDoubleIdentifier(std::string const& name, double initialValue = 0);
+            
+            /*!
+             * Sets the value of the boolean identifier with the given name to the given value.
+             *
+             * @param name The name of the boolean identifier whose value to set.
+             * @param value The new value of the boolean identifier.
+             */
+            void setBooleanValue(std::string const& name, bool value);
+
+            /*!
+             * Sets the value of the integer identifier with the given name to the given value.
+             *
+             * @param name The name of the integer identifier whose value to set.
+             * @param value The new value of the integer identifier.
+             */
+            void setIntegerValue(std::string const& name, int_fast64_t value);
+
+            /*!
+             * Sets the value of the double identifier with the given name to the given value.
+             *
+             * @param name The name of the double identifier whose value to set.
+             * @param value The new value of the double identifier.
+             */
+            void setDoubleValue(std::string const& name, double value);
+            
+            // Override base class methods.
+            virtual bool getBooleanValue(std::string const& name) const override;
+            virtual int_fast64_t getIntegerValue(std::string const& name) const override;
+            virtual double getDoubleValue(std::string const& name) const override;
+            
+            friend std::ostream& operator<<(std::ostream& stream, SimpleValuation const& valuation);
+
+        private:
+            // A mapping of boolean identifiers to their local indices in the value container.
+            std::shared_ptr<std::unordered_map<std::string, uint_fast64_t>> booleanIdentifierToIndexMap;
+            
+            // A mapping of integer identifiers to their local indices in the value container.
+            std::shared_ptr<std::unordered_map<std::string, uint_fast64_t>> integerIdentifierToIndexMap;
+            
+            // A mapping of double identifiers to their local indices in the value container.
+            std::shared_ptr<std::unordered_map<std::string, uint_fast64_t>> doubleIdentifierToIndexMap;
+            
+            // The value container for all boolean identifiers.
+            std::vector<bool> booleanValues;
+            
+            // The value container for all integer identifiers.
+            std::vector<int_fast64_t> integerValues;
+            
+            // The value container for all double identifiers.
+            std::vector<double> doubleValues;
+        };
+        
+        /*!
+         * A helper class that can pe used as the hash functor for data structures that need to hash a simple valuations
+         * given via pointers.
+         */
+        class SimpleValuationPointerHash {
+        public:
+            std::size_t operator()(SimpleValuation* valuation) const;
+        };
+        
+        /*!
+         * A helper class that can be used as the comparison functor wrt. equality for data structures that need to
+         * store pointers to a simple valuations and need to compare the elements wrt. their content (rather than
+         * pointer equality).
+         */
+        class SimpleValuationPointerCompare {
+        public:
+            bool operator()(SimpleValuation* valuation1, SimpleValuation* valuation2) const;
+        };
+        
+        /*!
+         * A helper class that can be used as the comparison functor wrt. "<" for data structures that need to
+         * store pointers to a simple valuations and need to compare the elements wrt. their content (rather than
+         * pointer equality).
+         */
+        class SimpleValuationPointerLess {
+        public:
+            bool operator()(SimpleValuation* valuation1, SimpleValuation* valuation2) const;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_SIMPLEVALUATION_H_ */
\ No newline at end of file
diff --git a/src/storage/expressions/SubstitutionVisitor.cpp b/src/storage/expressions/SubstitutionVisitor.cpp
new file mode 100644
index 000000000..c3f2ea0a8
--- /dev/null
+++ b/src/storage/expressions/SubstitutionVisitor.cpp
@@ -0,0 +1,200 @@
+#include <map>
+#include <unordered_map>
+
+#include "src/storage/expressions/SubstitutionVisitor.h"
+
+#include "src/storage/expressions/IfThenElseExpression.h"
+#include "src/storage/expressions/BinaryBooleanFunctionExpression.h"
+#include "src/storage/expressions/BinaryNumericalFunctionExpression.h"
+#include "src/storage/expressions/BinaryRelationExpression.h"
+#include "src/storage/expressions/BooleanConstantExpression.h"
+#include "src/storage/expressions/IntegerConstantExpression.h"
+#include "src/storage/expressions/DoubleConstantExpression.h"
+#include "src/storage/expressions/BooleanLiteralExpression.h"
+#include "src/storage/expressions/IntegerLiteralExpression.h"
+#include "src/storage/expressions/DoubleLiteralExpression.h"
+#include "src/storage/expressions/VariableExpression.h"
+#include "src/storage/expressions/UnaryBooleanFunctionExpression.h"
+#include "src/storage/expressions/UnaryNumericalFunctionExpression.h"
+
+namespace storm {
+    namespace expressions  {
+        template<template<typename... Arguments> class MapType>
+        SubstitutionVisitor<MapType>::SubstitutionVisitor(MapType<std::string, Expression> const& identifierToExpressionMap) : identifierToExpressionMap(identifierToExpressionMap) {
+            // Intentionally left empty.
+        }
+
+        template<template<typename... Arguments> class MapType>
+        Expression SubstitutionVisitor<MapType>::substitute(BaseExpression const* expression) {
+            expression->accept(this);
+            return Expression(this->expressionStack.top());
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void SubstitutionVisitor<MapType>::visit(IfThenElseExpression const* expression) {
+            expression->getCondition()->accept(this);
+            std::shared_ptr<BaseExpression const> conditionExpression = expressionStack.top();
+            expressionStack.pop();
+            
+            expression->getThenExpression()->accept(this);
+            std::shared_ptr<BaseExpression const> thenExpression = expressionStack.top();
+            expressionStack.pop();
+
+            expression->getElseExpression()->accept(this);
+            std::shared_ptr<BaseExpression const> elseExpression = expressionStack.top();
+            expressionStack.pop();
+
+            // If the arguments did not change, we simply push the expression itself.
+            if (conditionExpression.get() == expression->getCondition().get() && thenExpression.get() == expression->getThenExpression().get() && elseExpression.get() == expression->getElseExpression().get()) {
+                this->expressionStack.push(expression->getSharedPointer());
+            } else {
+                this->expressionStack.push(std::shared_ptr<BaseExpression>(new IfThenElseExpression(expression->getReturnType(), conditionExpression, thenExpression, elseExpression)));
+            }
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void SubstitutionVisitor<MapType>::visit(BinaryBooleanFunctionExpression const* expression) {
+            expression->getFirstOperand()->accept(this);
+            std::shared_ptr<BaseExpression const> firstExpression = expressionStack.top();
+            expressionStack.pop();
+            
+            expression->getSecondOperand()->accept(this);
+            std::shared_ptr<BaseExpression const> secondExpression = expressionStack.top();
+            expressionStack.pop();
+
+            // If the arguments did not change, we simply push the expression itself.
+            if (firstExpression.get() == expression->getFirstOperand().get() && secondExpression.get() == expression->getSecondOperand().get()) {
+                this->expressionStack.push(expression->getSharedPointer());
+            } else {
+                this->expressionStack.push(std::shared_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(expression->getReturnType(), firstExpression, secondExpression, expression->getOperatorType())));
+            }
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void SubstitutionVisitor<MapType>::visit(BinaryNumericalFunctionExpression const* expression) {
+            expression->getFirstOperand()->accept(this);
+            std::shared_ptr<BaseExpression const> firstExpression = expressionStack.top();
+            expressionStack.pop();
+            
+            expression->getSecondOperand()->accept(this);
+            std::shared_ptr<BaseExpression const> secondExpression = expressionStack.top();
+            expressionStack.pop();
+            
+            // If the arguments did not change, we simply push the expression itself.
+            if (firstExpression.get() == expression->getFirstOperand().get() && secondExpression.get() == expression->getSecondOperand().get()) {
+                this->expressionStack.push(expression->getSharedPointer());
+            } else {
+                this->expressionStack.push(std::shared_ptr<BaseExpression>(new BinaryNumericalFunctionExpression(expression->getReturnType(), firstExpression, secondExpression, expression->getOperatorType())));
+            }
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void SubstitutionVisitor<MapType>::visit(BinaryRelationExpression const* expression) {
+            expression->getFirstOperand()->accept(this);
+            std::shared_ptr<BaseExpression const> firstExpression = expressionStack.top();
+            expressionStack.pop();
+            
+            expression->getSecondOperand()->accept(this);
+            std::shared_ptr<BaseExpression const> secondExpression = expressionStack.top();
+            expressionStack.pop();
+            
+            // If the arguments did not change, we simply push the expression itself.
+            if (firstExpression.get() == expression->getFirstOperand().get() && secondExpression.get() == expression->getSecondOperand().get()) {
+                this->expressionStack.push(expression->getSharedPointer());
+            } else {
+                this->expressionStack.push(std::shared_ptr<BaseExpression>(new BinaryRelationExpression(expression->getReturnType(), firstExpression, secondExpression, expression->getRelationType())));
+            }
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void SubstitutionVisitor<MapType>::visit(BooleanConstantExpression const* expression) {
+            // If the boolean constant is in the key set of the substitution, we need to replace it.
+            auto const& nameExpressionPair = this->identifierToExpressionMap.find(expression->getConstantName());
+            if (nameExpressionPair != this->identifierToExpressionMap.end()) {
+                this->expressionStack.push(nameExpressionPair->second.getBaseExpressionPointer());
+            } else {
+                this->expressionStack.push(expression->getSharedPointer());
+            }
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void SubstitutionVisitor<MapType>::visit(DoubleConstantExpression const* expression) {
+            // If the double constant is in the key set of the substitution, we need to replace it.
+            auto const& nameExpressionPair = this->identifierToExpressionMap.find(expression->getConstantName());
+            if (nameExpressionPair != this->identifierToExpressionMap.end()) {
+                this->expressionStack.push(nameExpressionPair->second.getBaseExpressionPointer());
+            } else {
+                this->expressionStack.push(expression->getSharedPointer());
+            }
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void SubstitutionVisitor<MapType>::visit(IntegerConstantExpression const* expression) {
+            // If the integer constant is in the key set of the substitution, we need to replace it.
+            auto const& nameExpressionPair = this->identifierToExpressionMap.find(expression->getConstantName());
+            if (nameExpressionPair != this->identifierToExpressionMap.end()) {
+                this->expressionStack.push(nameExpressionPair->second.getBaseExpressionPointer());
+            } else {
+                this->expressionStack.push(expression->getSharedPointer());
+            }
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void SubstitutionVisitor<MapType>::visit(VariableExpression const* expression) {
+            // If the variable is in the key set of the substitution, we need to replace it.
+            auto const& nameExpressionPair = this->identifierToExpressionMap.find(expression->getVariableName());
+            if (nameExpressionPair != this->identifierToExpressionMap.end()) {
+                this->expressionStack.push(nameExpressionPair->second.getBaseExpressionPointer());
+            } else {
+                this->expressionStack.push(expression->getSharedPointer());
+            }
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void SubstitutionVisitor<MapType>::visit(UnaryBooleanFunctionExpression const* expression) {
+            expression->getOperand()->accept(this);
+            std::shared_ptr<BaseExpression const> operandExpression = expressionStack.top();
+            expressionStack.pop();
+            
+            // If the argument did not change, we simply push the expression itself.
+            if (operandExpression.get() == expression->getOperand().get()) {
+                expressionStack.push(expression->getSharedPointer());
+            } else {
+                expressionStack.push(std::shared_ptr<BaseExpression>(new UnaryBooleanFunctionExpression(expression->getReturnType(), operandExpression, expression->getOperatorType())));
+            }
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void SubstitutionVisitor<MapType>::visit(UnaryNumericalFunctionExpression const* expression) {
+            expression->getOperand()->accept(this);
+            std::shared_ptr<BaseExpression const> operandExpression = expressionStack.top();
+            expressionStack.pop();
+            
+            // If the argument did not change, we simply push the expression itself.
+            if (operandExpression.get() == expression->getOperand().get()) {
+                expressionStack.push(expression->getSharedPointer());
+            } else {
+                expressionStack.push(std::shared_ptr<BaseExpression>(new UnaryNumericalFunctionExpression(expression->getReturnType(), operandExpression, expression->getOperatorType())));
+            }
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void SubstitutionVisitor<MapType>::visit(BooleanLiteralExpression const* expression) {
+            this->expressionStack.push(expression->getSharedPointer());
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void SubstitutionVisitor<MapType>::visit(IntegerLiteralExpression const* expression) {
+            this->expressionStack.push(expression->getSharedPointer());
+        }
+        
+        template<template<typename... Arguments> class MapType>
+        void SubstitutionVisitor<MapType>::visit(DoubleLiteralExpression const* expression) {
+            this->expressionStack.push(expression->getSharedPointer());
+        }
+        
+        // Explicitly instantiate the class with map and unordered_map.
+        template class SubstitutionVisitor<std::map>;
+        template class SubstitutionVisitor<std::unordered_map>;
+    }
+}
diff --git a/src/storage/expressions/SubstitutionVisitor.h b/src/storage/expressions/SubstitutionVisitor.h
new file mode 100644
index 000000000..ad29ad6ab
--- /dev/null
+++ b/src/storage/expressions/SubstitutionVisitor.h
@@ -0,0 +1,55 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_SUBSTITUTIONVISITOR_H_
+#define STORM_STORAGE_EXPRESSIONS_SUBSTITUTIONVISITOR_H_
+
+#include <stack>
+
+#include "src/storage/expressions/Expression.h"
+#include "src/storage/expressions/ExpressionVisitor.h"
+
+namespace storm {
+    namespace expressions {
+        template<template<typename... Arguments> class MapType>
+        class SubstitutionVisitor : public ExpressionVisitor {
+        public:
+            /*!
+             * Creates a new substitution visitor that uses the given map to replace identifiers.
+             *
+             * @param identifierToExpressionMap A mapping from identifiers to expressions.
+             */
+            SubstitutionVisitor(MapType<std::string, Expression> const& identifierToExpressionMap);
+            
+            /*!
+             * Substitutes the identifiers in the given expression according to the previously given map and returns the
+             * resulting expression.
+             *
+             * @param expression The expression in which to substitute the identifiers.
+             * @return The expression in which all identifiers in the key set of the previously given mapping are
+             * substituted with the mapped-to expressions.
+             */
+            Expression substitute(BaseExpression const* expression);
+            
+            virtual void visit(IfThenElseExpression const* expression) override;
+            virtual void visit(BinaryBooleanFunctionExpression const* expression) override;
+            virtual void visit(BinaryNumericalFunctionExpression const* expression) override;
+            virtual void visit(BinaryRelationExpression const* expression) override;
+            virtual void visit(BooleanConstantExpression const* expression) override;
+            virtual void visit(DoubleConstantExpression const* expression) override;
+            virtual void visit(IntegerConstantExpression const* expression) override;
+            virtual void visit(VariableExpression const* expression) override;
+            virtual void visit(UnaryBooleanFunctionExpression const* expression) override;
+            virtual void visit(UnaryNumericalFunctionExpression const* expression) override;
+            virtual void visit(BooleanLiteralExpression const* expression) override;
+            virtual void visit(IntegerLiteralExpression const* expression) override;
+            virtual void visit(DoubleLiteralExpression const* expression) override;
+            
+        private:
+            // A stack of expression used to pass the results to the higher levels.
+            std::stack<std::shared_ptr<BaseExpression const>> expressionStack;
+            
+            // A mapping of identifier names to expressions with which they shall be replaced.
+            MapType<std::string, Expression> const& identifierToExpressionMap;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_SUBSTITUTIONVISITOR_H_ */
\ No newline at end of file
diff --git a/src/storage/expressions/UnaryBooleanFunctionExpression.cpp b/src/storage/expressions/UnaryBooleanFunctionExpression.cpp
new file mode 100644
index 000000000..7e405bb29
--- /dev/null
+++ b/src/storage/expressions/UnaryBooleanFunctionExpression.cpp
@@ -0,0 +1,50 @@
+#include "src/storage/expressions/UnaryBooleanFunctionExpression.h"
+#include "src/storage/expressions/BooleanLiteralExpression.h"
+#include "src/exceptions/ExceptionMacros.h"
+#include "src/exceptions/InvalidTypeException.h"
+
+namespace storm {
+    namespace expressions {
+        UnaryBooleanFunctionExpression::UnaryBooleanFunctionExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& operand, OperatorType operatorType) : UnaryExpression(returnType, operand), operatorType(operatorType) {
+            // Intentionally left empty.
+        }
+        
+        UnaryBooleanFunctionExpression::OperatorType UnaryBooleanFunctionExpression::getOperatorType() const {
+            return this->operatorType;
+        }
+        
+        bool UnaryBooleanFunctionExpression::evaluateAsBool(Valuation const* valuation) const {
+            LOG_THROW(this->hasBooleanReturnType(), storm::exceptions::InvalidTypeException, "Unable to evaluate expression as boolean.");
+
+            bool operandEvaluated = this->getOperand()->evaluateAsBool(valuation);
+            switch (this->getOperatorType()) {
+                case OperatorType::Not: return !operandEvaluated; break;
+            }
+        }
+        
+        std::shared_ptr<BaseExpression const> UnaryBooleanFunctionExpression::simplify() const {
+            std::shared_ptr<BaseExpression const> operandSimplified = this->getOperand()->simplify();
+            switch (this->getOperatorType()) {
+                case OperatorType::Not: if (operandSimplified->isTrue()) {
+                    return std::shared_ptr<BaseExpression>(new BooleanLiteralExpression(false));
+                } else {
+                    return std::shared_ptr<BaseExpression>(new BooleanLiteralExpression(true));
+                }
+            }
+            
+            if (operandSimplified.get() == this->getOperand().get()) {
+                return this->shared_from_this();
+            } else {
+                return std::shared_ptr<BaseExpression>(new UnaryBooleanFunctionExpression(this->getReturnType(), operandSimplified, this->getOperatorType()));
+            }
+        }
+        
+        void UnaryBooleanFunctionExpression::accept(ExpressionVisitor* visitor) const {
+            visitor->visit(this);
+        }
+        
+        void UnaryBooleanFunctionExpression::printToStream(std::ostream& stream) const {
+            stream << "!(" << *this->getOperand() << ")";
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/expressions/UnaryBooleanFunctionExpression.h b/src/storage/expressions/UnaryBooleanFunctionExpression.h
new file mode 100644
index 000000000..1f2800d8e
--- /dev/null
+++ b/src/storage/expressions/UnaryBooleanFunctionExpression.h
@@ -0,0 +1,57 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_UNARYBOOLEANFUNCTIONEXPRESSION_H_
+#define STORM_STORAGE_EXPRESSIONS_UNARYBOOLEANFUNCTIONEXPRESSION_H_
+
+#include "src/storage/expressions/UnaryExpression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace expressions {
+        class UnaryBooleanFunctionExpression : public UnaryExpression {
+        public:
+            /*!
+             * An enum type specifying the different functions applicable.
+             */
+            enum class OperatorType { Not };
+            
+            /*!
+             * Creates a unary boolean function expression with the given return type, operand and operator.
+             *
+             * @param returnType The return type of the expression.
+             * @param operand The operand of the expression.
+             * @param operatorType The operator of the expression.
+             */
+            UnaryBooleanFunctionExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& operand, OperatorType operatorType);
+
+            // Instantiate constructors and assignments with their default implementations.
+            UnaryBooleanFunctionExpression(UnaryBooleanFunctionExpression const& other) = default;
+            UnaryBooleanFunctionExpression& operator=(UnaryBooleanFunctionExpression const& other) = default;
+#ifndef WINDOWS
+            UnaryBooleanFunctionExpression(UnaryBooleanFunctionExpression&&) = default;
+            UnaryBooleanFunctionExpression& operator=(UnaryBooleanFunctionExpression&&) = default;
+#endif
+            virtual ~UnaryBooleanFunctionExpression() = default;
+            
+            // Override base class methods.
+            virtual bool evaluateAsBool(Valuation const* valuation = nullptr) const override;
+            virtual std::shared_ptr<BaseExpression const> simplify() const override;
+            virtual void accept(ExpressionVisitor* visitor) const override;
+
+            /*!
+             * Retrieves the operator associated with this expression.
+             *
+             * @return The operator associated with this expression.
+             */
+            OperatorType getOperatorType() const;
+            
+        protected:
+            // Override base class method.
+            virtual void printToStream(std::ostream& stream) const override;
+
+        private:
+            // The operator of this expression.
+            OperatorType operatorType;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_UNARYBOOLEANFUNCTIONEXPRESSION_H_ */
diff --git a/src/storage/expressions/UnaryExpression.cpp b/src/storage/expressions/UnaryExpression.cpp
new file mode 100644
index 000000000..1e2d9135e
--- /dev/null
+++ b/src/storage/expressions/UnaryExpression.cpp
@@ -0,0 +1,25 @@
+#include "src/storage/expressions/UnaryExpression.h"
+
+namespace storm {
+    namespace expressions {
+        UnaryExpression::UnaryExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& operand) : BaseExpression(returnType), operand(operand) {
+            // Intentionally left empty.
+        }
+
+        bool UnaryExpression::isConstant() const {
+            return this->getOperand()->isConstant();
+        }
+        
+        std::set<std::string> UnaryExpression::getVariables() const {
+            return this->getOperand()->getVariables();
+        }
+        
+        std::set<std::string> UnaryExpression::getConstants() const {
+            return this->getOperand()->getVariables();
+        }
+        
+        std::shared_ptr<BaseExpression const> const& UnaryExpression::getOperand() const {
+            return this->operand;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/expressions/UnaryExpression.h b/src/storage/expressions/UnaryExpression.h
new file mode 100644
index 000000000..f81bc08ad
--- /dev/null
+++ b/src/storage/expressions/UnaryExpression.h
@@ -0,0 +1,47 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_UNARYEXPRESSION_H_
+#define STORM_STORAGE_EXPRESSIONS_UNARYEXPRESSION_H_
+
+#include "src/storage/expressions/BaseExpression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace expressions {
+        class UnaryExpression : public BaseExpression {
+        public:
+            /*!
+             * Creates a unary expression with the given return type and operand.
+             *
+             * @param returnType The return type of the expression.
+             * @param operand The operand of the unary expression.
+             */
+            UnaryExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& operand);
+
+            // Instantiate constructors and assignments with their default implementations.
+            UnaryExpression(UnaryExpression const& other);
+            UnaryExpression& operator=(UnaryExpression const& other);
+#ifndef WINDOWS
+            UnaryExpression(UnaryExpression&&) = default;
+            UnaryExpression& operator=(UnaryExpression&&) = default;
+#endif
+            virtual ~UnaryExpression() = default;
+            
+            // Override base class methods.
+            virtual bool isConstant() const override;
+            virtual std::set<std::string> getVariables() const override;
+            virtual std::set<std::string> getConstants() const override;
+            
+            /*!
+             * Retrieves the operand of the unary expression.
+             *
+             * @return The operand of the unary expression.
+             */
+            std::shared_ptr<BaseExpression const> const& getOperand() const;
+            
+        private:
+            // The operand of the unary expression.
+            std::shared_ptr<BaseExpression const> operand;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_UNARYEXPRESSION_H_ */
\ No newline at end of file
diff --git a/src/storage/expressions/UnaryNumericalFunctionExpression.cpp b/src/storage/expressions/UnaryNumericalFunctionExpression.cpp
new file mode 100644
index 000000000..02a4bee30
--- /dev/null
+++ b/src/storage/expressions/UnaryNumericalFunctionExpression.cpp
@@ -0,0 +1,62 @@
+#include <cmath>
+
+#include "src/storage/expressions/UnaryNumericalFunctionExpression.h"
+#include "src/exceptions/ExceptionMacros.h"
+#include "src/exceptions/InvalidTypeException.h"
+
+namespace storm {
+    namespace expressions {
+        UnaryNumericalFunctionExpression::UnaryNumericalFunctionExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& operand, OperatorType operatorType) : UnaryExpression(returnType, operand), operatorType(operatorType) {
+            // Intentionally left empty.
+        }
+        
+        UnaryNumericalFunctionExpression::OperatorType UnaryNumericalFunctionExpression::getOperatorType() const {
+            return this->operatorType;
+        }
+        
+        int_fast64_t UnaryNumericalFunctionExpression::evaluateAsInt(Valuation const* valuation) const {
+            LOG_THROW(this->hasIntegralReturnType(), storm::exceptions::InvalidTypeException, "Unable to evaluate expression as integer.");
+
+            int_fast64_t operandEvaluated = this->getOperand()->evaluateAsInt(valuation);
+            switch (this->getOperatorType()) {
+                case OperatorType::Minus: return -operandEvaluated; break;
+                case OperatorType::Floor: return std::floor(operandEvaluated); break;
+                case OperatorType::Ceil: return std::ceil(operandEvaluated); break;
+            }
+        }
+        
+        double UnaryNumericalFunctionExpression::evaluateAsDouble(Valuation const* valuation) const {
+            LOG_THROW(this->hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Unable to evaluate expression as double.");
+
+            double operandEvaluated = this->getOperand()->evaluateAsDouble(valuation);
+            switch (this->getOperatorType()) {
+                case OperatorType::Minus: return -operandEvaluated; break;
+                case OperatorType::Floor: return std::floor(operandEvaluated); break;
+                case OperatorType::Ceil: return std::ceil(operandEvaluated); break;
+            }
+        }
+        
+        std::shared_ptr<BaseExpression const> UnaryNumericalFunctionExpression::simplify() const {
+            std::shared_ptr<BaseExpression const> operandSimplified = this->getOperand()->simplify();
+            
+            if (operandSimplified.get() == this->getOperand().get()) {
+                return this->shared_from_this();
+            } else {
+                return std::shared_ptr<BaseExpression>(new UnaryNumericalFunctionExpression(this->getReturnType(), operandSimplified, this->getOperatorType()));
+            }
+        }
+        
+        void UnaryNumericalFunctionExpression::accept(ExpressionVisitor* visitor) const {
+            visitor->visit(this);
+        }
+        
+        void UnaryNumericalFunctionExpression::printToStream(std::ostream& stream) const {
+            switch (this->getOperatorType()) {
+                case OperatorType::Minus: stream << "-("; break;
+                case OperatorType::Floor: stream << "floor("; break;
+                case OperatorType::Ceil: stream << "ceil("; break;
+            }
+            stream << *this->getOperand() << ")";
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/expressions/UnaryNumericalFunctionExpression.h b/src/storage/expressions/UnaryNumericalFunctionExpression.h
new file mode 100644
index 000000000..daa0df40f
--- /dev/null
+++ b/src/storage/expressions/UnaryNumericalFunctionExpression.h
@@ -0,0 +1,58 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_UNARYNUMERICALFUNCTIONEXPRESSION_H_
+#define STORM_STORAGE_EXPRESSIONS_UNARYNUMERICALFUNCTIONEXPRESSION_H_
+
+#include "src/storage/expressions/UnaryExpression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace expressions {
+        class UnaryNumericalFunctionExpression : public UnaryExpression {
+        public:
+            /*!
+             * An enum type specifying the different functions applicable.
+             */
+            enum class OperatorType {Minus, Floor, Ceil};
+            
+            /*!
+             * Creates a unary numerical function expression with the given return type, operand and operator.
+             *
+             * @param returnType The return type of the expression.
+             * @param operand The operand of the expression.
+             * @param operatorType The operator of the expression.
+             */
+            UnaryNumericalFunctionExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& operand, OperatorType operatorType);
+            
+            // Instantiate constructors and assignments with their default implementations.
+            UnaryNumericalFunctionExpression(UnaryNumericalFunctionExpression const& other) = default;
+            UnaryNumericalFunctionExpression& operator=(UnaryNumericalFunctionExpression const& other) = default;
+#ifndef WINDOWS
+            UnaryNumericalFunctionExpression(UnaryNumericalFunctionExpression&&) = default;
+            UnaryNumericalFunctionExpression& operator=(UnaryNumericalFunctionExpression&&) = default;
+#endif
+            virtual ~UnaryNumericalFunctionExpression() = default;
+            
+            // Override base class methods.
+            virtual int_fast64_t evaluateAsInt(Valuation const* valuation = nullptr) const override;
+            virtual double evaluateAsDouble(Valuation const* valuation = nullptr) const override;
+            virtual std::shared_ptr<BaseExpression const> simplify() const override;
+            virtual void accept(ExpressionVisitor* visitor) const override;
+     
+            /*!
+             * Retrieves the operator associated with this expression.
+             *
+             * @return The operator associated with this expression.
+             */
+            OperatorType getOperatorType() const;
+            
+        protected:
+            // Override base class method.
+            virtual void printToStream(std::ostream& stream) const override;
+
+        private:
+            // The operator of this expression.
+            OperatorType operatorType;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_UNARYNUMERICALFUNCTIONEXPRESSION_H_ */
diff --git a/src/storage/expressions/Valuation.h b/src/storage/expressions/Valuation.h
new file mode 100644
index 000000000..7aa32a859
--- /dev/null
+++ b/src/storage/expressions/Valuation.h
@@ -0,0 +1,41 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_VALUATION_H_
+#define STORM_STORAGE_EXPRESSIONS_VALUATION_H_
+
+#include <string>
+
+namespace storm {
+    namespace expressions {
+        /*!
+         * The base class of all valuations where a valuation assigns a concrete value to all identifiers. This is, for
+         * example, used for evaluating expressions.
+         */
+        class Valuation {
+        public:
+            /*!
+             * Retrieves the boolean value of the identifier with the given name.
+             *
+             * @param name The name of the boolean identifier whose value to retrieve.
+             * @return The value of the boolean identifier.
+             */
+            virtual bool getBooleanValue(std::string const& name) const = 0;
+            
+            /*!
+             * Retrieves the integer value of the identifier with the given name.
+             *
+             * @param name The name of the integer identifier whose value to retrieve.
+             * @return The value of the integer identifier.
+             */
+            virtual int_fast64_t getIntegerValue(std::string const& name) const = 0;
+            
+            /*!
+             * Retrieves the double value of the identifier with the given name.
+             *
+             * @param name The name of the double identifier whose value to retrieve.
+             * @return The value of the double identifier.
+             */
+            virtual double getDoubleValue(std::string const& name) const = 0;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_VALUATION_H_ */
\ No newline at end of file
diff --git a/src/storage/expressions/VariableExpression.cpp b/src/storage/expressions/VariableExpression.cpp
new file mode 100644
index 000000000..d7765f14a
--- /dev/null
+++ b/src/storage/expressions/VariableExpression.cpp
@@ -0,0 +1,64 @@
+#include "src/storage/expressions/VariableExpression.h"
+#include "src/exceptions/ExceptionMacros.h"
+#include "src/exceptions/InvalidTypeException.h"
+
+namespace storm {
+    namespace expressions {
+        VariableExpression::VariableExpression(ExpressionReturnType returnType, std::string const& variableName) : BaseExpression(returnType), variableName(variableName) {
+            // Intentionally left empty.
+        }
+        
+        std::string const& VariableExpression::getVariableName() const {
+            return this->variableName;
+        }
+        
+        bool VariableExpression::evaluateAsBool(Valuation const* valuation) const {
+            LOG_ASSERT(valuation != nullptr, "Evaluating expressions with unknowns without valuation.");
+            LOG_THROW(this->hasBooleanReturnType(), storm::exceptions::InvalidTypeException, "Cannot evaluate expression as boolean: return type is not a boolean.");
+            
+            return valuation->getBooleanValue(this->getVariableName());
+        }
+
+        int_fast64_t VariableExpression::evaluateAsInt(Valuation const* valuation) const {
+            LOG_ASSERT(valuation != nullptr, "Evaluating expressions with unknowns without valuation.");
+            LOG_THROW(this->hasIntegralReturnType(), storm::exceptions::InvalidTypeException, "Cannot evaluate expression as integer: return type is not an integer.");
+            
+            return valuation->getIntegerValue(this->getVariableName());
+        }
+        
+        double VariableExpression::evaluateAsDouble(Valuation const* valuation) const {
+            LOG_ASSERT(valuation != nullptr, "Evaluating expressions with unknowns without valuation.");
+            LOG_THROW(this->hasNumericalReturnType(), storm::exceptions::InvalidTypeException, "Cannot evaluate expression as double: return type is not a double.");
+            
+            switch (this->getReturnType()) {
+                case ExpressionReturnType::Int: return static_cast<double>(valuation->getIntegerValue(this->getVariableName())); break;
+                case ExpressionReturnType::Double: valuation->getDoubleValue(this->getVariableName()); break;
+                default: break;
+            }
+            LOG_ASSERT(false, "Type of variable is required to be numeric.");
+            
+            // Silence warning. This point can never be reached.
+            return 0;
+        }
+        
+        std::set<std::string> VariableExpression::getVariables() const {
+            return {this->getVariableName()};
+        }
+        
+        std::set<std::string> VariableExpression::getConstants() const {
+            return std::set<std::string>();
+        }
+        
+        std::shared_ptr<BaseExpression const> VariableExpression::simplify() const {
+            return this->shared_from_this();
+        }
+        
+        void VariableExpression::accept(ExpressionVisitor* visitor) const {
+            visitor->visit(this);
+        }
+        
+        void VariableExpression::printToStream(std::ostream& stream) const {
+            stream << this->getVariableName();
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/expressions/VariableExpression.h b/src/storage/expressions/VariableExpression.h
new file mode 100644
index 000000000..2d83b7160
--- /dev/null
+++ b/src/storage/expressions/VariableExpression.h
@@ -0,0 +1,55 @@
+#ifndef STORM_STORAGE_EXPRESSIONS_VARIABLEEXPRESSION_H_
+#define STORM_STORAGE_EXPRESSIONS_VARIABLEEXPRESSION_H_
+
+#include "src/storage/expressions/BaseExpression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace expressions {
+        class VariableExpression : public BaseExpression {
+        public:
+            /*!
+             * Creates a variable expression with the given return type and variable name.
+             *
+             * @param returnType The return type of the variable expression.
+             * @param variableName The name of the variable associated with this expression.
+             */
+            VariableExpression(ExpressionReturnType returnType, std::string const& variableName);
+            
+            // Instantiate constructors and assignments with their default implementations.
+            VariableExpression(VariableExpression const&) = default;
+            VariableExpression& operator=(VariableExpression const&) = default;
+#ifndef WINDOWS
+            VariableExpression(VariableExpression&&) = default;
+            VariableExpression& operator=(VariableExpression&&) = default;
+#endif
+            virtual ~VariableExpression() = default;
+
+            // Override base class methods.
+            virtual bool evaluateAsBool(Valuation const* valuation = nullptr) const override;
+            virtual int_fast64_t evaluateAsInt(Valuation const* valuation = nullptr) const override;
+            virtual double evaluateAsDouble(Valuation const* valuation = nullptr) const override;
+            virtual std::set<std::string> getVariables() const override;
+            virtual std::set<std::string> getConstants() const override;
+            virtual std::shared_ptr<BaseExpression const> simplify() const override;
+            virtual void accept(ExpressionVisitor* visitor) const override;
+
+            /*!
+             * Retrieves the name of the variable associated with this expression.
+             *
+             * @return The name of the variable.
+             */
+            std::string const& getVariableName() const;
+
+        protected:
+            // Override base class method.
+            virtual void printToStream(std::ostream& stream) const override;
+
+        private:
+            // The variable name associated with this expression.
+            std::string variableName;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_EXPRESSIONS_VARIABLEEXPRESSION_H_ */
\ No newline at end of file
diff --git a/src/storage/prism/Assignment.cpp b/src/storage/prism/Assignment.cpp
new file mode 100644
index 000000000..f15797e6d
--- /dev/null
+++ b/src/storage/prism/Assignment.cpp
@@ -0,0 +1,27 @@
+#include "Assignment.h"
+
+namespace storm {
+    namespace prism {
+        Assignment::Assignment(std::string const& variableName, storm::expressions::Expression const& expression, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), variableName(variableName), expression(expression) {
+            // Intentionally left empty.
+        }
+        
+        std::string const& Assignment::getVariableName() const {
+            return variableName;
+        }
+        
+        storm::expressions::Expression const& Assignment::getExpression() const {
+            return this->expression;
+        }
+        
+        Assignment Assignment::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const {
+            return Assignment(this->getVariableName(), this->getExpression().substitute<std::map>(substitution), this->getFilename(), this->getLineNumber());
+        }
+        
+        std::ostream& operator<<(std::ostream& stream, Assignment const& assignment) {
+            stream << "(" << assignment.getVariableName() << "' = " << assignment.getExpression() << ")";
+            return stream;
+        }
+
+    } // namespace prism
+} // namespace storm
diff --git a/src/storage/prism/Assignment.h b/src/storage/prism/Assignment.h
new file mode 100644
index 000000000..c6604a03e
--- /dev/null
+++ b/src/storage/prism/Assignment.h
@@ -0,0 +1,67 @@
+#ifndef STORM_STORAGE_PRISM_ASSIGNMENT_H_
+#define STORM_STORAGE_PRISM_ASSIGNMENT_H_
+
+#include <map>
+
+#include "src/storage/prism/LocatedInformation.h"
+#include "src/storage/expressions/Expression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace prism {
+        class Assignment : public LocatedInformation {
+        public:
+            /*!
+             * Constructs an assignment using the given variable name and expression.
+             *
+             * @param variableName The variable that this assignment targets.
+             * @param expression The expression to assign to the variable.
+             * @param filename The filename in which the assignment is defined.
+             * @param lineNumber The line number in which the assignment is defined.
+             */
+            Assignment(std::string const& variableName, storm::expressions::Expression const& expression, std::string const& filename = "", uint_fast64_t lineNumber = 0);
+                        
+            // Create default implementations of constructors/assignment.
+            Assignment() = default;
+            Assignment(Assignment const& other) = default;
+            Assignment& operator=(Assignment const& other)= default;
+#ifndef WINDOWS
+            Assignment(Assignment&& other) = default;
+            Assignment& operator=(Assignment&& other) = default;
+#endif
+            
+            /*!
+             * Retrieves the name of the variable that this assignment targets.
+             *
+             * @return The name of the variable that this assignment targets.
+             */
+            std::string const& getVariableName() const;
+            
+            /*!
+             * Retrieves the expression that is assigned to the variable.
+             *
+             * @return The expression that is assigned to the variable.
+             */
+            storm::expressions::Expression const& getExpression() const;
+            
+            /*!
+             * Substitutes all identifiers in the assignment according to the given map.
+             *
+             * @param substitution The substitution to perform.
+             * @return The resulting assignment.
+             */
+            Assignment substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const;
+            
+            friend std::ostream& operator<<(std::ostream& stream, Assignment const& assignment);
+            
+        private:
+            // The name of the variable that this assignment targets.
+            std::string variableName;
+            
+            // The expression that is assigned to the variable.
+            storm::expressions::Expression expression;
+        };
+    } // namespace ir
+} // namespace storm
+
+#endif /* STORM_STORAGE_PRISM_ASSIGNMENT_H_ */
diff --git a/src/storage/prism/BooleanVariable.cpp b/src/storage/prism/BooleanVariable.cpp
new file mode 100644
index 000000000..478b9322d
--- /dev/null
+++ b/src/storage/prism/BooleanVariable.cpp
@@ -0,0 +1,23 @@
+#include "src/storage/prism/BooleanVariable.h"
+
+namespace storm {
+    namespace prism {
+        BooleanVariable::BooleanVariable(std::string const& variableName, std::string const& filename, uint_fast64_t lineNumber) : Variable(variableName, storm::expressions::Expression::createFalse(), true, filename, lineNumber) {
+            // Nothing to do here.
+        }
+
+        BooleanVariable::BooleanVariable(std::string const& variableName, storm::expressions::Expression const& initialValueExpression, std::string const& filename, uint_fast64_t lineNumber) : Variable(variableName, initialValueExpression, false, filename, lineNumber) {
+            // Nothing to do here.
+        }
+        
+        BooleanVariable BooleanVariable::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const {
+            return BooleanVariable(this->getName(), this->getInitialValueExpression().substitute<std::map>(substitution), this->getFilename(), this->getLineNumber());
+        }
+        
+        std::ostream& operator<<(std::ostream& stream, BooleanVariable const& variable) {
+            stream << variable.getName() << ": bool " << variable.getInitialValueExpression() << ";";
+            return stream;
+        }
+        
+    } // namespace prism
+} // namespace storm
diff --git a/src/storage/prism/BooleanVariable.h b/src/storage/prism/BooleanVariable.h
new file mode 100644
index 000000000..f32035010
--- /dev/null
+++ b/src/storage/prism/BooleanVariable.h
@@ -0,0 +1,55 @@
+#ifndef STORM_STORAGE_PRISM_BOOLEANVARIABLE_H_
+#define STORM_STORAGE_PRISM_BOOLEANVARIABLE_H_
+
+#include <map>
+
+#include "src/storage/prism/Variable.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace prism {
+        class BooleanVariable : public Variable {
+        public:
+            // Create default implementations of constructors/assignment.
+            BooleanVariable() = default;
+            BooleanVariable(BooleanVariable const& other) = default;
+            BooleanVariable& operator=(BooleanVariable const& other)= default;
+#ifndef WINDOWS
+            BooleanVariable(BooleanVariable&& other) = default;
+            BooleanVariable& operator=(BooleanVariable&& other) = default;
+#endif
+
+            /*!
+             * Creates a boolean variable with the given name and the default initial value expression.
+             *
+             * @param variableName The name of the variable.
+             * @param filename The filename in which the variable is defined.
+             * @param lineNumber The line number in which the variable is defined.
+             */
+            BooleanVariable(std::string const& variableName, std::string const& filename = "", uint_fast64_t lineNumber = 0);
+
+            /*!
+             * Creates a boolean variable with the given name and the given constant initial value expression.
+             *
+             * @param variableName The name of the variable.
+             * @param initialValueExpression The constant expression that defines the initial value of the variable.
+             * @param filename The filename in which the variable is defined.
+             * @param lineNumber The line number in which the variable is defined.
+             */
+            BooleanVariable(std::string const& variableName, storm::expressions::Expression const& initialValueExpression, std::string const& filename = "", uint_fast64_t lineNumber = 0);
+            
+            /*!
+             * Substitutes all identifiers in the boolean variable according to the given map.
+             *
+             * @param substitution The substitution to perform.
+             * @return The resulting boolean variable.
+             */
+            BooleanVariable substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const;
+            
+            friend std::ostream& operator<<(std::ostream& stream, BooleanVariable const& variable);
+        };
+        
+    } // namespace prism
+} // namespace storm
+
+#endif /* STORM_STORAGE_PRISM_BOOLEANVARIABLE_H_ */
diff --git a/src/storage/prism/Command.cpp b/src/storage/prism/Command.cpp
new file mode 100644
index 000000000..f075ff6c6
--- /dev/null
+++ b/src/storage/prism/Command.cpp
@@ -0,0 +1,55 @@
+#include "Command.h"
+
+namespace storm {
+    namespace prism {
+        Command::Command(uint_fast64_t globalIndex, std::string const& actionName, storm::expressions::Expression const& guardExpression, std::vector<storm::prism::Update> const& updates, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), actionName(actionName), guardExpression(guardExpression), updates(updates), globalIndex(globalIndex) {
+            // Nothing to do here.
+        }
+
+        std::string const& Command::getActionName() const {
+            return this->actionName;
+        }
+        
+        storm::expressions::Expression const& Command::getGuardExpression() const {
+            return guardExpression;
+        }
+        
+        std::size_t Command::getNumberOfUpdates() const {
+            return this->updates.size();
+        }
+        
+        storm::prism::Update const& Command::getUpdate(uint_fast64_t index) const {
+            return this->updates[index];
+        }
+        
+        std::vector<storm::prism::Update> const& Command::getUpdates() const {
+            return this->updates;
+        }
+        
+        uint_fast64_t Command::getGlobalIndex() const {
+            return this->globalIndex;
+        }
+        
+        Command Command::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const {
+            std::vector<Update> newUpdates;
+            newUpdates.reserve(this->getNumberOfUpdates());
+            for (auto const& update : this->getUpdates()) {
+                newUpdates.emplace_back(update.substitute(substitution));
+            }
+            
+            return Command(this->getGlobalIndex(), this->getActionName(), this->getGuardExpression().substitute<std::map>(substitution), newUpdates, this->getFilename(), this->getLineNumber());
+        }
+        
+        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) {
+                stream << command.getUpdate(i);
+                if (i < command.getUpdates().size() - 1) {
+                    stream << " + ";
+                }
+            }
+            stream << ";";
+            return stream;
+        }
+    } // namespace ir
+} // namespace storm
diff --git a/src/storage/prism/Command.h b/src/storage/prism/Command.h
new file mode 100644
index 000000000..6e32eba5e
--- /dev/null
+++ b/src/storage/prism/Command.h
@@ -0,0 +1,106 @@
+#ifndef STORM_STORAGE_PRISM_COMMAND_H_
+#define STORM_STORAGE_PRISM_COMMAND_H_
+
+#include <vector>
+#include <string>
+#include <map>
+
+#include "src/storage/expressions/Expression.h"
+#include "src/storage/prism/Update.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace prism {
+        class Command : public LocatedInformation {
+        public:
+            /*!
+             * Creates a command with the given action name, guard and updates.
+             *
+             * @param globalIndex The global index of the command.
+             * @param actionName The action name of the command.
+             * @param guardExpression the expression that defines the guard of the command.
+             * @param updates A list of updates that is associated with this command.
+             * @param filename The filename in which the command is defined.
+             * @param lineNumber The line number in which the command is defined.
+             */
+            Command(uint_fast64_t globalIndex, std::string const& actionName, storm::expressions::Expression const& guardExpression, std::vector<storm::prism::Update> const& updates, std::string const& filename = "", uint_fast64_t lineNumber = 0);
+            
+            // Create default implementations of constructors/assignment.
+            Command() = default;
+            Command(Command const& other) = default;
+            Command& operator=(Command const& other)= default;
+#ifndef WINDOWS
+            Command(Command&& other) = default;
+            Command& operator=(Command&& other) = default;
+#endif
+            
+            /*!
+             * Retrieves the action name of this command.
+             *
+             * @return The action name of this command.
+             */
+            std::string const& getActionName() const;
+            
+            /*!
+             * Retrieves a reference to the guard of the command.
+             *
+             * @return A reference to the guard of the command.
+             */
+            storm::expressions::Expression const& getGuardExpression() const;
+            
+            /*!
+             * Retrieves the number of updates associated with this command.
+             *
+             * @return The number of updates associated with this command.
+             */
+            std::size_t getNumberOfUpdates() const;
+            
+            /*!
+             * Retrieves a reference to the update with the given index.
+             *
+             * @return A reference to the update with the given index.
+             */
+            storm::prism::Update const& getUpdate(uint_fast64_t index) const;
+            
+            /*!
+             * Retrieves a vector of all updates associated with this command.
+             *
+             * @return A vector of updates associated with this command.
+             */
+            std::vector<storm::prism::Update> const& getUpdates() const;
+            
+            /*!
+             * Retrieves the global index of the command, that is, a unique index over all modules.
+             *
+             * @return The global index of the command.
+             */
+            uint_fast64_t getGlobalIndex() const;
+            
+            /*!
+             * Substitutes all identifiers in the command according to the given map.
+             *
+             * @param substitution The substitution to perform.
+             * @return The resulting command.
+             */
+            Command substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const;
+            
+            friend std::ostream& operator<<(std::ostream& stream, Command const& command);
+            
+        private:
+            // The name of the command.
+            std::string actionName;
+            
+            // The expression that defines the guard of the command.
+            storm::expressions::Expression guardExpression;
+            
+            // The list of updates of the command.
+            std::vector<storm::prism::Update> updates;
+            
+            // The global index of the command.
+            uint_fast64_t globalIndex;
+        };
+        
+    } // namespace prism
+} // namespace storm
+
+#endif /* STORM_STORAGE_PRISM_COMMAND_H_ */
diff --git a/src/storage/prism/Constant.cpp b/src/storage/prism/Constant.cpp
new file mode 100644
index 000000000..160e9ad22
--- /dev/null
+++ b/src/storage/prism/Constant.cpp
@@ -0,0 +1,49 @@
+#include "src/storage/prism/Constant.h"
+
+namespace storm {
+    namespace prism {
+        Constant::Constant(storm::expressions::ExpressionReturnType type, std::string const& name, storm::expressions::Expression const& expression, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), type(type), name(name), defined(true), expression(expression) {
+            // Intentionally left empty.
+        }
+        
+        Constant::Constant(storm::expressions::ExpressionReturnType type, std::string const& name, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), type(type), name(name), defined(false), expression() {
+            // Intentionally left empty.
+        }
+        
+        std::string const& Constant::getName() const {
+            return this->name;
+        }
+        
+        storm::expressions::ExpressionReturnType Constant::getType() const {
+            return this->type;
+        }
+        
+        bool Constant::isDefined() const {
+            return this->defined;
+        }
+        
+        storm::expressions::Expression const& Constant::getExpression() const {
+            return this->expression;
+        }
+        
+        Constant Constant::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const {
+            return Constant(this->getType(), this->getName(), this->getExpression().substitute<std::map>(substitution), this->getFilename(), this->getLineNumber());
+        }
+        
+        std::ostream& operator<<(std::ostream& stream, Constant const& constant) {
+            stream << "const ";
+            switch (constant.getType()) {
+                case storm::expressions::ExpressionReturnType::Undefined: stream << "undefined "; break;
+                case storm::expressions::ExpressionReturnType::Bool: stream << "bool "; break;
+                case storm::expressions::ExpressionReturnType::Int: stream << "int "; break;
+                case storm::expressions::ExpressionReturnType::Double: stream << "double "; break;
+            }
+            stream << constant.getName();
+            if (constant.isDefined()) {
+                stream << " = " << constant.getExpression();
+            }
+            stream << ";";
+            return stream;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/prism/Constant.h b/src/storage/prism/Constant.h
new file mode 100644
index 000000000..2e1c27590
--- /dev/null
+++ b/src/storage/prism/Constant.h
@@ -0,0 +1,99 @@
+#ifndef STORM_STORAGE_PRISM_CONSTANT_H_
+#define STORM_STORAGE_PRISM_CONSTANT_H_
+
+#include <map>
+
+#include "src/storage/prism/LocatedInformation.h"
+#include "src/storage/expressions/Expression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace prism {
+        class Constant : public LocatedInformation {
+        public:
+            /*!
+             * Creates a constant with the given type, name and defining expression.
+             *
+             * @param type The type of the constant.
+             * @param name The name of the constant.
+             * @param expression The expression that defines the constant.
+             * @param filename The filename in which the transition reward is defined.
+             * @param lineNumber The line number in which the transition reward is defined.
+             */
+            Constant(storm::expressions::ExpressionReturnType type, std::string const& name, storm::expressions::Expression const& expression, std::string const& filename = "", uint_fast64_t lineNumber = 0);
+
+            /*!
+             * Creates an undefined constant with the given type and name.
+             *
+             * @param constantType The type of the constant.
+             * @param constantName The name of the constant.
+             * @param filename The filename in which the transition reward is defined.
+             * @param lineNumber The line number in which the transition reward is defined.
+             */
+            Constant(storm::expressions::ExpressionReturnType constantType, std::string const& constantName, std::string const& filename = "", uint_fast64_t lineNumber = 0);
+            
+            // Create default implementations of constructors/assignment.
+            Constant() = default;
+            Constant(Constant const& other) = default;
+            Constant& operator=(Constant const& other)= default;
+#ifndef WINDOWS
+            Constant(Constant&& other) = default;
+            Constant& operator=(Constant&& other) = default;
+#endif
+            
+            /*!
+             * Retrieves the name of the constant.
+             *
+             * @return The name of the constant.
+             */
+            std::string const& getName() const;
+            
+            /*!
+             * Retrieves the type of the constant.
+             *
+             * @return The type of the constant;
+             */
+            storm::expressions::ExpressionReturnType getType() const;
+            
+            /*!
+             * Retrieves whether the constant is defined, i.e., whether there is an expression defining its value.
+             *
+             * @return True iff the constant is defined.
+             */
+            bool isDefined() const;
+            
+            /*!
+             * Retrieves the expression that defines the constant. This may only be called if the object is a defined
+             * constant.
+             *
+             * @return The expression that defines the constant.
+             */
+            storm::expressions::Expression const& getExpression() const;
+            
+            /*!
+             * Substitutes all identifiers in the constant according to the given map.
+             *
+             * @param substitution The substitution to perform.
+             * @return The resulting constant.
+             */
+            Constant substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const;
+            
+            friend std::ostream& operator<<(std::ostream& stream, Constant const& constant);
+            
+        private:
+            // The type of the constant.
+            storm::expressions::ExpressionReturnType type;
+            
+            // The name of the constant.
+            std::string name;
+            
+            // A flag that stores whether or not the constant is defined.
+            bool defined;
+            
+            // The expression that defines the constant (in case it is defined).
+            storm::expressions::Expression expression;
+        };
+    } // namespace prism
+} // namespace storm
+
+#endif /* STORM_STORAGE_PRISM_CONSTANT_H_ */
diff --git a/src/storage/prism/Formula.cpp b/src/storage/prism/Formula.cpp
new file mode 100644
index 000000000..3bf72a7de
--- /dev/null
+++ b/src/storage/prism/Formula.cpp
@@ -0,0 +1,30 @@
+#include "src/storage/prism/Formula.h"
+
+namespace storm {
+    namespace prism {
+        Formula::Formula(std::string const& name, storm::expressions::Expression const& expression, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), name(name), expression(expression) {
+            // Intentionally left empty.
+        }
+        
+        std::string const& Formula::getName() const {
+            return this->name;
+        }
+        
+        storm::expressions::Expression const& Formula::getExpression() const {
+            return this->expression;
+        }
+        
+        storm::expressions::ExpressionReturnType Formula::getType() const {
+            return this->getExpression().getReturnType();
+        }
+        
+        Formula Formula::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const {
+            return Formula(this->getName(), this->getExpression().substitute<std::map>(substitution), this->getFilename(), this->getLineNumber());
+        }
+        
+        std::ostream& operator<<(std::ostream& stream, Formula const& formula) {
+            stream << "formula " << formula.getName() << " = " << formula.getExpression() << ";";
+            return stream;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/prism/Formula.h b/src/storage/prism/Formula.h
new file mode 100644
index 000000000..2df8e6d32
--- /dev/null
+++ b/src/storage/prism/Formula.h
@@ -0,0 +1,74 @@
+#ifndef STORM_STORAGE_PRISM_FORMULA_H_
+#define STORM_STORAGE_PRISM_FORMULA_H_
+
+#include <map>
+
+#include "src/storage/prism/LocatedInformation.h"
+#include "src/storage/expressions/Expression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace prism {
+        class Formula : public LocatedInformation {
+        public:
+            /*!
+             * Creates a formula with the given name and expression.
+             *
+             * @param name The name of the formula.
+             * @param expression The expression associated with this formula.
+             * @param filename The filename in which the transition reward is defined.
+             * @param lineNumber The line number in which the transition reward is defined.
+             */
+            Formula(std::string const& name, storm::expressions::Expression const& expression, std::string const& filename = "", uint_fast64_t lineNumber = 0);
+            
+            // Create default implementations of constructors/assignment.
+            Formula() = default;
+            Formula(Formula const& other) = default;
+            Formula& operator=(Formula const& other)= default;
+#ifndef WINDOWS
+            Formula(Formula&& other) = default;
+            Formula& operator=(Formula&& other) = default;
+#endif
+            
+            /*!
+             * Retrieves the name that is associated with this formula.
+             *
+             * @return The name that is associated with this formula.
+             */
+            std::string const& getName() const;
+            
+            /*!
+             * Retrieves the expression that is associated with this formula.
+             *
+             * @return The expression that is associated with this formula.
+             */
+            storm::expressions::Expression const& getExpression() const;
+            
+            /*!
+             * Retrieves the return type of the formula, i.e., the return-type of the defining expression.
+             *
+             * @return The return type of the formula.
+             */
+            storm::expressions::ExpressionReturnType getType() const;
+            
+            /*!
+             * Substitutes all identifiers in the expression of the formula according to the given map.
+             *
+             * @param substitution The substitution to perform.
+             * @return The resulting formula.
+             */
+            Formula substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const;
+            
+            friend std::ostream& operator<<(std::ostream& stream, Formula const& formula);
+            
+        private:
+            // The name of the formula.
+            std::string name;
+            
+            // A predicate that needs to be satisfied by states for the label to be attached.
+            storm::expressions::Expression expression;
+        };
+    } // namespace prism
+} // namespace storm
+
+#endif /* STORM_STORAGE_PRISM_FORMULA_H_ */
diff --git a/src/storage/prism/IntegerVariable.cpp b/src/storage/prism/IntegerVariable.cpp
new file mode 100644
index 000000000..a80b6394e
--- /dev/null
+++ b/src/storage/prism/IntegerVariable.cpp
@@ -0,0 +1,30 @@
+#include "src/storage/prism/IntegerVariable.h"
+
+namespace storm {
+    namespace prism {
+        IntegerVariable::IntegerVariable(std::string const& name, storm::expressions::Expression const& lowerBoundExpression, storm::expressions::Expression const& upperBoundExpression, std::string const& filename, uint_fast64_t lineNumber) : Variable(name, lowerBoundExpression, true, filename, lineNumber), lowerBoundExpression(lowerBoundExpression), upperBoundExpression(upperBoundExpression) {
+            // Intentionally left empty.
+        }
+
+        IntegerVariable::IntegerVariable(std::string const& name, storm::expressions::Expression const& lowerBoundExpression, storm::expressions::Expression const& upperBoundExpression, storm::expressions::Expression const& initialValueExpression, std::string const& filename, uint_fast64_t lineNumber) : Variable(name, initialValueExpression, false, filename, lineNumber), lowerBoundExpression(lowerBoundExpression), upperBoundExpression(upperBoundExpression) {
+            // Intentionally left empty.
+        }
+        
+        storm::expressions::Expression const& IntegerVariable::getLowerBoundExpression() const {
+            return this->lowerBoundExpression;
+        }
+        
+        storm::expressions::Expression const& IntegerVariable::getUpperBoundExpression() const {
+            return this->upperBoundExpression;
+        }
+        
+        IntegerVariable IntegerVariable::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const {
+            return IntegerVariable(this->getName(), this->getLowerBoundExpression().substitute<std::map>(substitution), this->getUpperBoundExpression().substitute<std::map>(substitution), this->getInitialValueExpression().substitute<std::map>(substitution), this->getFilename(), this->getLineNumber());
+        }
+        
+        std::ostream& operator<<(std::ostream& stream, IntegerVariable const& variable) {
+            stream << variable.getName() << ": [" << variable.getLowerBoundExpression() << ".." << variable.getUpperBoundExpression() << "]" << " init " << variable.getInitialValueExpression() << ";";
+            return stream;
+        }
+    } // namespace prism
+} // namespace storm
diff --git a/src/storage/prism/IntegerVariable.h b/src/storage/prism/IntegerVariable.h
new file mode 100644
index 000000000..a7c069c53
--- /dev/null
+++ b/src/storage/prism/IntegerVariable.h
@@ -0,0 +1,80 @@
+#ifndef STORM_STORAGE_PRISM_INTEGERVARIABLE_H_
+#define STORM_STORAGE_PRISM_INTEGERVARIABLE_H_
+
+#include <map>
+
+#include "src/storage/prism/Variable.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace prism {
+        class IntegerVariable : public Variable {
+        public:
+            // Create default implementations of constructors/assignment.
+            IntegerVariable() = default;
+            IntegerVariable(IntegerVariable const& other) = default;
+            IntegerVariable& operator=(IntegerVariable const& other)= default;
+#ifndef WINDOWS
+            IntegerVariable(IntegerVariable&& other) = default;
+            IntegerVariable& operator=(IntegerVariable&& other) = default;
+#endif
+
+            /*!
+             * Creates an integer variable with the given name and a default initial value.
+             *
+             * @param name The name of the variable.
+             * @param lowerBoundExpression A constant expression defining the lower bound of the domain of the variable.
+             * @param upperBoundExpression A constant expression defining the upper bound of the domain of the variable.
+             * @param filename The filename in which the variable is defined.
+             * @param lineNumber The line number in which the variable is defined.
+             */
+            IntegerVariable(std::string const& name, storm::expressions::Expression const& lowerBoundExpression, storm::expressions::Expression const& upperBoundExpression, std::string const& filename = "", uint_fast64_t lineNumber = 0);
+
+            /*!
+             * Creates an integer variable with the given name and the given initial value expression.
+             *
+             * @param name The name of the variable.
+             * @param lowerBoundExpression A constant expression defining the lower bound of the domain of the variable.
+             * @param upperBoundExpression A constant expression defining the upper bound of the domain of the variable.
+             * @param initialValueExpression A constant expression that defines the initial value of the variable.
+             * @param filename The filename in which the variable is defined.
+             * @param lineNumber The line number in which the variable is defined.
+             */
+            IntegerVariable(std::string const& name, storm::expressions::Expression const& lowerBoundExpression, storm::expressions::Expression const& upperBoundExpression, storm::expressions::Expression const& initialValueExpression, std::string const& filename = "", uint_fast64_t lineNumber = 0);
+            
+            /*!
+             * Retrieves an expression defining the lower bound for this integer variable.
+             *
+             * @return An expression defining the lower bound for this integer variable.
+             */
+            storm::expressions::Expression const& getLowerBoundExpression() const;
+            
+            /*!
+             * Retrieves an expression defining the upper bound for this integer variable.
+             *
+             * @return An expression defining the upper bound for this integer variable.
+             */
+            storm::expressions::Expression const& getUpperBoundExpression() const;
+            
+            /*!
+             * Substitutes all identifiers in the boolean variable according to the given map.
+             *
+             * @param substitution The substitution to perform.
+             * @return The resulting boolean variable.
+             */
+            IntegerVariable substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const;
+            
+            friend std::ostream& operator<<(std::ostream& stream, IntegerVariable const& variable);
+            
+        private:
+            // A constant expression that specifies the lower bound of the domain of the variable.
+            storm::expressions::Expression lowerBoundExpression;
+            
+            // A constant expression that specifies the upper bound of the domain of the variable.
+            storm::expressions::Expression upperBoundExpression;
+        };
+        
+    } // namespace prism
+} // namespace storm
+
+#endif /* STORM_STORAGE_PRISM_INTEGERVARIABLE_H_ */
diff --git a/src/storage/prism/Label.cpp b/src/storage/prism/Label.cpp
new file mode 100644
index 000000000..a78f9079f
--- /dev/null
+++ b/src/storage/prism/Label.cpp
@@ -0,0 +1,26 @@
+#include "src/storage/prism/Label.h"
+
+namespace storm {
+    namespace prism {
+        Label::Label(std::string const& name, storm::expressions::Expression const& statePredicateExpression, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), name(name), statePredicateExpression(statePredicateExpression) {
+            // Intentionally left empty.
+        }
+
+        std::string const& Label::getName() const {
+            return this->name;
+        }
+        
+        storm::expressions::Expression const& Label::getStatePredicateExpression() const {
+            return this->statePredicateExpression;
+        }
+        
+        Label Label::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const {
+            return Label(this->getName(), this->getStatePredicateExpression().substitute<std::map>(substitution), this->getFilename(), this->getLineNumber());
+        }
+        
+        std::ostream& operator<<(std::ostream& stream, Label const& label) {
+            stream << "label \"" << label.getName() << "\" = " << label.getStatePredicateExpression() << ";";
+            return stream;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/prism/Label.h b/src/storage/prism/Label.h
new file mode 100644
index 000000000..96934adf2
--- /dev/null
+++ b/src/storage/prism/Label.h
@@ -0,0 +1,68 @@
+#ifndef STORM_STORAGE_PRISM_LABEL_H_
+#define STORM_STORAGE_PRISM_LABEL_H_
+
+#include <map>
+
+#include "src/storage/prism/LocatedInformation.h"
+#include "src/storage/expressions/Expression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace prism {
+        class Label : public LocatedInformation {
+        public:
+            /*!
+             * Creates a label with the given name and state predicate expression.
+             *
+             * @param name The name of the label.
+             * @param statePredicateExpression The predicate that needs to hold before taking a transition with the previously
+             * specified name in order to obtain the reward.
+             * @param filename The filename in which the transition reward is defined.
+             * @param lineNumber The line number in which the transition reward is defined.
+             */
+            Label(std::string const& name, storm::expressions::Expression const& statePredicateExpression, std::string const& filename = "", uint_fast64_t lineNumber = 0);
+            
+            // Create default implementations of constructors/assignment.
+            Label() = default;
+            Label(Label const& other) = default;
+            Label& operator=(Label const& other)= default;
+#ifndef WINDOWS
+            Label(Label&& other) = default;
+            Label& operator=(Label&& other) = default;
+#endif
+            
+            /*!
+             * Retrieves the name that is associated with this label.
+             *
+             * @return The name that is associated with this label.
+             */
+            std::string const& getName() const;
+            
+            /*!
+             * Retrieves the state predicate expression that is associated with this label.
+             *
+             * @return The state predicate expression that is associated with this label.
+             */
+            storm::expressions::Expression const& getStatePredicateExpression() const;
+            
+            /*!
+             * Substitutes all identifiers in the expression of the label according to the given map.
+             *
+             * @param substitution The substitution to perform.
+             * @return The resulting label.
+             */
+            Label substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const;
+            
+            friend std::ostream& operator<<(std::ostream& stream, Label const& label);
+            
+        private:
+            // The name of the label.
+            std::string name;
+            
+            // A predicate that needs to be satisfied by states for the label to be attached.
+            storm::expressions::Expression statePredicateExpression;
+        };
+    } // namespace prism
+} // namespace storm
+
+#endif /* STORM_STORAGE_PRISM_LABEL_H_ */
diff --git a/src/storage/prism/LocatedInformation.cpp b/src/storage/prism/LocatedInformation.cpp
new file mode 100644
index 000000000..a5a493319
--- /dev/null
+++ b/src/storage/prism/LocatedInformation.cpp
@@ -0,0 +1,25 @@
+#include "src/storage/prism/LocatedInformation.h"
+
+namespace storm {
+    namespace prism {
+        LocatedInformation::LocatedInformation(std::string const& filename, uint_fast64_t lineNumber) : filename(filename), lineNumber(lineNumber) {
+            // Intentionally left empty.
+        }
+
+        std::string const& LocatedInformation::getFilename() const {
+            return this->filename;
+        }
+        
+        void LocatedInformation::setFilename(std::string const& filename) {
+            this->filename = filename;
+        }
+        
+        uint_fast64_t LocatedInformation::getLineNumber() const {
+            return this->lineNumber;
+        }
+        
+        void LocatedInformation::setLineNumber(uint_fast64_t lineNumber) {
+            this->lineNumber = lineNumber;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/prism/LocatedInformation.h b/src/storage/prism/LocatedInformation.h
new file mode 100644
index 000000000..8aa4d301e
--- /dev/null
+++ b/src/storage/prism/LocatedInformation.h
@@ -0,0 +1,67 @@
+#ifndef STORM_STORAGE_PRISM_LOCATEDINFORMATION_H_
+#define STORM_STORAGE_PRISM_LOCATEDINFORMATION_H_
+
+#include <string>
+
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace prism {
+        class LocatedInformation {
+        public:
+            /*!
+             * Constructs a located information with the given filename and line number.
+             *
+             * @param filename The file in which the information was found.
+             * @param lineNumber The line number in which the information was found.
+             */
+            LocatedInformation(std::string const& filename, uint_fast64_t lineNumber);
+            
+            // Create default implementations of constructors/assignment.
+            LocatedInformation() = default;
+            LocatedInformation(LocatedInformation const& other) = default;
+            LocatedInformation& operator=(LocatedInformation const& other)= default;
+#ifndef WINDOWS
+            LocatedInformation(LocatedInformation&& other) = default;
+            LocatedInformation& operator=(LocatedInformation&& other) = default;
+#endif
+            
+            /*!
+             * Retrieves the name of the file in which the information was found.
+             *
+             * @return The name of the file in which the information was found.
+             */
+            std::string const& getFilename() const;
+            
+            /*!
+             * Sets the filename of this information.
+             *
+             * @param filename The new filename of this information.
+             */
+            void setFilename(std::string const& filename);
+            
+            /*!
+             * Retrieves the line number in which the information was found.
+             *
+             * @return The line number in which the information was found.
+             */
+            uint_fast64_t getLineNumber() const;
+            
+            /*!
+             * Sets the line number of this information.
+             *
+             * @param lineNumber The new line number for this information.
+             */
+            void setLineNumber(uint_fast64_t lineNumber);
+
+        private:
+            // The file in which the piece of information was found.
+            std::string filename;
+            
+            // The line in the file in which the piece of information was found.
+            uint_fast64_t lineNumber;
+        };
+    }
+}
+
+#endif /* STORM_STORAGE_PRISM_LOCATEDINFORMATION_H_ */
\ No newline at end of file
diff --git a/src/storage/prism/Module.cpp b/src/storage/prism/Module.cpp
new file mode 100644
index 000000000..f17e1bc12
--- /dev/null
+++ b/src/storage/prism/Module.cpp
@@ -0,0 +1,169 @@
+#include "src/storage/prism/Module.h"
+#include "src/exceptions/ExceptionMacros.h"
+#include "src/exceptions/OutOfRangeException.h"
+#include "src/exceptions/InvalidArgumentException.h"
+
+namespace storm {
+    namespace prism {
+        Module::Module(std::string const& moduleName, std::vector<storm::prism::BooleanVariable> const& booleanVariables, std::vector<storm::prism::IntegerVariable> const& integerVariables, std::vector<storm::prism::Command> const& commands, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), moduleName(moduleName), booleanVariables(booleanVariables), booleanVariableToIndexMap(), integerVariables(integerVariables), integerVariableToIndexMap(), commands(commands), actions(), actionsToCommandIndexMap() {
+            // Initialize the internal mappings for fast information retrieval.
+            this->createMappings();
+        }
+                
+        std::size_t Module::getNumberOfBooleanVariables() const {
+            return this->booleanVariables.size();
+        }
+        
+        std::size_t Module::getNumberOfIntegerVariables() const {
+            return this->integerVariables.size();
+        }
+        
+        storm::prism::BooleanVariable const& Module::getBooleanVariable(std::string const& variableName) const {
+            auto const& nameIndexPair = this->booleanVariableToIndexMap.find(variableName);
+            LOG_THROW(nameIndexPair != this->booleanVariableToIndexMap.end(), storm::exceptions::InvalidArgumentException, "Unknown boolean variable '" << variableName << "'.");
+            return this->getBooleanVariables()[nameIndexPair->second];
+        }
+        
+        std::vector<storm::prism::BooleanVariable> const& Module::getBooleanVariables() const {
+            return this->booleanVariables;
+        }
+
+        storm::prism::IntegerVariable const& Module::getIntegerVariable(std::string const& variableName) const {
+            auto const& nameIndexPair = this->integerVariableToIndexMap.find(variableName);
+            LOG_THROW(nameIndexPair != this->integerVariableToIndexMap.end(), storm::exceptions::InvalidArgumentException, "Unknown integer variable '" << variableName << "'.");
+            return this->getIntegerVariables()[nameIndexPair->second];
+        }
+        
+        std::vector<storm::prism::IntegerVariable> const& Module::getIntegerVariables() const {
+            return this->integerVariables;
+        }
+        
+        std::size_t Module::getNumberOfCommands() const {
+            return this->commands.size();
+        }
+        
+        std::size_t Module::getNumberOfUpdates() const {
+            std::size_t result = 0;
+            for (auto const& command : this->getCommands()) {
+                result += command.getNumberOfUpdates();
+            }
+            return result;
+        }
+        
+        storm::prism::Command const& Module::getCommand(uint_fast64_t index) const {
+            return this->commands[index];
+        }
+        
+        std::vector<storm::prism::Command> const& Module::getCommands() const {
+            return this->commands;
+        }
+        
+        std::string const& Module::getName() const {
+            return this->moduleName;
+        }
+        
+        std::set<std::string> const& Module::getActions() const {
+            return this->actions;
+        }
+        
+        bool Module::hasAction(std::string const& action) const {
+            auto const& actionEntry = this->actions.find(action);
+            return actionEntry != this->actions.end();
+        }
+        
+        std::set<uint_fast64_t> const& Module::getCommandIndicesByAction(std::string const& action) const {
+            auto actionsCommandSetPair = this->actionsToCommandIndexMap.find(action);
+            if (actionsCommandSetPair != this->actionsToCommandIndexMap.end()) {
+                return actionsCommandSetPair->second;
+            }
+            
+            LOG_THROW(false, storm::exceptions::OutOfRangeException, "Action name '" << action << "' does not exist in module.");
+        }
+        
+        void Module::createMappings() {
+            // Clear the current mappings.
+            this->actionsToCommandIndexMap.clear();
+            this->booleanVariableToIndexMap.clear();
+            this->integerVariableToIndexMap.clear();
+            
+            // Create the mappings for the variables.
+            for (uint_fast64_t i = 0; i < this->booleanVariables.size(); ++i) {
+                this->booleanVariableToIndexMap[this->getBooleanVariables()[i].getName()] = i;
+            }
+            for (uint_fast64_t i = 0; i < this->integerVariables.size(); ++i) {
+                this->integerVariableToIndexMap[this->getIntegerVariables()[i].getName()] = i;
+            }
+            
+            // Add the mapping for all commands.
+            for (uint_fast64_t i = 0; i < this->commands.size(); i++) {
+                std::string const& action = this->commands[i].getActionName();
+                if (action != "") {
+                    if (this->actionsToCommandIndexMap.find(action) == this->actionsToCommandIndexMap.end()) {
+                        this->actionsToCommandIndexMap.emplace(action, std::set<uint_fast64_t>());
+                    }
+                    this->actionsToCommandIndexMap[action].insert(i);
+                    this->actions.insert(action);
+                }
+            }
+            
+            // For all actions that are "in the module", but for which no command exists, we add the mapping to an empty
+            // set of commands.
+            for (auto const& action : this->actions) {
+                if (this->actionsToCommandIndexMap.find(action) == this->actionsToCommandIndexMap.end()) {
+                    this->actionsToCommandIndexMap[action] = std::set<uint_fast64_t>();
+                }
+            }
+        }
+        
+        Module Module::restrictCommands(boost::container::flat_set<uint_fast64_t> const& indexSet) const {
+            // First construct the new vector of commands.
+            std::vector<storm::prism::Command> newCommands;
+            for (auto const& command : commands) {
+                if (indexSet.find(command.getGlobalIndex()) != indexSet.end()) {
+                    newCommands.push_back(command);
+                }
+            }
+            
+            return Module(this->getName(), this->getBooleanVariables(), this->getIntegerVariables(), newCommands);
+        }
+        
+        Module Module::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const {
+            std::vector<BooleanVariable> newBooleanVariables;
+            newBooleanVariables.reserve(this->getNumberOfBooleanVariables());
+            for (auto const& booleanVariable : this->getBooleanVariables()) {
+                newBooleanVariables.emplace_back(booleanVariable.substitute(substitution));
+            }
+            
+            std::vector<IntegerVariable> newIntegerVariables;
+            newBooleanVariables.reserve(this->getNumberOfIntegerVariables());
+            for (auto const& integerVariable : this->getIntegerVariables()) {
+                newIntegerVariables.emplace_back(integerVariable.substitute(substitution));
+            }
+            
+            std::vector<Command> newCommands;
+            newCommands.reserve(this->getNumberOfCommands());
+            for (auto const& command : this->getCommands()) {
+                newCommands.emplace_back(command.substitute(substitution));
+            }
+            
+            return Module(this->getName(), newBooleanVariables, newIntegerVariables, newCommands, this->getFilename(), this->getLineNumber());
+        }
+        
+        std::ostream& operator<<(std::ostream& stream, Module const& module) {
+            stream << "module " << module.getName() << std::endl;
+            for (auto const& booleanVariable : module.getBooleanVariables()) {
+                stream << "\t" << booleanVariable << std::endl;
+            }
+            for (auto const& integerVariable : module.getIntegerVariables()) {
+                stream << "\t" << integerVariable << std::endl;
+            }
+            for (auto const& command : module.getCommands()) {
+                stream << "\t" << command << std::endl;
+            }
+            stream << "endmodule" << std::endl;
+            return stream;
+        }
+
+        
+    } // namespace ir
+} // namespace storm
diff --git a/src/storage/prism/Module.h b/src/storage/prism/Module.h
new file mode 100644
index 000000000..f4fd21f29
--- /dev/null
+++ b/src/storage/prism/Module.h
@@ -0,0 +1,196 @@
+#ifndef STORM_STORAGE_PRISM_MODULE_H_
+#define STORM_STORAGE_PRISM_MODULE_H_
+
+#include <set>
+#include <string>
+#include <vector>
+#include <memory>
+#include <boost/container/flat_set.hpp>
+
+#include "src/storage/prism/BooleanVariable.h"
+#include "src/storage/prism/IntegerVariable.h"
+#include "src/storage/prism/Command.h"
+#include "src/storage/expressions/VariableExpression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace prism {
+        class Module : public LocatedInformation {
+        public:
+            /*!
+             * Creates a module with the given name, variables and commands.
+             *
+             * @param moduleName The name of the module.
+             * @param booleanVariables The boolean variables defined by the module.
+             * @param integerVariables The integer variables defined by the module.
+             * @param commands The commands of the module.
+             * @param filename The filename in which the module is defined.
+             * @param lineNumber The line number in which the module is defined.
+             */
+            Module(std::string const& moduleName, std::vector<storm::prism::BooleanVariable> const& booleanVariables, std::vector<storm::prism::IntegerVariable> const& integerVariables, std::vector<storm::prism::Command> const& commands, std::string const& filename = "", uint_fast64_t lineNumber = 0);
+            
+            // Create default implementations of constructors/assignment.
+            Module() = default;
+            Module(Module const& other) = default;
+            Module& operator=(Module const& other)= default;
+#ifndef WINDOWS
+            Module(Module&& other) = default;
+            Module& operator=(Module&& other) = default;
+#endif
+            
+            /*!
+             * Retrieves the number of boolean variables in the module.
+             *
+             * @return the number of boolean variables in the module.
+             */
+            std::size_t getNumberOfBooleanVariables() const;
+            
+            /*!
+             * Retrieves the number of integer variables in the module.
+             *
+             * @return The number of integer variables in the module.
+             */
+            std::size_t getNumberOfIntegerVariables() const;
+            
+            /*!
+             * Retrieves a reference to the boolean variable with the given name.
+             *
+             * @param variableName The name of the boolean variable to retrieve.
+             * @return A reference to the boolean variable with the given name.
+             */
+            storm::prism::BooleanVariable const& getBooleanVariable(std::string const& variableName) const;
+            
+            /*!
+             * Retrieves the boolean variables of the module.
+             *
+             * @return The boolean variables of the module.
+             */
+            std::vector<storm::prism::BooleanVariable> const& getBooleanVariables() const;
+            
+            /*!
+             * Retrieves a reference to the integer variable with the given name.
+             *
+             * @param variableName The name of the integer variable to retrieve.
+             * @return A reference to the integer variable with the given name.
+             */
+            storm::prism::IntegerVariable const& getIntegerVariable(std::string const& variableName) const;
+
+            /*!
+             * Retrieves the integer variables of the module.
+             *
+             * @return The integer variables of the module.
+             */
+            std::vector<storm::prism::IntegerVariable> const& getIntegerVariables() const;
+
+            /*!
+             * Retrieves the number of commands of this module.
+             *
+             * @return The number of commands of this module.
+             */
+            std::size_t getNumberOfCommands() const;
+            
+            /*!
+             * Retrieves the total number of updates of this module.
+             *
+             * @return The total number of updates of this module.
+             */
+            std::size_t getNumberOfUpdates() const;
+            
+            /*!
+             * Retrieves a reference to the command with the given index.
+             *
+             * @param index The index of the command to retrieve.
+             * @return A reference to the command with the given index.
+             */
+            storm::prism::Command const& getCommand(uint_fast64_t index) const;
+            
+            /*!
+             * Retrieves the commands of the module.
+             *
+             * @return The commands of the module.
+             */
+            std::vector<storm::prism::Command> const& getCommands() const;
+            
+            /*!
+             * Retrieves the name of the module.
+             *
+             * @return The name of the module.
+             */
+            std::string const& getName() const;
+            
+            /*!
+             * Retrieves the set of actions present in this module.
+             *
+             * @return the set of actions present in this module.
+             */
+            std::set<std::string> const& getActions() const;
+            
+            /*!
+             * Retrieves whether or not this module contains a command labeled with the given action.
+             *
+             * @param action The action name to look for in this module.
+             * @return True iff the module has at least one command labeled with the given action.
+             */
+            bool hasAction(std::string const& action) const;
+            
+            /*!
+             * Retrieves the indices of all commands within this module that are labelled by the given action.
+             *
+             * @param action The action with which the commands have to be labelled.
+             * @return A set of indices of commands that are labelled with the given action.
+             */
+            std::set<uint_fast64_t> const& getCommandIndicesByAction(std::string const& action) const;
+            
+            /*!
+             * Creates a new module that drops all commands whose indices are not in the given set.
+             *
+             * @param indexSet The set of indices for which to keep the commands.
+             * @return The module resulting from erasing all commands whose indices are not in the given set.
+             */
+            Module restrictCommands(boost::container::flat_set<uint_fast64_t> const& indexSet) const;
+            
+            /*!
+             * Substitutes all identifiers in the module according to the given map.
+             *
+             * @param substitution The substitution to perform.
+             * @return The resulting module.
+             */
+            Module substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const;
+            
+            friend std::ostream& operator<<(std::ostream& stream, Module const& module);
+
+        private:
+            /*!
+             * Computes the locally maintained mappings for fast data retrieval.
+             */
+            void createMappings();
+            
+            // The name of the module.
+            std::string moduleName;
+            
+            // A list of boolean variables.
+            std::vector<storm::prism::BooleanVariable> booleanVariables;
+            
+            // A mapping from boolean variables to the corresponding indices in the vector.
+            std::map<std::string, uint_fast64_t> booleanVariableToIndexMap;
+            
+            // A list of integer variables.
+            std::vector<storm::prism::IntegerVariable> integerVariables;
+
+            // A mapping from integer variables to the corresponding indices in the vector.
+            std::map<std::string, uint_fast64_t> integerVariableToIndexMap;
+
+            // The commands associated with the module.
+            std::vector<storm::prism::Command> commands;
+            
+            // The set of actions present in this module.
+            std::set<std::string> actions;
+            
+            // A map of actions to the set of commands labeled with this action.
+            std::map<std::string, std::set<uint_fast64_t>> actionsToCommandIndexMap;
+        };
+        
+    } // namespace prism
+} // namespace storm
+
+#endif /* STORM_STORAGE_PRISM_MODULE_H_ */
diff --git a/src/storage/prism/Program.cpp b/src/storage/prism/Program.cpp
new file mode 100644
index 000000000..cdbba3e22
--- /dev/null
+++ b/src/storage/prism/Program.cpp
@@ -0,0 +1,365 @@
+#include "src/storage/prism/Program.h"
+#include "src/exceptions/ExceptionMacros.h"
+#include "exceptions/InvalidArgumentException.h"
+#include "src/exceptions/OutOfRangeException.h"
+
+namespace storm {
+    namespace prism {
+        Program::Program(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::vector<RewardModel> const& rewardModels, bool hasInitialStatesExpression, storm::expressions::Expression const& initialStatesExpression, std::vector<Label> const& labels, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), modelType(modelType), constants(constants), constantToIndexMap(), globalBooleanVariables(globalBooleanVariables), globalBooleanVariableToIndexMap(), globalIntegerVariables(globalIntegerVariables), globalIntegerVariableToIndexMap(), formulas(formulas), formulaToIndexMap(), modules(modules), moduleToIndexMap(), rewardModels(rewardModels), rewardModelToIndexMap(), hasInitialStatesExpression(hasInitialStatesExpression), initialStatesExpression(initialStatesExpression), labels(labels), labelToIndexMap(), actions(), actionsToModuleIndexMap(), variableToModuleIndexMap() {
+            this->createMappings();
+        }
+        
+        Program::ModelType Program::getModelType() const {
+            return modelType;
+        }
+        
+        bool Program::hasUndefinedConstants() const {
+            for (auto const& constant : this->getConstants()) {
+                if (!constant.isDefined()) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        
+        bool Program::hasConstant(std::string const& constantName) const {
+            return this->constantToIndexMap.find(constantName) != this->constantToIndexMap.end();
+        }
+        
+        Constant const& Program::getConstant(std::string const& constantName) const {
+            auto const& constantIndexPair = this->constantToIndexMap.find(constantName);
+            return this->getConstants()[constantIndexPair->second];
+        }
+        
+        std::vector<Constant> const& Program::getConstants() const {
+            return this->constants;
+        }
+        
+        std::size_t Program::getNumberOfConstants() const {
+            return this->getConstants().size();
+        }
+
+        std::vector<BooleanVariable> const& Program::getGlobalBooleanVariables() const {
+            return this->globalBooleanVariables;
+        }
+        
+        std::vector<IntegerVariable> const& Program::getGlobalIntegerVariables() const {
+            return this->globalIntegerVariables;
+        }
+
+        BooleanVariable const& Program::getGlobalBooleanVariable(std::string const& variableName) const {
+            auto const& nameIndexPair = this->globalBooleanVariableToIndexMap.find(variableName);
+            LOG_THROW(nameIndexPair != this->globalBooleanVariableToIndexMap.end(), storm::exceptions::OutOfRangeException, "Unknown boolean variable '" << variableName << "'.");
+            return this->getGlobalBooleanVariables()[nameIndexPair->second];
+        }
+
+        IntegerVariable const& Program::getGlobalIntegerVariable(std::string const& variableName) const {
+            auto const& nameIndexPair = this->globalIntegerVariableToIndexMap.find(variableName);
+            LOG_THROW(nameIndexPair != this->globalIntegerVariableToIndexMap.end(), storm::exceptions::OutOfRangeException, "Unknown integer variable '" << variableName << "'.");
+            return this->getGlobalIntegerVariables()[nameIndexPair->second];
+        }
+        
+        std::size_t Program::getNumberOfGlobalBooleanVariables() const {
+            return this->getGlobalBooleanVariables().size();
+        }
+        
+        std::size_t Program::getNumberOfGlobalIntegerVariables() const {
+            return this->getGlobalIntegerVariables().size();
+        }
+        
+        std::vector<Formula> const& Program::getFormulas() const {
+            return this->formulas;
+        }
+        
+        std::size_t Program::getNumberOfFormulas() const {
+            return this->getFormulas().size();
+        }
+        
+        std::size_t Program::getNumberOfModules() const {
+            return this->getModules().size();
+        }
+        
+        storm::prism::Module const& Program::getModule(uint_fast64_t index) const {
+            return this->modules[index];
+        }
+        
+        Module const& Program::getModule(std::string const& moduleName) const {
+            auto const& nameIndexPair = this->moduleToIndexMap.find(moduleName);
+            LOG_THROW(nameIndexPair != this->moduleToIndexMap.end(), storm::exceptions::OutOfRangeException, "Unknown module '" << moduleName << "'.");
+            return this->getModules()[nameIndexPair->second];
+        }
+        
+        std::vector<storm::prism::Module> const& Program::getModules() const {
+            return this->modules;
+        }
+        
+        bool Program::definesInitialStatesExpression() const {
+            return this->hasInitialStatesExpression;
+        }
+        
+        storm::expressions::Expression Program::getInitialStatesExpression() const {
+            // If the program specifies the initial states explicitly, we simply return the expression.
+            if (this->definesInitialStatesExpression()) {
+                return this->initialStatesExpression;
+            } else {
+                // Otherwise, we need to assert that all variables are equal to their initial value.
+                storm::expressions::Expression result = storm::expressions::Expression::createTrue();
+                
+                for (auto const& module : this->getModules()) {
+                    for (auto const& booleanVariable : module.getBooleanVariables()) {
+                        result = result && (storm::expressions::Expression::createBooleanVariable(booleanVariable.getName()).iff(booleanVariable.getInitialValueExpression()));
+                    }
+                    for (auto const& integerVariable : module.getIntegerVariables()) {
+                        result = result && (storm::expressions::Expression::createIntegerVariable(integerVariable.getName()) == integerVariable.getInitialValueExpression());
+                    }
+                }
+                return result;
+            }
+        }
+        
+        std::set<std::string> const& Program::getActions() const {
+            return this->actions;
+        }
+        
+        std::set<uint_fast64_t> const& Program::getModuleIndicesByAction(std::string const& action) const {
+            auto const& actionModuleSetPair = this->actionsToModuleIndexMap.find(action);
+            LOG_THROW(actionModuleSetPair != this->actionsToModuleIndexMap.end(), storm::exceptions::OutOfRangeException, "Action name '" << action << "' does not exist.");
+            return actionModuleSetPair->second;
+        }
+        
+        uint_fast64_t Program::getModuleIndexByVariable(std::string const& variableName) const {
+            auto const& variableNameToModuleIndexPair = this->variableToModuleIndexMap.find(variableName);
+            LOG_THROW(variableNameToModuleIndexPair != this->variableToModuleIndexMap.end(), storm::exceptions::OutOfRangeException, "Variable '" << variableName << "' does not exist.");
+            return variableNameToModuleIndexPair->second;
+        }
+        
+        std::vector<storm::prism::RewardModel> const& Program::getRewardModels() const {
+            return this->rewardModels;
+        }
+        
+        std::size_t Program::getNumberOfRewardModels() const {
+            return this->getRewardModels().size();
+        }
+        
+        storm::prism::RewardModel const& Program::getRewardModel(std::string const& name) const {
+            auto const& nameIndexPair = this->rewardModelToIndexMap.find(name);
+            LOG_THROW(nameIndexPair != this->rewardModelToIndexMap.end(), storm::exceptions::OutOfRangeException, "Reward model '" << name << "' does not exist.");
+            return this->getRewardModels()[nameIndexPair->second];
+        }
+        
+        std::vector<Label> const& Program::getLabels() const {
+            return this->labels;
+        }
+        
+        std::size_t Program::getNumberOfLabels() const {
+            return this->getLabels().size();
+        }
+        
+        Program Program::restrictCommands(boost::container::flat_set<uint_fast64_t> const& indexSet) const {
+            std::vector<storm::prism::Module> newModules;
+            newModules.reserve(this->getNumberOfModules());
+            
+            for (auto const& module : this->getModules()) {
+                newModules.push_back(module.restrictCommands(indexSet));
+            }
+            
+            return Program(this->getModelType(), this->getConstants(), this->getGlobalBooleanVariables(), this->getGlobalIntegerVariables(), this->getFormulas(), newModules, this->getRewardModels(), this->definesInitialStatesExpression(), this->getInitialStatesExpression(), this->getLabels());
+        }
+        
+        void Program::createMappings() {
+            // Build the mappings for constants, global variables, formulas, modules, reward models and labels.
+            for (uint_fast64_t constantIndex = 0; constantIndex < this->getNumberOfConstants(); ++constantIndex) {
+                this->constantToIndexMap[this->getConstants()[constantIndex].getName()] = constantIndex;
+            }
+            for (uint_fast64_t globalVariableIndex = 0; globalVariableIndex < this->getNumberOfGlobalBooleanVariables(); ++globalVariableIndex) {
+                this->globalBooleanVariableToIndexMap[this->getGlobalBooleanVariables()[globalVariableIndex].getName()] = globalVariableIndex;
+            }
+            for (uint_fast64_t globalVariableIndex = 0; globalVariableIndex < this->getNumberOfGlobalIntegerVariables(); ++globalVariableIndex) {
+                this->globalIntegerVariableToIndexMap[this->getGlobalIntegerVariables()[globalVariableIndex].getName()] = globalVariableIndex;
+            }
+            for (uint_fast64_t formulaIndex = 0; formulaIndex < this->getNumberOfFormulas(); ++formulaIndex) {
+                this->formulaToIndexMap[this->getFormulas()[formulaIndex].getName()] = formulaIndex;
+            }
+            for (uint_fast64_t moduleIndex = 0; moduleIndex < this->getNumberOfModules(); ++moduleIndex) {
+                this->moduleToIndexMap[this->getModules()[moduleIndex].getName()] = moduleIndex;
+            }
+            for (uint_fast64_t rewardModelIndex = 0; rewardModelIndex < this->getNumberOfRewardModels(); ++rewardModelIndex) {
+                this->rewardModelToIndexMap[this->getRewardModels()[rewardModelIndex].getName()] = rewardModelIndex;
+            }
+            for (uint_fast64_t labelIndex = 0; labelIndex < this->getNumberOfLabels(); ++labelIndex) {
+                this->labelToIndexMap[this->getLabels()[labelIndex].getName()] = labelIndex;
+            }
+            
+            // Build the mapping from action names to module indices so that the lookup can later be performed quickly.
+            for (unsigned int moduleIndex = 0; moduleIndex < this->getNumberOfModules(); moduleIndex++) {
+                Module const& module = this->getModule(moduleIndex);
+                
+                for (auto const& action : module.getActions()) {
+                    auto const& actionModuleIndicesPair = this->actionsToModuleIndexMap.find(action);
+                    if (actionModuleIndicesPair == this->actionsToModuleIndexMap.end()) {
+                        this->actionsToModuleIndexMap[action] = std::set<uint_fast64_t>();
+                    }
+                    this->actionsToModuleIndexMap[action].insert(moduleIndex);
+                    this->actions.insert(action);
+                }
+                
+                // Put in the appropriate entries for the mapping from variable names to module index.
+                for (auto const& booleanVariable : module.getBooleanVariables()) {
+                    this->variableToModuleIndexMap[booleanVariable.getName()] = moduleIndex;
+                }
+                for (auto const& integerVariable : module.getBooleanVariables()) {
+                    this->variableToModuleIndexMap[integerVariable.getName()] = moduleIndex;
+                }
+            }
+
+        }
+        
+        Program Program::defineUndefinedConstants(std::map<std::string, storm::expressions::Expression> const& constantDefinitions) const {
+            // For sanity checking, we keep track of all undefined constants that we define in the course of this
+            // procedure.
+            std::set<std::string> definedUndefinedConstants;
+            
+            std::vector<Constant> newConstants;
+            newConstants.reserve(this->getNumberOfConstants());
+            for (auto const& constant : this->getConstants()) {
+                // If the constant is already defined, we need to replace the appearances of undefined constants in its
+                // defining expression
+                if (constant.isDefined()) {
+                    // Make sure we are not trying to define an already defined constant.
+                    LOG_THROW(constantDefinitions.find(constant.getName()) == constantDefinitions.end(), storm::exceptions::InvalidArgumentException, "Illegally defining already defined constant '" << constant.getName() << "'.");
+                    
+                    // Now replace the occurrences of undefined constants in its defining expression.
+                    newConstants.emplace_back(constant.getType(), constant.getName(), constant.getExpression().substitute<std::map>(constantDefinitions), constant.getFilename(), constant.getLineNumber());
+                } else {
+                    auto const& variableExpressionPair = constantDefinitions.find(constant.getName());
+                    
+                    // If the constant is not defined by the mapping, we leave it like it is.
+                    if (variableExpressionPair == constantDefinitions.end()) {
+                        newConstants.emplace_back(constant);
+                    } else {
+                        // Otherwise, we add it to the defined constants and assign it the appropriate expression.
+                        definedUndefinedConstants.insert(constant.getName());
+                        
+                        // Make sure the type of the constant is correct.
+                        LOG_THROW(variableExpressionPair->second.getReturnType() == constant.getType(), storm::exceptions::InvalidArgumentException, "Illegal type of expression defining constant '" << constant.getName() << "'.");
+                        
+                        // Now create the defined constant.
+                        newConstants.emplace_back(constant.getType(), constant.getName(), variableExpressionPair->second, constant.getFilename(), constant.getLineNumber());
+                    }
+                }
+            }
+            
+            // As a sanity check, we make sure that the given mapping does not contain any definitions for identifiers
+            // that are not undefined constants.
+            for (auto const& constantExpressionPair : constantDefinitions) {
+                LOG_THROW(definedUndefinedConstants.find(constantExpressionPair.first) != definedUndefinedConstants.end(), storm::exceptions::InvalidArgumentException, "Unable to define non-existant constant.");
+            }
+            
+            return Program(this->getModelType(), newConstants, this->getGlobalBooleanVariables(), this->getGlobalIntegerVariables(), this->getFormulas(), this->getModules(), this->getRewardModels(), this->definesInitialStatesExpression(), this->getInitialStatesExpression(), this->getLabels());
+        }
+        
+        Program Program::substituteConstants() const {
+            // We start by creating the appropriate substitution
+            std::map<std::string, storm::expressions::Expression> constantSubstitution;
+            std::vector<Constant> newConstants(this->getConstants());
+            for (uint_fast64_t constantIndex = 0; constantIndex < newConstants.size(); ++constantIndex) {
+                auto const& constant = newConstants[constantIndex];
+                LOG_THROW(constant.isDefined(), storm::exceptions::InvalidArgumentException, "Cannot substitute constants in program that contains undefined constants.");
+                
+                // Put the corresponding expression in the substitution.
+                constantSubstitution.emplace(constant.getName(), constant.getExpression());
+                
+                // If there is at least one more constant to come, we substitute the costants we have so far.
+                if (constantIndex + 1 < newConstants.size()) {
+                    newConstants[constantIndex + 1] = newConstants[constantIndex + 1].substitute(constantSubstitution);
+                }
+            }
+            
+            // Now we can substitute the constants in all expressions appearing in the program.
+            std::vector<BooleanVariable> newBooleanVariables;
+            newBooleanVariables.reserve(this->getNumberOfGlobalBooleanVariables());
+            for (auto const& booleanVariable : this->getGlobalBooleanVariables()) {
+                newBooleanVariables.emplace_back(booleanVariable.substitute(constantSubstitution));
+            }
+            
+            std::vector<IntegerVariable> newIntegerVariables;
+            newBooleanVariables.reserve(this->getNumberOfGlobalIntegerVariables());
+            for (auto const& integerVariable : this->getGlobalIntegerVariables()) {
+                newIntegerVariables.emplace_back(integerVariable.substitute(constantSubstitution));
+            }
+            
+            std::vector<Formula> newFormulas;
+            newFormulas.reserve(this->getNumberOfFormulas());
+            for (auto const& formula : this->getFormulas()) {
+                newFormulas.emplace_back(formula.substitute(constantSubstitution));
+            }
+            
+            std::vector<Module> newModules;
+            newModules.reserve(this->getNumberOfModules());
+            for (auto const& module : this->getModules()) {
+                newModules.emplace_back(module.substitute(constantSubstitution));
+            }
+            
+            std::vector<RewardModel> newRewardModels;
+            newRewardModels.reserve(this->getNumberOfRewardModels());
+            for (auto const& rewardModel : this->getRewardModels()) {
+                newRewardModels.emplace_back(rewardModel.substitute(constantSubstitution));
+            }
+            
+            storm::expressions::Expression newInitialStateExpression = this->getInitialStatesExpression().substitute<std::map>(constantSubstitution);
+            
+            std::vector<Label> newLabels;
+            newLabels.reserve(this->getNumberOfLabels());
+            for (auto const& label : this->getLabels()) {
+                newLabels.emplace_back(label.substitute(constantSubstitution));
+            }
+            
+            return Program(this->getModelType(), newConstants, newBooleanVariables, newIntegerVariables, newFormulas, newModules, newRewardModels, this->definesInitialStatesExpression(), newInitialStateExpression, newLabels);
+        }
+        
+        std::ostream& operator<<(std::ostream& stream, Program const& program) {
+            switch (program.getModelType()) {
+                case Program::ModelType::UNDEFINED: stream << "undefined"; break;
+                case Program::ModelType::DTMC: stream << "dtmc"; break;
+                case Program::ModelType::CTMC: stream << "ctmc"; break;
+                case Program::ModelType::MDP: stream << "mdp"; break;
+                case Program::ModelType::CTMDP: stream << "ctmdp"; break;
+                case Program::ModelType::MA: stream << "ma"; break;
+            }
+            stream << std::endl;
+            
+            for (auto const& constant : program.getConstants()) {
+                stream << constant << std::endl;
+            }
+            stream << std::endl;
+            
+            for (auto const& variable : program.getGlobalBooleanVariables()) {
+                stream << "global " << variable << std::endl;
+            }
+            for (auto const& variable : program.getGlobalIntegerVariables()) {
+                stream << "global " << variable << std::endl;
+            }
+            stream << std::endl;
+            
+            for (auto const& formula : program.getFormulas()) {
+                stream << formula << std::endl;
+            }
+            stream << std::endl;
+            
+            for (auto const& module : program.getModules()) {
+                stream << module << std::endl;
+            }
+            
+            for (auto const& rewardModel : program.getRewardModels()) {
+                stream << rewardModel << std::endl;
+            }
+            
+            for (auto const& label : program.getLabels()) {
+                stream << label << std::endl;
+            }
+            
+            return stream;
+        }
+        
+    } // namespace ir
+} // namepsace storm
diff --git a/src/storage/prism/Program.h b/src/storage/prism/Program.h
new file mode 100644
index 000000000..40f8047e1
--- /dev/null
+++ b/src/storage/prism/Program.h
@@ -0,0 +1,359 @@
+#ifndef STORM_STORAGE_PRISM_PROGRAM_H_
+#define STORM_STORAGE_PRISM_PROGRAM_H_
+
+#include <map>
+#include <vector>
+#include <set>
+#include <boost/container/flat_set.hpp>
+
+#include "src/storage/expressions/Expression.h"
+#include "src/storage/prism/Constant.h"
+#include "src/storage/prism/Formula.h"
+#include "src/storage/prism/Label.h"
+#include "src/storage/prism/Module.h"
+#include "src/storage/prism/RewardModel.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace prism {
+        class Program : public LocatedInformation {
+        public:
+            /*!
+             * An enum for the different model types.
+             */
+            enum class ModelType {UNDEFINED, DTMC, CTMC, MDP, CTMDP, MA};
+            
+            /*!
+             * Creates a program with the given model type, undefined constants, global variables, modules, reward
+             * models, labels and initial states.
+             *
+             * @param modelType The type of the program.
+             * @param constants The constants of the program.
+             * @param globalBooleanVariables The global boolean variables of the program.
+             * @param globalIntegerVariables The global integer variables of the program.
+             * @param formulas The formulas defined in the program.
+             * @param modules The modules of the program.
+             * @param hasInitialStatesExpression A flag indicating whether the program specifies its initial states via
+             * an explicit initial construct.
+             * @param initialStatesExpression If the model specifies an explicit initial construct, this
+             * expression defines its initial states. Otherwise it is irrelevant and may be set to an arbitrary (but
+             * valid) expression, e.g. false.
+             * @param rewardModels The reward models of the program.
+             * @param labels The labels defined for this program.
+             * @param filename The filename in which the program is defined.
+             * @param lineNumber The line number in which the program is defined.
+             */
+            Program(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::vector<RewardModel> const& rewardModels, bool hasInitialStatesExpression, storm::expressions::Expression const& initialStatesExpression, std::vector<Label> const& labels, std::string const& filename = "", uint_fast64_t lineNumber = 0);
+            
+            // Provide default implementations for constructors and assignments.
+            Program() = default;
+            Program(Program const& other) = default;
+            Program& operator=(Program const& other) = default;
+#ifndef WINDOWS
+            Program(Program&& other) = default;
+            Program& operator=(Program&& other) = default;
+#endif
+            
+            /*!
+             * Retrieves the model type of the model.
+             *
+             * @return The type of the model.
+             */
+            ModelType getModelType() const;
+
+            /*!
+             * Retrieves whether there are undefined constants of any type in the program.
+             *
+             * @return True iff there are undefined constants of any type in the program.
+             */
+            bool hasUndefinedConstants() const;
+
+            /*!
+             * Retrieves whether the given constant exists in the program.
+             *
+             * @param constantName The name of the constant to search.
+             * @return True iff the constant exists in the program.
+             */
+            bool hasConstant(std::string const& constantName) const;
+            
+            /*!
+             * Retrieves the constant with the given name if it exists.
+             *
+             * @param constantName The name of the constant to retrieve.
+             * @return The constant with the given name if it exists.
+             */
+            Constant const& getConstant(std::string const& constantName) const;
+            
+            /*!
+             * Retrieves all constants defined in the program.
+             *
+             * @return The constants defined in the program.
+             */
+            std::vector<Constant> const& getConstants() const;
+            
+            /*!
+             * Retrieves the number of all constants defined in the program.
+             *
+             * @return The number of constants defined in the program.
+             */
+            std::size_t getNumberOfConstants() const;
+            
+            /*!
+             * Retrieves the global boolean variables of the program.
+             *
+             * @return The global boolean variables of the program.
+             */
+            std::vector<BooleanVariable> const& getGlobalBooleanVariables() const;
+            
+            /*!
+             * Retrieves a the global boolean variable with the given name.
+             *
+             * @param variableName The name of the global boolean variable to retrieve.
+             * @return The global boolean variable with the given name.
+             */
+            BooleanVariable const& getGlobalBooleanVariable(std::string const& variableName) const;
+            
+            /*!
+             * Retrieves the global integer variables of the program.
+             *
+             * @return The global integer variables of the program.
+             */
+            std::vector<IntegerVariable> const& getGlobalIntegerVariables() const;
+
+            /*!
+             * Retrieves a the global integer variable with the given name.
+             *
+             * @param variableName The name of the global integer variable to retrieve.
+             * @return The global integer variable with the given name.
+             */
+            IntegerVariable const& getGlobalIntegerVariable(std::string const& variableName) const;
+
+            /*!
+             * Retrieves the number of global boolean variables of the program.
+             *
+             * @return The number of global boolean variables of the program.
+             */
+            std::size_t getNumberOfGlobalBooleanVariables() const;
+            
+            /*!
+             * Retrieves the number of global integer variables of the program.
+             *
+             * @return The number of global integer variables of the program.
+             */
+            std::size_t getNumberOfGlobalIntegerVariables() const;
+
+            /*!
+             * Retrieves the formulas defined in the program.
+             *
+             * @return The formulas defined in the program.
+             */
+            std::vector<Formula> const& getFormulas() const;
+            
+            /*!
+             * Retrieves the number of formulas in the program.
+             *
+             * @return The number of formulas in the program.
+             */
+            std::size_t getNumberOfFormulas() const;
+            
+            /*!
+             * Retrieves the number of modules in the program.
+             *
+             * @return The number of modules in the program.
+             */
+            std::size_t getNumberOfModules() const;
+            
+            /*!
+             * Retrieves the module with the given index.
+             *
+             * @param index The index of the module to retrieve.
+             * @return The module with the given index.
+             */
+            Module const& getModule(uint_fast64_t index) const;
+
+            /*!
+             * Retrieves the module with the given name.
+             *
+             * @param moduleName The name of the module to retrieve.
+             * @return The module with the given name.
+             */
+            Module const& getModule(std::string const& moduleName) const;
+            
+            /*!
+             * Retrieves all modules of the program.
+             *
+             * @return All modules of the program.
+             */
+            std::vector<Module> const& getModules() const;
+            
+            /*!
+             * Retrieves whether the program explicitly specifies an expression characterizing the initial states.
+             *
+             * @return True iff the program specifies an expression defining the initial states.
+             */
+            bool definesInitialStatesExpression() const;
+            
+            /*!
+             * Retrieves an expression characterizing the initial states of the program.
+             *
+             * @return An expression characterizing the initial states.
+             */
+            storm::expressions::Expression getInitialStatesExpression() const;
+            
+            /*!
+             * Retrieves the set of actions present in the program.
+             *
+             * @return The set of actions present in the program.
+             */
+            std::set<std::string> const& getActions() const;
+            
+            /*!
+             * Retrieves the indices of all modules within this program that contain commands that are labelled with the
+             * given action.
+             *
+             * @param action The name of the action the modules are supposed to possess.
+             * @return A set of indices of all matching modules.
+             */
+            std::set<uint_fast64_t> const& getModuleIndicesByAction(std::string const& action) const;
+            
+            /*!
+             * Retrieves the index of the module in which the given variable name was declared.
+             *
+             * @param variableName The name of the variable to search.
+             * @return The index of the module in which the given variable name was declared.
+             */
+            uint_fast64_t getModuleIndexByVariable(std::string const& variableName) const;
+            
+            /*!
+             * Retrieves the reward models of the program.
+             *
+             * @return The reward models of the program.
+             */
+            std::vector<RewardModel> const& getRewardModels() const;
+            
+            /*!
+             * Retrieves the number of reward models in the program.
+             *
+             * @return The number of reward models in the program.
+             */
+            std::size_t getNumberOfRewardModels() const;
+            
+            /*!
+             * Retrieves the reward model with the given name.
+             *
+             * @param rewardModelName The name of the reward model to return.
+             * @return The reward model with the given name.
+             */
+            RewardModel const& getRewardModel(std::string const& rewardModelName) const;
+            
+            /*!
+             * Retrieves all labels that are defined by the probabilitic program.
+             *
+             * @return A set of labels that are defined in the program.
+             */
+            std::vector<Label> const& getLabels() const;
+            
+            /*!
+             * Retrieves the number of labels in the program.
+             *
+             * @return The number of labels in the program.
+             */
+            std::size_t getNumberOfLabels() const;
+
+            /*!
+             * Creates a new program that drops all commands whose indices are not in the given set.
+             *
+             * @param indexSet The set of indices for which to keep the commands.
+             */
+            Program restrictCommands(boost::container::flat_set<uint_fast64_t> const& indexSet) const;
+            
+            /*!
+             * Defines the undefined constants according to the given map and returns the resulting program.
+             *
+             * @param constantDefinitions A mapping from undefined constant names to the expressions they are supposed
+             * to be replaced with.
+             * @return The program after all undefined constants in the given map have been replaced with their
+             * definitions.
+             */
+            Program defineUndefinedConstants(std::map<std::string, storm::expressions::Expression> const& constantDefinitions) const;
+            
+            /*!
+             * Substitutes all constants appearing in the expressions of the program by their defining expressions. For
+             * this to work, all constants need to be defined prior to calling this.
+             *
+             * @return The resulting program that only contains expressions over variables of the program.
+             */
+            Program substituteConstants() const;
+            
+            friend std::ostream& operator<<(std::ostream& stream, Program const& program);
+            
+        private:
+            // Creates the internal mappings.
+            void createMappings();
+            
+            // The type of the model.
+            ModelType modelType;
+            
+            // The undefined constants of the program.
+            std::vector<Constant> constants;
+            
+            // A mapping from constant names to their corresponding indices.
+            std::map<std::string, uint_fast64_t> constantToIndexMap;
+
+            // The global boolean variables.
+            std::vector<BooleanVariable> globalBooleanVariables;
+            
+            // A mapping from global boolean variable names to their corresponding indices.
+            std::map<std::string, uint_fast64_t> globalBooleanVariableToIndexMap;
+            
+            // The global integer variables.
+            std::vector<IntegerVariable> globalIntegerVariables;
+            
+            // A mapping from global integer variable names to their corresponding indices.
+            std::map<std::string, uint_fast64_t> globalIntegerVariableToIndexMap;
+            
+            // The formulas defined in the program.
+            std::vector<Formula> formulas;
+            
+            // A mapping of formula names to their corresponding indices.
+            std::map<std::string, uint_fast64_t> formulaToIndexMap;
+            
+            // The modules associated with the program.
+            std::vector<Module> modules;
+            
+            // A mapping of module names to their indices.
+            std::map<std::string, uint_fast64_t> moduleToIndexMap;
+            
+            // The reward models associated with the program.
+            std::vector<RewardModel> rewardModels;
+            
+            // A mapping of reward models to their indices.
+            std::map<std::string, uint_fast64_t> rewardModelToIndexMap;
+            
+            // A flag that indicates whether the initial states of the program were given explicitly (in the form of an
+            // initial construct) or implicitly (attached to the variable declarations).
+            bool hasInitialStatesExpression;
+            
+            // The expression contained in the initial construct (if any).
+            storm::expressions::Expression initialStatesExpression;
+            
+            // The labels that are defined for this model.
+            std::vector<Label> labels;
+            
+            // A mapping from label names to their corresponding indices.
+            std::map<std::string, uint_fast64_t> labelToIndexMap;
+            
+            // The set of actions present in this program.
+            std::set<std::string> actions;
+            
+            // A map of actions to the set of modules containing commands labelled with this action.
+            std::map<std::string, std::set<uint_fast64_t>> actionsToModuleIndexMap;
+            
+            // A mapping from variable names to the modules in which they were declared.
+            std::map<std::string, uint_fast64_t> variableToModuleIndexMap;
+        };
+        
+    } // namespace prism
+} // namespace storm
+
+#endif /* STORM_STORAGE_PRISM_PROGRAM_H_ */
diff --git a/src/storage/prism/RewardModel.cpp b/src/storage/prism/RewardModel.cpp
new file mode 100644
index 000000000..a6c68b34f
--- /dev/null
+++ b/src/storage/prism/RewardModel.cpp
@@ -0,0 +1,57 @@
+#include "src/storage/prism/RewardModel.h"
+
+namespace storm {
+    namespace prism {
+        RewardModel::RewardModel(std::string const& rewardModelName, std::vector<storm::prism::StateReward> const& stateRewards, std::vector<storm::prism::TransitionReward> const& transitionRewards, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), rewardModelName(rewardModelName), stateRewards(stateRewards), transitionRewards(transitionRewards) {
+            // Nothing to do here.
+        }
+        
+        std::string const& RewardModel::getName() const {
+            return this->rewardModelName;
+        }
+        
+        bool RewardModel::hasStateRewards() const {
+            return this->stateRewards.size() > 0;
+        }
+        
+        std::vector<storm::prism::StateReward> const& RewardModel::getStateRewards() const {
+            return this->stateRewards;
+        }
+        
+        bool RewardModel::hasTransitionRewards() const {
+            return this->transitionRewards.size() > 0;
+        }
+        
+        std::vector<storm::prism::TransitionReward> const& RewardModel::getTransitionRewards() const {
+            return this->transitionRewards;
+        }
+        
+        RewardModel RewardModel::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const {
+            std::vector<StateReward> newStateRewards;
+            newStateRewards.reserve(this->getStateRewards().size());
+            for (auto const& stateReward : this->getStateRewards()) {
+                newStateRewards.emplace_back(stateReward.substitute(substitution));
+            }
+            
+            std::vector<TransitionReward> newTransitionRewards;
+            newTransitionRewards.reserve(this->getTransitionRewards().size());
+            for (auto const& transitionReward : this->getTransitionRewards()) {
+                newTransitionRewards.emplace_back(transitionReward.substitute(substitution));
+            }
+            return RewardModel(this->getName(), newStateRewards, newTransitionRewards, this->getFilename(), this->getLineNumber());
+        }
+        
+        std::ostream& operator<<(std::ostream& stream, RewardModel const& rewardModel) {
+            stream << "rewards \"" << rewardModel.getName() << "\"" << std::endl;
+            for (auto const& reward : rewardModel.getStateRewards()) {
+                stream << reward << std::endl;
+            }
+            for (auto const& reward : rewardModel.getTransitionRewards()) {
+                stream << reward << std::endl;
+            }
+            stream << "endrewards" << std::endl;
+            return stream;
+        }
+        
+    } // namespace prism
+} // namespace storm
diff --git a/src/storage/prism/RewardModel.h b/src/storage/prism/RewardModel.h
new file mode 100644
index 000000000..3bb68d1b5
--- /dev/null
+++ b/src/storage/prism/RewardModel.h
@@ -0,0 +1,95 @@
+#ifndef STORM_STORAGE_PRISM_REWARDMODEL_H_
+#define STORM_STORAGE_PRISM_REWARDMODEL_H_
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include "src/storage/prism/StateReward.h"
+#include "src/storage/prism/TransitionReward.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace prism {
+        class RewardModel : public LocatedInformation {
+        public:
+            /*!
+             * Creates a reward model with the given name, state and transition rewards.
+             *
+             * @param rewardModelName The name of the reward model.
+             * @param stateRewards A vector of state-based rewards.
+             * @param transitionRewards A vector of transition-based rewards.
+             * @param filename The filename in which the reward model is defined.
+             * @param lineNumber The line number in which the reward model is defined.
+             */
+            RewardModel(std::string const& rewardModelName, std::vector<storm::prism::StateReward> const& stateRewards, std::vector<storm::prism::TransitionReward> const& transitionRewards, std::string const& filename = "", uint_fast64_t lineNumber = 0);
+            
+            // Create default implementations of constructors/assignment.
+            RewardModel() = default;
+            RewardModel(RewardModel const& other) = default;
+            RewardModel& operator=(RewardModel const& other)= default;
+#ifndef WINDOWS
+            RewardModel(RewardModel&& other) = default;
+            RewardModel& operator=(RewardModel&& other) = default;
+#endif
+            
+            /*!
+             * Retrieves the name of the reward model.
+             *
+             * @return The name of the reward model.
+             */
+            std::string const& getName() const;
+            
+            /*!
+             * Retrieves whether there are any state rewards.
+             *
+             * @return True iff there are any state rewards.
+             */
+            bool hasStateRewards() const;
+            
+            /*!
+             * Retrieves all state rewards associated with this reward model.
+             *
+             * @return The state rewards associated with this reward model.
+             */
+            std::vector<storm::prism::StateReward> const& getStateRewards() const;
+            
+            /*!
+             * Retrieves whether there are any transition rewards.
+             *
+             * @return True iff there are any transition rewards.
+             */
+            bool hasTransitionRewards() const;
+            
+            /*!
+             * Retrieves all transition rewards associated with this reward model.
+             *
+             * @return The transition rewards associated with this reward model.
+             */
+            std::vector<storm::prism::TransitionReward> const& getTransitionRewards() const;
+            
+            /*!
+             * Substitutes all identifiers in the reward model according to the given map.
+             *
+             * @param substitution The substitution to perform.
+             * @return The resulting reward model.
+             */
+            RewardModel substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const;
+            
+            friend std::ostream& operator<<(std::ostream& stream, RewardModel const& rewardModel);
+
+        private:
+            // The name of the reward model.
+            std::string rewardModelName;
+            
+            // The state-based rewards associated with this reward model.
+            std::vector<storm::prism::StateReward> stateRewards;
+            
+            // The transition-based rewards associated with this reward model.
+            std::vector<storm::prism::TransitionReward> transitionRewards;
+        };
+        
+    } // namespace prism
+} // namespace storm
+
+#endif /* STORM_STORAGE_PRISM_REWARDMODEL_H_ */
diff --git a/src/storage/prism/StateReward.cpp b/src/storage/prism/StateReward.cpp
new file mode 100644
index 000000000..ab2f0974b
--- /dev/null
+++ b/src/storage/prism/StateReward.cpp
@@ -0,0 +1,26 @@
+#include "src/storage/prism/StateReward.h"
+
+namespace storm {
+    namespace prism {
+        StateReward::StateReward(storm::expressions::Expression const& statePredicateExpression, storm::expressions::Expression const& rewardValueExpression, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), statePredicateExpression(statePredicateExpression), rewardValueExpression(rewardValueExpression) {
+            // Nothing to do here.
+        }
+        
+        storm::expressions::Expression const& StateReward::getStatePredicateExpression() const {
+            return this->statePredicateExpression;
+        }
+        
+        storm::expressions::Expression const& StateReward::getRewardValueExpression() const {
+            return this->rewardValueExpression;
+        }
+        
+        StateReward StateReward::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const {
+            return StateReward(this->getStatePredicateExpression().substitute<std::map>(substitution), this->getRewardValueExpression().substitute<std::map>(substitution), this->getFilename(), this->getLineNumber());
+        }
+        
+        std::ostream& operator<<(std::ostream& stream, StateReward const& stateReward) {
+            stream << "\t" << stateReward.getStatePredicateExpression() << ": " << stateReward.getRewardValueExpression() << ";";
+            return stream;
+        }
+    } // namespace prism
+} // namespace storm
diff --git a/src/storage/prism/StateReward.h b/src/storage/prism/StateReward.h
new file mode 100644
index 000000000..f64dc9e4d
--- /dev/null
+++ b/src/storage/prism/StateReward.h
@@ -0,0 +1,69 @@
+#ifndef STORM_STORAGE_PRISM_STATEREWARD_H_
+#define STORM_STORAGE_PRISM_STATEREWARD_H_
+
+#include <map>
+
+#include "src/storage/prism/LocatedInformation.h"
+#include "src/storage/expressions/Expression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace prism {
+        class StateReward : public LocatedInformation {
+        public:
+            /*!
+             * Creates a state reward for the states satisfying the given expression with the value given by a second
+             * expression.
+             *
+             * @param statePredicateExpression The predicate that states earning this state-based reward need to satisfy.
+             * @param rewardValueExpression An expression specifying the values of the rewards to attach to the states.
+             * @param filename The filename in which the state reward is defined.
+             * @param lineNumber The line number in which the state reward is defined.
+             */
+            StateReward(storm::expressions::Expression const& statePredicateExpression, storm::expressions::Expression const& rewardValueExpression, std::string const& filename = "", uint_fast64_t lineNumber = 0);
+            
+            // Create default implementations of constructors/assignment.
+            StateReward() = default;
+            StateReward(StateReward const& other) = default;
+            StateReward& operator=(StateReward const& other)= default;
+#ifndef WINDOWS
+            StateReward(StateReward&& other) = default;
+            StateReward& operator=(StateReward&& other) = default;
+#endif
+            
+            /*!
+             * Retrieves the state predicate that is associated with this state reward.
+             *
+             * @return The state predicate that is associated with this state reward.
+             */
+            storm::expressions::Expression const& getStatePredicateExpression() const;
+            
+            /*!
+             * Retrieves the reward value associated with this state reward.
+             *
+             * @return The reward value associated with this state reward.
+             */
+            storm::expressions::Expression const& getRewardValueExpression() const;
+            
+            /*!
+             * Substitutes all identifiers in the state reward according to the given map.
+             *
+             * @param substitution The substitution to perform.
+             * @return The resulting state reward.
+             */
+            StateReward substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const;
+            
+            friend std::ostream& operator<<(std::ostream& stream, StateReward const& stateReward);
+
+        private:
+            // The predicate that characterizes the states that obtain this reward.
+            storm::expressions::Expression statePredicateExpression;
+            
+            // The expression that specifies the value of the reward obtained.
+            storm::expressions::Expression rewardValueExpression;
+        };
+        
+    } // namespace prism
+} // namespace storm
+
+#endif /* STORM_STORAGE_PRISM_STATEREWARD_H_ */
diff --git a/src/storage/prism/TransitionReward.cpp b/src/storage/prism/TransitionReward.cpp
new file mode 100644
index 000000000..0034231d8
--- /dev/null
+++ b/src/storage/prism/TransitionReward.cpp
@@ -0,0 +1,31 @@
+#include "src/storage/prism/TransitionReward.h"
+
+namespace storm {
+    namespace prism {
+        TransitionReward::TransitionReward(std::string const& commandName, storm::expressions::Expression const& statePredicateExpression, storm::expressions::Expression const& rewardValueExpression, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), commandName(commandName), statePredicateExpression(statePredicateExpression), rewardValueExpression(rewardValueExpression) {
+            // Nothing to do here.
+        }
+        
+        std::string const& TransitionReward::getActionName() const {
+            return this->commandName;
+        }
+        
+        storm::expressions::Expression const& TransitionReward::getStatePredicateExpression() const {
+            return this->statePredicateExpression;
+        }
+        
+        storm::expressions::Expression const& TransitionReward::getRewardValueExpression() const {
+            return this->rewardValueExpression;
+        }
+        
+        TransitionReward TransitionReward::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const {
+            return TransitionReward(this->getActionName(), this->getStatePredicateExpression().substitute<std::map>(substitution), this->getRewardValueExpression().substitute<std::map>(substitution), this->getFilename(), this->getLineNumber());
+        }
+        
+        std::ostream& operator<<(std::ostream& stream, TransitionReward const& transitionReward) {
+            stream << "\t[" << transitionReward.getActionName() << "] " << transitionReward.getStatePredicateExpression() << ": " << transitionReward.getRewardValueExpression() << ";";
+            return stream;
+        }
+        
+    } // namespace prism
+} // namespace storm
diff --git a/src/storage/prism/TransitionReward.h b/src/storage/prism/TransitionReward.h
new file mode 100644
index 000000000..2c118cec7
--- /dev/null
+++ b/src/storage/prism/TransitionReward.h
@@ -0,0 +1,82 @@
+#ifndef STORM_STORAGE_PRISM_TRANSITIONREWARD_H_
+#define STORM_STORAGE_PRISM_TRANSITIONREWARD_H_
+
+#include <map>
+
+#include "src/storage/prism/LocatedInformation.h"
+#include "src/storage/expressions/Expression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace prism {
+        class TransitionReward : public LocatedInformation {
+        public:
+            /*!
+             * Creates a transition reward for the transitions with the given name emanating from states satisfying the
+             * given expression with the value given by another expression.
+             *
+             * @param actionName The name of the command that obtains this reward.
+             * @param statePredicateExpression The predicate that needs to hold before taking a transition with the previously
+             * specified name in order to obtain the reward.
+             * @param rewardValueExpression An expression specifying the values of the rewards to attach to the transitions.
+             * @param filename The filename in which the transition reward is defined.
+             * @param lineNumber The line number in which the transition reward is defined.
+             */
+            TransitionReward(std::string const& actionName, storm::expressions::Expression const& statePredicateExpression, storm::expressions::Expression const& rewardValueExpression, std::string const& filename = "", uint_fast64_t lineNumber = 0);
+            
+            // Create default implementations of constructors/assignment.
+            TransitionReward() = default;
+            TransitionReward(TransitionReward const& other) = default;
+            TransitionReward& operator=(TransitionReward const& other)= default;
+#ifndef WINDOWS
+            TransitionReward(TransitionReward&& other) = default;
+            TransitionReward& operator=(TransitionReward&& other) = default;
+#endif
+            
+            /*!
+             * Retrieves the action name that is associated with this transition reward.
+             *
+             * @return The action name that is associated with this transition reward.
+             */
+            std::string const& getActionName() const;
+            
+            /*!
+             * Retrieves the state predicate expression that is associated with this state reward.
+             *
+             * @return The state predicate expression that is associated with this state reward.
+             */
+            storm::expressions::Expression const& getStatePredicateExpression() const;
+            
+            /*!
+             * Retrieves the reward value expression associated with this state reward.
+             *
+             * @return The reward value expression associated with this state reward.
+             */
+            storm::expressions::Expression const& getRewardValueExpression() const;
+            
+            /*!
+             * Substitutes all identifiers in the transition reward according to the given map.
+             *
+             * @param substitution The substitution to perform.
+             * @return The resulting transition reward.
+             */
+            TransitionReward substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const;
+            
+            friend std::ostream& operator<<(std::ostream& stream, TransitionReward const& transitionReward);
+
+        private:
+            // The name of the command this transition-based reward is attached to.
+            std::string commandName;
+            
+            // A predicate that needs to be satisfied by states for the reward to be obtained (by taking
+            // a corresponding command transition).
+            storm::expressions::Expression statePredicateExpression;
+            
+            // The expression specifying the value of the reward obtained along the transitions.
+            storm::expressions::Expression rewardValueExpression;
+        };
+        
+    } // namespace prism
+} // namespace storm
+
+#endif /* STORM_STORAGE_PRISM_TRANSITIONREWARD_H_ */
diff --git a/src/storage/prism/Update.cpp b/src/storage/prism/Update.cpp
new file mode 100644
index 000000000..2e01187c9
--- /dev/null
+++ b/src/storage/prism/Update.cpp
@@ -0,0 +1,64 @@
+#include "Update.h"
+#include "src/exceptions/ExceptionMacros.h"
+#include "src/exceptions/OutOfRangeException.h"
+
+namespace storm {
+    namespace prism {
+        Update::Update(uint_fast64_t globalIndex, storm::expressions::Expression const& likelihoodExpression, std::vector<storm::prism::Assignment> const& assignments, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), likelihoodExpression(likelihoodExpression), assignments(assignments), variableToAssignmentIndexMap(), globalIndex(globalIndex) {
+            this->createAssignmentMapping();
+        }
+        
+        storm::expressions::Expression const& Update::getLikelihoodExpression() const {
+            return likelihoodExpression;
+        }
+        
+        std::size_t Update::getNumberOfAssignments() const {
+            return this->assignments.size();
+        }
+        
+        std::vector<storm::prism::Assignment> const& Update::getAssignments() const {
+            return this->assignments;
+        }
+        
+        storm::prism::Assignment const& Update::getAssignment(std::string const& variableName) const {
+            auto const& variableIndexPair = this->variableToAssignmentIndexMap.find(variableName);
+            LOG_THROW(variableIndexPair != this->variableToAssignmentIndexMap.end(), storm::exceptions::OutOfRangeException, "Variable '" << variableName << "' is not assigned in update.");
+            return this->getAssignments()[variableIndexPair->second];
+        }
+        
+        uint_fast64_t Update::getGlobalIndex() const {
+            return this->globalIndex;
+        }
+        
+        void Update::createAssignmentMapping() {
+            this->variableToAssignmentIndexMap.clear();
+            for (uint_fast64_t assignmentIndex = 0; assignmentIndex < this->getAssignments().size(); ++assignmentIndex) {
+                this->variableToAssignmentIndexMap[this->getAssignments()[assignmentIndex].getVariableName()] = assignmentIndex;
+            }
+        }
+        
+        Update Update::substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const {
+            std::vector<Assignment> newAssignments;
+            newAssignments.reserve(this->getNumberOfAssignments());
+            for (auto const& assignment : this->getAssignments()) {
+                newAssignments.emplace_back(assignment.substitute(substitution));
+            }
+            
+            return Update(this->getGlobalIndex(), this->getLikelihoodExpression().substitute<std::map>(substitution), newAssignments, this->getFilename(), this->getLineNumber());
+        }
+        
+        std::ostream& operator<<(std::ostream& stream, Update const& update) {
+            stream << update.getLikelihoodExpression() << " : ";
+            uint_fast64_t i = 0;
+            for (auto const& assignment : update.getAssignments()) {
+                stream << assignment;
+                if (i < update.getAssignments().size() - 1) {
+                    stream << " & ";
+                }
+                ++i;
+            }
+            return stream;
+        }
+        
+    } // namespace ir
+} // namespace storm
diff --git a/src/storage/prism/Update.h b/src/storage/prism/Update.h
new file mode 100644
index 000000000..b48aa99e4
--- /dev/null
+++ b/src/storage/prism/Update.h
@@ -0,0 +1,100 @@
+#ifndef STORM_STORAGE_PRISM_UPDATE_H_
+#define STORM_STORAGE_PRISM_UPDATE_H_
+
+#include <vector>
+
+#include "src/storage/prism/LocatedInformation.h"
+#include "src/storage/prism/Assignment.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace prism {
+        class Update : public LocatedInformation {
+        public:
+            /*!
+             * Creates an update with the given expression specifying the likelihood and assignments.
+             *
+             * @param globalIndex The global index of the update.
+             * @param likelihoodExpression An expression specifying the likelihood of this update.
+             * @param assignments A assignments to variables.
+             * @param filename The filename in which the update is defined.
+             * @param lineNumber The line number in which the update is defined.
+             */
+            Update(uint_fast64_t globalIndex, storm::expressions::Expression const& likelihoodExpression, std::vector<storm::prism::Assignment> const& assignments, std::string const& filename = "", uint_fast64_t lineNumber = 0);
+            
+            // Create default implementations of constructors/assignment.
+            Update() = default;
+            Update(Update const& other) = default;
+            Update& operator=(Update const& other)= default;
+#ifndef WINDOWS
+            Update(Update&& other) = default;
+            Update& operator=(Update&& other) = default;
+#endif
+            
+            /*!
+             * Retrieves the expression for the likelihood of this update.
+             *
+             * @return The expression for the likelihood of this update.
+             */
+            storm::expressions::Expression const& getLikelihoodExpression() const;
+            
+            /*!
+             * Retrieves the number of assignments associated with this update.
+             *
+             * @return The number of assignments associated with this update.
+             */
+            std::size_t getNumberOfAssignments() const;
+            
+            /*!
+             * Retrieves a reference to the map of variable names to their respective assignments.
+             *
+             * @return A reference to the map of variable names to their respective assignments.
+             */
+            std::vector<storm::prism::Assignment> const& getAssignments() const;
+            
+            /*!
+             * Retrieves a reference to the assignment for the variable with the given name.
+             *
+             * @return A reference to the assignment for the variable with the given name.
+             */
+            storm::prism::Assignment const& getAssignment(std::string const& variableName) const;
+            
+            /*!
+             * Retrieves the global index of the update, that is, a unique index over all modules.
+             *
+             * @return The global index of the update.
+             */
+            uint_fast64_t getGlobalIndex() const;
+            
+            /*!
+             * Substitutes all identifiers in the update according to the given map.
+             *
+             * @param substitution The substitution to perform.
+             * @return The resulting update.
+             */
+            Update substitute(std::map<std::string, storm::expressions::Expression> const& substitution) const;
+            
+            friend std::ostream& operator<<(std::ostream& stream, Update const& assignment);
+            
+        private:
+            /*!
+             * Creates the internal mapping of variables to their assignments.
+             */
+            void createAssignmentMapping();
+            
+            // An expression specifying the likelihood of taking this update.
+            storm::expressions::Expression likelihoodExpression;
+            
+            // The assignments of this update.
+            std::vector<storm::prism::Assignment> assignments;
+            
+            // A mapping from variable names to their assignments.
+            std::map<std::string, uint_fast64_t> variableToAssignmentIndexMap;
+            
+            // The global index of the update.
+            uint_fast64_t globalIndex;
+        };
+    } // namespace prism
+} // namespace storm
+
+#endif /* STORM_STORAGE_PRISM_UPDATE_H_ */
diff --git a/src/storage/prism/Variable.cpp b/src/storage/prism/Variable.cpp
new file mode 100644
index 000000000..e6c884813
--- /dev/null
+++ b/src/storage/prism/Variable.cpp
@@ -0,0 +1,27 @@
+#include <map>
+
+#include "src/storage/prism/Variable.h"
+
+namespace storm {
+    namespace prism {
+        Variable::Variable(std::string const& name, storm::expressions::Expression const& initialValueExpression, bool defaultInitialValue, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), name(name), initialValueExpression(initialValueExpression), defaultInitialValue(defaultInitialValue) {
+            // Nothing to do here.
+        }
+        
+        Variable::Variable(Variable const& oldVariable, std::string const& newName, std::map<std::string, std::string> const& renaming, std::string const& filename, uint_fast64_t lineNumber) : LocatedInformation(filename, lineNumber), name(newName), initialValueExpression(oldVariable.getInitialValueExpression().substitute<std::map>(renaming)), defaultInitialValue(oldVariable.hasDefaultInitialValue()) {
+            // Intentionally left empty.
+        }
+        
+        std::string const& Variable::getName() const {
+            return this->name;
+        }
+        
+        bool Variable::hasDefaultInitialValue() const {
+            return this->defaultInitialValue;
+        }
+
+        storm::expressions::Expression const& Variable::getInitialValueExpression() const {
+            return this->initialValueExpression;
+        }
+    } // namespace prism
+} // namespace storm
diff --git a/src/storage/prism/Variable.h b/src/storage/prism/Variable.h
new file mode 100644
index 000000000..a4cb76cb9
--- /dev/null
+++ b/src/storage/prism/Variable.h
@@ -0,0 +1,84 @@
+#ifndef STORM_STORAGE_PRISM_VARIABLE_H_
+#define STORM_STORAGE_PRISM_VARIABLE_H_
+
+#include <map>
+
+#include "src/storage/prism/LocatedInformation.h"
+#include "src/storage/expressions/Expression.h"
+#include "src/utility/OsDetection.h"
+
+namespace storm {
+    namespace prism {
+        class Variable : public LocatedInformation {
+        public:
+            // Create default implementations of constructors/assignment.
+            Variable(Variable const& otherVariable) = default;
+            Variable& operator=(Variable const& otherVariable)= default;
+#ifndef WINDOWS
+            Variable(Variable&& otherVariable) = default;
+            Variable& operator=(Variable&& otherVariable) = default;
+#endif
+            
+            /*!
+             * Retrieves the name of the variable.
+             *
+             * @return The name of the variable.
+             */
+            std::string const& getName() const;
+            
+            /*!
+             * Retrieves the expression defining the initial value of the variable.
+             *
+             * @return The expression defining the initial value of the variable.
+             */
+            storm::expressions::Expression const& getInitialValueExpression() const;
+            
+            /*!
+             * Retrieves whether the variable has the default initial value with respect to its type.
+             *
+             * @return True iff the variable has the default initial value.
+             */
+            bool hasDefaultInitialValue() const;
+            
+            // Make the constructors protected to forbid instantiation of this class.
+        protected:
+            Variable() = default;
+            
+            /*!
+             * Creates a variable with the given name and initial value.
+             *
+             * @param name The name of the variable.
+             * @param initialValueExpression The constant expression that defines the initial value of the variable.
+             * @param hasDefaultInitialValue A flag indicating whether the initial value of the variable is its default
+             * value.
+             * @param filename The filename in which the variable is defined.
+             * @param lineNumber The line number in which the variable is defined.
+             */
+            Variable(std::string const& name, storm::expressions::Expression const& initialValueExpression, bool defaultInitialValue, std::string const& filename = "", uint_fast64_t lineNumber = 0);
+            
+            /*!
+             * Creates a copy of the given variable and performs the provided renaming.
+             *
+             * @param oldVariable The variable to copy.
+             * @param newName New name of this variable.
+             * @param renaming A mapping from names that are to be renamed to the names they are to be replaced with.
+             * @param filename The filename in which the variable is defined.
+             * @param lineNumber The line number in which the variable is defined.
+             */
+            Variable(Variable const& oldVariable, std::string const& newName, std::map<std::string, std::string> const& renaming, std::string const& filename = "", uint_fast64_t lineNumber = 0);
+            
+        private:
+            // The name of the variable.
+            std::string name;
+            
+            // The constant expression defining the initial value of the variable.
+            storm::expressions::Expression initialValueExpression;
+            
+            // A flag that stores whether the variable has its default initial expression.
+            bool defaultInitialValue;
+        };
+        
+    } // namespace prism
+} // namespace storm
+
+#endif /* STORM_STORAGE_PRISM_VARIABLE_H_ */
diff --git a/src/storm.cpp b/src/storm.cpp
index a13bf8e23..c7b40247a 100644
--- a/src/storm.cpp
+++ b/src/storm.cpp
@@ -34,7 +34,7 @@
 #include "src/solver/GmmxxNondeterministicLinearEquationSolver.h"
 #include "src/solver/GurobiLpSolver.h"
 #include "src/counterexamples/MILPMinimalLabelSetGenerator.h"
-#include "src/counterexamples/SMTMinimalCommandSetGenerator.h"
+// #include "src/counterexamples/SMTMinimalCommandSetGenerator.h"
 #include "src/counterexamples/PathBasedSubsystemGenerator.h"
 #include "src/parser/AutoParser.h"
 #include "src/parser/MarkovAutomatonParser.h"
@@ -54,10 +54,11 @@
 #include "log4cplus/loggingmacros.h"
 #include "log4cplus/consoleappender.h"
 #include "log4cplus/fileappender.h"
+log4cplus::Logger logger;
 
 #include "src/parser/PrismParser.h"
 #include "src/adapters/ExplicitModelAdapter.h"
-#include "src/adapters/SymbolicModelAdapter.h"
+// #include "src/adapters/SymbolicModelAdapter.h"
 
 #include "src/exceptions/InvalidSettingsException.h"
 
@@ -121,8 +122,6 @@ void printUsage() {
 #endif
 }
 
-log4cplus::Logger logger;
-
 /*!
  * Initializes the logging framework and sets up logging to console.
  */
@@ -535,7 +534,7 @@ int main(const int argc, const char* argv[]) {
             // First, we build the model using the given symbolic model description and constant definitions.
             std::string const& programFile = s->getOptionByLongName("symbolic").getArgument(0).getValueAsString();
             std::string const& constants = s->getOptionByLongName("constants").getArgument(0).getValueAsString();
-            storm::ir::Program program = storm::parser::PrismParserFromFile(programFile);
+            storm::prism::Program program = storm::parser::PrismParser::parse(programFile);
             std::shared_ptr<storm::models::AbstractModel<double>> model = storm::adapters::ExplicitModelAdapter<double>::translateProgram(program, constants);
             model->printModelInformationToStream(std::cout);
             
@@ -559,7 +558,7 @@ int main(const int argc, const char* argv[]) {
                     if (useMILP) {
                         storm::counterexamples::MILPMinimalLabelSetGenerator<double>::computeCounterexample(program, *mdp, formulaPtr);
                     } else {
-                        storm::counterexamples::SMTMinimalCommandSetGenerator<double>::computeCounterexample(program, constants, *mdp, formulaPtr);
+                        // storm::counterexamples::SMTMinimalCommandSetGenerator<double>::computeCounterexample(program, constants, *mdp, formulaPtr);
                     }
                     
                     // Once we are done with the formula, delete it.
diff --git a/src/utility/IRUtility.h b/src/utility/IRUtility.h
deleted file mode 100644
index a75f1972d..000000000
--- a/src/utility/IRUtility.h
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
- * IRUtility.h
- *
- *  Created on: 05.10.2013
- *      Author: Christian Dehnert
- */
-
-#ifndef STORM_UTILITY_IRUTILITY_H_
-#define STORM_UTILITY_IRUTILITY_H_
-
-#include <boost/algorithm/string.hpp>
-
-#include "src/storage/LabeledValues.h"
-#include "src/ir/IR.h"
-#include "src/exceptions/InvalidArgumentException.h"
-
-#include "log4cplus/logger.h"
-#include "log4cplus/loggingmacros.h"
-
-extern log4cplus::Logger logger;
-
-namespace storm {
-    namespace utility {
-        namespace ir {
-
-            /*!
-             * A state of the model, i.e. a valuation of all variables.
-             */
-            typedef std::pair<std::vector<bool>, std::vector<int_fast64_t>> StateType;
-            
-            /*!
-             * A helper class that provides the functionality to compute a hash value for states of the model.
-             */
-            class StateHash {
-            public:
-                std::size_t operator()(StateType* state) const {
-                    size_t seed = 0;
-                    for (auto it : state->first) {
-                        boost::hash_combine<bool>(seed, it);
-                    }
-                    for (auto it : state->second) {
-                        boost::hash_combine<int_fast64_t>(seed, it);
-                    }
-                    return seed;
-                }
-            };
-            
-            /*!
-             * A helper class that provides the functionality to compare states of the model wrt. equality.
-             */
-            class StateCompare {
-            public:
-                bool operator()(StateType* state1, StateType* state2) const {
-                    return *state1 == *state2;
-                }
-            };
-            
-            /*!
-             * A helper class that provides the functionality to compare states of the model wrt. the relation "<".
-             */
-            class StateLess {
-            public:
-                bool operator()(StateType* state1, StateType* state2) const {
-                    // Compare boolean variables.
-                    for (uint_fast64_t i = 0; i < state1->first.size(); ++i) {
-                        if (!state1->first.at(i) && state2->first.at(i)) {
-                            return true;
-                        }
-                    }
-                    // Then compare integer variables.
-                    for (uint_fast64_t i = 0; i < state1->second.size(); ++i) {
-                        if (!state1->second.at(i) && state2->second.at(i)) {
-                            return true;
-                        }
-                    }
-                    return false;
-                }
-            };
-            
-            // A structure holding information about a particular choice.
-            template<typename ValueType, typename KeyType=uint_fast64_t, typename Compare=std::less<uint_fast64_t>>
-            struct Choice {
-            public:
-                Choice(std::string const& actionLabel) : distribution(), actionLabel(actionLabel), choiceLabels() {
-                    // Intentionally left empty.
-                }
-                
-                /*!
-                 * Returns an iterator to the first element of this choice.
-                 *
-                 * @return An iterator to the first element of this choice.
-                 */
-                typename std::map<KeyType, ValueType>::iterator begin() {
-                    return distribution.begin();
-                }
-                
-                /*!
-                 * Returns an iterator to the first element of this choice.
-                 *
-                 * @return An iterator to the first element of this choice.
-                 */
-                typename std::map<KeyType, ValueType>::const_iterator begin() const {
-                    return distribution.cbegin();
-                }
-                
-                /*!
-                 * Returns an iterator that points past the elements of this choice.
-                 *
-                 * @return An iterator that points past the elements of this choice.
-                 */
-                typename std::map<KeyType, ValueType>::iterator end() {
-                    return distribution.end();
-                }
-                
-                /*!
-                 * Returns an iterator that points past the elements of this choice.
-                 *
-                 * @return An iterator that points past the elements of this choice.
-                 */
-                typename std::map<KeyType, ValueType>::const_iterator end() const {
-                    return distribution.cend();
-                }
-                
-                /*!
-                 * Returns an iterator to the element with the given key, if there is one. Otherwise, the iterator points to
-                 * distribution.end().
-                 *
-                 * @param value The value to find.
-                 * @return An iterator to the element with the given key, if there is one.
-                 */
-                typename std::map<KeyType, ValueType>::iterator find(uint_fast64_t value) {
-                    return distribution.find(value);
-                }
-                
-                /*!
-                 * Inserts the contents of this object to the given output stream.
-                 *
-                 * @param out The stream in which to insert the contents.
-                 */
-                friend std::ostream& operator<<(std::ostream& out, Choice<ValueType> const& choice) {
-                    out << "<";
-                    for (auto const& stateProbabilityPair : choice.distribution) {
-                        out << stateProbabilityPair.first << " : " << stateProbabilityPair.second << ", ";
-                    }
-                    out << ">";
-                    return out;
-                }
-                
-                /*!
-                 * Adds the given label to the labels associated with this choice.
-                 *
-                 * @param label The label to associate with this choice.
-                 */
-                void addChoiceLabel(uint_fast64_t label) {
-                    choiceLabels.insert(label);
-                }
-                
-                /*!
-                 * Adds the given label set to the labels associated with this choice.
-                 *
-                 * @param labelSet The label set to associate with this choice.
-                 */
-                void addChoiceLabels(boost::container::flat_set<uint_fast64_t> const& labelSet) {
-                    for (uint_fast64_t label : labelSet) {
-                        addChoiceLabel(label);
-                    }
-                }
-                
-                /*!
-                 * Retrieves the set of labels associated with this choice.
-                 *
-                 * @return The set of labels associated with this choice.
-                 */
-                boost::container::flat_set<uint_fast64_t> const& getChoiceLabels() const {
-                    return choiceLabels;
-                }
-                
-                /*!
-                 * Retrieves the action label of this choice.
-                 *
-                 * @return The action label of this choice.
-                 */
-                std::string const& getActionLabel() const {
-                    return actionLabel;
-                }
-                
-                /*!
-                 * Retrieves the entry in the choice that is associated with the given state and creates one if none exists,
-                 * yet.
-                 *
-                 * @param state The state for which to add the entry.
-                 * @return A reference to the entry that is associated with the given state.
-                 */
-                ValueType& getOrAddEntry(uint_fast64_t state) {
-                    auto stateProbabilityPair = distribution.find(state);
-                    
-                    if (stateProbabilityPair == distribution.end()) {
-                        distribution[state] = ValueType();
-                    }
-                    return distribution.at(state);
-                }
-                
-                /*!
-                 * Retrieves the entry in the choice that is associated with the given state and creates one if none exists,
-                 * yet.
-                 *
-                 * @param state The state for which to add the entry.
-                 * @return A reference to the entry that is associated with the given state.
-                 */
-                ValueType const& getOrAddEntry(uint_fast64_t state) const {
-                    auto stateProbabilityPair = distribution.find(state);
-                    
-                    if (stateProbabilityPair == distribution.end()) {
-                        distribution[state] = ValueType();
-                    }
-                    return distribution.at(state);
-                }
-                
-            private:
-                // The distribution that is associated with the choice.
-                std::map<KeyType, ValueType, Compare> distribution;
-                
-                // The label of the choice.
-                std::string actionLabel;
-                
-                // The labels that are associated with this choice.
-                boost::container::flat_set<uint_fast64_t> choiceLabels;
-            };
-            
-            /*!
-             * Adds the target state and probability to the given choice and ignores the labels. This function overloads with
-             * other functions to ensure the proper treatment of labels.
-             *
-             * @param choice The choice to which to add the target state and probability.
-             * @param state The target state of the probability.
-             * @param probability The probability to reach the target state in one step.
-             * @param labels A set of labels that is supposed to be associated with this state and probability. NOTE: this
-             * is ignored by this particular function but not by the overloaded functions.
-             */
-            template<typename ValueType>
-            void addProbabilityToChoice(Choice<ValueType>& choice, uint_fast64_t state, ValueType probability, boost::container::flat_set<uint_fast64_t> const& labels) {
-                choice.getOrAddEntry(state) += probability;
-            }
-            
-            /*!
-             * Adds the target state and probability to the given choice and labels it accordingly. This function overloads
-             * with other functions to ensure the proper treatment of labels.
-             *
-             * @param choice The choice to which to add the target state and probability.
-             * @param state The target state of the probability.
-             * @param probability The probability to reach the target state in one step.
-             * @param labels A set of labels that is supposed to be associated with this state and probability.
-             */
-            template<typename ValueType>
-            void addProbabilityToChoice(Choice<storm::storage::LabeledValues<ValueType>>& choice, uint_fast64_t state, ValueType probability, boost::container::flat_set<uint_fast64_t> const& labels) {
-                auto& labeledEntry = choice.getOrAddEntry(state);
-                labeledEntry.addValue(probability, labels);
-            }
-            
-            // A structure storing information about the used variables of the program.
-            struct VariableInformation {
-                VariableInformation() : booleanVariables(), booleanVariableToIndexMap(), integerVariables(), integerVariableToIndexMap() {
-                    // Intentinally left empty.
-                }
-                
-                // List of all boolean variables.
-                std::vector<storm::ir::BooleanVariable> booleanVariables;
-                
-                // A mapping of boolean variable names to their indices.
-                std::map<std::string, uint_fast64_t> booleanVariableToIndexMap;
-                                
-                // List of all integer variables.
-                std::vector<storm::ir::IntegerVariable> integerVariables;
-                
-                // List of all lower bounds for integer variables.
-                std::vector<int_fast64_t> lowerBounds;
-                
-                // List of all upper bounds for integer variables.
-                std::vector<int_fast64_t> upperBounds;
-                
-                // A mapping of integer variable names to their indices.
-                std::map<std::string, uint_fast64_t> integerVariableToIndexMap;
-            };
-
-            /*!
-             * Aggregates information about the variables in the program.
-             *
-             * @param program The program whose variables to aggregate.
-             * @return A structure containing information about the variables in the program.
-             */
-            static VariableInformation createVariableInformation(storm::ir::Program const& program) {
-                VariableInformation result;
-                
-                uint_fast64_t numberOfIntegerVariables = 0;
-                uint_fast64_t numberOfBooleanVariables = 0;
-                
-                // Count number of variables.
-                numberOfBooleanVariables += program.getNumberOfGlobalBooleanVariables();
-                numberOfIntegerVariables += program.getNumberOfGlobalIntegerVariables();
-                for (uint_fast64_t i = 0; i < program.getNumberOfModules(); ++i) {
-                    numberOfBooleanVariables += program.getModule(i).getNumberOfBooleanVariables();
-                    numberOfIntegerVariables += program.getModule(i).getNumberOfIntegerVariables();
-                }
-                
-                // Resize the variable vectors appropriately.
-                result.booleanVariables.resize(numberOfBooleanVariables);
-                result.integerVariables.resize(numberOfIntegerVariables);
-                result.lowerBounds.resize(numberOfIntegerVariables);
-                result.upperBounds.resize(numberOfIntegerVariables);
-                
-                // Create variables.
-                for (uint_fast64_t i = 0; i < program.getNumberOfGlobalBooleanVariables(); ++i) {
-                    storm::ir::BooleanVariable const& var = program.getGlobalBooleanVariable(i);
-                    result.booleanVariables[var.getGlobalIndex()] = var;
-                    result.booleanVariableToIndexMap[var.getName()] = var.getGlobalIndex();
-                }
-                for (uint_fast64_t i = 0; i < program.getNumberOfGlobalIntegerVariables(); ++i) {
-                    storm::ir::IntegerVariable const& var = program.getGlobalIntegerVariable(i);
-                    result.integerVariables[var.getGlobalIndex()] = var;
-                    result.integerVariableToIndexMap[var.getName()] = var.getGlobalIndex();
-                    result.lowerBounds[var.getGlobalIndex()] = var.getLowerBound()->getValueAsInt(nullptr);
-                    result.upperBounds[var.getGlobalIndex()] = var.getUpperBound()->getValueAsInt(nullptr);
-                }
-                for (uint_fast64_t i = 0; i < program.getNumberOfModules(); ++i) {
-                    storm::ir::Module const& module = program.getModule(i);
-                    
-                    for (uint_fast64_t j = 0; j < module.getNumberOfBooleanVariables(); ++j) {
-                        storm::ir::BooleanVariable const& var = module.getBooleanVariable(j);
-                        result.booleanVariables[var.getGlobalIndex()] = var;
-                        result.booleanVariableToIndexMap[var.getName()] = var.getGlobalIndex();
-                    }
-                    for (uint_fast64_t j = 0; j < module.getNumberOfIntegerVariables(); ++j) {
-                        storm::ir::IntegerVariable const& var = module.getIntegerVariable(j);
-                        result.integerVariables[var.getGlobalIndex()] = var;
-                        result.integerVariableToIndexMap[var.getName()] = var.getGlobalIndex();
-                        result.lowerBounds[var.getGlobalIndex()] = var.getLowerBound()->getValueAsInt(nullptr);
-                        result.upperBounds[var.getGlobalIndex()] = var.getUpperBound()->getValueAsInt(nullptr);
-                    }
-                }
-                
-                return result;
-            }
-            
-            /*!
-             * Generates the initial state of the given program.
-             *
-             * @param program The program for which to construct the initial state.
-             * @param variableInformation A structure with information about the variables in the program.
-             * @return The initial state.
-             */
-            static StateType* getInitialState(storm::ir::Program const& program, VariableInformation const& variableInformation) {
-                StateType* initialState = new StateType();
-                initialState->first.resize(variableInformation.booleanVariables.size());
-                initialState->second.resize(variableInformation.integerVariables.size());
-                
-                // Start with boolean variables.
-                for (uint_fast64_t i = 0; i < variableInformation.booleanVariables.size(); ++i) {
-                    // Check if an initial value is given
-                    if (variableInformation.booleanVariables[i].getInitialValue().get() == nullptr) {
-                        // If no initial value was given, we assume that the variable is initially false.
-                        std::get<0>(*initialState)[i] = false;
-                    } else {
-                        // Initial value was given.
-                        bool initialValue = variableInformation.booleanVariables[i].getInitialValue()->getValueAsBool(nullptr);
-                        std::get<0>(*initialState)[i] = initialValue;
-                    }
-                }
-                
-                // Now process integer variables.
-                for (uint_fast64_t i = 0; i < variableInformation.integerVariables.size(); ++i) {
-                    // Check if an initial value was given.
-                    if (variableInformation.integerVariables[i].getInitialValue().get() == nullptr) {
-                        // No initial value was given, so we assume that the variable initially has the least value it can take.
-                        std::get<1>(*initialState)[i] = variableInformation.integerVariables[i].getLowerBound()->getValueAsInt(nullptr);
-                    } else {
-                        // Initial value was given.
-                        int_fast64_t initialValue = variableInformation.integerVariables[i].getInitialValue()->getValueAsInt(nullptr);
-                        std::get<1>(*initialState)[i] = initialValue;
-                    }
-                }
-                
-                LOG4CPLUS_DEBUG(logger, "Generated initial state.");
-                return initialState;
-            }
-            
-            /*!
-             * Sets some boolean variable in the given state object.
-             *
-             * @param state The state to modify.
-             * @param index The index of the boolean variable to modify.
-             * @param value The new value of the variable.
-             */
-            static void setValue(StateType* state, uint_fast64_t index, bool value) {
-                std::get<0>(*state)[index] = value;
-            }
-            
-            /*!
-             * Set some integer variable in the given state object.
-             *
-             * @param state The state to modify.
-             * @param index index of the integer variable to modify.
-             * @param value The new value of the variable.
-             */
-            static void setValue(StateType* state, uint_fast64_t index, int_fast64_t value) {
-                std::get<1>(*state)[index] = value;
-            }
-
-            /*!
-             * Defines the undefined constants of the given program using the given string.
-             *
-             * @param program The program in which to define the constants.
-             * @param constantDefinitionString A comma-separated list of constant definitions.
-             */
-            static void defineUndefinedConstants(storm::ir::Program& program, std::string const& constantDefinitionString) {
-                if (!constantDefinitionString.empty()) {
-                    // Parse the string that defines the undefined constants of the model and make sure that it contains exactly
-                    // one value for each undefined constant of the model.
-                    std::vector<std::string> definitions;
-                    boost::split(definitions, constantDefinitionString, boost::is_any_of(","));
-                    for (auto& definition : definitions) {
-                        boost::trim(definition);
-                        
-                        // Check whether the token could be a legal constant definition.
-                        uint_fast64_t positionOfAssignmentOperator = definition.find('=');
-                        if (positionOfAssignmentOperator == std::string::npos) {
-                            throw storm::exceptions::InvalidArgumentException() << "Illegal constant definition string: syntax error.";
-                        }
-                        
-                        // Now extract the variable name and the value from the string.
-                        std::string constantName = definition.substr(0, positionOfAssignmentOperator);
-                        boost::trim(constantName);
-                        std::string value = definition.substr(positionOfAssignmentOperator + 1);
-                        boost::trim(value);
-                        
-                        // Check whether the constant is a legal undefined constant of the program and if so, of what type it is.
-                        if (program.hasUndefinedBooleanConstant(constantName)) {
-                            if (value == "true") {
-                                program.getUndefinedBooleanConstantExpression(constantName)->define(true);
-                            } else if (value == "false") {
-                                program.getUndefinedBooleanConstantExpression(constantName)->define(false);
-                            } else {
-                                throw storm::exceptions::InvalidArgumentException() << "Illegal value for boolean constant: " << value << ".";
-                            }
-                        } else if (program.hasUndefinedIntegerConstant(constantName)) {
-                            try {
-                                int_fast64_t integerValue = std::stoi(value);
-                                program.getUndefinedIntegerConstantExpression(constantName)->define(integerValue);
-                            } catch (std::invalid_argument const&) {
-                                throw storm::exceptions::InvalidArgumentException() << "Illegal value of integer constant: " << value << ".";
-                            } catch (std::out_of_range const&) {
-                                throw storm::exceptions::InvalidArgumentException() << "Illegal value of integer constant: " << value << " (value too big).";
-                            }
-                        } else if (program.hasUndefinedDoubleConstant(constantName)) {
-                            try {
-                                double doubleValue = std::stod(value);
-                                program.getUndefinedDoubleConstantExpression(constantName)->define(doubleValue);
-                            } catch (std::invalid_argument const&) {
-                                throw storm::exceptions::InvalidArgumentException() << "Illegal value of double constant: " << value << ".";
-                            } catch (std::out_of_range const&) {
-                                throw storm::exceptions::InvalidArgumentException() << "Illegal value of double constant: " << value << " (value too big).";
-                            }
-                            
-                        } else {
-                            throw storm::exceptions::InvalidArgumentException() << "Illegal constant definition string: unknown undefined constant " << constantName << ".";
-                        }
-                    }
-                }
-            }
-            
-            /*!
-             * Undefines all previously defined constants in the given program.
-             *
-             * @param program The program in which to undefine the constants.
-             */
-            static void undefineUndefinedConstants(storm::ir::Program& program) {
-                for (auto const& nameExpressionPair : program.getBooleanUndefinedConstantExpressionsMap()) {
-                    nameExpressionPair.second->undefine();
-                }
-                for (auto const& nameExpressionPair : program.getIntegerUndefinedConstantExpressionsMap()) {
-                    nameExpressionPair.second->undefine();
-                }
-                for (auto const& nameExpressionPair : program.getDoubleUndefinedConstantExpressionsMap()) {
-                    nameExpressionPair.second->undefine();
-                }
-            }
-
-            /*!
-             * Computes the weakest precondition of the given boolean expression wrt. the given updates. The weakest
-             * precondition is the most liberal expression that must hold in order to satisfy the given boolean
-             * expression after performing the updates. The updates must be disjoint in the sense that they must not
-             * assign an expression to a variable twice or more.
-             *
-             * @param expression The expression for which to build the weakest precondition.
-             * @param update The update with respect to which to compute the weakest precondition.
-             */
-            std::unique_ptr<storm::ir::expressions::BaseExpression> getWeakestPrecondition(std::unique_ptr<storm::ir::expressions::BaseExpression> const& booleanExpression, std::vector<std::reference_wrapper<storm::ir::Update const>> const& updates) {
-                std::map<std::string, std::reference_wrapper<storm::ir::expressions::BaseExpression>> variableToExpressionMap;
-                
-                // Construct the full substitution we need to perform later.
-                for (auto const& update : updates) {
-                    for (auto const& variableAssignmentPair : update.get().getBooleanAssignments()) {
-                        variableToExpressionMap.emplace(variableAssignmentPair.first, *variableAssignmentPair.second.getExpression());
-                    }
-                    for (auto const& variableAssignmentPair : update.get().getIntegerAssignments()) {
-                        variableToExpressionMap.emplace(variableAssignmentPair.first, *variableAssignmentPair.second.getExpression());
-                    }
-                }
-                
-                // Copy the given expression and apply the substitution.
-                return storm::ir::expressions::BaseExpression::substitute(booleanExpression->clone(), variableToExpressionMap);
-            }
-            
-        } // namespace ir
-    } // namespace utility
-} // namespace storm
-
-#endif /* STORM_UTILITY_IRUTILITY_H_ */
diff --git a/src/utility/PrismUtility.h b/src/utility/PrismUtility.h
new file mode 100644
index 000000000..9ed15411a
--- /dev/null
+++ b/src/utility/PrismUtility.h
@@ -0,0 +1,195 @@
+#ifndef STORM_UTILITY_PRISMUTILITY
+#define STORM_UTILITY_PRISMUTILITY
+
+#include "src/storage/LabeledValues.h"
+#include "src/storage/prism/Program.h"
+#include "src/exceptions/ExceptionMacros.h"
+#include "src/exceptions/InvalidArgumentException.h"
+
+namespace storm {
+    namespace utility {
+        namespace prism {
+            // A structure holding information about a particular choice.
+            template<typename ValueType, typename KeyType=uint_fast64_t, typename Compare=std::less<uint_fast64_t>>
+            struct Choice {
+            public:
+                Choice(std::string const& actionLabel) : distribution(), actionLabel(actionLabel), choiceLabels() {
+                    // Intentionally left empty.
+                }
+                
+                /*!
+                 * Returns an iterator to the first element of this choice.
+                 *
+                 * @return An iterator to the first element of this choice.
+                 */
+                typename std::map<KeyType, ValueType>::iterator begin() {
+                    return distribution.begin();
+                }
+                
+                /*!
+                 * Returns an iterator to the first element of this choice.
+                 *
+                 * @return An iterator to the first element of this choice.
+                 */
+                typename std::map<KeyType, ValueType>::const_iterator begin() const {
+                    return distribution.cbegin();
+                }
+                
+                /*!
+                 * Returns an iterator that points past the elements of this choice.
+                 *
+                 * @return An iterator that points past the elements of this choice.
+                 */
+                typename std::map<KeyType, ValueType>::iterator end() {
+                    return distribution.end();
+                }
+                
+                /*!
+                 * Returns an iterator that points past the elements of this choice.
+                 *
+                 * @return An iterator that points past the elements of this choice.
+                 */
+                typename std::map<KeyType, ValueType>::const_iterator end() const {
+                    return distribution.cend();
+                }
+                
+                /*!
+                 * Returns an iterator to the element with the given key, if there is one. Otherwise, the iterator points to
+                 * distribution.end().
+                 *
+                 * @param value The value to find.
+                 * @return An iterator to the element with the given key, if there is one.
+                 */
+                typename std::map<KeyType, ValueType>::iterator find(uint_fast64_t value) {
+                    return distribution.find(value);
+                }
+                
+                /*!
+                 * Inserts the contents of this object to the given output stream.
+                 *
+                 * @param out The stream in which to insert the contents.
+                 */
+                friend std::ostream& operator<<(std::ostream& out, Choice<ValueType> const& choice) {
+                    out << "<";
+                    for (auto const& stateProbabilityPair : choice.distribution) {
+                        out << stateProbabilityPair.first << " : " << stateProbabilityPair.second << ", ";
+                    }
+                    out << ">";
+                    return out;
+                }
+                
+                /*!
+                 * Adds the given label to the labels associated with this choice.
+                 *
+                 * @param label The label to associate with this choice.
+                 */
+                void addChoiceLabel(uint_fast64_t label) {
+                    choiceLabels.insert(label);
+                }
+                
+                /*!
+                 * Adds the given label set to the labels associated with this choice.
+                 *
+                 * @param labelSet The label set to associate with this choice.
+                 */
+                void addChoiceLabels(boost::container::flat_set<uint_fast64_t> const& labelSet) {
+                    for (uint_fast64_t label : labelSet) {
+                        addChoiceLabel(label);
+                    }
+                }
+                
+                /*!
+                 * Retrieves the set of labels associated with this choice.
+                 *
+                 * @return The set of labels associated with this choice.
+                 */
+                boost::container::flat_set<uint_fast64_t> const& getChoiceLabels() const {
+                    return choiceLabels;
+                }
+                
+                /*!
+                 * Retrieves the action label of this choice.
+                 *
+                 * @return The action label of this choice.
+                 */
+                std::string const& getActionLabel() const {
+                    return actionLabel;
+                }
+                
+                /*!
+                 * Retrieves the entry in the choice that is associated with the given state and creates one if none exists,
+                 * yet.
+                 *
+                 * @param state The state for which to add the entry.
+                 * @return A reference to the entry that is associated with the given state.
+                 */
+                ValueType& getOrAddEntry(uint_fast64_t state) {
+                    auto stateProbabilityPair = distribution.find(state);
+                    
+                    if (stateProbabilityPair == distribution.end()) {
+                        distribution[state] = ValueType();
+                    }
+                    return distribution.at(state);
+                }
+                
+                /*!
+                 * Retrieves the entry in the choice that is associated with the given state and creates one if none exists,
+                 * yet.
+                 *
+                 * @param state The state for which to add the entry.
+                 * @return A reference to the entry that is associated with the given state.
+                 */
+                ValueType const& getOrAddEntry(uint_fast64_t state) const {
+                    auto stateProbabilityPair = distribution.find(state);
+                    
+                    if (stateProbabilityPair == distribution.end()) {
+                        distribution[state] = ValueType();
+                    }
+                    return distribution.at(state);
+                }
+                
+            private:
+                // The distribution that is associated with the choice.
+                std::map<KeyType, ValueType, Compare> distribution;
+                
+                // The label of the choice.
+                std::string actionLabel;
+                
+                // The labels that are associated with this choice.
+                boost::container::flat_set<uint_fast64_t> choiceLabels;
+            };
+            
+            /*!
+             * Adds the target state and probability to the given choice and ignores the labels. This function overloads with
+             * other functions to ensure the proper treatment of labels.
+             *
+             * @param choice The choice to which to add the target state and probability.
+             * @param state The target state of the probability.
+             * @param probability The probability to reach the target state in one step.
+             * @param labels A set of labels that is supposed to be associated with this state and probability. NOTE: this
+             * is ignored by this particular function but not by the overloaded functions.
+             */
+            template<typename ValueType>
+            void addProbabilityToChoice(Choice<ValueType>& choice, uint_fast64_t state, ValueType probability, boost::container::flat_set<uint_fast64_t> const& labels) {
+                choice.getOrAddEntry(state) += probability;
+            }
+            
+            /*!
+             * Adds the target state and probability to the given choice and labels it accordingly. This function overloads
+             * with other functions to ensure the proper treatment of labels.
+             *
+             * @param choice The choice to which to add the target state and probability.
+             * @param state The target state of the probability.
+             * @param probability The probability to reach the target state in one step.
+             * @param labels A set of labels that is supposed to be associated with this state and probability.
+             */
+            template<typename ValueType>
+            void addProbabilityToChoice(Choice<storm::storage::LabeledValues<ValueType>>& choice, uint_fast64_t state, ValueType probability, boost::container::flat_set<uint_fast64_t> const& labels) {
+                auto& labeledEntry = choice.getOrAddEntry(state);
+                labeledEntry.addValue(probability, labels);
+            }
+        } // namespace prism
+    } // namespace utility
+} // namespace storm
+
+#endif /* STORM_UTILITY_PRISMUTILITY_H_ */
diff --git a/test/functional/parser/ParsePrismTest.cpp b/test/functional/parser/ParsePrismTest.cpp
deleted file mode 100644
index 0a8abb420..000000000
--- a/test/functional/parser/ParsePrismTest.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "gtest/gtest.h"
-#include "storm-config.h"
-#include "src/parser/PrismParser.h"
-//#include "src/utility/IoUtility.h"
-#include "src/ir/Program.h"
-#include "src/adapters/ExplicitModelAdapter.h"
-#include "src/models/Dtmc.h"
-#include "src/models/Mdp.h"
-#include "src/settings/Settings.h"
-#include "src/settings/InternalOptionMemento.h"
-
-TEST(ParsePrismTest, parseCrowds5_5) {
-	storm::settings::InternalOptionMemento deadlockOption("fixDeadlocks", true);
-	ASSERT_TRUE(storm::settings::Settings::getInstance()->isSet("fixDeadlocks"));
-	storm::ir::Program program;
-	ASSERT_NO_THROW(program = storm::parser::PrismParserFromFile(STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.pm"));
-	std::shared_ptr<storm::models::AbstractModel<double>> model = storm::adapters::ExplicitModelAdapter<double>::translateProgram(program);
-    
-	ASSERT_EQ(model->getNumberOfStates(), 8607ull);
-	ASSERT_EQ(model->getNumberOfTransitions(), 15113ull);
-}
-
-TEST(ParsePrismTest, parseTwoDice) {
-	storm::ir::Program program;
-	ASSERT_NO_THROW(program = storm::parser::PrismParserFromFile(STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.nm"));
-
-	std::shared_ptr<storm::models::AbstractModel<double>> model = storm::adapters::ExplicitModelAdapter<double>::translateProgram(program, "", "coinflips");
-	
-	ASSERT_EQ(model->getNumberOfStates(), 169ull);
-	ASSERT_EQ(model->as<storm::models::AbstractNondeterministicModel<double>>()->getNumberOfChoices(), 254ull);
-	ASSERT_EQ(model->getNumberOfTransitions(), 436ull);
-}
diff --git a/test/functional/parser/PrismParserTest.cpp b/test/functional/parser/PrismParserTest.cpp
new file mode 100644
index 000000000..739d9ca5b
--- /dev/null
+++ b/test/functional/parser/PrismParserTest.cpp
@@ -0,0 +1,170 @@
+#include "gtest/gtest.h"
+#include "storm-config.h"
+#include "src/parser/PrismParser.h"
+
+TEST(PrismParser, SimpleParsingOnlyTest) {
+    std::string testInput =
+    R"(dtmc
+    module mod1
+        b : bool;
+        [a] true -> 1: (b'=true);
+    endmodule)";
+    
+    storm::prism::Program result;
+    EXPECT_NO_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile", false));
+    EXPECT_EQ(1, result.getNumberOfModules());
+    EXPECT_EQ(storm::prism::Program::ModelType::DTMC, result.getModelType());
+}
+
+TEST(PrismParser, StandardModelParsingTest) {
+    storm::prism::Program result;
+    EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/coin2.nm", false));
+    EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/crowds5_5.pm", false));
+    EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/csma2_2.nm", false));
+    EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/die.pm", false));
+    EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/firewire.nm", false));
+    EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/leader3.nm", false));
+    EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/leader3_5.pm", false));
+    EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/two_dice.nm", false));
+    EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/wlan0_collide.nm", false));
+}
+
+TEST(PrismParser, StandardModelFullTest) {
+    storm::prism::Program result;
+    EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/coin2.nm", true));
+    EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/crowds5_5.pm", true));
+    EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/csma2_2.nm", true));
+    EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/die.pm", true));
+    EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/firewire.nm", true));
+    EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/leader3.nm", true));
+    EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/leader3_5.pm", true));
+    EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/two_dice.nm", true));
+    EXPECT_NO_THROW(result = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/parser/prism/wlan0_collide.nm", true));
+}
+
+TEST(PrismParser, SimpleFullTest) {
+    std::string testInput =
+    R"(dtmc
+    module mod1
+        b : bool;
+        [a] true -> 1: (b'=true);
+    endmodule)";
+    
+    storm::prism::Program result;
+    EXPECT_NO_THROW(result = storm::parser::PrismParser::parseFromString(testInput, "testfile", true));
+    EXPECT_EQ(1, result.getNumberOfModules());
+    EXPECT_EQ(storm::prism::Program::ModelType::DTMC, result.getModelType());
+}
+
+TEST(PrismParser, ComplexFullTest) {
+    std::string testInput =
+    R"(ma
+    
+    const int a;
+    const int b = 10;
+    const bool c;
+    const bool d = true | false;
+    const double e;
+    const double f = 9;
+    
+    formula test = a >= 10 & (max(a,b) > floor(e));
+    formula test2 = a+b;
+    formula test3 = (a + b > 10 ? floor(a) : h) + a;
+    
+    global g : bool init false;
+    global h : [0 .. b];
+    
+    module mod1
+        i : bool;
+        j : bool init c;
+        k : [125..a] init a;
+
+        [a] test&false -> (i'=true)&(k'=1+1) + 1 : (k'=floor(a) <= max(k, b) - 1 + k);
+    endmodule
+                                              
+    module mod2
+        [b] (k > 3) & false & (min(a, 0) < max(h, k)) -> 1-e: (j'=(1-a) * 2 + floor(f));
+    endmodule
+    
+    module mod3 = mod1 [ i = i1, j = j1, k = k1 ] endmodule
+                                                               
+    label "mal" = max(a, 10) > 0;
+                                                               
+    init
+        true
+    endinit
+    
+    rewards "testrewards"
+        [stateRew] true : a + 7;
+        max(f, a) <= 8 : 2*b;
+    endrewards
+                                                               
+    rewards "testrewards2"
+        [stateRew] true : a + 7;
+        max(f, a) <= 8 : 2*b;
+    endrewards)";
+    
+    storm::prism::Program result;
+    result = storm::parser::PrismParser::parseFromString(testInput, "testfile", true);
+    EXPECT_EQ(storm::prism::Program::ModelType::MA, result.getModelType());
+    EXPECT_EQ(3, result.getNumberOfModules());
+    EXPECT_EQ(2, result.getNumberOfRewardModels());
+    EXPECT_EQ(1, result.getNumberOfLabels());
+    EXPECT_TRUE(result.definesInitialStatesExpression());
+}
+
+TEST(PrismParser, ComplexParsingTest) {
+    std::string testInput =
+    R"(ma
+    
+    const int a;
+    const int b = 10;
+    const bool c;
+    const bool d = true | false;
+    const double e;
+    const double f = 9;
+    
+    formula test = (a >= 10 & (max(a, b) > floor(e)));
+
+    global g : bool init false;
+    global h : [0 .. b];
+    
+    module mod1
+        i : bool;
+        j : bool init c;
+        k : [125..a] init a;
+        [a] true -> (i'=true)&(h'=1+1) + 1 : (j'=floor(a) <= max(k, b) - 1 + k);
+    endmodule
+                                    
+    module mod2
+        [b] (x > 3) & false & (min(a, b0) < max(as8, b)) -> y: (x'=(1-g) * 2 + a);
+        [] s=1 -> (a'=a);
+        [read] c<N-1 -> 1 : (c'=floor(c) + 1);
+    endmodule
+                             
+    module mod3 = mod2 [ x = y ] endmodule
+             
+    label "mal" = max(x, i) > 0;
+                             
+    init
+        true
+    endinit
+                             
+    rewards "testrewards"
+        [stateRew] true : a + 7;
+        max(z, f) <= 8 : 2*b;
+    endrewards
+                             
+    rewards "testrewards2"
+        [stateRew] true : a + 7;
+        max(z, f) <= 8 : 2*b;
+    endrewards)";
+    
+    storm::prism::Program result;
+    result = storm::parser::PrismParser::parseFromString(testInput, "testfile", false);
+    EXPECT_EQ(storm::prism::Program::ModelType::MA, result.getModelType());
+    EXPECT_EQ(3, result.getNumberOfModules());
+    EXPECT_EQ(2, result.getNumberOfRewardModels());
+    EXPECT_EQ(1, result.getNumberOfLabels());
+    EXPECT_TRUE(result.definesInitialStatesExpression());
+}
\ No newline at end of file
diff --git a/test/functional/storage/CuddDdTest.cpp b/test/functional/storage/CuddDdTest.cpp
index a92dbc929..8a5be849a 100644
--- a/test/functional/storage/CuddDdTest.cpp
+++ b/test/functional/storage/CuddDdTest.cpp
@@ -6,9 +6,8 @@
 #include "src/storage/dd/DdMetaVariable.h"
 
 TEST(CuddDdManager, Constants) {
-    std::shared_ptr<storm::dd::DdManager<storm::dd::CUDD>> manager(new storm::dd::DdManager<storm::dd::CUDD>());
-    
-    storm::dd::Dd<storm::dd::CUDD> zero;
+    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());
     
     EXPECT_EQ(0, zero.getNonZeroCount());
@@ -17,7 +16,7 @@ TEST(CuddDdManager, Constants) {
     EXPECT_EQ(0, zero.getMin());
     EXPECT_EQ(0, zero.getMax());
     
-    storm::dd::Dd<storm::dd::CUDD> one;
+    storm::dd::Dd<storm::dd::DdType::CUDD> one;
     ASSERT_NO_THROW(one = manager->getOne());
     
     EXPECT_EQ(1, one.getNonZeroCount());
@@ -26,7 +25,7 @@ TEST(CuddDdManager, Constants) {
     EXPECT_EQ(1, one.getMin());
     EXPECT_EQ(1, one.getMax());
 
-    storm::dd::Dd<storm::dd::CUDD> two;
+    storm::dd::Dd<storm::dd::DdType::CUDD> two;
     ASSERT_NO_THROW(two = manager->getConstant(2));
     
     EXPECT_EQ(1, two.getNonZeroCount());
@@ -36,9 +35,8 @@ TEST(CuddDdManager, Constants) {
     EXPECT_EQ(2, two.getMax());
 }
 
-TEST(CuddDdManager, MetaVariableTest) {
-    std::shared_ptr<storm::dd::DdManager<storm::dd::CUDD>> manager(new storm::dd::DdManager<storm::dd::CUDD>());
-    
+TEST(CuddDdManager, AddGetMetaVariableTest) {
+    std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
     ASSERT_NO_THROW(manager->addMetaVariable("x", 1, 9));
     EXPECT_EQ(1, manager->getNumberOfMetaVariables());
     
@@ -58,9 +56,55 @@ TEST(CuddDdManager, MetaVariableTest) {
     std::set<std::string> metaVariableSet = {"x", "y", "y'"};
     EXPECT_EQ(metaVariableSet, manager->getAllMetaVariableNames());
     
-    ASSERT_THROW(storm::dd::DdMetaVariable<storm::dd::CUDD> const& metaVariableX = manager->getMetaVariable("x'"), storm::exceptions::InvalidArgumentException);
-    ASSERT_NO_THROW(storm::dd::DdMetaVariable<storm::dd::CUDD> const& metaVariableX = manager->getMetaVariable("x"));
-    storm::dd::DdMetaVariable<storm::dd::CUDD> const& metaVariableX = manager->getMetaVariable("x");
+    ASSERT_THROW(storm::dd::DdMetaVariable<storm::dd::DdType::CUDD> const& metaVariableX = manager->getMetaVariable("x'"), storm::exceptions::InvalidArgumentException);
+    ASSERT_NO_THROW(storm::dd::DdMetaVariable<storm::dd::DdType::CUDD> const& metaVariableX = manager->getMetaVariable("x"));
+}
+
+TEST(CuddDdManager, EncodingTest) {
+    std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
+    manager->addMetaVariable("x", 1, 9);
+    
+    storm::dd::Dd<storm::dd::DdType::CUDD> encoding;
+    ASSERT_THROW(encoding = manager->getEncoding("x", 0), storm::exceptions::InvalidArgumentException);
+    ASSERT_THROW(encoding = manager->getEncoding("x", 10), storm::exceptions::InvalidArgumentException);
+    ASSERT_NO_THROW(encoding = manager->getEncoding("x", 4));
+    EXPECT_EQ(1, encoding.getNonZeroCount());
+    EXPECT_EQ(6, encoding.getNodeCount());
+    EXPECT_EQ(2, encoding.getLeafCount());
+}
+
+TEST(CuddDdManager, RangeTest) {
+    std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
+    ASSERT_NO_THROW(manager->addMetaVariable("x", 1, 9));
+    
+    storm::dd::Dd<storm::dd::DdType::CUDD> range;
+    ASSERT_THROW(range = manager->getRange("y"), storm::exceptions::InvalidArgumentException);
+    ASSERT_NO_THROW(range = manager->getRange("x"));
+    
+    EXPECT_EQ(9, range.getNonZeroCount());
+    EXPECT_EQ(2, range.getLeafCount());
+    EXPECT_EQ(6, range.getNodeCount());
+}
+
+TEST(CuddDdManager, IdentityTest) {
+    std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
+    manager->addMetaVariable("x", 1, 9);
+    
+    storm::dd::Dd<storm::dd::DdType::CUDD> range;
+    ASSERT_THROW(range = manager->getIdentity("y"), storm::exceptions::InvalidArgumentException);
+    ASSERT_NO_THROW(range = manager->getIdentity("x"));
+    
+    EXPECT_EQ(9, range.getNonZeroCount());
+    EXPECT_EQ(10, range.getLeafCount());
+    EXPECT_EQ(21, range.getNodeCount());
+}
+
+TEST(CuddDdMetaVariable, AccessorTest) {
+    std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
+    manager->addMetaVariable("x", 1, 9);
+    EXPECT_EQ(1, manager->getNumberOfMetaVariables());
+    ASSERT_NO_THROW(storm::dd::DdMetaVariable<storm::dd::DdType::CUDD> const& metaVariableX = manager->getMetaVariable("x"));
+    storm::dd::DdMetaVariable<storm::dd::DdType::CUDD> const& metaVariableX = manager->getMetaVariable("x");
     
     EXPECT_EQ(1, metaVariableX.getLow());
     EXPECT_EQ(9, metaVariableX.getHigh());
@@ -69,3 +113,153 @@ TEST(CuddDdManager, MetaVariableTest) {
     EXPECT_EQ(4, metaVariableX.getNumberOfDdVariables());
 }
 
+TEST(CuddDd, OperatorTest) {
+    std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
+    manager->addMetaVariable("x", 1, 9);
+    EXPECT_TRUE(manager->getZero() == manager->getZero());
+    EXPECT_FALSE(manager->getZero() == manager->getOne());
+
+    EXPECT_FALSE(manager->getZero() != manager->getZero());
+    EXPECT_TRUE(manager->getZero() != manager->getOne());
+    
+    storm::dd::Dd<storm::dd::DdType::CUDD> dd1 = manager->getOne();
+    storm::dd::Dd<storm::dd::DdType::CUDD> dd2 = manager->getOne();
+    storm::dd::Dd<storm::dd::DdType::CUDD> dd3 = dd1 + dd2;
+    EXPECT_TRUE(dd3 == manager->getConstant(2));
+    
+    dd3 += manager->getZero();
+    EXPECT_TRUE(dd3 == manager->getConstant(2));
+    
+    dd3 = dd1 * manager->getConstant(3);
+    EXPECT_TRUE(dd3 == manager->getConstant(3));
+    
+    dd3 *= manager->getConstant(2);
+    EXPECT_TRUE(dd3 == manager->getConstant(6));
+    
+    dd3 = dd1 - dd2;
+    EXPECT_TRUE(dd3 == manager->getZero());
+    
+    dd3 -= manager->getConstant(-2);
+    EXPECT_TRUE(dd3 == manager->getConstant(2));
+    
+    dd3 /= manager->getConstant(2);
+    EXPECT_TRUE(dd3 == manager->getOne());
+    
+    dd3.complement();
+    EXPECT_TRUE(dd3 == manager->getZero());
+    
+    dd1 = ~dd3;
+    EXPECT_TRUE(dd1 == manager->getOne());
+    
+    dd1 = manager->getIdentity("x");
+    dd2 = manager->getConstant(5);
+
+    dd3 = dd1.equals(dd2);
+    EXPECT_EQ(1, dd3.getNonZeroCount());
+    
+    storm::dd::Dd<storm::dd::DdType::CUDD> dd4 = dd1.notEquals(dd2);
+    EXPECT_TRUE(dd4 == ~dd3);
+    
+    dd3 = dd1.less(dd2);
+    EXPECT_EQ(11, dd3.getNonZeroCount());
+    
+    dd3 = dd1.lessOrEqual(dd2);
+    EXPECT_EQ(12, dd3.getNonZeroCount());
+    
+    dd3 = dd1.greater(dd2);
+    EXPECT_EQ(4, dd3.getNonZeroCount());
+
+    dd3 = dd1.greaterOrEqual(dd2);
+    EXPECT_EQ(5, dd3.getNonZeroCount());
+}
+
+TEST(CuddDd, AbstractionTest) {
+    std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
+    manager->addMetaVariablesInterleaved({"x", "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;
+    
+    dd1 = manager->getIdentity("x");
+    dd2 = manager->getConstant(5);
+    dd3 = dd1.equals(dd2);
+    EXPECT_EQ(1, dd3.getNonZeroCount());
+    ASSERT_THROW(dd3.existsAbstract({"x'"}), storm::exceptions::InvalidArgumentException);
+    ASSERT_NO_THROW(dd3.existsAbstract({"x"}));
+    EXPECT_EQ(1, dd3.getNonZeroCount());
+    EXPECT_EQ(1, dd3.getMax());
+
+    dd3 = dd1.equals(dd2);
+    dd3 *= manager->getConstant(3);
+    EXPECT_EQ(1, dd3.getNonZeroCount());
+    ASSERT_THROW(dd3.existsAbstract({"x'"}), storm::exceptions::InvalidArgumentException);
+    ASSERT_NO_THROW(dd3.existsAbstract({"x"}));
+    EXPECT_TRUE(dd3 == manager->getZero());
+
+    dd3 = dd1.equals(dd2);
+    dd3 *= manager->getConstant(3);
+    ASSERT_THROW(dd3.sumAbstract({"x'"}), storm::exceptions::InvalidArgumentException);
+    ASSERT_NO_THROW(dd3.sumAbstract({"x"}));
+    EXPECT_EQ(1, dd3.getNonZeroCount());
+    EXPECT_EQ(3, dd3.getMax());
+
+    dd3 = dd1.equals(dd2);
+    dd3 *= manager->getConstant(3);
+    ASSERT_THROW(dd3.minAbstract({"x'"}), storm::exceptions::InvalidArgumentException);
+    ASSERT_NO_THROW(dd3.minAbstract({"x"}));
+    EXPECT_EQ(0, dd3.getNonZeroCount());
+    EXPECT_EQ(0, dd3.getMax());
+
+    dd3 = dd1.equals(dd2);
+    dd3 *= manager->getConstant(3);
+    ASSERT_THROW(dd3.maxAbstract({"x'"}), storm::exceptions::InvalidArgumentException);
+    ASSERT_NO_THROW(dd3.maxAbstract({"x"}));
+    EXPECT_EQ(1, dd3.getNonZeroCount());
+    EXPECT_EQ(3, dd3.getMax());
+}
+
+TEST(CuddDd, SwapTest) {
+    std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
+    
+    manager->addMetaVariablesInterleaved({"x", "x'"}, 1, 9);
+    manager->addMetaVariable("z", 2, 8);
+    storm::dd::Dd<storm::dd::DdType::CUDD> dd1;
+    storm::dd::Dd<storm::dd::DdType::CUDD> dd2;
+    
+    dd1 = manager->getIdentity("x");
+    ASSERT_THROW(dd1.swapVariables({std::make_pair("x", "z")}), storm::exceptions::InvalidArgumentException);
+    ASSERT_NO_THROW(dd1.swapVariables({std::make_pair("x", "x'")}));
+    EXPECT_TRUE(dd1 == manager->getIdentity("x'"));
+}
+
+TEST(CuddDd, MultiplyMatrixTest) {
+    std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
+    manager->addMetaVariablesInterleaved({"x", "x'"}, 1, 9);
+    
+    storm::dd::Dd<storm::dd::DdType::CUDD> dd1 = manager->getIdentity("x").equals(manager->getIdentity("x'"));
+    storm::dd::Dd<storm::dd::DdType::CUDD> dd2 = manager->getRange("x'");
+    storm::dd::Dd<storm::dd::DdType::CUDD> dd3;
+    dd1 *= manager->getConstant(2);
+    
+    ASSERT_NO_THROW(dd3 = dd1.multiplyMatrix(dd2, {"x'"}));
+    ASSERT_NO_THROW(dd3.swapVariables({std::make_pair("x", "x'")}));
+    EXPECT_TRUE(dd3 == dd2 * manager->getConstant(2));
+}
+
+TEST(CuddDd, GetSetValueTest) {
+    std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
+    manager->addMetaVariable("x", 1, 9);
+    
+    storm::dd::Dd<storm::dd::DdType::CUDD> dd1 = manager->getOne();
+    ASSERT_NO_THROW(dd1.setValue("x", 4, 2));
+    EXPECT_EQ(2, dd1.getLeafCount());
+    dd1.exportToDot("dd1.dot");
+    
+    std::map<std::string, int_fast64_t> metaVariableToValueMap;
+    metaVariableToValueMap.emplace("x", 1);
+    EXPECT_EQ(1, dd1.getValue(metaVariableToValueMap));
+    
+    metaVariableToValueMap.clear();
+    metaVariableToValueMap.emplace("x", 4);
+    EXPECT_EQ(2, dd1.getValue(metaVariableToValueMap));
+}
diff --git a/test/functional/storage/ExpressionTest.cpp b/test/functional/storage/ExpressionTest.cpp
new file mode 100644
index 000000000..0c19c5bfb
--- /dev/null
+++ b/test/functional/storage/ExpressionTest.cpp
@@ -0,0 +1,383 @@
+#include <map>
+
+#include "gtest/gtest.h"
+#include "src/storage/expressions/Expression.h"
+#include "src/storage/expressions/SimpleValuation.h"
+#include "src/exceptions/InvalidTypeException.h"
+
+TEST(Expression, FactoryMethodTest) {
+    EXPECT_NO_THROW(storm::expressions::Expression::createBooleanLiteral(true));
+    EXPECT_NO_THROW(storm::expressions::Expression::createTrue());
+    EXPECT_NO_THROW(storm::expressions::Expression::createFalse());
+    EXPECT_NO_THROW(storm::expressions::Expression::createIntegerLiteral(3));
+    EXPECT_NO_THROW(storm::expressions::Expression::createDoubleLiteral(3.14));
+    EXPECT_NO_THROW(storm::expressions::Expression::createBooleanVariable("x"));
+    EXPECT_NO_THROW(storm::expressions::Expression::createIntegerVariable("y"));
+    EXPECT_NO_THROW(storm::expressions::Expression::createDoubleVariable("z"));
+    EXPECT_NO_THROW(storm::expressions::Expression::createBooleanConstant("a"));
+    EXPECT_NO_THROW(storm::expressions::Expression::createIntegerConstant("b"));
+    EXPECT_NO_THROW(storm::expressions::Expression::createDoubleConstant("c"));
+}
+
+TEST(Expression, AccessorTest) {
+    storm::expressions::Expression trueExpression;
+    storm::expressions::Expression falseExpression;
+    storm::expressions::Expression threeExpression;
+    storm::expressions::Expression piExpression;
+    storm::expressions::Expression boolVarExpression;
+    storm::expressions::Expression intVarExpression;
+    storm::expressions::Expression doubleVarExpression;
+    storm::expressions::Expression boolConstExpression;
+    storm::expressions::Expression intConstExpression;
+    storm::expressions::Expression doubleConstExpression;
+    
+    ASSERT_NO_THROW(trueExpression = storm::expressions::Expression::createTrue());
+    ASSERT_NO_THROW(falseExpression = storm::expressions::Expression::createFalse());
+    ASSERT_NO_THROW(threeExpression = storm::expressions::Expression::createIntegerLiteral(3));
+    ASSERT_NO_THROW(piExpression = storm::expressions::Expression::createDoubleLiteral(3.14));
+    ASSERT_NO_THROW(boolVarExpression = storm::expressions::Expression::createBooleanVariable("x"));
+    ASSERT_NO_THROW(intVarExpression = storm::expressions::Expression::createIntegerVariable("y"));
+    ASSERT_NO_THROW(doubleVarExpression = storm::expressions::Expression::createDoubleVariable("z"));
+    ASSERT_NO_THROW(boolConstExpression = storm::expressions::Expression::createBooleanConstant("a"));
+    ASSERT_NO_THROW(intConstExpression = storm::expressions::Expression::createIntegerConstant("b"));
+    ASSERT_NO_THROW(doubleConstExpression = storm::expressions::Expression::createDoubleConstant("c"));
+    
+    EXPECT_TRUE(trueExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    EXPECT_TRUE(trueExpression.isConstant());
+    EXPECT_TRUE(trueExpression.isTrue());
+    EXPECT_FALSE(trueExpression.isFalse());
+    EXPECT_TRUE(trueExpression.getVariables() == std::set<std::string>());
+    EXPECT_TRUE(trueExpression.getConstants() == std::set<std::string>());
+    
+    EXPECT_TRUE(falseExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    EXPECT_TRUE(falseExpression.isConstant());
+    EXPECT_FALSE(falseExpression.isTrue());
+    EXPECT_TRUE(falseExpression.isFalse());
+    EXPECT_TRUE(falseExpression.getVariables() == std::set<std::string>());
+    EXPECT_TRUE(falseExpression.getConstants() == std::set<std::string>());
+
+    EXPECT_TRUE(threeExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int);
+    EXPECT_TRUE(threeExpression.isConstant());
+    EXPECT_FALSE(threeExpression.isTrue());
+    EXPECT_FALSE(threeExpression.isFalse());
+    EXPECT_TRUE(threeExpression.getVariables() == std::set<std::string>());
+    EXPECT_TRUE(threeExpression.getConstants() == std::set<std::string>());
+    
+    EXPECT_TRUE(piExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double);
+    EXPECT_TRUE(piExpression.isConstant());
+    EXPECT_FALSE(piExpression.isTrue());
+    EXPECT_FALSE(piExpression.isFalse());
+    EXPECT_TRUE(piExpression.getVariables() == std::set<std::string>());
+    EXPECT_TRUE(piExpression.getConstants() == std::set<std::string>());
+    
+    EXPECT_TRUE(boolVarExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    EXPECT_FALSE(boolVarExpression.isConstant());
+    EXPECT_FALSE(boolVarExpression.isTrue());
+    EXPECT_FALSE(boolVarExpression.isFalse());
+    EXPECT_TRUE(boolVarExpression.getVariables() == std::set<std::string>({"x"}));
+    EXPECT_TRUE(boolVarExpression.getConstants() == std::set<std::string>());
+
+    EXPECT_TRUE(intVarExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int);
+    EXPECT_FALSE(intVarExpression.isConstant());
+    EXPECT_FALSE(intVarExpression.isTrue());
+    EXPECT_FALSE(intVarExpression.isFalse());
+    EXPECT_TRUE(intVarExpression.getVariables() == std::set<std::string>({"y"}));
+    EXPECT_TRUE(intVarExpression.getConstants() == std::set<std::string>());
+
+    EXPECT_TRUE(doubleVarExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double);
+    EXPECT_FALSE(doubleVarExpression.isConstant());
+    EXPECT_FALSE(doubleVarExpression.isTrue());
+    EXPECT_FALSE(doubleVarExpression.isFalse());
+    EXPECT_TRUE(doubleVarExpression.getVariables() == std::set<std::string>({"z"}));
+    EXPECT_TRUE(doubleVarExpression.getConstants() == std::set<std::string>());
+
+    EXPECT_TRUE(boolConstExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    EXPECT_FALSE(boolConstExpression.isConstant());
+    EXPECT_FALSE(boolConstExpression.isTrue());
+    EXPECT_FALSE(boolConstExpression.isFalse());
+    EXPECT_TRUE(boolConstExpression.getVariables() == std::set<std::string>());
+    EXPECT_TRUE(boolConstExpression.getConstants() == std::set<std::string>({"a"}));
+    
+    EXPECT_TRUE(intConstExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int);
+    EXPECT_FALSE(intConstExpression.isConstant());
+    EXPECT_FALSE(intConstExpression.isTrue());
+    EXPECT_FALSE(intConstExpression.isFalse());
+    EXPECT_TRUE(intConstExpression.getVariables() == std::set<std::string>());
+    EXPECT_TRUE(intConstExpression.getConstants() == std::set<std::string>({"b"}));
+
+    EXPECT_TRUE(doubleConstExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double);
+    EXPECT_FALSE(doubleConstExpression.isConstant());
+    EXPECT_FALSE(doubleConstExpression.isTrue());
+    EXPECT_FALSE(doubleConstExpression.isFalse());
+    EXPECT_TRUE(doubleConstExpression.getVariables() == std::set<std::string>());
+    EXPECT_TRUE(doubleConstExpression.getConstants() == std::set<std::string>({"c"}));
+}
+
+TEST(Expression, OperatorTest) {
+    storm::expressions::Expression trueExpression;
+    storm::expressions::Expression falseExpression;
+    storm::expressions::Expression threeExpression;
+    storm::expressions::Expression piExpression;
+    storm::expressions::Expression boolVarExpression;
+    storm::expressions::Expression intVarExpression;
+    storm::expressions::Expression doubleVarExpression;
+    storm::expressions::Expression boolConstExpression;
+    storm::expressions::Expression intConstExpression;
+    storm::expressions::Expression doubleConstExpression;
+    
+    ASSERT_NO_THROW(trueExpression = storm::expressions::Expression::createTrue());
+    ASSERT_NO_THROW(falseExpression = storm::expressions::Expression::createFalse());
+    ASSERT_NO_THROW(threeExpression = storm::expressions::Expression::createIntegerLiteral(3));
+    ASSERT_NO_THROW(piExpression = storm::expressions::Expression::createDoubleLiteral(3.14));
+    ASSERT_NO_THROW(boolVarExpression = storm::expressions::Expression::createBooleanVariable("x"));
+    ASSERT_NO_THROW(intVarExpression = storm::expressions::Expression::createIntegerVariable("y"));
+    ASSERT_NO_THROW(doubleVarExpression = storm::expressions::Expression::createDoubleVariable("z"));
+    ASSERT_NO_THROW(boolConstExpression = storm::expressions::Expression::createBooleanConstant("a"));
+    ASSERT_NO_THROW(intConstExpression = storm::expressions::Expression::createIntegerConstant("b"));
+    ASSERT_NO_THROW(doubleConstExpression = storm::expressions::Expression::createDoubleConstant("c"));
+    
+    storm::expressions::Expression tempExpression;
+
+    ASSERT_THROW(tempExpression = trueExpression.ite(falseExpression, piExpression), storm::exceptions::InvalidTypeException);
+    ASSERT_NO_THROW(tempExpression = boolConstExpression.ite(threeExpression, doubleVarExpression));
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double);
+    ASSERT_NO_THROW(tempExpression = boolConstExpression.ite(threeExpression, intVarExpression));
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int);
+    ASSERT_NO_THROW(tempExpression = boolConstExpression.ite(trueExpression, falseExpression));
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    
+    ASSERT_THROW(tempExpression = trueExpression + piExpression, storm::exceptions::InvalidTypeException);
+    ASSERT_NO_THROW(tempExpression = threeExpression + threeExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int);
+    ASSERT_NO_THROW(tempExpression = threeExpression + piExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double);
+    ASSERT_NO_THROW(tempExpression = doubleVarExpression + doubleConstExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double);
+    
+    ASSERT_THROW(tempExpression = trueExpression - piExpression, storm::exceptions::InvalidTypeException);
+    ASSERT_NO_THROW(tempExpression = threeExpression - threeExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int);
+    ASSERT_NO_THROW(tempExpression = threeExpression - piExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double);
+    ASSERT_NO_THROW(tempExpression = doubleVarExpression - doubleConstExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double);
+    
+    ASSERT_THROW(tempExpression = -trueExpression, storm::exceptions::InvalidTypeException);
+    ASSERT_NO_THROW(tempExpression = -threeExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int);
+    ASSERT_NO_THROW(tempExpression = -piExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double);
+    ASSERT_NO_THROW(tempExpression = -doubleVarExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double);
+
+    ASSERT_THROW(tempExpression = trueExpression * piExpression, storm::exceptions::InvalidTypeException);
+    ASSERT_NO_THROW(tempExpression = threeExpression * threeExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int);
+    ASSERT_NO_THROW(tempExpression = threeExpression * piExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double);
+    ASSERT_NO_THROW(tempExpression = intVarExpression * intConstExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int);
+
+    ASSERT_THROW(tempExpression = trueExpression / piExpression, storm::exceptions::InvalidTypeException);
+    ASSERT_NO_THROW(tempExpression = threeExpression / threeExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int);
+    ASSERT_NO_THROW(tempExpression = threeExpression / piExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double);
+    ASSERT_NO_THROW(tempExpression = doubleVarExpression / intConstExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double);
+
+    ASSERT_THROW(tempExpression = trueExpression && piExpression, storm::exceptions::InvalidTypeException);
+    ASSERT_NO_THROW(tempExpression = trueExpression && falseExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    ASSERT_NO_THROW(tempExpression = boolVarExpression && boolConstExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+
+    ASSERT_THROW(tempExpression = trueExpression || piExpression, storm::exceptions::InvalidTypeException);
+    ASSERT_NO_THROW(tempExpression = trueExpression || falseExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    ASSERT_NO_THROW(tempExpression = boolVarExpression || boolConstExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+
+    ASSERT_THROW(tempExpression = !threeExpression, storm::exceptions::InvalidTypeException);
+    ASSERT_NO_THROW(tempExpression = !trueExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    ASSERT_NO_THROW(tempExpression = !boolVarExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+
+    ASSERT_THROW(tempExpression = trueExpression == piExpression, storm::exceptions::InvalidTypeException);
+    ASSERT_NO_THROW(tempExpression = threeExpression == threeExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    ASSERT_NO_THROW(tempExpression = intVarExpression == doubleConstExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+
+    ASSERT_THROW(tempExpression = trueExpression != piExpression, storm::exceptions::InvalidTypeException);
+    ASSERT_NO_THROW(tempExpression = threeExpression != threeExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    ASSERT_NO_THROW(tempExpression = intVarExpression != doubleConstExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+
+    ASSERT_THROW(tempExpression = trueExpression > piExpression, storm::exceptions::InvalidTypeException);
+    ASSERT_NO_THROW(tempExpression = threeExpression > threeExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    ASSERT_NO_THROW(tempExpression = intVarExpression > doubleConstExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    
+    ASSERT_THROW(tempExpression = trueExpression >= piExpression, storm::exceptions::InvalidTypeException);
+    ASSERT_NO_THROW(tempExpression = threeExpression >= threeExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    ASSERT_NO_THROW(tempExpression = intVarExpression >= doubleConstExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    
+    ASSERT_THROW(tempExpression = trueExpression < piExpression, storm::exceptions::InvalidTypeException);
+    ASSERT_NO_THROW(tempExpression = threeExpression < threeExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    ASSERT_NO_THROW(tempExpression = intVarExpression < doubleConstExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    
+    ASSERT_THROW(tempExpression = trueExpression <= piExpression, storm::exceptions::InvalidTypeException);
+    ASSERT_NO_THROW(tempExpression = threeExpression <= threeExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    ASSERT_NO_THROW(tempExpression = intVarExpression <= doubleConstExpression);
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    
+    ASSERT_THROW(tempExpression = storm::expressions::Expression::minimum(trueExpression, piExpression), storm::exceptions::InvalidTypeException);
+    ASSERT_NO_THROW(tempExpression = storm::expressions::Expression::minimum(threeExpression, threeExpression));
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int);
+    ASSERT_NO_THROW(tempExpression = storm::expressions::Expression::minimum(intVarExpression, doubleConstExpression));
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double);
+
+    ASSERT_THROW(tempExpression = storm::expressions::Expression::maximum(trueExpression, piExpression), storm::exceptions::InvalidTypeException);
+    ASSERT_NO_THROW(tempExpression = storm::expressions::Expression::maximum(threeExpression, threeExpression));
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int);
+    ASSERT_NO_THROW(tempExpression = storm::expressions::Expression::maximum(intVarExpression, doubleConstExpression));
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Double);
+    
+    ASSERT_THROW(tempExpression = trueExpression.implies(piExpression), storm::exceptions::InvalidTypeException);
+    ASSERT_NO_THROW(tempExpression = trueExpression.implies(falseExpression));
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    ASSERT_NO_THROW(tempExpression = boolVarExpression.implies(boolConstExpression));
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    
+    ASSERT_THROW(tempExpression = trueExpression.iff(piExpression), storm::exceptions::InvalidTypeException);
+    ASSERT_NO_THROW(tempExpression = trueExpression.iff(falseExpression));
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    ASSERT_NO_THROW(tempExpression = boolVarExpression.iff(boolConstExpression));
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Bool);
+    
+    ASSERT_THROW(tempExpression = trueExpression.floor(), storm::exceptions::InvalidTypeException);
+    ASSERT_NO_THROW(tempExpression = threeExpression.floor());
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int);
+    ASSERT_NO_THROW(tempExpression = doubleConstExpression.floor());
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int);
+
+    ASSERT_THROW(tempExpression = trueExpression.ceil(), storm::exceptions::InvalidTypeException);
+    ASSERT_NO_THROW(tempExpression = threeExpression.ceil());
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int);
+    ASSERT_NO_THROW(tempExpression = doubleConstExpression.ceil());
+    EXPECT_TRUE(tempExpression.getReturnType() == storm::expressions::ExpressionReturnType::Int);
+}
+
+TEST(Expression, SubstitutionTest) {
+    storm::expressions::Expression trueExpression;
+    storm::expressions::Expression falseExpression;
+    storm::expressions::Expression threeExpression;
+    storm::expressions::Expression piExpression;
+    storm::expressions::Expression boolVarExpression;
+    storm::expressions::Expression intVarExpression;
+    storm::expressions::Expression doubleVarExpression;
+    storm::expressions::Expression boolConstExpression;
+    storm::expressions::Expression intConstExpression;
+    storm::expressions::Expression doubleConstExpression;
+    
+    ASSERT_NO_THROW(trueExpression = storm::expressions::Expression::createTrue());
+    ASSERT_NO_THROW(falseExpression = storm::expressions::Expression::createFalse());
+    ASSERT_NO_THROW(threeExpression = storm::expressions::Expression::createIntegerLiteral(3));
+    ASSERT_NO_THROW(piExpression = storm::expressions::Expression::createDoubleLiteral(3.14));
+    ASSERT_NO_THROW(boolVarExpression = storm::expressions::Expression::createBooleanVariable("x"));
+    ASSERT_NO_THROW(intVarExpression = storm::expressions::Expression::createIntegerVariable("y"));
+    ASSERT_NO_THROW(doubleVarExpression = storm::expressions::Expression::createDoubleVariable("z"));
+    ASSERT_NO_THROW(boolConstExpression = storm::expressions::Expression::createBooleanConstant("a"));
+    ASSERT_NO_THROW(intConstExpression = storm::expressions::Expression::createIntegerConstant("b"));
+    ASSERT_NO_THROW(doubleConstExpression = storm::expressions::Expression::createDoubleConstant("c"));
+    
+    storm::expressions::Expression tempExpression;
+    ASSERT_NO_THROW(tempExpression = (intVarExpression < threeExpression || boolVarExpression) && boolConstExpression);
+
+    std::map<std::string, storm::expressions::Expression> substution = { std::make_pair("y", doubleConstExpression), std::make_pair("x", storm::expressions::Expression::createTrue()), std::make_pair("a", storm::expressions::Expression::createTrue()) };
+    storm::expressions::Expression substitutedExpression;
+    ASSERT_NO_THROW(substitutedExpression = tempExpression.substitute<std::map>(substution));
+    EXPECT_TRUE(substitutedExpression.simplify().isTrue());
+}
+
+TEST(Expression, SimplificationTest) {
+    storm::expressions::Expression trueExpression;
+    storm::expressions::Expression falseExpression;
+    storm::expressions::Expression threeExpression;
+    storm::expressions::Expression intVarExpression;
+    
+    ASSERT_NO_THROW(trueExpression = storm::expressions::Expression::createTrue());
+    ASSERT_NO_THROW(falseExpression = storm::expressions::Expression::createFalse());
+    ASSERT_NO_THROW(threeExpression = storm::expressions::Expression::createIntegerLiteral(3));
+    ASSERT_NO_THROW(intVarExpression = storm::expressions::Expression::createIntegerVariable("y"));
+    
+    storm::expressions::Expression tempExpression;
+    storm::expressions::Expression simplifiedExpression;
+
+    ASSERT_NO_THROW(tempExpression = trueExpression || intVarExpression > threeExpression);
+    ASSERT_NO_THROW(simplifiedExpression = tempExpression.simplify());
+    EXPECT_TRUE(simplifiedExpression.isTrue());
+
+    ASSERT_NO_THROW(tempExpression = falseExpression && intVarExpression > threeExpression);
+    ASSERT_NO_THROW(simplifiedExpression = tempExpression.simplify());
+    EXPECT_TRUE(simplifiedExpression.isFalse());
+}
+
+TEST(Expression, SimpleEvaluationTest) {
+    storm::expressions::Expression trueExpression;
+    storm::expressions::Expression falseExpression;
+    storm::expressions::Expression threeExpression;
+    storm::expressions::Expression piExpression;
+    storm::expressions::Expression boolVarExpression;
+    storm::expressions::Expression intVarExpression;
+    storm::expressions::Expression doubleVarExpression;
+    storm::expressions::Expression boolConstExpression;
+    storm::expressions::Expression intConstExpression;
+    storm::expressions::Expression doubleConstExpression;
+    
+    ASSERT_NO_THROW(trueExpression = storm::expressions::Expression::createTrue());
+    ASSERT_NO_THROW(falseExpression = storm::expressions::Expression::createFalse());
+    ASSERT_NO_THROW(threeExpression = storm::expressions::Expression::createIntegerLiteral(3));
+    ASSERT_NO_THROW(piExpression = storm::expressions::Expression::createDoubleLiteral(3.14));
+    ASSERT_NO_THROW(boolVarExpression = storm::expressions::Expression::createBooleanVariable("x"));
+    ASSERT_NO_THROW(intVarExpression = storm::expressions::Expression::createIntegerVariable("y"));
+    ASSERT_NO_THROW(doubleVarExpression = storm::expressions::Expression::createDoubleVariable("z"));
+    ASSERT_NO_THROW(boolConstExpression = storm::expressions::Expression::createBooleanConstant("a"));
+    ASSERT_NO_THROW(intConstExpression = storm::expressions::Expression::createIntegerConstant("b"));
+    ASSERT_NO_THROW(doubleConstExpression = storm::expressions::Expression::createDoubleConstant("c"));
+    
+    storm::expressions::Expression tempExpression;
+    
+    ASSERT_NO_THROW(tempExpression = (intVarExpression < threeExpression || boolVarExpression) && boolConstExpression);
+    
+    ASSERT_NO_THROW(storm::expressions::SimpleValuation valuation);
+    storm::expressions::SimpleValuation valuation;
+    ASSERT_NO_THROW(valuation.addBooleanIdentifier("x"));
+    ASSERT_NO_THROW(valuation.addBooleanIdentifier("a"));
+    ASSERT_NO_THROW(valuation.addIntegerIdentifier("y"));
+    ASSERT_NO_THROW(valuation.addIntegerIdentifier("b"));
+    ASSERT_NO_THROW(valuation.addDoubleIdentifier("z"));
+    ASSERT_NO_THROW(valuation.addDoubleIdentifier("c"));
+    
+    ASSERT_THROW(tempExpression.evaluateAsDouble(&valuation), storm::exceptions::InvalidTypeException);
+    ASSERT_THROW(tempExpression.evaluateAsInt(&valuation), storm::exceptions::InvalidTypeException);
+    EXPECT_FALSE(tempExpression.evaluateAsBool(&valuation));
+    ASSERT_NO_THROW(valuation.setBooleanValue("a", true));
+    EXPECT_TRUE(tempExpression.evaluateAsBool(&valuation));
+    ASSERT_NO_THROW(valuation.setIntegerValue("y", 3));
+    EXPECT_FALSE(tempExpression.evaluateAsBool(&valuation));
+    
+    ASSERT_NO_THROW(tempExpression = ((intVarExpression < threeExpression).ite(trueExpression, falseExpression)));
+    ASSERT_THROW(tempExpression.evaluateAsDouble(&valuation), storm::exceptions::InvalidTypeException);
+    ASSERT_THROW(tempExpression.evaluateAsInt(&valuation), storm::exceptions::InvalidTypeException);
+    EXPECT_FALSE(tempExpression.evaluateAsBool(&valuation));
+}
\ No newline at end of file