diff --git a/resources/examples/testfiles/dtmc/die.pm b/resources/examples/testfiles/dtmc/die.pm
index 1873bb8c1..e41139001 100644
--- a/resources/examples/testfiles/dtmc/die.pm
+++ b/resources/examples/testfiles/dtmc/die.pm
@@ -1,5 +1,5 @@
 // Knuth's model of a fair die using only fair coins
-mdp
+dtmc
 
 module die
 
diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h
index 8cf964ca5..4180bdc33 100644
--- a/src/storm-cli-utilities/model-handling.h
+++ b/src/storm-cli-utilities/model-handling.h
@@ -373,8 +373,7 @@ namespace storm {
             STORM_LOG_THROW(model->isSparseModel(), storm::exceptions::NotSupportedException, "Counterexample generation is currently only supported for sparse models.");
             auto sparseModel = model->as<storm::models::sparse::Model<ValueType>>();
             
-            STORM_LOG_THROW(sparseModel->isOfType(storm::models::ModelType::Mdp), storm::exceptions::NotSupportedException, "Counterexample is currently only supported for MDPs.");
-            auto mdp = sparseModel->template as<storm::models::sparse::Mdp<ValueType>>();
+            STORM_LOG_THROW(sparseModel->isOfType(storm::models::ModelType::Dtmc) || sparseModel->isOfType(storm::models::ModelType::Mdp), storm::exceptions::NotSupportedException, "Counterexample is currently only supported for discrete-time models.");
             
             auto counterexampleSettings = storm::settings::getModule<storm::settings::modules::CounterexampleGeneratorSettings>();
             if (counterexampleSettings.isMinimalCommandSetGenerationSet()) {
@@ -387,9 +386,15 @@ namespace storm {
                     printComputingCounterexample(property);
                     storm::utility::Stopwatch watch(true);
                     if (useMilp) {
-                        counterexample = storm::api::computePrismHighLevelCounterexampleMilp(program, mdp, property.getRawFormula());
+                        STORM_LOG_THROW(sparseModel->isOfType(storm::models::ModelType::Mdp), storm::exceptions::NotSupportedException, "Counterexample generation using MILP is currently only supported for MDPs.");
+                        counterexample = storm::api::computePrismHighLevelCounterexampleMilp(program, sparseModel->template as<storm::models::sparse::Mdp<ValueType>>(), property.getRawFormula());
                     } else {
-                        counterexample = storm::api::computePrismHighLevelCounterexampleMaxSmt(program, mdp, property.getRawFormula());
+                        STORM_LOG_THROW(sparseModel->isOfType(storm::models::ModelType::Dtmc) || sparseModel->isOfType(storm::models::ModelType::Mdp), storm::exceptions::NotSupportedException, "Counterexample generation using MaxSAT is currently only supported for discrete-time models.");
+                        if (sparseModel->isOfType(storm::models::ModelType::Dtmc)) {
+                            counterexample = storm::api::computePrismHighLevelCounterexampleMaxSmt(program, sparseModel->template as<storm::models::sparse::Dtmc<ValueType>>(), property.getRawFormula());
+                        } else {
+                            counterexample = storm::api::computePrismHighLevelCounterexampleMaxSmt(program, sparseModel->template as<storm::models::sparse::Mdp<ValueType>>(), property.getRawFormula());
+                        }
                     }
                     watch.stop();
                     printCounterexample(counterexample, &watch);
diff --git a/src/storm/api/counterexamples.cpp b/src/storm/api/counterexamples.cpp
index 98c2f07bf..483dc57d4 100644
--- a/src/storm/api/counterexamples.cpp
+++ b/src/storm/api/counterexamples.cpp
@@ -10,9 +10,9 @@ namespace storm {
             return storm::counterexamples::MILPMinimalLabelSetGenerator<double>::computeCounterexample(env, program, *mdp, formula);
         }
         
-        std::shared_ptr<storm::counterexamples::Counterexample> computePrismHighLevelCounterexampleMaxSmt(storm::prism::Program const& program, std::shared_ptr<storm::models::sparse::Mdp<double>> mdp, std::shared_ptr<storm::logic::Formula const> const& formula) {
+        std::shared_ptr<storm::counterexamples::Counterexample> computePrismHighLevelCounterexampleMaxSmt(storm::prism::Program const& program, std::shared_ptr<storm::models::sparse::Model<double>> model, std::shared_ptr<storm::logic::Formula const> const& formula) {
             Environment env;
-            return storm::counterexamples::SMTMinimalLabelSetGenerator<double>::computeCounterexample(env, program, *mdp, formula);
+            return storm::counterexamples::SMTMinimalLabelSetGenerator<double>::computeCounterexample(env, program, *model, formula);
         }
         
     }
diff --git a/src/storm/api/counterexamples.h b/src/storm/api/counterexamples.h
index d8f3d1ddd..6481c4efd 100644
--- a/src/storm/api/counterexamples.h
+++ b/src/storm/api/counterexamples.h
@@ -8,7 +8,7 @@ namespace storm {
         
         std::shared_ptr<storm::counterexamples::Counterexample> computePrismHighLevelCounterexampleMilp(storm::prism::Program const& program, std::shared_ptr<storm::models::sparse::Mdp<double>> mdp, std::shared_ptr<storm::logic::Formula const> const& formula);
         
-        std::shared_ptr<storm::counterexamples::Counterexample> computePrismHighLevelCounterexampleMaxSmt(storm::prism::Program const& program, std::shared_ptr<storm::models::sparse::Mdp<double>> mdp, std::shared_ptr<storm::logic::Formula const> const& formula);
+        std::shared_ptr<storm::counterexamples::Counterexample> computePrismHighLevelCounterexampleMaxSmt(storm::prism::Program const& program, std::shared_ptr<storm::models::sparse::Model<double>> model, std::shared_ptr<storm::logic::Formula const> const& formula);
         
     }
 }
diff --git a/src/storm/counterexamples/SMTMinimalLabelSetGenerator.h b/src/storm/counterexamples/SMTMinimalLabelSetGenerator.h
index e659209a3..5ad54a0f5 100644
--- a/src/storm/counterexamples/SMTMinimalLabelSetGenerator.h
+++ b/src/storm/counterexamples/SMTMinimalLabelSetGenerator.h
@@ -119,7 +119,7 @@ namespace storm {
 
                 // Retrieve some references for convenient access.
                 storm::storage::SparseMatrix<T> const& transitionMatrix = model.getTransitionMatrix();
-                std::vector<uint_fast64_t> const& nondeterministicChoiceIndices = model.getNondeterministicChoiceIndices();
+                std::vector<uint_fast64_t> const& nondeterministicChoiceIndices = transitionMatrix.getRowGroupIndices();
 
                 // Now traverse all choices of all relevant states and check whether there is a successor target state.
                 // If so, the associated labels become relevant. Also, if a choice of a relevant state has at least one
@@ -1374,7 +1374,7 @@ namespace storm {
                 }
                 
                 storm::storage::SparseMatrix<T> const& transitionMatrix = subModel.getTransitionMatrix();
-                std::vector<uint_fast64_t> const& nondeterministicChoiceIndices = subModel.getNondeterministicChoiceIndices();
+                std::vector<uint_fast64_t> const& nondeterministicChoiceIndices = transitionMatrix.getRowGroupIndices();
                 
                 // Now determine which states and labels are actually reachable.
                 boost::container::flat_set<uint_fast64_t> reachableLabels;
@@ -1498,7 +1498,7 @@ namespace storm {
                 }
                 
                 storm::storage::SparseMatrix<T> const& transitionMatrix = subModel.getTransitionMatrix();
-                std::vector<uint_fast64_t> const& nondeterministicChoiceIndices = subModel.getNondeterministicChoiceIndices();
+                std::vector<uint_fast64_t> const& nondeterministicChoiceIndices = transitionMatrix.getRowGroupIndices();
                 
                 // Now determine which states and labels are actually reachable.
                 boost::container::flat_set<uint_fast64_t> reachableLabels;
@@ -1821,10 +1821,10 @@ namespace storm {
                 auto startTime = std::chrono::high_resolution_clock::now();
                 
                 // Create sub-model that only contains the choices allowed by the given command set.
-                storm::models::sparse::Model<T> subModel = restrictModelToLabelSet(model, commandSet).first;
+                std::shared_ptr<storm::models::sparse::Model<T>> subModel = restrictModelToLabelSet(model, commandSet).first;
                 
                 // Then determine all prob0E(psi) states that are reachable in the sub-model.
-                storm::storage::BitVector reachableProb0EStates = storm::utility::graph::getReachableStates(subModel.getTransitionMatrix(), subModel.getInitialStates(), phiStates, psiStates);
+                storm::storage::BitVector reachableProb0EStates = storm::utility::graph::getReachableStates(subModel->getTransitionMatrix(), subModel->getInitialStates(), phiStates, psiStates);
                 
                 // Create a queue of reachable prob0E(psi) states so we can check which commands need to be added
                 // to give them a strategy that avoids psi states.
@@ -1887,6 +1887,7 @@ namespace storm {
             }
 
             static boost::container::flat_set<uint_fast64_t>  computeCounterexampleCommandSet(Environment const& env, storm::prism::Program program, storm::models::sparse::Model<T> const& model, std::shared_ptr<storm::logic::Formula const> const& formula) {
+                STORM_LOG_THROW(model.isOfType(storm::models::ModelType::Dtmc) || model.isOfType(storm::models::ModelType::Mdp), storm::exceptions::NotSupportedException, "MaxSAT-based counterexample generation is supported only for discrete-time models.");
                 std::cout << std::endl << "Generating minimal label counterexample for formula " << *formula << std::endl;
 
                 STORM_LOG_THROW(formula->isProbabilityOperatorFormula(), storm::exceptions::InvalidPropertyException, "Counterexample generation does not support this kind of formula. Expecting a probability operator as the outermost formula element.");
diff --git a/src/storm/models/sparse/NondeterministicModel.h b/src/storm/models/sparse/NondeterministicModel.h
index 2274e137a..ac8603e7f 100644
--- a/src/storm/models/sparse/NondeterministicModel.h
+++ b/src/storm/models/sparse/NondeterministicModel.h
@@ -19,10 +19,8 @@ namespace storm {
              * The base class of sparse nondeterministic models.
              */
             template<class ValueType, typename RewardModelType = StandardRewardModel<ValueType>>
-            class NondeterministicModel: public Model<ValueType, RewardModelType> {
+            class NondeterministicModel : public Model<ValueType, RewardModelType> {
             public:
-                
-                
                 /*!
                  * Constructs a model from the given data.
                  *
@@ -39,6 +37,8 @@ namespace storm {
                  */
                 std::vector<uint_fast64_t> const& getNondeterministicChoiceIndices() const;
                 
+                using Model<ValueType, RewardModelType>::getNumberOfChoices;
+                
                 /*!
                  * @param state State for which we want to know how many choices it has
                  * 
diff --git a/src/storm/utility/counterexamples.h b/src/storm/utility/counterexamples.h
index ec20c20cb..1ff429a5d 100644
--- a/src/storm/utility/counterexamples.h
+++ b/src/storm/utility/counterexamples.h
@@ -18,20 +18,20 @@ namespace storm {
              * @return The set of labels that is visited on all paths from any state to a target state.
              */
             template <typename T>
-            std::vector<boost::container::flat_set<uint_fast64_t>> getGuaranteedLabelSets(storm::models::sparse::Mdp<T> const& mdp, std::vector<boost::container::flat_set<uint_fast64_t>> const& labelSets, storm::storage::BitVector const& psiStates, boost::container::flat_set<uint_fast64_t> const& relevantLabels) {
-                STORM_LOG_THROW(mdp.getNumberOfChoices() == labelSets.size(), storm::exceptions::InvalidArgumentException, "The given number of labels does not match the number of choices.");
+            std::vector<boost::container::flat_set<uint_fast64_t>> getGuaranteedLabelSets(storm::models::sparse::Model<T> const& model, std::vector<boost::container::flat_set<uint_fast64_t>> const& labelSets, storm::storage::BitVector const& psiStates, boost::container::flat_set<uint_fast64_t> const& relevantLabels) {
+                STORM_LOG_THROW(model.getNumberOfChoices() == labelSets.size(), storm::exceptions::InvalidArgumentException, "The given number of labels does not match the number of choices.");
                 
-                // Get some data from the MDP for convenient access.
-                storm::storage::SparseMatrix<T> const& transitionMatrix = mdp.getTransitionMatrix();
-                std::vector<uint_fast64_t> const& nondeterministicChoiceIndices = mdp.getNondeterministicChoiceIndices();
-                storm::storage::SparseMatrix<T> backwardTransitions = mdp.getBackwardTransitions();
+                // Get some data from the model for convenient access.
+                storm::storage::SparseMatrix<T> const& transitionMatrix = model.getTransitionMatrix();
+                std::vector<uint_fast64_t> const& nondeterministicChoiceIndices = transitionMatrix.getRowGroupIndices();
+                storm::storage::SparseMatrix<T> backwardTransitions = model.getBackwardTransitions();
 
                 // Now we compute the set of labels that is present on all paths from the initial to the target states.
-                std::vector<boost::container::flat_set<uint_fast64_t>> analysisInformation(mdp.getNumberOfStates(), relevantLabels);
+                std::vector<boost::container::flat_set<uint_fast64_t>> analysisInformation(model.getNumberOfStates(), relevantLabels);
                 
                 std::queue<uint_fast64_t> worklist;
-                storm::storage::BitVector statesInWorkList(mdp.getNumberOfStates());
-                storm::storage::BitVector markedStates(mdp.getNumberOfStates());
+                storm::storage::BitVector statesInWorkList(model.getNumberOfStates());
+                storm::storage::BitVector markedStates(model.getNumberOfStates());
                 
                 // Initially, put all predecessors of target states in the worklist and empty the analysis information them.
                 for (auto state : psiStates) {
@@ -108,12 +108,12 @@ namespace storm {
              * @return The set of labels that is executed on all paths from an initial state to a target state.
              */
             template <typename T>
-            boost::container::flat_set<uint_fast64_t> getGuaranteedLabelSet(storm::models::sparse::Mdp<T> const& mdp, std::vector<boost::container::flat_set<uint_fast64_t>> const& labelSets, storm::storage::BitVector const& psiStates, boost::container::flat_set<uint_fast64_t> const& relevantLabels) {
-                std::vector<boost::container::flat_set<uint_fast64_t>> guaranteedLabels = getGuaranteedLabelSets(mdp, labelSets, psiStates, relevantLabels);
+            boost::container::flat_set<uint_fast64_t> getGuaranteedLabelSet(storm::models::sparse::Model<T> const& model, std::vector<boost::container::flat_set<uint_fast64_t>> const& labelSets, storm::storage::BitVector const& psiStates, boost::container::flat_set<uint_fast64_t> const& relevantLabels) {
+                std::vector<boost::container::flat_set<uint_fast64_t>> guaranteedLabels = getGuaranteedLabelSets(model, labelSets, psiStates, relevantLabels);
                 
                 boost::container::flat_set<uint_fast64_t> knownLabels(relevantLabels);
                 boost::container::flat_set<uint_fast64_t> tempIntersection;
-                for (auto initialState : mdp.getInitialStates()) {
+                for (auto initialState : model.getInitialStates()) {
                     std::set_intersection(knownLabels.begin(), knownLabels.end(), guaranteedLabels[initialState].begin(), guaranteedLabels[initialState].end(), std::inserter(tempIntersection, tempIntersection.end()));
                     std::swap(knownLabels, tempIntersection);
                 }