diff --git a/src/builder/BuilderOptions.cpp b/src/builder/BuilderOptions.cpp
index 87dcc69b8..e189e7200 100644
--- a/src/builder/BuilderOptions.cpp
+++ b/src/builder/BuilderOptions.cpp
@@ -35,7 +35,7 @@ namespace storm {
             return boost::get<storm::expressions::Expression>(labelOrExpression);
         }
         
-        BuilderOptions::BuilderOptions(bool buildAllRewardModels, bool buildAllLabels) : buildAllRewardModels(buildAllRewardModels), buildAllLabels(buildAllLabels), buildChoiceLabels(false) {
+        BuilderOptions::BuilderOptions(bool buildAllRewardModels, bool buildAllLabels) : buildAllRewardModels(buildAllRewardModels), buildAllLabels(buildAllLabels), buildChoiceLabels(false), explorationChecks(false) {
             // Intentionally left empty.
         }
         
diff --git a/src/builder/jit/ExplicitJitJaniModelBuilder.cpp b/src/builder/jit/ExplicitJitJaniModelBuilder.cpp
index 2d4d13877..7dd4d78d6 100644
--- a/src/builder/jit/ExplicitJitJaniModelBuilder.cpp
+++ b/src/builder/jit/ExplicitJitJaniModelBuilder.cpp
@@ -9,6 +9,7 @@
 #include "src/solver/SmtSolver.h"
 #include "src/storage/jani/AutomatonComposition.h"
 #include "src/storage/jani/ParallelComposition.h"
+#include "src/storage/jani/JSONExporter.h"
 
 #include "src/builder/RewardModelInformation.h"
 
@@ -44,7 +45,7 @@ namespace storm {
 #endif
             
             template <typename ValueType, typename RewardModelType>
-            ExplicitJitJaniModelBuilder<ValueType, RewardModelType>::ExplicitJitJaniModelBuilder(storm::jani::Model const& model, storm::builder::BuilderOptions const& options) : options(options), model(model), modelComponentsBuilder(model.getModelType()) {
+            ExplicitJitJaniModelBuilder<ValueType, RewardModelType>::ExplicitJitJaniModelBuilder(storm::jani::Model const& model, storm::builder::BuilderOptions const& options) : options(options), model(model.substituteConstants()), modelComponentsBuilder(model.getModelType()) {
                 
                 // Load all options from the settings module.
                 storm::settings::modules::JitBuilderSettings const& settings = storm::settings::getModule<storm::settings::modules::JitBuilderSettings>();
@@ -124,6 +125,10 @@ namespace storm {
                     STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "The input model contains undefined constants that influence the graph structure of the underlying model, which is not allowed.");
                 }
 #endif
+      
+                // Comment this in to print the JANI model for debugging purposes. 
+                // this->model.makeStandardJaniCompliant();
+                // storm::jani::JsonExporter::toStream(this->model, std::vector<std::shared_ptr<storm::logic::Formula const>>(), std::cout, false);
             }
             
             template <typename ValueType, typename RewardModelType>
@@ -419,7 +424,13 @@ namespace storm {
                 
                 // (6) Execute the build function of the builder in the shared library and build the actual model.
                 auto start = std::chrono::high_resolution_clock::now();
-                auto sparseModel = builder->build();
+                
+                std::shared_ptr<storm::models::sparse::Model<ValueType, storm::models::sparse::StandardRewardModel<ValueType>>> sparseModel(nullptr);
+                try {
+                    sparseModel = std::shared_ptr<storm::models::sparse::Model<ValueType, storm::models::sparse::StandardRewardModel<ValueType>>>(builder->build());
+                } catch (std::exception const& e) {
+                    STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, "Model building failed. Reason: " << e.what());
+                }
                 auto end = std::chrono::high_resolution_clock::now();
                 STORM_LOG_TRACE("Building model took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms.");
                 
@@ -427,15 +438,22 @@ namespace storm {
                 boost::filesystem::remove(dynamicLibraryPath);
                 
                 // Return the constructed model.
-                return std::shared_ptr<storm::models::sparse::Model<ValueType, RewardModelType>>(sparseModel);
+                return sparseModel;
             }
             
             template <typename ValueType, typename RewardModelType>
             cpptempl::data_map ExplicitJitJaniModelBuilder<ValueType, RewardModelType>::generateModelData() {
                 cpptempl::data_map modelData;
                 // Generate trivial model-information.
-                modelData["deterministic_model"] = model.isDeterministicModel() ? "true" : "false";
-                modelData["discrete_time_model"] = model.isDiscreteTimeModel() ? "true" : "false";
+                modelData["deterministic_model"] = asString(model.isDeterministicModel());
+                modelData["discrete_time_model"] = asString(model.isDiscreteTimeModel());
+                
+                // Use a list here to enable if query in skeleton program.
+                cpptempl::data_list list;
+                if (options.isExplorationChecksSet()) {
+                    list.push_back(cpptempl::data_map());
+                }
+                modelData["exploration_checks"] = cpptempl::make_data(list);
 
                 // Generate non-trivial model-information.
                 generateVariables(modelData);
@@ -894,6 +912,9 @@ namespace storm {
                     vectorSource << "int64_t lowestLevel, int64_t highestLevel, ";
                 }
                 vectorSource << "Choice<IndexType, ValueType>& choice) {" << std::endl;
+                if (options.isExplorationChecksSet()) {
+                    indent(vectorSource, indentLevel + 1) << "VariableWrites variableWrites;" << std::endl;
+                }
                 indent(vectorSource, indentLevel + 1) << "StateType out(in);" << std::endl;
                 indent(vectorSource, indentLevel + 1) << "TransientVariables transientIn;" << std::endl;
                 indent(vectorSource, indentLevel + 1) << "TransientVariables transientOut;" << std::endl;
@@ -907,7 +928,11 @@ namespace storm {
                     if (generateLevelCode) {
                         vectorSource << "level, ";
                     }
-                    vectorSource << "in, out, transientIn, transientOut);" << std::endl;
+                    vectorSource << "in, out, transientIn, transientOut";
+                    if (options.isExplorationChecksSet()) {
+                        vectorSource << ", variableWrites";
+                    }
+                    vectorSource << ");" << std::endl;
                 }
                 if (generateLevelCode) {
                     --indentLevel;
@@ -916,7 +941,7 @@ namespace storm {
                 indent(vectorSource, indentLevel + 1) << "IndexType outStateIndex = getOrAddIndex(out, statesToExplore);" << std::endl;
                 indent(vectorSource, indentLevel + 1) << "ValueType probability = ";
                 for (uint64_t index = 0; index < numberOfActionInputs; ++index) {
-                    vectorSource << "destination" << index << ".value()";
+                    vectorSource << "destination" << index << ".value(in)";
                     if (index + 1 < numberOfActionInputs) {
                         vectorSource << " * ";
                     }
@@ -975,20 +1000,34 @@ namespace storm {
                     }
                     if (index > 0) {
                         vectorSource << ", TransientVariables const& transientIn, TransientVariables& transientOut";
+                        if (options.isExplorationChecksSet()) {
+                            vectorSource << ", VariableWrites& variableWrites";
+                        }
                     }
                     vectorSource << ") {" << std::endl;
                     if (index == 0) {
+                        if (options.isExplorationChecksSet()) {
+                            indent(vectorSource, indentLevel + 1) << "VariableWrites variableWrites;" << std::endl;
+                        }
                         indent(vectorSource, indentLevel + 1) << "TransientVariables transientIn;" << std::endl;
                         indent(vectorSource, indentLevel + 1) << "TransientVariables transientOut;" << std::endl;
                     }
                     indent(vectorSource, indentLevel + 1) << "for (auto const& edge" << index << " : edges[" << index << "]) {" << std::endl;
-                    indent(vectorSource, indentLevel + 2) << "edge" << index << ".get().perform(in, transientIn, transientOut);" << std::endl;
+                    indent(vectorSource, indentLevel + 2) << "edge" << index << ".get().perform(in, transientIn, transientOut";
+                    if (options.isExplorationChecksSet()) {
+                        vectorSource << ", variableWrites";
+                    }
+                    vectorSource << ");" << std::endl;
                     if (index + 1 < numberOfActionInputs) {
                         indent(vectorSource, indentLevel + 2) << "performSynchronizedEdges_" << synchronizationVectorIndex << "_" << (index + 1) << "(in, edges, behaviour, statesToExplore, ";
                         for (uint64_t innerIndex = 0; innerIndex <= index; ++innerIndex) {
                             vectorSource << "edge" << innerIndex << ", ";
                         }
-                        vectorSource << "transientIn, transientOut);" << std::endl;
+                        vectorSource << "transientIn, transientOut";
+                        if (options.isExplorationChecksSet()) {
+                            vectorSource << ", variableWrites";
+                        }
+                        vectorSource << ");" << std::endl;
                     } else {
                         indent(vectorSource, indentLevel + 2) << "Choice<IndexType, ValueType>& choice = behaviour.addChoice();" << std::endl;
                         
@@ -1038,6 +1077,9 @@ namespace storm {
                 indent(vectorSource, indentLevel) << "}" << std::endl << std::endl;
                 
                 indent(vectorSource, indentLevel) << "void exploreSynchronizationVector_" << synchronizationVectorIndex << "(StateType const& state, StateBehaviour<IndexType, ValueType>& behaviour, StateSet<StateType>& statesToExplore) {" << std::endl;
+                indent(vectorSource, indentLevel + 1) << "#ifndef NDEBUG" << std::endl;
+                indent(vectorSource, indentLevel + 1) << "std::cout << \"exploring synchronization vector " << synchronizationVectorIndex << "\" << std::endl;" << std::endl;
+                indent(vectorSource, indentLevel + 1) << "#endif" << std::endl;
                 indent(vectorSource, indentLevel + 1) << "std::vector<std::vector<std::reference_wrapper<Edge const>>> edges(" << synchronizationVector.getNumberOfActionInputs() << ");" << std::endl;
                 
                 participatingPosition = 0;
@@ -1162,7 +1204,7 @@ namespace storm {
                 uint64_t destinationIndex = 0;
                 std::set<storm::expressions::Variable> transientVariablesInDestinations;
                 for (auto const& destination : edge.getDestinations()) {
-                    destinations.push_back(generateDestination(destinationIndex, destination));
+                    destinations.push_back(generateDestination(destinationIndex, destination, edge.getOptionalRate()));
                     
                     for (auto const& assignment : destination.getOrderedAssignments().getAllAssignments()) {
                         if (assignment.isTransient()) {
@@ -1183,6 +1225,7 @@ namespace storm {
                 edgeData["destinations"] = cpptempl::make_data(destinations);
                 edgeData["name"] = automaton.getName() + "_" + std::to_string(edgeIndex);
                 edgeData["transient_assignments"] = cpptempl::make_data(edgeAssignments);
+                edgeData["markovian"] = asString(edge.hasRate());
                 
                 cpptempl::data_list transientVariablesInDestinationsData;
                 for (auto const& variable : transientVariablesInDestinations) {
@@ -1198,13 +1241,17 @@ namespace storm {
             }
             
             template <typename ValueType, typename RewardModelType>
-            cpptempl::data_map ExplicitJitJaniModelBuilder<ValueType, RewardModelType>::generateDestination(uint64_t destinationIndex, storm::jani::EdgeDestination const& destination) {
+                cpptempl::data_map ExplicitJitJaniModelBuilder<ValueType, RewardModelType>::generateDestination(uint64_t destinationIndex, storm::jani::EdgeDestination const& destination, boost::optional<storm::expressions::Expression> const& rate) {
                 cpptempl::data_map destinationData;
                 
                 cpptempl::data_list levels = generateLevels(destination.getOrderedAssignments());
                 destinationData["name"] = asString(destinationIndex);
                 destinationData["levels"] = cpptempl::make_data(levels);
-                destinationData["value"] = expressionTranslator.translate(shiftVariablesWrtLowerBound(destination.getProbability()), storm::expressions::ToCppTranslationOptions(variablePrefixes, variableToName, "double"));
+                if (rate) {
+                    destinationData["value"] = expressionTranslator.translate(shiftVariablesWrtLowerBound(rate.get() * destination.getProbability()), storm::expressions::ToCppTranslationOptions(variablePrefixes, variableToName, "double"));
+                } else {
+                    destinationData["value"] = expressionTranslator.translate(shiftVariablesWrtLowerBound(destination.getProbability()), storm::expressions::ToCppTranslationOptions(variablePrefixes, variableToName, "double"));
+                }
                 if (destination.getOrderedAssignments().empty()) {
                     destinationData["lowestLevel"] = "0";
                     destinationData["highestLevel"] = "0";
@@ -1262,7 +1309,14 @@ namespace storm {
             cpptempl::data_map ExplicitJitJaniModelBuilder<ValueType, RewardModelType>::generateAssignment(storm::jani::Variable const& variable, ValueTypePrime value) const {
                 cpptempl::data_map result;
                 result["variable"] = getVariableName(variable.getExpressionVariable());
-                result["value"] = asString(value);
+                
+                // Check if the variable has a non-zero lower bound and, if so, shift it appropriately.
+                auto it = lowerBounds.find(variable.getExpressionVariable());
+                if (it != lowerBounds.end()) {
+                    result["value"] = asString(value) + " - " + asString(it->second);
+                } else {
+                    result["value"] = asString(value);
+                }
                 return result;
             }
             
@@ -1438,6 +1492,8 @@ namespace storm {
 #include "src/builder/jit/ModelComponentsBuilder.h"
 #include "src/builder/RewardModelInformation.h"
                 
+#include "src/exceptions/WrongFormatException.h"
+                
                 namespace storm {
                     namespace builder {
                         namespace jit {
@@ -1538,6 +1594,60 @@ namespace storm {
                                 return out;
                             }
                             
+                            {% if exploration_checks %}
+                            struct VariableWrites {
+                                VariableWrites() {
+                                    reset();
+                                }
+                                
+                                void reset() {
+                                    {% for variable in nontransient_variables.boolean %}{$variable.name} = false;
+                                    {% endfor %}
+                                    {% for variable in nontransient_variables.boundedInteger %}{$variable.name} = false;
+                                    {% endfor %}
+                                    {% for variable in nontransient_variables.unboundedInteger %}{$variable.name} = false;
+                                    {% endfor %}
+                                    {% for variable in nontransient_variables.real %}{$variable.name} = false;
+                                    {% endfor %}
+                                    {% for variable in nontransient_variables.locations %}{$variable.name} = false;
+                                    {% endfor %}
+                                    {% for variable in transient_variables.boolean %}{$variable.name} = false;
+                                    {% endfor %}
+                                    {% for variable in transient_variables.boundedInteger %}{$variable.name} = false;
+                                    {% endfor %}
+                                    {% for variable in transient_variables.unboundedInteger %}{$variable.name} = false;
+                                    {% endfor %}
+                                    {% for variable in transient_variables.real %}{$variable.name} = false;
+                                    {% endfor %}
+                                }
+                                
+                                // Boolean variables.
+                                {% for variable in nontransient_variables.boolean %}bool {$variable.name} : 1;
+                                {% endfor %}
+                                {% for variable in transient_variables.boolean %}bool {$variable.name} : 1;
+                                {% endfor %}
+                                // Bounded integer variables.
+                                {% for variable in nontransient_variables.boundedInteger %}bool {$variable.name} : 1;
+                                {% endfor %}
+                                {% for variable in transient_variables.boundedInteger %}bool {$variable.name} : 1;
+                                {% endfor %}
+                                // Unbounded integer variables.
+                                {% for variable in nontransient_variables.unboundedInteger %}bool {$variable.name} : 1;
+                                {% endfor %}
+                                {% for variable in transient_variables.unboundedInteger %}bool {$variable.name} : 1;
+                                {% endfor %}
+                                // Real variables.
+                                {% for variable in nontransient_variables.real %}bool {$variable.name} : 1;
+                                {% endfor %}
+                                {% for variable in transient_variables.real %}bool {$variable.name} : 1;
+                                {% endfor %}
+
+                                // Location variables.
+                                {% for variable in nontransient_variables.locations %}bool {$variable.name} : 1;
+                                {% endfor %}
+                            };
+                            {% endif %}
+                            
                         }
                     }
                 }
@@ -1575,6 +1685,15 @@ namespace storm {
                                 return {$discrete_time_model};
                             }
                             
+                            static bool perform_exploration_checks() {
+                                {% if exploration_checks %}
+                                return true;
+                                {% endif %}
+                                {% if not exploration_checks %}
+                                return false;
+                                {% endif %}
+                            }
+                            
                             // Non-synchronizing edges.
                             {% for edge in nonsynch_edges %}static bool edge_enabled_{$edge.name}(StateType const& in) {
                                 if ({$edge.guard}) {
@@ -1583,41 +1702,73 @@ namespace storm {
                                 return false;
                             }
                             
-                            static void edge_perform_{$edge.name}(StateType const& in, TransientVariables const& transientIn, TransientVariables& transientOut) {
+                            static void edge_perform_{$edge.name}(StateType const& in, TransientVariables const& transientIn, TransientVariables& transientOut {% if exploration_checks %}, VariableWrites& variableWrites {% endif %}) {
                                 {% for assignment in edge.transient_assignments %}transientOut.{$assignment.variable} = {$assignment.value};
+                                {% if exploration_checks %}
+                                if (variableWrites.{$assignment.variable}) {
+                                    throw storm::exceptions::WrongFormatException("Illegal write to {$assignment.variable}, variable has been written before.");
+                                } else {
+                                    variableWrites.{$assignment.variable} = true;
+                                }
+                                {% endif %}
                                 {% endfor %}
                             }
                             
                             {% for destination in edge.destinations %}
-                            static void destination_perform_level_{$edge.name}_{$destination.name}(int_fast64_t level, StateType const& in, StateType& out) {
+                            static void destination_perform_level_{$edge.name}_{$destination.name}(int_fast64_t level, StateType const& in, StateType& out {% if exploration_checks %}, VariableWrites& variableWrites {% endif %}) {
                                 {% for level in destination.levels %}if (level == {$level.index}) {
                                     {% for assignment in level.non_transient_assignments %}out.{$assignment.variable} = {$assignment.value};
+                                    {% if exploration_checks %}
+                                    if (variableWrites.{$assignment.variable}) {
+                                        throw storm::exceptions::WrongFormatException("Illegal write to {$assignment.variable}, variable has been written before.");
+                                    } else {
+                                        variableWrites.{$assignment.variable} = true;
+                                    }
+                                    {% endif %}
                                     {% endfor %}
                                 }
                                 {% endfor %}
                             }
                             
-                            static void destination_perform_{$edge.name}_{$destination.name}(StateType const& in, StateType& out) {
+                            static void destination_perform_{$edge.name}_{$destination.name}(StateType const& in, StateType& out {% if exploration_checks %}, VariableWrites& variableWrites {% endif %}) {
                                 {% for level in destination.levels %}
-                                destination_perform_level_{$edge.name}_{$destination.name}({$level.index}, in, out);
+                                destination_perform_level_{$edge.name}_{$destination.name}({$level.index}, in, out {% if exploration_checks %}, variableWrites {% endif %});
                                 {% endfor %}
                             }
                             
-                            static void destination_perform_level_{$edge.name}_{$destination.name}(int_fast64_t level, StateType const& in, StateType& out, TransientVariables const& transientIn, TransientVariables& transientOut) {
+                            static void destination_perform_level_{$edge.name}_{$destination.name}(int_fast64_t level, StateType const& in, StateType& out, TransientVariables const& transientIn, TransientVariables& transientOut {% if exploration_checks %}, VariableWrites& variableWrites {% endif %}) {
                                 {% for level in destination.levels %}if (level == {$level.index}) {
                                     {% for assignment in level.non_transient_assignments %}out.{$assignment.variable} = {$assignment.value};
+                                    {% if exploration_checks %}
+                                    if (variableWrites.{$assignment.variable}) {
+                                        throw storm::exceptions::WrongFormatException("Illegal write to {$assignment.variable}, variable has been written before.");
+                                    } else {
+                                        variableWrites.{$assignment.variable} = true;
+                                    }
+                                    {% endif %}
                                     {% endfor %}
                                     {% for assignment in level.transient_assignments %}transientOut.{$assignment.variable} = {$assignment.value};
+                                    {% if exploration_checks %}
+                                    if (variableWrites.{$assignment.variable}) {
+                                        throw storm::exceptions::WrongFormatException("Illegal write to {$assignment.variable}, variable has been written before.");
+                                    } else {
+                                        variableWrites.{$assignment.variable} = true;
+                                    }
+                                    {% endif %}
                                     {% endfor %}
                                 }
                                 {% endfor %}
                             }
                             
-                            static void destination_perform_{$edge.name}_{$destination.name}(StateType const& in, StateType& out, TransientVariables const& transientIn, TransientVariables& transientOut) {
+                            static void destination_perform_{$edge.name}_{$destination.name}(StateType const& in, StateType& out, TransientVariables const& transientIn, TransientVariables& transientOut {% if exploration_checks %}, VariableWrites& variableWrites {% endif %}) {
                                 {% for level in destination.levels %}
-                                destination_perform_level_{$edge.name}_{$destination.name}({$level.index}, in, out, transientIn, transientOut);
+                                destination_perform_level_{$edge.name}_{$destination.name}({$level.index}, in, out, transientIn, transientOut {% if exploration_checks %}, variableWrites {% endif %});
                                 {% endfor %}
                             }
+
+                            static ValueType destination_value_{$edge.name}_{$destination.name}(StateType const& in) {
+                                return {$destination.value};
+                            }
                             {% endfor %}{% endfor %}
                             
                             // Synchronizing edges.
@@ -1628,55 +1779,88 @@ namespace storm {
                                 return false;
                             }
                             
-                            static void edge_perform_{$edge.name}(StateType const& in, TransientVariables const& transientIn, TransientVariables& transientOut) {
+                            static void edge_perform_{$edge.name}(StateType const& in, TransientVariables const& transientIn, TransientVariables& transientOut {% if exploration_checks %}, VariableWrites& variableWrites {% endif %}) {
                                 {% for assignment in edge.transient_assignments %}transientOut.{$assignment.variable} = {$assignment.value};
+                                {% if exploration_checks %}
+                                if (variableWrites.{$assignment.variable}) {
+                                    throw storm::exceptions::WrongFormatException("Illegal write to {$assignment.variable}, variable has been written before.");
+                                } else {
+                                    variableWrites.{$assignment.variable} = true;
+                                }
+                                {% endif %}
                                 {% endfor %}
                             }
                             
                             {% for destination in edge.destinations %}
-                            static void destination_perform_level_{$edge.name}_{$destination.name}(int_fast64_t level, StateType const& in, StateType& out) {
+                            static void destination_perform_level_{$edge.name}_{$destination.name}(int_fast64_t level, StateType const& in, StateType& out {% if exploration_checks %}, VariableWrites& variableWrites {% endif %}) {
                                 {% for level in destination.levels %}if (level == {$level.index}) {
                                     {% for assignment in level.non_transient_assignments %}out.{$assignment.variable} = {$assignment.value};
+                                    {% if exploration_checks %}
+                                    if (variableWrites.{$assignment.variable}) {
+                                        throw storm::exceptions::WrongFormatException("Illegal write to {$assignment.variable}, variable has been written before.");
+                                    } else {
+                                        variableWrites.{$assignment.variable} = true;
+                                    }
+                                    {% endif %}
                                     {% endfor %}
                                 }
                                 {% endfor %}
                             }
                             
-                            static void destination_perform_{$edge.name}_{$destination.name}(StateType const& in, StateType& out) {
+                            static void destination_perform_{$edge.name}_{$destination.name}(StateType const& in, StateType& out {% if exploration_checks %}, VariableWrites& variableWrites {% endif %}) {
                                 {% for level in destination.levels %}
-                                destination_perform_level_{$edge.name}_{$destination.name}({$level.index}, in, out);
+                                destination_perform_level_{$edge.name}_{$destination.name}({$level.index}, in, out {% if exploration_checks %}, variableWrites {% endif %});
                                 {% endfor %}
                             }
                             
-                            static void destination_perform_level_{$edge.name}_{$destination.name}(int_fast64_t level, StateType const& in, StateType& out, TransientVariables const& transientIn, TransientVariables& transientOut) {
+                            static void destination_perform_level_{$edge.name}_{$destination.name}(int_fast64_t level, StateType const& in, StateType& out, TransientVariables const& transientIn, TransientVariables& transientOut {% if exploration_checks %}, VariableWrites& variableWrites {% endif %}) {
                                 {% for level in destination.levels %}if (level == {$level.index}) {
                                     {% for assignment in level.non_transient_assignments %}out.{$assignment.variable} = {$assignment.value};
+                                    {% if exploration_checks %}
+                                    if (variableWrites.{$assignment.variable}) {
+                                        throw storm::exceptions::WrongFormatException("Illegal write to {$assignment.variable}, variable has been written before.");
+                                    } else {
+                                        variableWrites.{$assignment.variable} = true;
+                                    }
+                                    {% endif %}
                                     {% endfor %}
                                     {% for assignment in level.transient_assignments %}transientOut.{$assignment.variable} = {$assignment.value};
+                                    {% if exploration_checks %}
+                                    if (variableWrites.{$assignment.variable}) {
+                                        throw storm::exceptions::WrongFormatException("Illegal write to {$assignment.variable}, variable has been written before.");
+                                    } else {
+                                        variableWrites.{$assignment.variable} = true;
+                                    }
+                                    {% endif %}
                                     {% endfor %}
                                 }
                                 {% endfor %}
                             }
                             
-                            static void destination_perform_{$edge.name}_{$destination.name}(StateType const& in, StateType& out, TransientVariables const& transientIn, TransientVariables& transientOut) {
+                            static void destination_perform_{$edge.name}_{$destination.name}(StateType const& in, StateType& out, TransientVariables const& transientIn, TransientVariables& transientOut {% if exploration_checks %}, VariableWrites& variableWrites {% endif %}) {
                                 {% for level in destination.levels %}
-                                destination_perform_level_{$edge.name}_{$destination.name}({$level.index}, in, out, transientIn, transientOut);
+                                destination_perform_level_{$edge.name}_{$destination.name}({$level.index}, in, out, transientIn, transientOut {% if exploration_checks %}, variableWrites {% endif %});
                                 {% endfor %}
                             }
+                            
+                            static ValueType destination_value_{$edge.name}_{$destination.name}(StateType const& in) {
+                                return {$destination.value};
+                            }
                             {% endfor %}{% endfor %}
                             
-                            typedef void (*DestinationLevelFunctionPtr)(int_fast64_t, StateType const&, StateType&, TransientVariables const&, TransientVariables&);
-                            typedef void (*DestinationFunctionPtr)(StateType const&, StateType&, TransientVariables const&, TransientVariables&);
-                            typedef void (*DestinationWithoutTransientLevelFunctionPtr)(int_fast64_t, StateType const&, StateType&);
-                            typedef void (*DestinationWithoutTransientFunctionPtr)(StateType const&, StateType&);
+                            typedef ValueType (*DestinationValueFunctionPtr)(StateType const&);
+                            typedef void (*DestinationLevelFunctionPtr)(int_fast64_t, StateType const&, StateType&, TransientVariables const&, TransientVariables& {% if exploration_checks %}, VariableWrites& {% endif %});
+                            typedef void (*DestinationFunctionPtr)(StateType const&, StateType&, TransientVariables const&, TransientVariables& {% if exploration_checks %}, VariableWrites& {% endif %});
+                            typedef void (*DestinationWithoutTransientLevelFunctionPtr)(int_fast64_t, StateType const&, StateType& {% if exploration_checks %}, VariableWrites& {% endif %});
+                            typedef void (*DestinationWithoutTransientFunctionPtr)(StateType const&, StateType& {% if exploration_checks %}, VariableWrites& {% endif %});
                             
                             class Destination {
                             public:
-                                Destination() : mLowestLevel(0), mHighestLevel(0), mValue(), destinationLevelFunction(nullptr), destinationFunction(nullptr), destinationWithoutTransientLevelFunction(nullptr), destinationWithoutTransientFunction(nullptr) {
+                                Destination() : mLowestLevel(0), mHighestLevel(0), destinationValueFunction(nullptr), destinationLevelFunction(nullptr), destinationFunction(nullptr), destinationWithoutTransientLevelFunction(nullptr), destinationWithoutTransientFunction(nullptr) {
                                     // Intentionally left empty.
                                 }
                                 
-                                Destination(int_fast64_t lowestLevel, int_fast64_t highestLevel, ValueType const& value, DestinationLevelFunctionPtr destinationLevelFunction, DestinationFunctionPtr destinationFunction, DestinationWithoutTransientLevelFunctionPtr destinationWithoutTransientLevelFunction, DestinationWithoutTransientFunctionPtr destinationWithoutTransientFunction) : mLowestLevel(lowestLevel), mHighestLevel(highestLevel), mValue(value), destinationLevelFunction(destinationLevelFunction), destinationFunction(destinationFunction), destinationWithoutTransientLevelFunction(destinationWithoutTransientLevelFunction), destinationWithoutTransientFunction(destinationWithoutTransientFunction) {
+                                Destination(int_fast64_t lowestLevel, int_fast64_t highestLevel, DestinationValueFunctionPtr destinationValueFunction, DestinationLevelFunctionPtr destinationLevelFunction, DestinationFunctionPtr destinationFunction, DestinationWithoutTransientLevelFunctionPtr destinationWithoutTransientLevelFunction, DestinationWithoutTransientFunctionPtr destinationWithoutTransientFunction) : mLowestLevel(lowestLevel), mHighestLevel(highestLevel), destinationValueFunction(destinationValueFunction), destinationLevelFunction(destinationLevelFunction), destinationFunction(destinationFunction), destinationWithoutTransientLevelFunction(destinationWithoutTransientLevelFunction), destinationWithoutTransientFunction(destinationWithoutTransientFunction) {
                                     // Intentionally left empty.
                                 }
                                 
@@ -1688,30 +1872,30 @@ namespace storm {
                                     return mHighestLevel;
                                 }
                                 
-                                ValueType const& value() const {
-                                    return mValue;
+                                ValueType value(StateType const& in) const {
+                                    return destinationValueFunction(in);
                                 }
                                 
-                                void perform(int_fast64_t level, StateType const& in, StateType& out, TransientVariables const& transientIn, TransientVariables& transientOut) const {
-                                    destinationLevelFunction(level, in, out, transientIn, transientOut);
+                                void perform(int_fast64_t level, StateType const& in, StateType& out, TransientVariables const& transientIn, TransientVariables& transientOut {% if exploration_checks %}, VariableWrites& variableWrites {% endif %}) const {
+                                    destinationLevelFunction(level, in, out, transientIn, transientOut {% if exploration_checks %}, variableWrites {% endif %});
                                 }
                                 
-                                void perform(StateType const& in, StateType& out, TransientVariables const& transientIn, TransientVariables& transientOut) const {
-                                    destinationFunction(in, out, transientIn, transientOut);
+                                void perform(StateType const& in, StateType& out, TransientVariables const& transientIn, TransientVariables& transientOut {% if exploration_checks %}, VariableWrites& variableWrites {% endif %}) const {
+                                    destinationFunction(in, out, transientIn, transientOut {% if exploration_checks %}, variableWrites {% endif %});
                                 }
                                 
-                                void perform(int_fast64_t level, StateType const& in, StateType& out) const {
-                                    destinationWithoutTransientLevelFunction(level, in, out);
+                                void perform(int_fast64_t level, StateType const& in, StateType& out {% if exploration_checks %}, VariableWrites& variableWrites {% endif %}) const {
+                                    destinationWithoutTransientLevelFunction(level, in, out {% if exploration_checks %}, variableWrites {% endif %});
                                 }
                                 
-                                void perform(StateType const& in, StateType& out) const {
-                                    destinationWithoutTransientFunction(in, out);
+                                void perform(StateType const& in, StateType& out {% if exploration_checks %}, VariableWrites& variableWrites {% endif %}) const {
+                                    destinationWithoutTransientFunction(in, out {% if exploration_checks %}, variableWrites {% endif %});
                                 }
                                 
                             private:
                                 int_fast64_t mLowestLevel;
                                 int_fast64_t mHighestLevel;
-                                ValueType mValue;
+                                DestinationValueFunctionPtr destinationValueFunction;
                                 DestinationLevelFunctionPtr destinationLevelFunction;
                                 DestinationFunctionPtr destinationFunction;
                                 DestinationWithoutTransientLevelFunctionPtr destinationWithoutTransientLevelFunction;
@@ -1719,7 +1903,7 @@ namespace storm {
                             };
                             
                             typedef bool (*EdgeEnabledFunctionPtr)(StateType const&);
-                            typedef void (*EdgeTransientFunctionPtr)(StateType const&, TransientVariables const& transientIn, TransientVariables& out);
+                            typedef void (*EdgeTransientFunctionPtr)(StateType const&, TransientVariables const& transientIn, TransientVariables& out {% if exploration_checks %}, VariableWrites& variableWrites {% endif %});
                             
                             class Edge {
                             public:
@@ -1741,8 +1925,8 @@ namespace storm {
                                     destinations.push_back(destination);
                                 }
                                 
-                                void addDestination(int_fast64_t lowestLevel, int_fast64_t highestLevel, ValueType const& value, DestinationLevelFunctionPtr destinationLevelFunction, DestinationFunctionPtr destinationFunction, DestinationWithoutTransientLevelFunctionPtr destinationWithoutTransientLevelFunction, DestinationWithoutTransientFunctionPtr destinationWithoutTransientFunction) {
-                                    destinations.emplace_back(lowestLevel, highestLevel, value, destinationLevelFunction, destinationFunction, destinationWithoutTransientLevelFunction, destinationWithoutTransientFunction);
+                                void addDestination(int_fast64_t lowestLevel, int_fast64_t highestLevel, DestinationValueFunctionPtr destinationValueFunction, DestinationLevelFunctionPtr destinationLevelFunction, DestinationFunctionPtr destinationFunction, DestinationWithoutTransientLevelFunctionPtr destinationWithoutTransientLevelFunction, DestinationWithoutTransientFunctionPtr destinationWithoutTransientFunction) {
+                                    destinations.emplace_back(lowestLevel, highestLevel, destinationValueFunction, destinationLevelFunction, destinationFunction, destinationWithoutTransientLevelFunction, destinationWithoutTransientFunction);
                                 }
                                 
                                 std::vector<Destination> const& getDestinations() const {
@@ -1757,8 +1941,8 @@ namespace storm {
                                     return destinations.end();
                                 }
                                 
-                                void perform(StateType const& in, TransientVariables const& transientIn, TransientVariables& transientOut) const {
-                                    edgeTransientFunction(in, transientIn, transientOut);
+                                void perform(StateType const& in, TransientVariables const& transientIn, TransientVariables& transientOut {% if exploration_checks %}, VariableWrites& variableWrites {% endif %}) const {
+                                    edgeTransientFunction(in, transientIn, transientOut {% if exploration_checks %}, variableWrites {% endif %});
                                 }
                                 
                             private:
@@ -1767,9 +1951,17 @@ namespace storm {
                                 ContainerType destinations;
                             };
                             
-                            void locations_perform(StateType const& in, TransientVariables const& transientIn, TransientVariables& transientOut) {
+                            void locations_perform(StateType const& in, TransientVariables const& transientIn, TransientVariables& transientOut {% if exploration_checks %}, VariableWrites& variableWrites {% endif %}) {
                                 {% for location in locations %}if ({$location.guard}) {
-                                    {% for assignment in location.assignments %}transientOut.{$assignment.variable} = {$assignment.value};{% endfor %}
+                                    {% for assignment in location.assignments %}transientOut.{$assignment.variable} = {$assignment.value};
+                                    {% if exploration_checks %}
+                                    if (variableWrites.{$assignment.variable}) {
+                                        throw storm::exceptions::WrongFormatException("Illegal write to {$assignment.variable}, variable has been written before.");
+                                    } else {
+                                        variableWrites.{$assignment.variable} = true;
+                                    }
+                                    {% endif %}
+                                    {% endfor %}
                                 }
                                 {% endfor %}
                             }
@@ -1785,13 +1977,13 @@ namespace storm {
                                     }{% endfor %}
                                     {% for edge in nonsynch_edges %}{
                                         edge_{$edge.name} = Edge(&edge_enabled_{$edge.name}, edge_perform_{$edge.name});
-                                        {% for destination in edge.destinations %}edge_{$edge.name}.addDestination({$destination.lowestLevel}, {$destination.highestLevel}, {$destination.value}, &destination_perform_level_{$edge.name}_{$destination.name}, &destination_perform_{$edge.name}_{$destination.name}, &destination_perform_level_{$edge.name}_{$destination.name}, &destination_perform_{$edge.name}_{$destination.name});
+                                        {% for destination in edge.destinations %}edge_{$edge.name}.addDestination({$destination.lowestLevel}, {$destination.highestLevel}, &destination_value_{$edge.name}_{$destination.name}, &destination_perform_level_{$edge.name}_{$destination.name}, &destination_perform_{$edge.name}_{$destination.name}, &destination_perform_level_{$edge.name}_{$destination.name}, &destination_perform_{$edge.name}_{$destination.name});
                                         {% endfor %}
                                     }
                                     {% endfor %}
                                     {% for edge in synch_edges %}{
                                         edge_{$edge.name} = Edge(&edge_enabled_{$edge.name}, edge_perform_{$edge.name});
-                                        {% for destination in edge.destinations %}edge_{$edge.name}.addDestination({$destination.lowestLevel}, {$destination.highestLevel}, {$destination.value}, &destination_perform_level_{$edge.name}_{$destination.name}, &destination_perform_{$edge.name}_{$destination.name}, &destination_perform_level_{$edge.name}_{$destination.name}, &destination_perform_{$edge.name}_{$destination.name});
+                                        {% for destination in edge.destinations %}edge_{$edge.name}.addDestination({$destination.lowestLevel}, {$destination.highestLevel}, &destination_value_{$edge.name}_{$destination.name}, &destination_perform_level_{$edge.name}_{$destination.name}, &destination_perform_{$edge.name}_{$destination.name}, &destination_perform_level_{$edge.name}_{$destination.name}, &destination_perform_{$edge.name}_{$destination.name});
                                         {% endfor %}
                                     }
                                     {% endfor %}
@@ -1870,10 +2062,13 @@ namespace storm {
                                             
                                             behaviour.setExpanded();
                                             
+                                            {% if exploration_checks %}VariableWrites variableWrites;
+                                            {% endif %}
+                                            
                                             // Perform transient location assignments.
                                             TransientVariables transientIn;
                                             TransientVariables transientOut;
-                                            locations_perform(currentState, transientIn, transientOut);
+                                            locations_perform(currentState, transientIn, transientOut {% if exploration_checks %}, variableWrites {% endif %});
                                             {% for reward in location_rewards %}
                                             behaviour.addStateReward(transientOut.{$reward.variable});
                                             {% endfor %}
@@ -1901,24 +2096,30 @@ namespace storm {
                                 void exploreNonSynchronizingEdges(StateType const& in, StateBehaviour<IndexType, ValueType>& behaviour, StateSet<StateType>& statesToExplore) {
                                     {% for edge in nonsynch_edges %}{
                                         if ({$edge.guard}) {
-                                            Choice<IndexType, ValueType>& choice = behaviour.addChoice();
+                                            Choice<IndexType, ValueType>& choice = behaviour.addChoice(!model_is_deterministic() && !model_is_discrete_time() && {$edge.markovian});
                                             choice.resizeRewards({$edge_destination_rewards_count}, 0);
                                             {
+                                                {% if exploration_checks %}VariableWrites variableWrites;
+                                                {% endif %}
+
                                                 TransientVariables transient;
                                                 {% if edge.transient_assignments %}
-                                                edge_perform_{$edge.name}(in, transient, transient);
+                                                edge_perform_{$edge.name}(in, transient, transient {% if exploration_checks %}, variableWrites{% endif %});
                                                 {% endif %}
                                                 {% for reward in edge_rewards %}
                                                 choice.addReward({$reward.index}, transient.{$reward.variable});
                                                 {% endfor %}
                                             }
                                             {% for destination in edge.destinations %}{
+                                                {% if exploration_checks %}VariableWrites variableWrites;
+                                                {% endif %}
+
                                                 StateType out(in);
                                                 TransientVariables transientIn;
                                                 TransientVariables transientOut;
-                                                destination_perform_{$edge.name}_{$destination.name}(in, out{% if edge.transient_variables_in_destinations %}, transientIn, transientOut{% endif %});
+                                                destination_perform_{$edge.name}_{$destination.name}(in, out{% if edge.transient_variables_in_destinations %}, transientIn, transientOut{% endif %}{% if exploration_checks %}, variableWrites{% endif %});
                                                 IndexType outStateIndex = getOrAddIndex(out, statesToExplore);
-                                                choice.add(outStateIndex, {$destination.value});
+                                                choice.add(outStateIndex, destination_value_{$edge.name}_{$destination.name}(in));
                                                 {% for reward in destination_rewards %}
                                                 choice.addReward({$reward.index}, transientOut.{$reward.variable});
                                                 {% endfor %}
diff --git a/src/builder/jit/ExplicitJitJaniModelBuilder.h b/src/builder/jit/ExplicitJitJaniModelBuilder.h
index beb148b62..2a652befe 100644
--- a/src/builder/jit/ExplicitJitJaniModelBuilder.h
+++ b/src/builder/jit/ExplicitJitJaniModelBuilder.h
@@ -98,7 +98,7 @@ namespace storm {
                 cpptempl::data_map generateSynchronizationVector(cpptempl::data_map& modelData, storm::jani::ParallelComposition const& parallelComposition, storm::jani::SynchronizationVector const& synchronizationVector, uint64_t synchronizationVectorIndex);
                 cpptempl::data_list generateLevels(storm::jani::OrderedAssignments const& assignments);
                 cpptempl::data_map generateEdge(storm::jani::Automaton const& automaton, uint64_t edgeIndex, storm::jani::Edge const& edge);
-                cpptempl::data_map generateDestination(uint64_t destinationIndex, storm::jani::EdgeDestination const& destination);
+                cpptempl::data_map generateDestination(uint64_t destinationIndex, storm::jani::EdgeDestination const& destination, boost::optional<storm::expressions::Expression> const& rate = boost::none);
                 template <typename ValueTypePrime>
                 cpptempl::data_map generateAssignment(storm::jani::Variable const& variable, ValueTypePrime value) const;
                 cpptempl::data_map generateLocationAssignment(storm::jani::Automaton const& automaton, uint64_t value) const;
diff --git a/src/builder/jit/StateBehaviour.cpp b/src/builder/jit/StateBehaviour.cpp
index 81e275abd..6ad82405e 100644
--- a/src/builder/jit/StateBehaviour.cpp
+++ b/src/builder/jit/StateBehaviour.cpp
@@ -19,8 +19,8 @@ namespace storm {
             }
             
             template <typename IndexType, typename ValueType>
-            Choice<IndexType, ValueType>& StateBehaviour<IndexType, ValueType>::addChoice() {
-                choices.emplace_back();
+            Choice<IndexType, ValueType>& StateBehaviour<IndexType, ValueType>::addChoice(bool markovian) {
+                choices.emplace_back(markovian);
                 return choices.back();
             }
             
diff --git a/src/builder/jit/StateBehaviour.h b/src/builder/jit/StateBehaviour.h
index 8aba9f10a..109449fb5 100644
--- a/src/builder/jit/StateBehaviour.h
+++ b/src/builder/jit/StateBehaviour.h
@@ -15,7 +15,7 @@ namespace storm {
                 StateBehaviour();
                 
                 void addChoice(Choice<IndexType, ValueType>&& choice);
-                Choice<IndexType, ValueType>& addChoice();
+                Choice<IndexType, ValueType>& addChoice(bool markovian = false);
                 ContainerType const& getChoices() const;
                 
                 /*!
diff --git a/src/storage/jani/Edge.cpp b/src/storage/jani/Edge.cpp
index 0cb150759..b672318ee 100644
--- a/src/storage/jani/Edge.cpp
+++ b/src/storage/jani/Edge.cpp
@@ -28,6 +28,10 @@ namespace storm {
             return rate.get();
         }
         
+        boost::optional<storm::expressions::Expression> const& Edge::getOptionalRate() const {
+            return rate;
+        }
+        
         void Edge::setRate(storm::expressions::Expression const& rate) {
             this->rate = rate;
         }
diff --git a/src/storage/jani/Edge.h b/src/storage/jani/Edge.h
index 60d202cd2..21d040295 100644
--- a/src/storage/jani/Edge.h
+++ b/src/storage/jani/Edge.h
@@ -39,6 +39,11 @@ namespace storm {
              * Retrieves the rate of this edge. Note that calling this is only valid if the edge has an associated rate.
              */
             storm::expressions::Expression const& getRate() const;
+            
+            /*!
+             * Retrieves an optional that stores the rate if there is any and none otherwise.
+             */
+            boost::optional<storm::expressions::Expression> const& getOptionalRate() const;
 
             /*!
              * Sets a new rate for this edge.
diff --git a/src/storage/prism/ToJaniConverter.cpp b/src/storage/prism/ToJaniConverter.cpp
index bda7ae812..acebc5ff3 100644
--- a/src/storage/prism/ToJaniConverter.cpp
+++ b/src/storage/prism/ToJaniConverter.cpp
@@ -218,13 +218,16 @@ namespace storm {
                     // Create the edge object so we can add transient assignments.
                     storm::jani::Edge newEdge(onlyLocationIndex, janiModel.getActionIndex(command.getActionName()), rateExpression, command.getGuardExpression(), destinations);
                     
-                    // Then add the transient assignments for the rewards.
+                    // Then add the transient assignments for the rewards. Note that we may do this only for the first
+                    // module that has this action, so we remove the assignments from the global list of assignments
+                    // to add after adding them to the created edge.
                     auto transientEdgeAssignmentsToAdd = transientEdgeAssignments.find(janiModel.getActionIndex(command.getActionName()));
                     if (transientEdgeAssignmentsToAdd != transientEdgeAssignments.end()) {
                         for (auto const& assignment : transientEdgeAssignmentsToAdd->second) {
                             newEdge.addTransientAssignment(assignment);
                         }
                     }
+                    transientEdgeAssignments.erase(transientEdgeAssignmentsToAdd);
                     
                     // Finally add the constructed edge.
                     automaton.addEdge(newEdge);
diff --git a/test/functional/builder/ExplicitJitJaniModelBuilderTest.cpp b/test/functional/builder/ExplicitJitJaniModelBuilderTest.cpp
index 0086008a6..8a1110d9e 100644
--- a/test/functional/builder/ExplicitJitJaniModelBuilderTest.cpp
+++ b/test/functional/builder/ExplicitJitJaniModelBuilderTest.cpp
@@ -1,12 +1,163 @@
 #include "gtest/gtest.h"
 #include "storm-config.h"
+#include "src/models/sparse/StandardRewardModel.h"
+#include "src/models/sparse/MarkovAutomaton.h"
+#include "src/settings/SettingMemento.h"
 #include "src/parser/PrismParser.h"
-#include "src/storage/jani/Model.h"
 #include "src/builder/jit/ExplicitJitJaniModelBuilder.h"
+#include "src/storage/jani/Model.h"
+
+#include "src/settings/SettingsManager.h"
+#include "src/settings/modules/IOSettings.h"
 
 TEST(ExplicitJitJaniModelBuilderTest, Dtmc) {
     storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/die.pm");
     storm::jani::Model janiModel = program.toJani();
     
-    storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel).build();
+    std::shared_ptr<storm::models::sparse::Model<double>> model = storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel).build();
+    EXPECT_EQ(13ul, model->getNumberOfStates());
+    EXPECT_EQ(20ul, model->getNumberOfTransitions());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/brp-16-2.pm");
+    janiModel = program.toJani();
+    model = storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel).build();
+    EXPECT_EQ(677ul, model->getNumberOfStates());
+    EXPECT_EQ(867ul, model->getNumberOfTransitions());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/crowds-5-5.pm");
+    janiModel = program.toJani();
+    model = storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel).build();
+    EXPECT_EQ(8607ul, model->getNumberOfStates());
+    EXPECT_EQ(15113ul, model->getNumberOfTransitions());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/leader-3-5.pm");
+    janiModel = program.toJani();
+    model = storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel).build();
+    EXPECT_EQ(273ul, model->getNumberOfStates());
+    EXPECT_EQ(397ul, model->getNumberOfTransitions());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/nand-5-2.pm");
+    janiModel = program.toJani();
+    model = storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel).build();
+    EXPECT_EQ(1728ul, model->getNumberOfStates());
+    EXPECT_EQ(2505ul, model->getNumberOfTransitions());
+}
+
+TEST(ExplicitJitJaniModelBuilderTest, Ctmc) {
+    // Set the PRISM compatibility mode temporarily. It is set to its old value once the returned object is destructed.
+    std::unique_ptr<storm::settings::SettingMemento> enablePrismCompatibility = storm::settings::mutableIOSettings().overridePrismCompatibilityMode(true);
+    
+    storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/cluster2.sm");
+    storm::jani::Model janiModel = program.toJani();
+    
+    std::shared_ptr<storm::models::sparse::Model<double>> model = storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel).build();
+    EXPECT_EQ(276ul, model->getNumberOfStates());
+    EXPECT_EQ(1120ul, model->getNumberOfTransitions());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/embedded2.sm");
+    janiModel = program.toJani();
+    model = storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel).build();
+    EXPECT_EQ(3478ul, model->getNumberOfStates());
+    EXPECT_EQ(14639ul, model->getNumberOfTransitions());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/polling2.sm");
+    janiModel = program.toJani();
+    model = storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel).build();
+    EXPECT_EQ(12ul, model->getNumberOfStates());
+    EXPECT_EQ(22ul, model->getNumberOfTransitions());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/fms2.sm");
+    janiModel = program.toJani();
+    model = storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel).build();
+    EXPECT_EQ(810ul, model->getNumberOfStates());
+    EXPECT_EQ(3699ul, model->getNumberOfTransitions());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/tandem5.sm");
+    janiModel = program.toJani();
+    model = storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel).build();
+    EXPECT_EQ(66ul, model->getNumberOfStates());
+    EXPECT_EQ(189ul, model->getNumberOfTransitions());
+}
+
+TEST(ExplicitJitJaniModelBuilderTest, Mdp) {
+    storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/two_dice.nm");
+    storm::jani::Model janiModel = program.toJani();
+    
+    std::shared_ptr<storm::models::sparse::Model<double>> model = storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel).build();
+    EXPECT_EQ(169ul, model->getNumberOfStates());
+    EXPECT_EQ(436ul, model->getNumberOfTransitions());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/leader3.nm");
+    janiModel = program.toJani();
+    model = storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel).build();
+    EXPECT_EQ(364ul, model->getNumberOfStates());
+    EXPECT_EQ(654ul, model->getNumberOfTransitions());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/coin2-2.nm");
+    janiModel = program.toJani();
+    model = storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel).build();
+    EXPECT_EQ(272ul, model->getNumberOfStates());
+    EXPECT_EQ(492ul, model->getNumberOfTransitions());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/csma2-2.nm");
+    janiModel = program.toJani();
+    model = storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel).build();
+    EXPECT_EQ(1038ul, model->getNumberOfStates());
+    EXPECT_EQ(1282ul, model->getNumberOfTransitions());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/firewire3-0.5.nm");
+    janiModel = program.toJani();
+    model = storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel).build();
+    EXPECT_EQ(4093ul, model->getNumberOfStates());
+    EXPECT_EQ(5585ul, model->getNumberOfTransitions());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/wlan0-2-2.nm");
+    janiModel = program.toJani();
+    model = storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel).build();
+    EXPECT_EQ(37ul, model->getNumberOfStates());
+    EXPECT_EQ(59ul, model->getNumberOfTransitions());
+}
+
+TEST(ExplicitJitJaniModelBuilderTest, Ma) {
+    storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/simple.ma");
+    storm::jani::Model janiModel = program.toJani();
+    
+    std::shared_ptr<storm::models::sparse::Model<double>> model = storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel).build();
+    EXPECT_EQ(5ul, model->getNumberOfStates());
+    EXPECT_EQ(8ul, model->getNumberOfTransitions());
+    ASSERT_TRUE(model->isOfType(storm::models::ModelType::MarkovAutomaton));
+    EXPECT_EQ(4ul, model->as<storm::models::sparse::MarkovAutomaton<double>>()->getMarkovianStates().getNumberOfSetBits());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/hybrid_states.ma");
+    janiModel = program.toJani();
+    model = storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel).build();
+    EXPECT_EQ(5ul, model->getNumberOfStates());
+    EXPECT_EQ(13ul, model->getNumberOfTransitions());
+    ASSERT_TRUE(model->isOfType(storm::models::ModelType::MarkovAutomaton));
+    EXPECT_EQ(5ul, model->as<storm::models::sparse::MarkovAutomaton<double>>()->getMarkovianStates().getNumberOfSetBits());
+    
+    program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/stream2.ma");
+    janiModel = program.toJani();
+    model = storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel).build();
+    EXPECT_EQ(12ul, model->getNumberOfStates());
+    EXPECT_EQ(14ul, model->getNumberOfTransitions());
+    ASSERT_TRUE(model->isOfType(storm::models::ModelType::MarkovAutomaton));
+    EXPECT_EQ(7ul, model->as<storm::models::sparse::MarkovAutomaton<double>>()->getMarkovianStates().getNumberOfSetBits());
+}
+
+TEST(ExplicitJitJaniModelBuilderTest, FailComposition) {
+    storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/system_composition.nm");
+    storm::jani::Model janiModel = program.toJani();
+    
+    ASSERT_THROW(storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel).build(), storm::exceptions::WrongFormatException);
 }
+
+TEST(ExplicitJitJaniModelBuilderTest, IllegalSynchronizingWrites) {
+    storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/coin2-2-illegalSynchronizingWrite.nm");
+    storm::jani::Model janiModel = program.toJani();
+    storm::builder::BuilderOptions options;
+    options.setExplorationChecks(true);
+    
+    ASSERT_THROW(storm::builder::jit::ExplicitJitJaniModelBuilder<double>(janiModel, options).build(), storm::exceptions::WrongFormatException);
+}
+