diff --git a/src/adapters/EigenAdapter.cpp b/src/adapters/EigenAdapter.cpp
index aebdcd0ef..45f5206bd 100644
--- a/src/adapters/EigenAdapter.cpp
+++ b/src/adapters/EigenAdapter.cpp
@@ -4,7 +4,7 @@ namespace storm {
     namespace adapters {
      
         template<typename ValueType>
-        static std::unique_ptr<Eigen::SparseMatrix<ValueType>> toEigenSparseMatrix(storm::storage::SparseMatrix<ValueType> const& matrix) {
+        std::unique_ptr<Eigen::SparseMatrix<ValueType>> EigenAdapter::toEigenSparseMatrix(storm::storage::SparseMatrix<ValueType> const& matrix) {
             // Build a list of triplets and let Eigen care about the insertion.
             std::vector<Eigen::Triplet<ValueType>> triplets;
             triplets.reserve(matrix.getNonzeroEntryCount());
@@ -20,6 +20,6 @@ namespace storm {
             return result;
         }
         
-        template std::unique_ptr<Eigen::SparseMatrix<double>> toEigenSparseMatrix(storm::storage::SparseMatrix<double> const& matrix);
+        template std::unique_ptr<Eigen::SparseMatrix<double>> EigenAdapter::toEigenSparseMatrix(storm::storage::SparseMatrix<double> const& matrix);
     }
 }
\ No newline at end of file
diff --git a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp
index 5a6045f66..d2a58b68c 100644
--- a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp
+++ b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp
@@ -18,67 +18,27 @@
 
 #include "src/logic/FragmentSpecification.h"
 
+#include "src/solver/stateelimination/LongRunAverageEliminator.h"
+#include "src/solver/stateelimination/ConditionalEliminator.h"
+#include "src/solver/stateelimination/PrioritizedStateEliminator.h"
+#include "src/solver/stateelimination/StaticStatePriorityQueue.h"
+#include "src/solver/stateelimination/DynamicStatePriorityQueue.h"
+
+#include "src/utility/stateelimination.h"
 #include "src/utility/graph.h"
 #include "src/utility/vector.h"
 #include "src/utility/macros.h"
+#include "src/utility/constants.h"
 
 #include "src/exceptions/InvalidPropertyException.h"
 #include "src/exceptions/InvalidStateException.h"
 #include "src/exceptions/InvalidSettingsException.h"
 #include "src/exceptions/IllegalArgumentException.h"
 
-#include "src/solver/stateelimination/LongRunAverageEliminator.h"
-#include "src/solver/stateelimination/ConditionalEliminator.h"
-#include "src/solver/stateelimination/PrioritizedEliminator.h"
-
 namespace storm {
     namespace modelchecker {
         
-        template<typename ValueType>
-        uint_fast64_t estimateComplexity(ValueType const& value) {
-            return 1;
-        }
-        
-#ifdef STORM_HAVE_CARL
-        template<>
-        uint_fast64_t estimateComplexity(storm::RationalFunction const& value) {
-            if (storm::utility::isConstant(value)) {
-                return 1;
-            }
-            if (value.denominator().isConstant()) {
-                return value.nominator().complexity();
-            } else {
-                return value.denominator().complexity() * value.nominator().complexity();
-            }
-        }
-#endif
-        
-        bool eliminationOrderNeedsDistances(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order) {
-            return order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::Forward ||
-            order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::ForwardReversed ||
-            order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::Backward ||
-            order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::BackwardReversed;
-        }
-        
-        bool eliminationOrderNeedsForwardDistances(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order) {
-            return order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::Forward ||
-            order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::ForwardReversed;
-        }
-        
-        bool eliminationOrderNeedsReversedDistances(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order) {
-            return order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::ForwardReversed ||
-            order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::BackwardReversed;
-        }
-        
-        bool eliminationOrderIsPenaltyBased(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order) {
-            return order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::StaticPenalty ||
-            order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::DynamicPenalty ||
-            order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::RegularExpression;
-        }
-        
-        bool eliminationOrderIsStatic(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order) {
-            return eliminationOrderNeedsDistances(order) || order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::StaticPenalty;
-        }
+        using namespace storm::utility::stateelimination;
         
         template<typename SparseDtmcModelType>
         SparseDtmcEliminationModelChecker<SparseDtmcModelType>::SparseDtmcEliminationModelChecker(storm::models::sparse::Dtmc<ValueType> const& model) : SparsePropositionalModelChecker<SparseDtmcModelType>(model) {
@@ -98,7 +58,7 @@ namespace storm {
             storm::logic::StateFormula const& stateFormula = checkTask.getFormula();
             std::unique_ptr<CheckResult> subResultPointer = this->check(stateFormula);
             storm::storage::BitVector const& psiStates = subResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector();
-
+            
             storm::storage::SparseMatrix<ValueType> const& transitionMatrix = this->getModel().getTransitionMatrix();
             uint_fast64_t numberOfStates = transitionMatrix.getRowCount();
             if (psiStates.empty()) {
@@ -157,7 +117,7 @@ namespace storm {
             // Do some sanity checks to establish some required properties.
             RewardModelType const& rewardModel = this->getModel().getRewardModel(checkTask.isRewardModelSet() ? checkTask.getRewardModel() : "");
             STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::IllegalArgumentException, "Input model does not have a reward model.");
-
+            
             storm::storage::BitVector const& initialStates = this->getModel().getInitialStates();
             STORM_LOG_THROW(initialStates.getNumberOfSetBits() == 1, storm::exceptions::IllegalArgumentException, "Input model is required to have exactly one initial state.");
             STORM_LOG_THROW(checkTask.isOnlyInitialStatesRelevantSet(), storm::exceptions::IllegalArgumentException, "Cannot compute long-run probabilities for all states.");
@@ -167,7 +127,7 @@ namespace storm {
             
             // Get the state-reward values from the reward model.
             std::vector<ValueType> stateRewardValues = rewardModel.getTotalRewardVector(this->getModel().getTransitionMatrix());
-        
+            
             storm::storage::BitVector maybeStates(stateRewardValues.size());
             uint_fast64_t index = 0;
             for (auto const& value : stateRewardValues) {
@@ -183,7 +143,7 @@ namespace storm {
             maybeStates = storm::utility::graph::performProbGreater0(backwardTransitions, allStates, maybeStates);
             
             std::vector<ValueType> result(numberOfStates, storm::utility::zero<ValueType>());
-
+            
             // Determine whether we need to perform some further computation.
             bool furtherComputationNeeded = true;
             if (checkTask.isOnlyInitialStatesRelevantSet() && initialStates.isDisjointFrom(maybeStates)) {
@@ -221,7 +181,7 @@ namespace storm {
             std::chrono::high_resolution_clock::time_point sccDecompositionStart = std::chrono::high_resolution_clock::now();
             storm::storage::StronglyConnectedComponentDecomposition<ValueType> bsccDecomposition(transitionMatrix, storm::storage::BitVector(transitionMatrix.getRowCount(), true), false, true);
             auto sccDecompositionEnd = std::chrono::high_resolution_clock::now();
-
+            
             std::chrono::high_resolution_clock::time_point conversionStart = std::chrono::high_resolution_clock::now();
             
             // Then, we convert the reduced matrix to a more flexible format to be able to perform state elimination more easily.
@@ -232,7 +192,7 @@ namespace storm {
             auto conversionEnd = std::chrono::high_resolution_clock::now();
             
             std::chrono::high_resolution_clock::time_point modelCheckingStart = std::chrono::high_resolution_clock::now();
-
+            
             storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder order = storm::settings::getModule<storm::settings::modules::SparseDtmcEliminationModelCheckerSettings>().getEliminationOrder();
             boost::optional<std::vector<uint_fast64_t>> distanceBasedPriorities;
             if (eliminationOrderNeedsDistances(order)) {
@@ -265,11 +225,11 @@ namespace storm {
             std::vector<ValueType> averageTimeInStates(stateValues.size(), storm::utility::one<ValueType>());
             
             // First, we eliminate all states in BSCCs (except for the representative states).
-            std::shared_ptr<StatePriorityQueue<ValueType>> priorityQueue = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, stateValues, regularStatesInBsccs);
-            storm::solver::stateelimination::LongRunAverageEliminator<SparseDtmcModelType> stateEliminator(flexibleMatrix, flexibleBackwardTransitions, priorityQueue, stateValues, averageTimeInStates);
+            std::shared_ptr<StatePriorityQueue> priorityQueue = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, stateValues, regularStatesInBsccs);
+            storm::solver::stateelimination::LongRunAverageEliminator<ValueType> stateEliminator(flexibleMatrix, flexibleBackwardTransitions, priorityQueue, stateValues, averageTimeInStates);
             
-            while (priorityQueue->hasNextState()) {
-                storm::storage::sparse::state_type state = priorityQueue->popNextState();
+            while (priorityQueue->hasNext()) {
+                storm::storage::sparse::state_type state = priorityQueue->pop();
                 stateEliminator.eliminateState(state, true);
 #ifdef STORM_DEV
                 STORM_LOG_ASSERT(checkConsistent(flexibleMatrix, flexibleBackwardTransitions), "The forward and backward transition matrices became inconsistent.");
@@ -294,7 +254,7 @@ namespace storm {
                     }
                     stateValues[*representativeIt] = bsccValue;
                 }
-
+                
                 FlexibleRowType& representativeForwardRow = flexibleMatrix.getRow(*representativeIt);
                 representativeForwardRow.clear();
                 representativeForwardRow.shrink_to_fit();
@@ -307,10 +267,10 @@ namespace storm {
                     }
                 }
                 representativeBackwardRow.erase(it);
-
+                
                 ++representativeIt;
             }
-
+            
             // If there are states remaining that are not in BSCCs, we need to eliminate them now.
             storm::storage::BitVector remainingStates = maybeStates & ~regularStatesInBsccs;
             
@@ -388,7 +348,7 @@ namespace storm {
             storm::storage::BitVector const& initialStates = this->getModel().getInitialStates();
             
             std::vector<ValueType> result(transitionMatrix.getRowCount(), storm::utility::zero<ValueType>());
-
+            
             if (furtherComputationNeeded) {
                 uint_fast64_t timeBound = pathFormula.getDiscreteTimeBound();
                 
@@ -399,7 +359,7 @@ namespace storm {
                     // Subtract from the maybe states the set of states that is not reachable (on a path from the initial to a target state).
                     statesWithProbabilityGreater0 &= reachableStates;
                 }
-
+                
                 // We then build the submatrix that only has the transitions of the maybe states.
                 storm::storage::SparseMatrix<ValueType> submatrix = transitionMatrix.getSubmatrix(true, statesWithProbabilityGreater0, statesWithProbabilityGreater0, true);
                 
@@ -408,7 +368,7 @@ namespace storm {
                 if (checkTask.isOnlyInitialStatesRelevantSet()) {
                     // Determine the set of initial states of the sub-model.
                     storm::storage::BitVector subInitialStates = this->getModel().getInitialStates() % statesWithProbabilityGreater0;
-
+                    
                     // Precompute the distances of the relevant states to the initial states.
                     distancesFromInitialStates = storm::utility::graph::getDistances(submatrix, subInitialStates, statesWithProbabilityGreater0);
                     
@@ -471,23 +431,23 @@ namespace storm {
             std::unique_ptr<CheckResult> rightResultPointer = this->check(pathFormula.getRightSubformula());
             storm::storage::BitVector const& phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector();
             storm::storage::BitVector const& psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector();
-
+            
             std::vector<ValueType> result = computeUntilProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getInitialStates(), phiStates, psiStates, checkTask.isOnlyInitialStatesRelevantSet());
-
+            
             // Construct check result.
             std::unique_ptr<CheckResult> checkResult(new ExplicitQuantitativeCheckResult<ValueType>(result));
             return checkResult;
         }
-
+        
         template<typename SparseDtmcModelType>
         std::vector<typename SparseDtmcModelType::ValueType> SparseDtmcEliminationModelChecker<SparseDtmcModelType>::computeUntilProbabilities(storm::storage::SparseMatrix<ValueType> const& probabilityMatrix, storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool computeForInitialStatesOnly) {
-
+            
             // Then, compute the subset of states that has a probability of 0 or 1, respectively.
             std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01 = storm::utility::graph::performProb01(backwardTransitions, phiStates, psiStates);
             storm::storage::BitVector statesWithProbability0 = statesWithProbability01.first;
             storm::storage::BitVector statesWithProbability1 = statesWithProbability01.second;
             storm::storage::BitVector maybeStates = ~(statesWithProbability0 | statesWithProbability1);
-
+            
             // Determine whether we need to perform some further computation.
             bool furtherComputationNeeded = true;
             if (computeForInitialStatesOnly && initialStates.isDisjointFrom(maybeStates)) {
@@ -497,7 +457,7 @@ namespace storm {
                 STORM_LOG_DEBUG("The probability for all states was found in a preprocessing step.");
                 furtherComputationNeeded = false;
             }
-
+            
             std::vector<ValueType> result(maybeStates.size());
             if (furtherComputationNeeded) {
                 // If we compute the results for the initial states only, we can cut off all maybe state that are not
@@ -505,29 +465,29 @@ namespace storm {
                 if (computeForInitialStatesOnly) {
                     // Determine the set of states that is reachable from the initial state without jumping over a target state.
                     storm::storage::BitVector reachableStates = storm::utility::graph::getReachableStates(probabilityMatrix, initialStates, maybeStates, statesWithProbability1);
-                
+                    
                     // Subtract from the maybe states the set of states that is not reachable (on a path from the initial to a target state).
                     maybeStates &= reachableStates;
                 }
-
+                
                 // Create a vector for the probabilities to go to a state with probability 1 in one step.
                 std::vector<ValueType> oneStepProbabilities = probabilityMatrix.getConstrainedRowSumVector(maybeStates, statesWithProbability1);
-
+                
                 // Determine the set of initial states of the sub-model.
                 storm::storage::BitVector newInitialStates = initialStates % maybeStates;
-
+                
                 // We then build the submatrix that only has the transitions of the maybe states.
                 storm::storage::SparseMatrix<ValueType> submatrix = probabilityMatrix.getSubmatrix(false, maybeStates, maybeStates);
                 storm::storage::SparseMatrix<ValueType> submatrixTransposed = submatrix.transpose();
-
+                
                 std::vector<ValueType> subresult = computeReachabilityValues(submatrix, oneStepProbabilities, submatrixTransposed, newInitialStates, computeForInitialStatesOnly, phiStates, psiStates, oneStepProbabilities);
                 storm::utility::vector::setVectorValues<ValueType>(result, maybeStates, subresult);
             }
-
+            
             // Construct full result.
             storm::utility::vector::setVectorValues<ValueType>(result, statesWithProbability0, storm::utility::zero<ValueType>());
             storm::utility::vector::setVectorValues<ValueType>(result, statesWithProbability1, storm::utility::one<ValueType>());
-
+            
             if (computeForInitialStatesOnly) {
                 // If we computed the results for the initial (and prob 0 and prob1) states only, we need to filter the
                 // result to only communicate these results.
@@ -547,19 +507,19 @@ namespace storm {
             
             // Do some sanity checks to establish some required properties.
             RewardModelType const& rewardModel = this->getModel().getRewardModel(checkTask.isRewardModelSet() ? checkTask.getRewardModel() : "");
-
+            
             STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::IllegalArgumentException, "Input model does not have a reward model.");
             std::vector<ValueType> result = computeReachabilityRewards(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getInitialStates(), targetStates,
                                                                        [&] (uint_fast64_t numberOfRows, storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::BitVector const& maybeStates) {
                                                                            return rewardModel.getTotalRewardVector(numberOfRows, transitionMatrix, maybeStates);
                                                                        },
                                                                        checkTask.isOnlyInitialStatesRelevantSet());
-
+            
             // Construct check result.
             std::unique_ptr<CheckResult> checkResult(new ExplicitQuantitativeCheckResult<ValueType>(result));
             return checkResult;
         }
-
+        
         template<typename SparseDtmcModelType>
         std::vector<typename SparseDtmcModelType::ValueType> SparseDtmcEliminationModelChecker<SparseDtmcModelType>::computeReachabilityRewards(storm::storage::SparseMatrix<ValueType> const& probabilityMatrix, storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, std::vector<ValueType>& stateRewardValues, bool computeForInitialStatesOnly) {
             return computeReachabilityRewards(probabilityMatrix, backwardTransitions, initialStates, targetStates,
@@ -570,10 +530,10 @@ namespace storm {
                                               },
                                               computeForInitialStatesOnly);
         }
-
+        
         template<typename SparseDtmcModelType>
         std::vector<typename SparseDtmcModelType::ValueType> SparseDtmcEliminationModelChecker<SparseDtmcModelType>::computeReachabilityRewards(storm::storage::SparseMatrix<ValueType> const& probabilityMatrix, storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, std::function<std::vector<ValueType>(uint_fast64_t, storm::storage::SparseMatrix<ValueType> const&, storm::storage::BitVector const&)> const& totalStateRewardVectorGetter, bool computeForInitialStatesOnly) {
-
+            
             uint_fast64_t numberOfStates = probabilityMatrix.getRowCount();
             
             // Compute the subset of states that has a reachability reward less than infinity.
@@ -594,7 +554,7 @@ namespace storm {
                     furtherComputationNeeded = false;
                 }
             }
-
+            
             std::vector<ValueType> result(maybeStates.size());
             if (furtherComputationNeeded) {
                 // If we compute the results for the initial states only, we can cut off all maybe state that are not
@@ -609,14 +569,14 @@ namespace storm {
                 
                 // Determine the set of initial states of the sub-model.
                 storm::storage::BitVector newInitialStates = initialStates % maybeStates;
-
+                
                 // We then build the submatrix that only has the transitions of the maybe states.
                 storm::storage::SparseMatrix<ValueType> submatrix = probabilityMatrix.getSubmatrix(false, maybeStates, maybeStates);
                 storm::storage::SparseMatrix<ValueType> submatrixTransposed = submatrix.transpose();
                 
                 // Project the state reward vector to all maybe-states.
                 std::vector<ValueType> stateRewardValues = totalStateRewardVectorGetter(submatrix.getRowCount(), probabilityMatrix, maybeStates);
-
+                
                 std::vector<ValueType> subresult = computeReachabilityValues(submatrix, stateRewardValues, submatrixTransposed, newInitialStates, computeForInitialStatesOnly, trueStates, targetStates, probabilityMatrix.getConstrainedRowSumVector(maybeStates, targetStates));
                 storm::utility::vector::setVectorValues<ValueType>(result, maybeStates, subresult);
             }
@@ -711,21 +671,21 @@ namespace storm {
             storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder order = storm::settings::getModule<storm::settings::modules::SparseDtmcEliminationModelCheckerSettings>().getEliminationOrder();
             if (eliminationOrderNeedsDistances(order)) {
                 distanceBasedPriorities = getDistanceBasedPriorities(submatrix, submatrixTransposed, newInitialStates, oneStepProbabilities,
-                                                             eliminationOrderNeedsForwardDistances(order),
-                                                             eliminationOrderNeedsReversedDistances(order));
+                                                                     eliminationOrderNeedsForwardDistances(order),
+                                                                     eliminationOrderNeedsReversedDistances(order));
             }
             
             storm::storage::FlexibleSparseMatrix<ValueType> flexibleMatrix(submatrix);
             storm::storage::FlexibleSparseMatrix<ValueType> flexibleBackwardTransitions(submatrixTransposed, true);
             
-            std::shared_ptr<StatePriorityQueue<ValueType>> statePriorities = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, statesToEliminate);
-
+            std::shared_ptr<StatePriorityQueue> statePriorities = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, statesToEliminate);
+            
             STORM_LOG_INFO("Computing conditional probilities." << std::endl);
             uint_fast64_t numberOfStatesToEliminate = statePriorities->size();
             STORM_LOG_INFO("Eliminating " << numberOfStatesToEliminate << " states using the state elimination technique." << std::endl);
             performPrioritizedStateElimination(statePriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, this->getModel().getInitialStates(), true);
             
-            storm::solver::stateelimination::ConditionalEliminator<SparseDtmcModelType> stateEliminator = storm::solver::stateelimination::ConditionalEliminator<SparseDtmcModelType>(flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, phiStates, psiStates);
+            storm::solver::stateelimination::ConditionalEliminator<ValueType> stateEliminator = storm::solver::stateelimination::ConditionalEliminator<ValueType>(flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, phiStates, psiStates);
             
             // Eliminate the transitions going into the initial state (if there are any).
             if (!flexibleBackwardTransitions.getRow(*newInitialStates.begin()).empty()) {
@@ -752,6 +712,7 @@ namespace storm {
                     // to eliminate all chains of non-psi states between the current state and psi states.
                     bool hasNonPsiSuccessor = true;
                     while (hasNonPsiSuccessor) {
+                        stateEliminator.setFilterPhi();
                         hasNonPsiSuccessor = false;
                         
                         // Only treat the state if it has an outgoing transition other than a self-loop.
@@ -764,9 +725,7 @@ namespace storm {
                                     // Eliminate the successor only if there possibly is a psi state reachable through it.
                                     if (successorRow.size() > 1 || (!successorRow.empty() && successorRow.front().getColumn() != element.getColumn())) {
                                         STORM_LOG_TRACE("Found non-psi successor " << element.getColumn() << " that needs to be eliminated.");
-                                        stateEliminator.setStatePhi();
                                         stateEliminator.eliminateState(element.getColumn(), false);
-                                        stateEliminator.clearState();
                                         hasNonPsiSuccessor = true;
                                     }
                                 }
@@ -774,6 +733,7 @@ namespace storm {
                             STORM_LOG_ASSERT(!flexibleMatrix.getRow(initialStateSuccessor).empty(), "(1) New transitions expected to be non-empty.");
                         }
                     }
+                    stateEliminator.unsetFilter();
                 } else {
                     STORM_LOG_ASSERT(psiStates.get(initialStateSuccessor), "Expected psi state.");
                     STORM_LOG_TRACE("Is a psi state.");
@@ -784,6 +744,7 @@ namespace storm {
                     
                     bool hasNonPhiSuccessor = true;
                     while (hasNonPhiSuccessor) {
+                        stateEliminator.setFilterPsi();
                         hasNonPhiSuccessor = false;
                         
                         // Only treat the state if it has an outgoing transition other than a self-loop.
@@ -795,15 +756,14 @@ namespace storm {
                                     FlexibleRowType const& successorRow = flexibleMatrix.getRow(element.getColumn());
                                     if (successorRow.size() > 1 || (!successorRow.empty() && successorRow.front().getColumn() != element.getColumn())) {
                                         STORM_LOG_TRACE("Found non-phi successor " << element.getColumn() << " that needs to be eliminated.");
-                                        stateEliminator.setStatePsi();
                                         stateEliminator.eliminateState(element.getColumn(), false);
-                                        stateEliminator.clearState();
                                         hasNonPhiSuccessor = true;
                                     }
                                 }
                             }
                         }
                     }
+                    stateEliminator.unsetFilter();
                 }
             }
             
@@ -844,62 +804,12 @@ namespace storm {
         }
         
         template<typename SparseDtmcModelType>
-        std::shared_ptr<StatePriorityQueue<typename SparseDtmcModelType::ValueType>> SparseDtmcEliminationModelChecker<SparseDtmcModelType>::createStatePriorityQueue(boost::optional<std::vector<uint_fast64_t>> const& distanceBasedStatePriorities, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType>& oneStepProbabilities, storm::storage::BitVector const& states) {
-            
-            STORM_LOG_TRACE("Creating state priority queue for states " << states);
-            
-            // Get the settings to customize the priority queue.
-            storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder order = storm::settings::getModule<storm::settings::modules::SparseDtmcEliminationModelCheckerSettings>().getEliminationOrder();
-            
-            std::vector<storm::storage::sparse::state_type> sortedStates(states.begin(), states.end());
-
-            if (order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::Random) {
-                std::random_device randomDevice;
-                std::mt19937 generator(randomDevice());
-                std::shuffle(sortedStates.begin(), sortedStates.end(), generator);
-                return std::make_unique<StaticStatePriorityQueue>(sortedStates);
-            } else {
-                if (eliminationOrderNeedsDistances(order)) {
-                    STORM_LOG_THROW(static_cast<bool>(distanceBasedStatePriorities), storm::exceptions::InvalidStateException, "Unable to build state priority queue without distance-based priorities.");
-                    std::sort(sortedStates.begin(), sortedStates.end(), [&distanceBasedStatePriorities] (storm::storage::sparse::state_type const& state1, storm::storage::sparse::state_type const& state2) { return distanceBasedStatePriorities.get()[state1] < distanceBasedStatePriorities.get()[state2]; } );
-                    return std::make_unique<StaticStatePriorityQueue>(sortedStates);
-                } else if (eliminationOrderIsPenaltyBased(order)) {
-                    std::vector<std::pair<storm::storage::sparse::state_type, uint_fast64_t>> statePenalties(sortedStates.size());
-                    PenaltyFunctionType penaltyFunction = order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::RegularExpression ? computeStatePenaltyRegularExpression : computeStatePenalty;
-                    for (uint_fast64_t index = 0; index < sortedStates.size(); ++index) {
-                        statePenalties[index] = std::make_pair(sortedStates[index], penaltyFunction(sortedStates[index], transitionMatrix, backwardTransitions, oneStepProbabilities));
-                    }
-                    
-                    std::sort(statePenalties.begin(), statePenalties.end(), [] (std::pair<storm::storage::sparse::state_type, uint_fast64_t> const& statePenalty1, std::pair<storm::storage::sparse::state_type, uint_fast64_t> const& statePenalty2) { return statePenalty1.second < statePenalty2.second; } );
-                    
-                    if (eliminationOrderIsStatic(order)) {
-                        // For the static penalty version, we need to strip the penalties to create the queue.
-                        for (uint_fast64_t index = 0; index < sortedStates.size(); ++index) {
-                            sortedStates[index] = statePenalties[index].first;
-                        }
-                        return std::make_unique<StaticStatePriorityQueue>(sortedStates);
-                    } else {
-                        // For the dynamic penalty version, we need to give the full state-penalty pairs.
-                        return std::make_unique<DynamicPenaltyStatePriorityQueue>(statePenalties, penaltyFunction);
-                    }
-                }
-            }
-            STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "Illegal elimination order selected.");
-        }
-        
-        template<typename SparseDtmcModelType>
-        std::shared_ptr<StatePriorityQueue<typename SparseDtmcModelType::ValueType>> SparseDtmcEliminationModelChecker<SparseDtmcModelType>::createNaivePriorityQueue(storm::storage::BitVector const& states) {
-            std::vector<storm::storage::sparse::state_type> sortedStates(states.begin(), states.end());
-            return std::shared_ptr<StatePriorityQueue<ValueType>>(new StaticStatePriorityQueue(sortedStates));
-        }
-        
-        template<typename SparseDtmcModelType>
-        void SparseDtmcEliminationModelChecker<SparseDtmcModelType>::performPrioritizedStateElimination(std::shared_ptr<StatePriorityQueue<ValueType>>& priorityQueue, storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, std::vector<ValueType>& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly) {
+        void SparseDtmcEliminationModelChecker<SparseDtmcModelType>::performPrioritizedStateElimination(std::shared_ptr<StatePriorityQueue>& priorityQueue, storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, std::vector<ValueType>& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly) {
             
-            storm::solver::stateelimination::PrioritizedEliminator<SparseDtmcModelType> stateEliminator(transitionMatrix, backwardTransitions, priorityQueue, values);
+            storm::solver::stateelimination::PrioritizedStateEliminator<ValueType> stateEliminator(transitionMatrix, backwardTransitions, priorityQueue, values);
             
-            while (priorityQueue->hasNextState()) {
-                storm::storage::sparse::state_type state = priorityQueue->popNextState();
+            while (priorityQueue->hasNext()) {
+                storm::storage::sparse::state_type state = priorityQueue->pop();
                 bool removeForwardTransitions = computeResultsForInitialStatesOnly && !initialStates.get(state);
                 stateEliminator.eliminateState(state, removeForwardTransitions);
                 if (removeForwardTransitions) {
@@ -913,7 +823,7 @@ namespace storm {
         
         template<typename SparseDtmcModelType>
         void SparseDtmcEliminationModelChecker<SparseDtmcModelType>::performOrdinaryStateElimination(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector<ValueType>& values, boost::optional<std::vector<uint_fast64_t>> const& distanceBasedPriorities) {
-            std::shared_ptr<StatePriorityQueue<ValueType>> statePriorities = createStatePriorityQueue(distanceBasedPriorities, transitionMatrix, backwardTransitions, values, subsystem);
+            std::shared_ptr<StatePriorityQueue> statePriorities = createStatePriorityQueue(distanceBasedPriorities, transitionMatrix, backwardTransitions, values, subsystem);
             
             std::size_t numberOfStatesToEliminate = statePriorities->size();
             STORM_LOG_DEBUG("Eliminating " << numberOfStatesToEliminate << " states using the state elimination technique." << std::endl);
@@ -932,7 +842,7 @@ namespace storm {
             if (storm::settings::getModule<storm::settings::modules::SparseDtmcEliminationModelCheckerSettings>().isEliminateEntryStatesLastSet()) {
                 STORM_LOG_DEBUG("Eliminating " << entryStateQueue.size() << " entry states as a last step.");
                 std::vector<storm::storage::sparse::state_type> sortedStates(entryStateQueue.begin(), entryStateQueue.end());
-                std::shared_ptr<StatePriorityQueue<ValueType>> queuePriorities = std::shared_ptr<StatePriorityQueue<ValueType>>(new StaticStatePriorityQueue(sortedStates));
+                std::shared_ptr<StatePriorityQueue> queuePriorities = std::make_shared<StaticStatePriorityQueue>(sortedStates);
                 performPrioritizedStateElimination(queuePriorities, transitionMatrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
             }
             STORM_LOG_DEBUG("Eliminated " << subsystem.size() << " states." << std::endl);
@@ -944,7 +854,7 @@ namespace storm {
             // Then, we convert the reduced matrix to a more flexible format to be able to perform state elimination more easily.
             storm::storage::FlexibleSparseMatrix<ValueType> flexibleMatrix(transitionMatrix);
             storm::storage::FlexibleSparseMatrix<ValueType> flexibleBackwardTransitions(backwardTransitions);
-
+            
             storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder order = storm::settings::getModule<storm::settings::modules::SparseDtmcEliminationModelCheckerSettings>().getEliminationOrder();
             boost::optional<std::vector<uint_fast64_t>> distanceBasedPriorities;
             if (eliminationOrderNeedsDistances(order)) {
@@ -961,7 +871,7 @@ namespace storm {
             } else if (storm::settings::getModule<storm::settings::modules::SparseDtmcEliminationModelCheckerSettings>().getEliminationMethod() == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationMethod::Hybrid) {
                 maximalDepth = performHybridStateElimination(transitionMatrix, flexibleMatrix, flexibleBackwardTransitions, subsystem, initialStates, computeResultsForInitialStatesOnly, values, distanceBasedPriorities);
             }
-        
+            
             STORM_LOG_ASSERT(flexibleMatrix.empty(), "Not all transitions were eliminated.");
             STORM_LOG_ASSERT(flexibleBackwardTransitions.empty(), "Not all transitions were eliminated.");
             
@@ -1000,11 +910,11 @@ namespace storm {
                     }
                 }
                 
-                std::shared_ptr<StatePriorityQueue<ValueType>> statePriorities = createStatePriorityQueue(distanceBasedPriorities, matrix, backwardTransitions, values, statesInTrivialSccs);
+                std::shared_ptr<StatePriorityQueue> statePriorities = createStatePriorityQueue(distanceBasedPriorities, matrix, backwardTransitions, values, statesInTrivialSccs);
                 STORM_LOG_TRACE("Eliminating " << statePriorities->size() << " trivial SCCs.");
                 performPrioritizedStateElimination(statePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
                 STORM_LOG_TRACE("Eliminated all trivial SCCs.");
-
+                
                 // And then recursively treat the remaining sub-SCCs.
                 STORM_LOG_TRACE("Eliminating " << remainingSccs.getNumberOfSetBits() << " remaining SCCs on level " << level << ".");
                 for (auto sccIndex : remainingSccs) {
@@ -1030,7 +940,7 @@ namespace storm {
             } else {
                 // In this case, we perform simple state elimination in the current SCC.
                 STORM_LOG_TRACE("SCC of size " << scc.getNumberOfSetBits() << " is small enough to be eliminated directly.");
-                std::shared_ptr<StatePriorityQueue<ValueType>> statePriorities = createStatePriorityQueue(distanceBasedPriorities, matrix, backwardTransitions, values, scc & ~entryStates);
+                std::shared_ptr<StatePriorityQueue> statePriorities = createStatePriorityQueue(distanceBasedPriorities, matrix, backwardTransitions, values, scc & ~entryStates);
                 performPrioritizedStateElimination(statePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
                 STORM_LOG_TRACE("Eliminated all states of SCC.");
             }
@@ -1038,7 +948,7 @@ namespace storm {
             // Finally, eliminate the entry states (if we are required to do so).
             if (eliminateEntryStates) {
                 STORM_LOG_TRACE("Finally, eliminating entry states.");
-                std::shared_ptr<StatePriorityQueue<ValueType>> naivePriorities = createNaivePriorityQueue(entryStates);
+                std::shared_ptr<StatePriorityQueue> naivePriorities = createNaivePriorityQueue(entryStates);
                 performPrioritizedStateElimination(naivePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
                 STORM_LOG_TRACE("Eliminated/added entry states.");
             } else {
@@ -1098,120 +1008,6 @@ namespace storm {
             }
         }
         
-        template<typename SparseDtmcModelType>
-        uint_fast64_t SparseDtmcEliminationModelChecker<SparseDtmcModelType>::computeStatePenalty(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities) {
-            uint_fast64_t penalty = 0;
-            bool hasParametricSelfLoop = false;
-            
-            for (auto const& predecessor : backwardTransitions.getRow(state)) {
-                for (auto const& successor : transitionMatrix.getRow(state)) {
-                    penalty += estimateComplexity(predecessor.getValue()) * estimateComplexity(successor.getValue());
-//                    STORM_LOG_TRACE("1) penalty += " << (estimateComplexity(predecessor.getValue()) * estimateComplexity(successor.getValue())) << " because of " << predecessor.getValue() << " and " << successor.getValue() << ".");
-                }
-                if (predecessor.getColumn() == state) {
-                    hasParametricSelfLoop = !storm::utility::isConstant(predecessor.getValue());
-                }
-                penalty += estimateComplexity(oneStepProbabilities[predecessor.getColumn()]) * estimateComplexity(predecessor.getValue()) * estimateComplexity(oneStepProbabilities[state]);
-//                STORM_LOG_TRACE("2) penalty += " << (estimateComplexity(oneStepProbabilities[predecessor.getColumn()]) * estimateComplexity(predecessor.getValue()) * estimateComplexity(oneStepProbabilities[state])) << " because of " << oneStepProbabilities[predecessor.getColumn()] << ", " << predecessor.getValue() << " and " << oneStepProbabilities[state] << ".");
-            }
-            
-            // If it is a self-loop that is parametric, we increase the penalty a lot.
-            if (hasParametricSelfLoop) {
-                penalty *= 10;
-//                STORM_LOG_TRACE("3) penalty *= 100, because of parametric self-loop.");
-            }
-            
-//            STORM_LOG_TRACE("New penalty of state " << state << " is " << penalty << ".");
-            return penalty;
-        }
-        
-        template<typename SparseDtmcModelType>
-        uint_fast64_t SparseDtmcEliminationModelChecker<SparseDtmcModelType>::computeStatePenaltyRegularExpression(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities) {
-            return backwardTransitions.getRow(state).size() * transitionMatrix.getRow(state).size();
-        }
-        
-        template<typename ValueType>
-        void StatePriorityQueue<ValueType>::update(storm::storage::sparse::state_type, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities) {
-            // Intentionally left empty.
-        }
-        
-        template<typename SparseDtmcModelType>
-        SparseDtmcEliminationModelChecker<SparseDtmcModelType>::StaticStatePriorityQueue::StaticStatePriorityQueue(std::vector<storm::storage::sparse::state_type> const& sortedStates) : StatePriorityQueue<ValueType>(), sortedStates(sortedStates), currentPosition(0) {
-            // Intentionally left empty.
-        }
-        
-        template<typename SparseDtmcModelType>
-        bool SparseDtmcEliminationModelChecker<SparseDtmcModelType>::StaticStatePriorityQueue::hasNextState() const {
-            return currentPosition < sortedStates.size();
-        }
-        
-        template<typename SparseDtmcModelType>
-        storm::storage::sparse::state_type SparseDtmcEliminationModelChecker<SparseDtmcModelType>::StaticStatePriorityQueue::popNextState() {
-            ++currentPosition;
-            return sortedStates[currentPosition - 1];
-        }
-        
-        template<typename SparseDtmcModelType>
-        std::size_t SparseDtmcEliminationModelChecker<SparseDtmcModelType>::StaticStatePriorityQueue::size() const {
-            return sortedStates.size() - currentPosition;
-        }
-        
-        template<typename SparseDtmcModelType>
-        SparseDtmcEliminationModelChecker<SparseDtmcModelType>::DynamicPenaltyStatePriorityQueue::DynamicPenaltyStatePriorityQueue(std::vector<std::pair<storm::storage::sparse::state_type, uint_fast64_t>> const& sortedStatePenaltyPairs, PenaltyFunctionType const& penaltyFunction) : StatePriorityQueue<ValueType>(), priorityQueue(), stateToPriorityMapping(), penaltyFunction(penaltyFunction) {
-            // Insert all state-penalty pairs into our priority queue.
-            for (auto const& statePenalty : sortedStatePenaltyPairs) {
-                priorityQueue.insert(priorityQueue.end(), statePenalty);
-            }
-            
-            // Insert all state-penalty pairs into auxiliary mapping.
-            for (auto const& statePenalty : sortedStatePenaltyPairs) {
-                stateToPriorityMapping.emplace(statePenalty);
-            }
-        }
-        
-        template<typename SparseDtmcModelType>
-        bool SparseDtmcEliminationModelChecker<SparseDtmcModelType>::DynamicPenaltyStatePriorityQueue::hasNextState() const {
-            return !priorityQueue.empty();
-        }
-        
-        template<typename SparseDtmcModelType>
-        storm::storage::sparse::state_type SparseDtmcEliminationModelChecker<SparseDtmcModelType>::DynamicPenaltyStatePriorityQueue::popNextState() {
-            auto it = priorityQueue.begin();
-            STORM_LOG_TRACE("Popping state " << it->first << " with priority " << it->second << ".");
-            storm::storage::sparse::state_type result = it->first;
-            priorityQueue.erase(priorityQueue.begin());
-            return result;
-        }
-        
-        template<typename SparseDtmcModelType>
-        void SparseDtmcEliminationModelChecker<SparseDtmcModelType>::DynamicPenaltyStatePriorityQueue::update(storm::storage::sparse::state_type state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities) {
-            // First, we need to find the priority until now.
-            auto priorityIt = stateToPriorityMapping.find(state);
-            
-            // If the priority queue does not store the priority of the given state, we must not update it.
-            if (priorityIt == stateToPriorityMapping.end()) {
-                return;
-            }
-            uint_fast64_t lastPriority = priorityIt->second;
-            
-            uint_fast64_t newPriority = penaltyFunction(state, transitionMatrix, backwardTransitions, oneStepProbabilities);
-            
-            if (lastPriority != newPriority) {
-                // Erase and re-insert into the priority queue with the new priority.
-                auto queueIt = priorityQueue.find(std::make_pair(state, lastPriority));
-                priorityQueue.erase(queueIt);
-                priorityQueue.emplace(state, newPriority);
-                
-                // Finally, update the probability in the mapping.
-                priorityIt->second = newPriority;
-            }
-        }
-        
-        template<typename SparseDtmcModelType>
-        std::size_t SparseDtmcEliminationModelChecker<SparseDtmcModelType>::DynamicPenaltyStatePriorityQueue::size() const {
-            return priorityQueue.size();
-        }
-        
         template<typename SparseDtmcModelType>
         bool SparseDtmcEliminationModelChecker<SparseDtmcModelType>::checkConsistent(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions) {
             for (uint_fast64_t forwardIndex = 0; forwardIndex < transitionMatrix.getRowCount(); ++forwardIndex) {
@@ -1235,13 +1031,9 @@ namespace storm {
             return true;
         }
         
-        template class StatePriorityQueue<double>;
         template class SparseDtmcEliminationModelChecker<storm::models::sparse::Dtmc<double>>;
-        template uint_fast64_t estimateComplexity(double const& value);
-            
-            
+        
 #ifdef STORM_HAVE_CARL
-        template class StatePriorityQueue<storm::RationalFunction>;
         template class SparseDtmcEliminationModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>>;
 #endif
     } // namespace modelchecker
diff --git a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h
index 7359ac93f..73f419425 100644
--- a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h
+++ b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h
@@ -1,26 +1,18 @@
 #ifndef STORM_MODELCHECKER_REACHABILITY_SPARSEDTMCELIMINATIONMODELCHECKER_H_
 #define STORM_MODELCHECKER_REACHABILITY_SPARSEDTMCELIMINATIONMODELCHECKER_H_
 
+#include "src/modelchecker/propositional/SparsePropositionalModelChecker.h"
+
+#include "src/models/sparse/Dtmc.h"
+
 #include "src/storage/sparse/StateType.h"
 #include "src/storage/FlexibleSparseMatrix.h"
-#include "src/models/sparse/Dtmc.h"
-#include "src/modelchecker/propositional/SparsePropositionalModelChecker.h"
-#include "src/utility/constants.h"
+#include "src/solver/stateelimination/StatePriorityQueue.h"
 
 namespace storm {
     namespace modelchecker {
         
-        template<typename ValueType>
-        uint_fast64_t estimateComplexity(ValueType const& value);
-
-        template<typename ValueType>
-        class StatePriorityQueue {
-        public:
-            virtual bool hasNextState() const = 0;
-            virtual storm::storage::sparse::state_type popNextState() = 0;
-            virtual void update(storm::storage::sparse::state_type state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities);
-            virtual std::size_t size() const = 0;
-        };
+        using namespace storm::solver::stateelimination;
         
         template<typename SparseDtmcModelType>
         class SparseDtmcEliminationModelChecker : public SparsePropositionalModelChecker<SparseDtmcModelType> {
@@ -52,54 +44,13 @@ namespace storm {
             static std::vector<ValueType> computeReachabilityRewards(storm::storage::SparseMatrix<ValueType> const& probabilityMatrix, storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, std::vector<ValueType>& stateRewardValues, bool computeForInitialStatesOnly);
 
         private:
-            
-            class StaticStatePriorityQueue : public StatePriorityQueue<ValueType> {
-            public:
-                StaticStatePriorityQueue(std::vector<storm::storage::sparse::state_type> const& sortedStates);
-                
-                virtual bool hasNextState() const override;
-                virtual storm::storage::sparse::state_type popNextState() override;
-                virtual std::size_t size() const override;
-                
-            private:
-                std::vector<uint_fast64_t> sortedStates;
-                uint_fast64_t currentPosition;
-            };
-            
-            struct PriorityComparator {
-                bool operator()(std::pair<storm::storage::sparse::state_type, uint_fast64_t> const& first, std::pair<storm::storage::sparse::state_type, uint_fast64_t> const& second) {
-                    return (first.second < second.second) || (first.second == second.second && first.first < second.first) ;
-                }
-            };
-            
-            typedef std::function<uint_fast64_t (storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities)> PenaltyFunctionType;
-            
-            class DynamicPenaltyStatePriorityQueue : public StatePriorityQueue<ValueType> {
-            public:
-                DynamicPenaltyStatePriorityQueue(std::vector<std::pair<storm::storage::sparse::state_type, uint_fast64_t>> const& sortedStatePenaltyPairs, PenaltyFunctionType const& penaltyFunction);
-                
-                virtual bool hasNextState() const override;
-                virtual storm::storage::sparse::state_type popNextState() override;
-                virtual void update(storm::storage::sparse::state_type state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities) override;
-                virtual std::size_t size() const override;
-
-            private:
-                std::set<std::pair<storm::storage::sparse::state_type, uint_fast64_t>, PriorityComparator> priorityQueue;
-                std::unordered_map<storm::storage::sparse::state_type, uint_fast64_t> stateToPriorityMapping;
-                PenaltyFunctionType penaltyFunction;
-            };
-            
             static std::vector<ValueType> computeLongRunValues(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& maybeStates, bool computeResultsForInitialStatesOnly, std::vector<ValueType>& stateValues);
             
             static std::vector<ValueType> computeReachabilityRewards(storm::storage::SparseMatrix<ValueType> const& probabilityMatrix, storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, std::function<std::vector<ValueType>(uint_fast64_t, storm::storage::SparseMatrix<ValueType> const&, storm::storage::BitVector const&)> const& totalStateRewardVectorGetter, bool computeForInitialStatesOnly);
 
             static std::vector<ValueType> computeReachabilityValues(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, std::vector<ValueType>& values, storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::vector<ValueType> const& oneStepProbabilitiesToTarget);
             
-            static std::shared_ptr<StatePriorityQueue<ValueType>> createStatePriorityQueue(boost::optional<std::vector<uint_fast64_t>> const& stateDistances, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType>& oneStepProbabilities, storm::storage::BitVector const& states);
-
-            static std::shared_ptr<StatePriorityQueue<ValueType>> createNaivePriorityQueue(storm::storage::BitVector const& states);
-            
-            static void performPrioritizedStateElimination(std::shared_ptr<StatePriorityQueue<ValueType>>& priorityQueue, storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, std::vector<ValueType>& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly);
+            static void performPrioritizedStateElimination(std::shared_ptr<StatePriorityQueue>& priorityQueue, storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, std::vector<ValueType>& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly);
             
             static void performOrdinaryStateElimination(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector<ValueType>& values, boost::optional<std::vector<ValueType>>& additionalStateValues, boost::optional<std::vector<uint_fast64_t>> const& distanceBasedPriorities);
 
@@ -112,11 +63,7 @@ namespace storm {
             static std::vector<uint_fast64_t> getDistanceBasedPriorities(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::SparseMatrix<ValueType> const& transitionMatrixTransposed, storm::storage::BitVector const& initialStates, std::vector<ValueType> const& oneStepProbabilities, bool forward, bool reverse);
             
             static std::vector<std::size_t> getStateDistances(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::SparseMatrix<ValueType> const& transitionMatrixTransposed, storm::storage::BitVector const& initialStates, std::vector<ValueType> const& oneStepProbabilities, bool forward);
-            
-            static uint_fast64_t computeStatePenalty(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities);
-            
-            static uint_fast64_t computeStatePenaltyRegularExpression(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities);
-            
+                        
             static bool checkConsistent(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions);
             
         };
diff --git a/src/models/sparse/MarkovAutomaton.cpp b/src/models/sparse/MarkovAutomaton.cpp
index b3b416cfc..b9739203f 100644
--- a/src/models/sparse/MarkovAutomaton.cpp
+++ b/src/models/sparse/MarkovAutomaton.cpp
@@ -5,7 +5,7 @@
 #include "src/adapters/CarlAdapter.h"
 #include "src/storage/FlexibleSparseMatrix.h"
 #include "src/models/sparse/Dtmc.h"
-#include "src/solver/stateelimination/MAEliminator.h"
+#include "src/solver/stateelimination/StateEliminator.h"
 #include "src/utility/vector.h"
 
 namespace storm {
@@ -273,7 +273,7 @@ namespace storm {
                 // Initialize
                 storm::storage::FlexibleSparseMatrix<ValueType> flexibleMatrix(this->getTransitionMatrix());
                 storm::storage::FlexibleSparseMatrix<ValueType> flexibleBackwardTransitions(this->getTransitionMatrix().transpose());
-                storm::solver::stateelimination::MAEliminator<storm::models::sparse::Dtmc<ValueType>> stateEliminator(flexibleMatrix, flexibleBackwardTransitions);
+                storm::solver::stateelimination::StateEliminator<ValueType> stateEliminator(flexibleMatrix, flexibleBackwardTransitions);
                 
                 for (uint_fast64_t state = 0; state < this->getNumberOfStates(); ++state) {
                     assert(!this->isHybridState(state));
diff --git a/src/solver/stateelimination/ConditionalEliminator.cpp b/src/solver/stateelimination/ConditionalEliminator.cpp
index f1e1c5df6..c45a31cb7 100644
--- a/src/solver/stateelimination/ConditionalEliminator.cpp
+++ b/src/solver/stateelimination/ConditionalEliminator.cpp
@@ -1,35 +1,38 @@
 #include "src/solver/stateelimination/ConditionalEliminator.h"
 
+#include "src/utility/macros.h"
+#include "src/utility/constants.h"
+
 namespace storm {
     namespace solver {
         namespace stateelimination {
             
-            template<typename SparseModelType>
-            ConditionalEliminator<SparseModelType>::ConditionalEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, std::vector<ValueType>& oneStepProbabilities, storm::storage::BitVector& phiStates, storm::storage::BitVector& psiStates) : StateEliminator<SparseModelType>(transitionMatrix, backwardTransitions), oneStepProbabilities(oneStepProbabilities), phiStates(phiStates), psiStates(psiStates), specificState(NONE) {
+            template<typename ValueType>
+            ConditionalEliminator<ValueType>::ConditionalEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, std::vector<ValueType>& oneStepProbabilities, storm::storage::BitVector& phiStates, storm::storage::BitVector& psiStates) : StateEliminator<ValueType>(transitionMatrix, backwardTransitions), oneStepProbabilities(oneStepProbabilities), phiStates(phiStates), psiStates(psiStates), filterLabel(StateLabel::NONE) {
             }
             
-            template<typename SparseModelType>
-            void ConditionalEliminator<SparseModelType>::updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) {
+            template<typename ValueType>
+            void ConditionalEliminator<ValueType>::updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) {
                 oneStepProbabilities[state] = storm::utility::simplify(loopProbability * oneStepProbabilities[state]);
             }
             
-            template<typename SparseModelType>
-            void ConditionalEliminator<SparseModelType>::updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) {
+            template<typename ValueType>
+            void ConditionalEliminator<ValueType>::updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) {
                 oneStepProbabilities[predecessor] = storm::utility::simplify(oneStepProbabilities[predecessor] * storm::utility::simplify(probability * oneStepProbabilities[state]));
             }
             
-            template<typename SparseModelType>
-            void ConditionalEliminator<SparseModelType>::updatePriority(storm::storage::sparse::state_type const& state) {
+            template<typename ValueType>
+            void ConditionalEliminator<ValueType>::updatePriority(storm::storage::sparse::state_type const& state) {
                 // Do nothing
             }
             
-            template<typename SparseModelType>
-            bool ConditionalEliminator<SparseModelType>::filterPredecessor(storm::storage::sparse::state_type const& state) {
+            template<typename ValueType>
+            bool ConditionalEliminator<ValueType>::filterPredecessor(storm::storage::sparse::state_type const& state) {
                 // TODO find better solution than flag
-                switch (specificState) {
-                    case PHI:
+                switch (filterLabel) {
+                    case StateLabel::PHI:
                         return phiStates.get(state);
-                    case PSI:
+                    case StateLabel::PSI:
                         return psiStates.get(state);
                     default:
                         STORM_LOG_ASSERT(false, "Specific state not set.");
@@ -37,16 +40,35 @@ namespace storm {
                 }
             }
             
-            template<typename SparseModelType>
-            bool ConditionalEliminator<SparseModelType>::isFilterPredecessor() const {
+            template<typename ValueType>
+            bool ConditionalEliminator<ValueType>::isFilterPredecessor() const {
                 return true;
             }
             
+            template<typename ValueType>
+            void ConditionalEliminator<ValueType>::setFilterPhi() {
+                filterLabel = StateLabel::PHI;
+            }
+            
+            template<typename ValueType>
+            void ConditionalEliminator<ValueType>::setFilterPsi() {
+                filterLabel = StateLabel::PSI;
+            }
+            
+            template<typename ValueType>
+            void ConditionalEliminator<ValueType>::setFilter(StateLabel const& stateLabel) {
+                filterLabel = stateLabel;
+            }
+            
+            template<typename ValueType>
+            void ConditionalEliminator<ValueType>::unsetFilter() {
+                filterLabel = StateLabel::NONE;
+            }
             
-            template class ConditionalEliminator<storm::models::sparse::Dtmc<double>>;
+            template class ConditionalEliminator<double>;
             
 #ifdef STORM_HAVE_CARL
-            template class ConditionalEliminator<storm::models::sparse::Dtmc<storm::RationalFunction>>;
+            template class ConditionalEliminator<storm::RationalFunction>;
 #endif
             
         } // namespace stateelimination
diff --git a/src/solver/stateelimination/ConditionalEliminator.h b/src/solver/stateelimination/ConditionalEliminator.h
index b98066d3f..ead6afeec 100644
--- a/src/solver/stateelimination/ConditionalEliminator.h
+++ b/src/solver/stateelimination/ConditionalEliminator.h
@@ -9,14 +9,11 @@ namespace storm {
     namespace solver {
         namespace stateelimination {
             
-            template<typename SparseModelType>
-            class ConditionalEliminator : public StateEliminator<SparseModelType> {
-
-                typedef typename SparseModelType::ValueType ValueType;
-
-                enum SpecificState { NONE, PHI, PSI};
-                
+            template<typename ValueType>
+            class ConditionalEliminator : public StateEliminator<ValueType> {
             public:
+                enum class StateLabel { NONE, PHI, PSI };
+                
                 ConditionalEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, std::vector<ValueType>& oneStepProbabilities, storm::storage::BitVector& phiStates, storm::storage::BitVector& psiStates);
                 
                 // Instantiaton of Virtual methods
@@ -26,24 +23,16 @@ namespace storm {
                 bool filterPredecessor(storm::storage::sparse::state_type const& state) override;
                 bool isFilterPredecessor() const override;
                 
-                void setStatePsi() {
-                    specificState = PSI;
-                }
-                
-                void setStatePhi() {
-                    specificState = PHI;
-                }
-                
-                void clearState() {
-                    specificState = NONE;
-                }
+                void setFilterPhi();
+                void setFilterPsi();
+                void setFilter(StateLabel const& stateLabel);
+                void unsetFilter();
                 
             private:
                 std::vector<ValueType>& oneStepProbabilities;
                 storm::storage::BitVector& phiStates;
                 storm::storage::BitVector& psiStates;
-                SpecificState specificState;
-                
+                StateLabel filterLabel;
             };
             
         } // namespace stateelimination
diff --git a/src/solver/stateelimination/DynamicStatePriorityQueue.cpp b/src/solver/stateelimination/DynamicStatePriorityQueue.cpp
new file mode 100644
index 000000000..8c4d0a83d
--- /dev/null
+++ b/src/solver/stateelimination/DynamicStatePriorityQueue.cpp
@@ -0,0 +1,75 @@
+#include "src/solver/stateelimination/DynamicStatePriorityQueue.h"
+
+#include "src/adapters/CarlAdapter.h"
+
+#include "src/utility/macros.h"
+#include "src/utility/constants.h"
+
+namespace storm {
+    namespace solver {
+        namespace stateelimination {
+            
+            template<typename ValueType>
+            DynamicStatePriorityQueue<ValueType>::DynamicStatePriorityQueue(std::vector<std::pair<storm::storage::sparse::state_type, uint_fast64_t>> const& sortedStatePenaltyPairs, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities, PenaltyFunctionType const& penaltyFunction) : StatePriorityQueue(), transitionMatrix(transitionMatrix), backwardTransitions(backwardTransitions), oneStepProbabilities(oneStepProbabilities), priorityQueue(), stateToPriorityMapping(), penaltyFunction(penaltyFunction) {
+                // Insert all state-penalty pairs into our priority queue.
+                for (auto const& statePenalty : sortedStatePenaltyPairs) {
+                    priorityQueue.insert(priorityQueue.end(), statePenalty);
+                }
+                
+                // Insert all state-penalty pairs into auxiliary mapping.
+                for (auto const& statePenalty : sortedStatePenaltyPairs) {
+                    stateToPriorityMapping.emplace(statePenalty);
+                }
+            }
+            
+            template<typename ValueType>
+            bool DynamicStatePriorityQueue<ValueType>::hasNext() const {
+                return !priorityQueue.empty();
+            }
+            
+            template<typename ValueType>
+            storm::storage::sparse::state_type DynamicStatePriorityQueue<ValueType>::pop() {
+                auto it = priorityQueue.begin();
+                STORM_LOG_TRACE("Popping state " << it->first << " with priority " << it->second << ".");
+                storm::storage::sparse::state_type result = it->first;
+                priorityQueue.erase(priorityQueue.begin());
+                return result;
+            }
+            
+            template<typename ValueType>
+            void DynamicStatePriorityQueue<ValueType>::update(storm::storage::sparse::state_type state) {
+                // First, we need to find the priority until now.
+                auto priorityIt = stateToPriorityMapping.find(state);
+                
+                // If the priority queue does not store the priority of the given state, we must not update it.
+                if (priorityIt == stateToPriorityMapping.end()) {
+                    return;
+                }
+                uint_fast64_t lastPriority = priorityIt->second;
+                
+                uint_fast64_t newPriority = penaltyFunction(state, transitionMatrix, backwardTransitions, oneStepProbabilities);
+                
+                if (lastPriority != newPriority) {
+                    // Erase and re-insert into the priority queue with the new priority.
+                    auto queueIt = priorityQueue.find(std::make_pair(state, lastPriority));
+                    priorityQueue.erase(queueIt);
+                    priorityQueue.emplace(state, newPriority);
+                    
+                    // Finally, update the probability in the mapping.
+                    priorityIt->second = newPriority;
+                }
+            }
+            
+            template<typename ValueType>
+            std::size_t DynamicStatePriorityQueue<ValueType>::size() const {
+                return priorityQueue.size();
+            }
+
+            template class DynamicStatePriorityQueue<double>;
+            
+#ifdef STORM_HAVE_CARL
+            template class DynamicStatePriorityQueue<storm::RationalFunction>;
+#endif
+        }
+    }
+}
diff --git a/src/solver/stateelimination/DynamicStatePriorityQueue.h b/src/solver/stateelimination/DynamicStatePriorityQueue.h
new file mode 100644
index 000000000..b5675440b
--- /dev/null
+++ b/src/solver/stateelimination/DynamicStatePriorityQueue.h
@@ -0,0 +1,48 @@
+#pragma once
+
+#include <functional>
+#include <vector>
+#include <set>
+#include <unordered_map>
+
+#include "src/solver/stateelimination/StatePriorityQueue.h"
+
+namespace storm {
+    namespace storage {
+        template<typename ValueType>
+        class FlexibleSparseMatrix;
+    }
+    
+    namespace solver {
+        namespace stateelimination {
+                        
+            struct PriorityComparator {
+                bool operator()(std::pair<storm::storage::sparse::state_type, uint_fast64_t> const& first, std::pair<storm::storage::sparse::state_type, uint_fast64_t> const& second) {
+                    return (first.second < second.second) || (first.second == second.second && first.first < second.first) ;
+                }
+            };
+            
+            template<typename ValueType>
+            class DynamicStatePriorityQueue : public StatePriorityQueue {
+            public:
+                typedef std::function<uint_fast64_t (storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities)> PenaltyFunctionType;
+                
+                DynamicStatePriorityQueue(std::vector<std::pair<storm::storage::sparse::state_type, uint_fast64_t>> const& sortedStatePenaltyPairs, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities, PenaltyFunctionType const& penaltyFunction);
+                
+                virtual bool hasNext() const override;
+                virtual storm::storage::sparse::state_type pop() override;
+                virtual void update(storm::storage::sparse::state_type state) override;
+                virtual std::size_t size() const override;
+                
+            private:
+                storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix;
+                storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions;
+                std::vector<ValueType> const& oneStepProbabilities;
+                std::set<std::pair<storm::storage::sparse::state_type, uint_fast64_t>, PriorityComparator> priorityQueue;
+                std::unordered_map<storm::storage::sparse::state_type, uint_fast64_t> stateToPriorityMapping;
+                PenaltyFunctionType penaltyFunction;
+            };
+            
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/solver/stateelimination/LongRunAverageEliminator.cpp b/src/solver/stateelimination/LongRunAverageEliminator.cpp
index 1757b87fa..c06fed5bb 100644
--- a/src/solver/stateelimination/LongRunAverageEliminator.cpp
+++ b/src/solver/stateelimination/LongRunAverageEliminator.cpp
@@ -1,46 +1,31 @@
 #include "src/solver/stateelimination/LongRunAverageEliminator.h"
 
+#include "src/utility/constants.h"
+
 namespace storm {
     namespace solver {
         namespace stateelimination {
             
-            template<typename SparseModelType>
-            LongRunAverageEliminator<SparseModelType>::LongRunAverageEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, PriorityQueuePointer priorityQueue, std::vector<ValueType>& stateValues, std::vector<ValueType>& averageTimeInStates) : StateEliminator<SparseModelType>(transitionMatrix, backwardTransitions), priorityQueue(priorityQueue), stateValues(stateValues), averageTimeInStates(averageTimeInStates) {
+            template<typename ValueType>
+            LongRunAverageEliminator<ValueType>::LongRunAverageEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, PriorityQueuePointer priorityQueue, std::vector<ValueType>& stateValues, std::vector<ValueType>& averageTimeInStates) : PrioritizedStateEliminator<ValueType>(transitionMatrix, backwardTransitions, priorityQueue, stateValues), averageTimeInStates(averageTimeInStates) {
             }
             
-            template<typename SparseModelType>
-            void LongRunAverageEliminator<SparseModelType>::updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) {
-                stateValues[state] = storm::utility::simplify(loopProbability * stateValues[state]);
+            template<typename ValueType>
+            void LongRunAverageEliminator<ValueType>::updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) {
+                this->stateValues[state] = storm::utility::simplify(loopProbability * this->stateValues[state]);
                 averageTimeInStates[state] = storm::utility::simplify(loopProbability * averageTimeInStates[state]);
             }
        
-            template<typename SparseModelType>
-            void LongRunAverageEliminator<SparseModelType>::updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) {
-                stateValues[predecessor] = storm::utility::simplify(stateValues[predecessor] + storm::utility::simplify(probability * stateValues[state]));
+            template<typename ValueType>
+            void LongRunAverageEliminator<ValueType>::updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) {
+                this->stateValues[predecessor] = storm::utility::simplify(this->stateValues[predecessor] + storm::utility::simplify(probability * this->stateValues[state]));
                 averageTimeInStates[predecessor] = storm::utility::simplify(averageTimeInStates[predecessor] + storm::utility::simplify(probability * averageTimeInStates[state]));
             }
             
-            template<typename SparseModelType>
-            void LongRunAverageEliminator<SparseModelType>::updatePriority(storm::storage::sparse::state_type const& state) {
-                priorityQueue->update(state, StateEliminator<SparseModelType>::transitionMatrix, StateEliminator<SparseModelType>::backwardTransitions, stateValues);
-            }
-            
-            template<typename SparseModelType>
-            bool LongRunAverageEliminator<SparseModelType>::filterPredecessor(storm::storage::sparse::state_type const& state) {
-                STORM_LOG_ASSERT(false, "Filter should not be applied.");
-                return false;
-            }
-            
-            template<typename SparseModelType>
-            bool LongRunAverageEliminator<SparseModelType>::isFilterPredecessor() const {
-                return false;
-            }
-            
-            
-            template class LongRunAverageEliminator<storm::models::sparse::Dtmc<double>>;
+            template class LongRunAverageEliminator<double>;
             
 #ifdef STORM_HAVE_CARL
-            template class LongRunAverageEliminator<storm::models::sparse::Dtmc<storm::RationalFunction>>;
+            template class LongRunAverageEliminator<storm::RationalFunction>;
 #endif
             
         } // namespace stateelimination
diff --git a/src/solver/stateelimination/LongRunAverageEliminator.h b/src/solver/stateelimination/LongRunAverageEliminator.h
index f9b1e9cce..d56e53e98 100644
--- a/src/solver/stateelimination/LongRunAverageEliminator.h
+++ b/src/solver/stateelimination/LongRunAverageEliminator.h
@@ -1,32 +1,26 @@
 #ifndef STORM_SOLVER_STATEELIMINATION_LONGRUNAVERAGEELIMINATOR_H_
 #define STORM_SOLVER_STATEELIMINATION_LONGRUNAVERAGEELIMINATOR_H_
 
-#include "src/solver/stateelimination/StateEliminator.h"
+#include "src/solver/stateelimination/PrioritizedStateEliminator.h"
 
 namespace storm {
     namespace solver {
         namespace stateelimination {
             
-            template<typename SparseModelType>
-            class LongRunAverageEliminator : public StateEliminator<SparseModelType> {
-
-                typedef typename SparseModelType::ValueType ValueType;
-                typedef typename std::shared_ptr<storm::modelchecker::StatePriorityQueue<ValueType>> PriorityQueuePointer;
+            class StatePriorityQueue;
 
+            template<typename ValueType>
+            class LongRunAverageEliminator : public PrioritizedStateEliminator<ValueType> {
             public:
+                typedef typename std::shared_ptr<StatePriorityQueue> PriorityQueuePointer;
+
                 LongRunAverageEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, PriorityQueuePointer priorityQueue, std::vector<ValueType>& stateValues, std::vector<ValueType>& averageTimeInStates);
                 
-                // Instantiaton of Virtual methods
+                // Instantiaton of virtual methods.
                 void updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) override;
                 void updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) override;
-                void updatePriority(storm::storage::sparse::state_type const& state) override;
-                bool filterPredecessor(storm::storage::sparse::state_type const& state) override;
-                bool isFilterPredecessor() const override;
                 
             private:
-                
-                PriorityQueuePointer priorityQueue;
-                std::vector<ValueType>& stateValues;
                 std::vector<ValueType>& averageTimeInStates;
             };
             
diff --git a/src/solver/stateelimination/MAEliminator.cpp b/src/solver/stateelimination/MAEliminator.cpp
deleted file mode 100644
index 911364ac7..000000000
--- a/src/solver/stateelimination/MAEliminator.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-#include "src/solver/stateelimination/MAEliminator.h"
-
-namespace storm {
-    namespace solver {
-        namespace stateelimination {
-            
-            template<typename SparseModelType>
-            MAEliminator<SparseModelType>::MAEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions) : StateEliminator<SparseModelType>(transitionMatrix, backwardTransitions){
-            }
-            
-            template<typename SparseModelType>
-            void MAEliminator<SparseModelType>::updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) {
-                // Do nothing
-            }
-       
-            template<typename SparseModelType>
-            void MAEliminator<SparseModelType>::updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) {
-                // Do nothing
-            }
-            
-            template<typename SparseModelType>
-            void MAEliminator<SparseModelType>::updatePriority(storm::storage::sparse::state_type const& state) {
-                // Do nothing
-            }
-            
-            template<typename SparseModelType>
-            bool MAEliminator<SparseModelType>::filterPredecessor(storm::storage::sparse::state_type const& state) {
-                STORM_LOG_ASSERT(false, "Filter should not be applied.");
-                return false;
-            }
-            
-            template<typename SparseModelType>
-            bool MAEliminator<SparseModelType>::isFilterPredecessor() const {
-                return false;
-            }
-            
-            
-            template class MAEliminator<storm::models::sparse::Dtmc<double>>;
-            
-#ifdef STORM_HAVE_CARL
-            template class MAEliminator<storm::models::sparse::Dtmc<storm::RationalFunction>>;
-#endif
-            
-        } // namespace stateelimination
-    } // namespace storage
-} // namespace storm
diff --git a/src/solver/stateelimination/MAEliminator.h b/src/solver/stateelimination/MAEliminator.h
deleted file mode 100644
index d4db284c3..000000000
--- a/src/solver/stateelimination/MAEliminator.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef STORM_SOLVER_STATEELIMINATION_MAELIMINATOR_H_
-#define STORM_SOLVER_STATEELIMINATION_MAELIMINATOR_H_
-
-#include "src/solver/stateelimination/StateEliminator.h"
-
-namespace storm {
-    namespace solver {
-        namespace stateelimination {
-            
-            template<typename SparseModelType>
-            class MAEliminator : public StateEliminator<SparseModelType> {
-
-                typedef typename SparseModelType::ValueType ValueType;
-
-            public:
-                MAEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions);
-                
-                // Instantiaton of Virtual methods
-                void updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) override;
-                void updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) override;
-                void updatePriority(storm::storage::sparse::state_type const& state) override;
-                bool filterPredecessor(storm::storage::sparse::state_type const& state) override;
-                bool isFilterPredecessor() const override;
-                
-            private:
-            };
-            
-        } // namespace stateelimination
-    } // namespace storage
-} // namespace storm
-
-#endif // STORM_SOLVER_STATEELIMINATION_MAELIMINATOR_H_
diff --git a/src/solver/stateelimination/PrioritizedEliminator.cpp b/src/solver/stateelimination/PrioritizedEliminator.cpp
deleted file mode 100644
index 17a9c0825..000000000
--- a/src/solver/stateelimination/PrioritizedEliminator.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-#include "src/solver/stateelimination/PrioritizedEliminator.h"
-
-namespace storm {
-    namespace solver {
-        namespace stateelimination {
-            
-            template<typename SparseModelType>
-            PrioritizedEliminator<SparseModelType>::PrioritizedEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, PriorityQueuePointer priorityQueue, std::vector<ValueType>& stateValues) : StateEliminator<SparseModelType>(transitionMatrix, backwardTransitions), priorityQueue(priorityQueue), stateValues(stateValues) {
-            }
-            
-            template<typename SparseModelType>
-            void PrioritizedEliminator<SparseModelType>::updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) {
-                stateValues[state] = storm::utility::simplify(loopProbability * stateValues[state]);
-            }
-       
-            template<typename SparseModelType>
-            void PrioritizedEliminator<SparseModelType>::updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) {
-                stateValues[predecessor] = storm::utility::simplify(stateValues[predecessor] + storm::utility::simplify(probability * stateValues[state]));
-            }
-            
-            template<typename SparseModelType>
-            void PrioritizedEliminator<SparseModelType>::updatePriority(storm::storage::sparse::state_type const& state) {
-                priorityQueue->update(state, StateEliminator<SparseModelType>::transitionMatrix, StateEliminator<SparseModelType>::backwardTransitions, stateValues);
-            }
-            
-            template<typename SparseModelType>
-            bool PrioritizedEliminator<SparseModelType>::filterPredecessor(storm::storage::sparse::state_type const& state) {
-                STORM_LOG_ASSERT(false, "Filter should not be applied.");
-                return false;
-            }
-            
-            template<typename SparseModelType>
-            bool PrioritizedEliminator<SparseModelType>::isFilterPredecessor() const {
-                return false;
-            }
-            
-            
-            template class PrioritizedEliminator<storm::models::sparse::Dtmc<double>>;
-            
-#ifdef STORM_HAVE_CARL
-            template class PrioritizedEliminator<storm::models::sparse::Dtmc<storm::RationalFunction>>;
-#endif
-            
-        } // namespace stateelimination
-    } // namespace storage
-} // namespace storm
diff --git a/src/solver/stateelimination/PrioritizedEliminator.h b/src/solver/stateelimination/PrioritizedEliminator.h
deleted file mode 100644
index 1180fad09..000000000
--- a/src/solver/stateelimination/PrioritizedEliminator.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef STORM_SOLVER_STATEELIMINATION_PRIORITIZEDELIMINATOR_H_
-#define STORM_SOLVER_STATEELIMINATION_PRIORITIZEDELIMINATOR_H_
-
-#include "src/solver/stateelimination/StateEliminator.h"
-
-namespace storm {
-    namespace solver {
-        namespace stateelimination {
-            
-            template<typename SparseModelType>
-            class PrioritizedEliminator : public StateEliminator<SparseModelType> {
-
-                typedef typename SparseModelType::ValueType ValueType;
-                typedef typename std::shared_ptr<storm::modelchecker::StatePriorityQueue<ValueType>> PriorityQueuePointer;
-
-            public:
-                PrioritizedEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, PriorityQueuePointer priorityQueue, std::vector<ValueType>& stateValues);
-                
-                // Instantiaton of Virtual methods
-                void updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) override;
-                void updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) override;
-                void updatePriority(storm::storage::sparse::state_type const& state) override;
-                bool filterPredecessor(storm::storage::sparse::state_type const& state) override;
-                bool isFilterPredecessor() const override;
-                
-            private:
-                PriorityQueuePointer priorityQueue;
-                std::vector<ValueType>& stateValues;
-            };
-            
-        } // namespace stateelimination
-    } // namespace storage
-} // namespace storm
-
-#endif // STORM_SOLVER_STATEELIMINATION_PRIORITIZEDELIMINATOR_H_
diff --git a/src/solver/stateelimination/PrioritizedStateEliminator.cpp b/src/solver/stateelimination/PrioritizedStateEliminator.cpp
new file mode 100644
index 000000000..b5915b659
--- /dev/null
+++ b/src/solver/stateelimination/PrioritizedStateEliminator.cpp
@@ -0,0 +1,39 @@
+#include "src/solver/stateelimination/PrioritizedStateEliminator.h"
+
+#include "src/solver/stateelimination/StatePriorityQueue.h"
+
+#include "src/utility/macros.h"
+#include "src/utility/constants.h"
+
+namespace storm {
+    namespace solver {
+        namespace stateelimination {
+            
+            template<typename ValueType>
+            PrioritizedStateEliminator<ValueType>::PrioritizedStateEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, PriorityQueuePointer priorityQueue, std::vector<ValueType>& stateValues) : StateEliminator<ValueType>(transitionMatrix, backwardTransitions), priorityQueue(priorityQueue), stateValues(stateValues) {
+            }
+            
+            template<typename ValueType>
+            void PrioritizedStateEliminator<ValueType>::updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) {
+                stateValues[state] = storm::utility::simplify(loopProbability * stateValues[state]);
+            }
+       
+            template<typename ValueType>
+            void PrioritizedStateEliminator<ValueType>::updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) {
+                stateValues[predecessor] = storm::utility::simplify(stateValues[predecessor] + storm::utility::simplify(probability * stateValues[state]));
+            }
+            
+            template<typename ValueType>
+            void PrioritizedStateEliminator<ValueType>::updatePriority(storm::storage::sparse::state_type const& state) {
+                priorityQueue->update(state);
+            }
+            
+            template class PrioritizedStateEliminator<double>;
+            
+#ifdef STORM_HAVE_CARL
+            template class PrioritizedStateEliminator<storm::RationalFunction>;
+#endif
+            
+        } // namespace stateelimination
+    } // namespace storage
+} // namespace storm
diff --git a/src/solver/stateelimination/PrioritizedStateEliminator.h b/src/solver/stateelimination/PrioritizedStateEliminator.h
new file mode 100644
index 000000000..b31c58932
--- /dev/null
+++ b/src/solver/stateelimination/PrioritizedStateEliminator.h
@@ -0,0 +1,33 @@
+#ifndef STORM_SOLVER_STATEELIMINATION_PRIORITIZEDSTATEELIMINATOR_H_
+#define STORM_SOLVER_STATEELIMINATION_PRIORITIZEDSTATEELIMINATOR_H_
+
+#include "src/solver/stateelimination/StateEliminator.h"
+
+namespace storm {
+    namespace solver {
+        namespace stateelimination {
+            
+            class StatePriorityQueue;
+            
+            template<typename ValueType>
+            class PrioritizedStateEliminator : public StateEliminator<ValueType> {
+            public:
+                typedef typename std::shared_ptr<StatePriorityQueue> PriorityQueuePointer;
+
+                PrioritizedStateEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, PriorityQueuePointer priorityQueue, std::vector<ValueType>& stateValues);
+                
+                // Instantiaton of virtual methods.
+                void updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) override;
+                void updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) override;
+                void updatePriority(storm::storage::sparse::state_type const& state) override;
+                
+            protected:
+                PriorityQueuePointer priorityQueue;
+                std::vector<ValueType>& stateValues;
+            };
+            
+        } // namespace stateelimination
+    } // namespace storage
+} // namespace storm
+
+#endif // STORM_SOLVER_STATEELIMINATION_PRIORITIZEDSTATEELIMINATOR_H_
diff --git a/src/solver/stateelimination/StateEliminator.cpp b/src/solver/stateelimination/StateEliminator.cpp
index 01dc8a5af..eebe90bbc 100644
--- a/src/solver/stateelimination/StateEliminator.cpp
+++ b/src/solver/stateelimination/StateEliminator.cpp
@@ -1,6 +1,11 @@
 #include "src/solver/stateelimination/StateEliminator.h"
 
+#include "src/adapters/CarlAdapter.h"
+
 #include "src/storage/BitVector.h"
+
+#include "src/utility/stateelimination.h"
+#include "src/utility/macros.h"
 #include "src/utility/constants.h"
 #include "src/utility/macros.h"
 #include "src/exceptions/InvalidStateException.h"
@@ -9,13 +14,15 @@ namespace storm {
     namespace solver {
         namespace stateelimination {
             
-            template<typename SparseModelType>
-            StateEliminator<SparseModelType>::StateEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions) : transitionMatrix(transitionMatrix), backwardTransitions(backwardTransitions) {
+            using namespace storm::utility::stateelimination;
+            
+            template<typename ValueType>
+            StateEliminator<ValueType>::StateEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions) : transitionMatrix(transitionMatrix), backwardTransitions(backwardTransitions) {
+                // Intentionally left empty.
             }
             
-            template<typename SparseModelType>
-            void StateEliminator<SparseModelType>::eliminateState(storm::storage::sparse::state_type state, bool removeForwardTransitions, storm::storage::BitVector predecessorConstraint) {
-                
+            template<typename ValueType>
+            void StateEliminator<ValueType>::eliminateState(storm::storage::sparse::state_type state, bool removeForwardTransitions, storm::storage::BitVector predecessorConstraint) {
                 STORM_LOG_TRACE("Eliminating state " << state << ".");
                 
                 // Start by finding loop probability.
@@ -124,7 +131,6 @@ namespace storm {
                             auto successorEntry = storm::utility::simplify(std::move(*first2 * multiplyFactor));
                             *result = successorEntry;
                             newBackwardProbabilities[successorOffsetInNewBackwardTransitions].emplace_back(predecessor, successorEntry.getValue());
-                            //                        std::cout << "(1) adding " << first2->getColumn() << " -> " << newBackwardProbabilities[successorOffsetInNewBackwardTransitions].back() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl;
                             ++first2;
                             ++successorOffsetInNewBackwardTransitions;
                         } else if (first1->getColumn() < first2->getColumn()) {
@@ -134,7 +140,6 @@ namespace storm {
                             auto probability = storm::utility::simplify(first1->getValue() + storm::utility::simplify(multiplyFactor * first2->getValue()));
                             *result = storm::storage::MatrixEntry<typename storm::storage::FlexibleSparseMatrix<ValueType>::index_type, typename storm::storage::FlexibleSparseMatrix<ValueType>::value_type>(first1->getColumn(), probability);
                             newBackwardProbabilities[successorOffsetInNewBackwardTransitions].emplace_back(predecessor, probability);
-                            //                        std::cout << "(2) adding " << first2->getColumn() << " -> " << newBackwardProbabilities[successorOffsetInNewBackwardTransitions].back() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl;
                             ++first1;
                             ++first2;
                             ++successorOffsetInNewBackwardTransitions;
@@ -145,7 +150,6 @@ namespace storm {
                             auto stateProbability = storm::utility::simplify(std::move(*first2 * multiplyFactor));
                             *result = stateProbability;
                             newBackwardProbabilities[successorOffsetInNewBackwardTransitions].emplace_back(predecessor, stateProbability.getValue());
-                            //                        std::cout << "(3) adding " << first2->getColumn() << " -> " << newBackwardProbabilities[successorOffsetInNewBackwardTransitions].back() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl;
                             ++successorOffsetInNewBackwardTransitions;
                         }
                     }
@@ -168,10 +172,6 @@ namespace storm {
                     }
                     
                     FlexibleRowType& successorBackwardTransitions = backwardTransitions.getRow(successorEntry.getColumn());
-                    //                std::cout << "old backward trans of " << successorEntry.getColumn() << std::endl;
-                    //                for (auto const& trans : successorBackwardTransitions) {
-                    //                    std::cout << trans << std::endl;
-                    //                }
                     
                     // Delete the current state as a predecessor of the successor state only if we are going to remove the
                     // current state's forward transitions.
@@ -186,11 +186,6 @@ namespace storm {
                     FlexibleRowIterator first2 = newBackwardProbabilities[successorOffsetInNewBackwardTransitions].begin();
                     FlexibleRowIterator last2 = newBackwardProbabilities[successorOffsetInNewBackwardTransitions].end();
                     
-                    //                std::cout << "adding backward trans " << successorEntry.getColumn() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl;
-                    //                for (auto const& trans : newBackwardProbabilities[successorOffsetInNewBackwardTransitions]) {
-                    //                    std::cout << trans << std::endl;
-                    //                }
-                    
                     FlexibleRowType newPredecessors;
                     newPredecessors.reserve((last1 - first1) + (last2 - first2));
                     std::insert_iterator<FlexibleRowType> result(newPredecessors, newPredecessors.end());
@@ -206,7 +201,7 @@ namespace storm {
                             }
                             ++first2;
                         } else if (first1->getColumn() == first2->getColumn()) {
-                            if (storm::modelchecker::estimateComplexity(first1->getValue()) > storm::modelchecker::estimateComplexity(first2->getValue())) {
+                            if (estimateComplexity(first1->getValue()) > estimateComplexity(first2->getValue())) {
                                 *result = *first1;
                             } else {
                                 *result = *first2;
@@ -225,10 +220,6 @@ namespace storm {
                     }
                     // Now move the new predecessors in place.
                     successorBackwardTransitions = std::move(newPredecessors);
-                    //                std::cout << "new backward trans of " << successorEntry.getColumn() << std::endl;
-                    //                for (auto const& trans : successorBackwardTransitions) {
-                    //                    std::cout << trans << std::endl;
-                    //                }
                     ++successorOffsetInNewBackwardTransitions;
                 }
                 STORM_LOG_TRACE("Fixed predecessor lists of successor states.");
@@ -244,13 +235,38 @@ namespace storm {
                     currentStatePredecessors.clear();
                     currentStatePredecessors.shrink_to_fit();
                 }
-
             }
             
-            template class StateEliminator<storm::models::sparse::Dtmc<double>>;
+            template<typename ValueType>
+            void StateEliminator<ValueType>::updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) {
+                // Intentionally left empty.
+            }
+            
+            template<typename ValueType>
+            void StateEliminator<ValueType>::updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) {
+                // Intentionally left empty.
+            }
+            
+            template<typename ValueType>
+            void StateEliminator<ValueType>::updatePriority(storm::storage::sparse::state_type const& state) {
+                // Intentionally left empty.
+            }
+            
+            template<typename ValueType>
+            bool StateEliminator<ValueType>::filterPredecessor(storm::storage::sparse::state_type const& state) {
+                STORM_LOG_ASSERT(false, "Must not filter predecessors.");
+                return false;
+            }
+            
+            template<typename ValueType>
+            bool StateEliminator<ValueType>::isFilterPredecessor() const {
+                return false;
+            }
+            
+            template class StateEliminator<double>;
             
 #ifdef STORM_HAVE_CARL
-            template class StateEliminator<storm::models::sparse::Dtmc<storm::RationalFunction>>;
+            template class StateEliminator<storm::RationalFunction>;
 #endif
             
         } // namespace stateelimination
diff --git a/src/solver/stateelimination/StateEliminator.h b/src/solver/stateelimination/StateEliminator.h
index 35c7b0521..bf2abd695 100644
--- a/src/solver/stateelimination/StateEliminator.h
+++ b/src/solver/stateelimination/StateEliminator.h
@@ -1,42 +1,35 @@
 #ifndef STORM_SOLVER_STATEELIMINATION_STATEELIMINATOR_H_
 #define STORM_SOLVER_STATEELIMINATION_STATEELIMINATOR_H_
 
-#include "src/storage/FlexibleSparseMatrix.h"
-#include "src/storage/SparseMatrix.h"
 #include "src/storage/sparse/StateType.h"
-#include "src/models/sparse/Dtmc.h"
-#include "src/models/sparse/StandardRewardModel.h"
-#include "src/adapters/CarlAdapter.h"
-#include "src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h"
-#include "src/utility/macros.h"
+
+#include "src/storage/FlexibleSparseMatrix.h"
+#include "src/storage/BitVector.h"
 
 namespace storm {
     namespace solver {
         namespace stateelimination {
             
-            template<typename SparseModelType>
+            template<typename ValueType>
             class StateEliminator {
-                typedef typename SparseModelType::ValueType ValueType;
+            public:
                 typedef typename storm::storage::FlexibleSparseMatrix<ValueType>::row_type FlexibleRowType;
                 typedef typename FlexibleRowType::iterator FlexibleRowIterator;
 
-            public:
                 StateEliminator(storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions);
                 
                 void eliminateState(storm::storage::sparse::state_type state, bool removeForwardTransitions, storm::storage::BitVector predecessorConstraint = storm::storage::BitVector());
                 
-                // Virtual methods for base classes to distinguish between different state elimination approaches
-                virtual void updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) = 0;
-                virtual void updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) = 0;
-                virtual void updatePriority(storm::storage::sparse::state_type const& state) = 0;
-                virtual bool filterPredecessor(storm::storage::sparse::state_type const& state) = 0;
-                virtual bool isFilterPredecessor() const = 0;
-                
+                // Provide virtual methods that can be customized by subclasses to govern side-effect of the elimination.
+                virtual void updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability);
+                virtual void updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state);
+                virtual void updatePriority(storm::storage::sparse::state_type const& state);
+                virtual bool filterPredecessor(storm::storage::sparse::state_type const& state);
+                virtual bool isFilterPredecessor() const;
                 
             protected:
                 storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix;
                 storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions;
-                
             };
             
         } // namespace stateelimination
diff --git a/src/solver/stateelimination/StatePriorityQueue.cpp b/src/solver/stateelimination/StatePriorityQueue.cpp
new file mode 100644
index 000000000..3db9d0db7
--- /dev/null
+++ b/src/solver/stateelimination/StatePriorityQueue.cpp
@@ -0,0 +1,13 @@
+#include "src/solver/stateelimination/StatePriorityQueue.h"
+
+namespace storm {
+    namespace solver {
+        namespace stateelimination {
+         
+            void StatePriorityQueue::update(storm::storage::sparse::state_type state) {
+                // Intentionally left empty.
+            }
+            
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/solver/stateelimination/StatePriorityQueue.h b/src/solver/stateelimination/StatePriorityQueue.h
new file mode 100644
index 000000000..9f1a9ac44
--- /dev/null
+++ b/src/solver/stateelimination/StatePriorityQueue.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include <cstddef>
+
+#include "src/storage/sparse/StateType.h"
+
+namespace storm {
+    namespace solver {
+        namespace stateelimination {
+         
+            class StatePriorityQueue {
+            public:
+                virtual bool hasNext() const = 0;
+                virtual storm::storage::sparse::state_type pop() = 0;
+                virtual void update(storm::storage::sparse::state_type state);
+                virtual std::size_t size() const = 0;
+            };
+            
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/solver/stateelimination/StaticStatePriorityQueue.cpp b/src/solver/stateelimination/StaticStatePriorityQueue.cpp
new file mode 100644
index 000000000..43efe9dcf
--- /dev/null
+++ b/src/solver/stateelimination/StaticStatePriorityQueue.cpp
@@ -0,0 +1,28 @@
+#include "src/solver/stateelimination/StaticStatePriorityQueue.h"
+
+#include "src/adapters/CarlAdapter.h"
+
+namespace storm {
+    namespace solver {
+        namespace stateelimination {
+            
+            StaticStatePriorityQueue::StaticStatePriorityQueue(std::vector<storm::storage::sparse::state_type> const& sortedStates) : StatePriorityQueue(), sortedStates(sortedStates), currentPosition(0) {
+                // Intentionally left empty.
+            }
+            
+            bool StaticStatePriorityQueue::hasNext() const {
+                return currentPosition < sortedStates.size();
+            }
+            
+            storm::storage::sparse::state_type StaticStatePriorityQueue::pop() {
+                ++currentPosition;
+                return sortedStates[currentPosition - 1];
+            }
+            
+            std::size_t StaticStatePriorityQueue::size() const {
+                return sortedStates.size() - currentPosition;
+            }
+            
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/solver/stateelimination/StaticStatePriorityQueue.h b/src/solver/stateelimination/StaticStatePriorityQueue.h
new file mode 100644
index 000000000..887c32141
--- /dev/null
+++ b/src/solver/stateelimination/StaticStatePriorityQueue.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <vector>
+
+#include "src/solver/stateelimination/StatePriorityQueue.h"
+
+namespace storm {
+    namespace solver {
+        namespace stateelimination {
+            
+            class StaticStatePriorityQueue : public StatePriorityQueue {
+            public:
+                StaticStatePriorityQueue(std::vector<storm::storage::sparse::state_type> const& sortedStates);
+                
+                virtual bool hasNext() const override;
+                virtual storm::storage::sparse::state_type pop() override;
+                virtual std::size_t size() const override;
+                
+            private:
+                std::vector<uint_fast64_t> sortedStates;
+                uint_fast64_t currentPosition;
+            };
+            
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/utility/stateelimination.cpp b/src/utility/stateelimination.cpp
new file mode 100644
index 000000000..f71e08a5b
--- /dev/null
+++ b/src/utility/stateelimination.cpp
@@ -0,0 +1,160 @@
+#include "src/utility/stateelimination.h"
+
+#include <random>
+
+#include "src/solver/stateelimination/StatePriorityQueue.h"
+#include "src/solver/stateelimination/StaticStatePriorityQueue.h"
+#include "src/solver/stateelimination/DynamicStatePriorityQueue.h"
+
+#include "src/storage/BitVector.h"
+#include "src/storage/FlexibleSparseMatrix.h"
+
+#include "src/settings/SettingsManager.h"
+
+#include "src/utility/macros.h"
+#include "src/utility/constants.h"
+#include "src/exceptions/InvalidStateException.h"
+#include "src/exceptions/InvalidSettingsException.h"
+
+namespace storm {
+    namespace utility {
+        namespace stateelimination {
+
+            bool eliminationOrderNeedsDistances(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order) {
+                return order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::Forward ||
+                order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::ForwardReversed ||
+                order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::Backward ||
+                order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::BackwardReversed;
+            }
+            
+            bool eliminationOrderNeedsForwardDistances(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order) {
+                return order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::Forward ||
+                order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::ForwardReversed;
+            }
+            
+            bool eliminationOrderNeedsReversedDistances(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order) {
+                return order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::ForwardReversed ||
+                order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::BackwardReversed;
+            }
+            
+            bool eliminationOrderIsPenaltyBased(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order) {
+                return order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::StaticPenalty ||
+                order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::DynamicPenalty ||
+                order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::RegularExpression;
+            }
+            
+            bool eliminationOrderIsStatic(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order) {
+                return eliminationOrderNeedsDistances(order) || order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::StaticPenalty;
+            }
+            
+            template<typename ValueType>
+            uint_fast64_t estimateComplexity(ValueType const& value) {
+                return 1;
+            }
+            
+#ifdef STORM_HAVE_CARL
+            template<>
+            uint_fast64_t estimateComplexity(storm::RationalFunction const& value) {
+                if (storm::utility::isConstant(value)) {
+                    return 1;
+                }
+                if (value.denominator().isConstant()) {
+                    return value.nominator().complexity();
+                } else {
+                    return value.denominator().complexity() * value.nominator().complexity();
+                }
+            }
+#endif
+            
+            template<typename ValueType>
+            uint_fast64_t computeStatePenalty(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities) {
+                uint_fast64_t penalty = 0;
+                bool hasParametricSelfLoop = false;
+                
+                for (auto const& predecessor : backwardTransitions.getRow(state)) {
+                    for (auto const& successor : transitionMatrix.getRow(state)) {
+                        penalty += estimateComplexity(predecessor.getValue()) * estimateComplexity(successor.getValue());
+                    }
+                    if (predecessor.getColumn() == state) {
+                        hasParametricSelfLoop = !storm::utility::isConstant(predecessor.getValue());
+                    }
+                    penalty += estimateComplexity(oneStepProbabilities[predecessor.getColumn()]) * estimateComplexity(predecessor.getValue()) * estimateComplexity(oneStepProbabilities[state]);
+                }
+                
+                // If it is a self-loop that is parametric, we increase the penalty a lot.
+                if (hasParametricSelfLoop) {
+                    penalty *= 10;
+                }
+                
+                return penalty;
+            }
+            
+            template<typename ValueType>
+            uint_fast64_t computeStatePenaltyRegularExpression(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities) {
+                return backwardTransitions.getRow(state).size() * transitionMatrix.getRow(state).size();
+            }
+            
+            template<typename ValueType>
+            std::shared_ptr<StatePriorityQueue> createStatePriorityQueue(boost::optional<std::vector<uint_fast64_t>> const& distanceBasedStatePriorities, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType>& oneStepProbabilities, storm::storage::BitVector const& states) {
+                
+                STORM_LOG_TRACE("Creating state priority queue for states " << states);
+                
+                // Get the settings to customize the priority queue.
+                storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder order = storm::settings::getModule<storm::settings::modules::SparseDtmcEliminationModelCheckerSettings>().getEliminationOrder();
+                
+                std::vector<storm::storage::sparse::state_type> sortedStates(states.begin(), states.end());
+                
+                if (order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::Random) {
+                    std::random_device randomDevice;
+                    std::mt19937 generator(randomDevice());
+                    std::shuffle(sortedStates.begin(), sortedStates.end(), generator);
+                    return std::make_unique<StaticStatePriorityQueue>(sortedStates);
+                } else {
+                    if (eliminationOrderNeedsDistances(order)) {
+                        STORM_LOG_THROW(static_cast<bool>(distanceBasedStatePriorities), storm::exceptions::InvalidStateException, "Unable to build state priority queue without distance-based priorities.");
+                        std::sort(sortedStates.begin(), sortedStates.end(), [&distanceBasedStatePriorities] (storm::storage::sparse::state_type const& state1, storm::storage::sparse::state_type const& state2) { return distanceBasedStatePriorities.get()[state1] < distanceBasedStatePriorities.get()[state2]; } );
+                        return std::make_unique<StaticStatePriorityQueue>(sortedStates);
+                    } else if (eliminationOrderIsPenaltyBased(order)) {
+                        std::vector<std::pair<storm::storage::sparse::state_type, uint_fast64_t>> statePenalties(sortedStates.size());
+                        typename DynamicStatePriorityQueue<ValueType>::PenaltyFunctionType penaltyFunction = order == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::RegularExpression ?  computeStatePenaltyRegularExpression<ValueType> : computeStatePenalty<ValueType>;
+                        for (uint_fast64_t index = 0; index < sortedStates.size(); ++index) {
+                            statePenalties[index] = std::make_pair(sortedStates[index], penaltyFunction(sortedStates[index], transitionMatrix, backwardTransitions, oneStepProbabilities));
+                        }
+                        
+                        std::sort(statePenalties.begin(), statePenalties.end(), [] (std::pair<storm::storage::sparse::state_type, uint_fast64_t> const& statePenalty1, std::pair<storm::storage::sparse::state_type, uint_fast64_t> const& statePenalty2) { return statePenalty1.second < statePenalty2.second; } );
+                        
+                        if (eliminationOrderIsStatic(order)) {
+                            // For the static penalty version, we need to strip the penalties to create the queue.
+                            for (uint_fast64_t index = 0; index < sortedStates.size(); ++index) {
+                                sortedStates[index] = statePenalties[index].first;
+                            }
+                            return std::make_unique<StaticStatePriorityQueue>(sortedStates);
+                        } else {
+                            // For the dynamic penalty version, we need to give the full state-penalty pairs.
+                            return std::make_unique<DynamicStatePriorityQueue<ValueType>>(statePenalties, transitionMatrix, backwardTransitions, oneStepProbabilities, penaltyFunction);
+                        }
+                    }
+                }
+                STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "Illegal elimination order selected.");
+            }
+            
+            std::shared_ptr<StatePriorityQueue> createNaivePriorityQueue(storm::storage::BitVector const& states) {
+                std::vector<storm::storage::sparse::state_type> sortedStates(states.begin(), states.end());
+                return std::make_shared<StaticStatePriorityQueue>(sortedStates);
+            }
+            
+            template uint_fast64_t estimateComplexity(double const& value);
+            template std::shared_ptr<StatePriorityQueue> createStatePriorityQueue(boost::optional<std::vector<uint_fast64_t>> const& distanceBasedStatePriorities, storm::storage::FlexibleSparseMatrix<double> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<double> const& backwardTransitions, std::vector<double>& oneStepProbabilities, storm::storage::BitVector const& states);
+            template uint_fast64_t computeStatePenalty(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<double> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<double> const& backwardTransitions, std::vector<double> const& oneStepProbabilities);
+            template uint_fast64_t computeStatePenaltyRegularExpression(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<double> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<double> const& backwardTransitions, std::vector<double> const& oneStepProbabilities);
+
+            
+#ifdef STORM_HAVE_CARL
+            template uint_fast64_t estimateComplexity(storm::RationalFunction const& value);
+            template std::shared_ptr<StatePriorityQueue> createStatePriorityQueue(boost::optional<std::vector<uint_fast64_t>> const& distanceBasedStatePriorities, storm::storage::FlexibleSparseMatrix<storm::RationalFunction> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<storm::RationalFunction> const& backwardTransitions, std::vector<storm::RationalFunction>& oneStepProbabilities, storm::storage::BitVector const& states);
+            template uint_fast64_t computeStatePenalty(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<storm::RationalFunction> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<storm::RationalFunction> const& backwardTransitions, std::vector<storm::RationalFunction> const& oneStepProbabilities);
+            template uint_fast64_t computeStatePenaltyRegularExpression(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<storm::RationalFunction> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<storm::RationalFunction> const& backwardTransitions, std::vector<storm::RationalFunction> const& oneStepProbabilities);
+#endif
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/utility/stateelimination.h b/src/utility/stateelimination.h
new file mode 100644
index 000000000..8dc3ab600
--- /dev/null
+++ b/src/utility/stateelimination.h
@@ -0,0 +1,60 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+
+#include <boost/optional.hpp>
+
+#include "src/storage/sparse/StateType.h"
+
+#include "src/adapters/CarlAdapter.h"
+
+#include "src/settings/modules/SparseDtmcEliminationModelCheckerSettings.h"
+
+namespace storm {
+    namespace solver {
+        namespace stateelimination {
+            class StatePriorityQueue;
+        }
+    }
+    
+    namespace storage {
+        class BitVector;
+        
+        template<typename ValueType>
+        class FlexibleSparseMatrix;
+    }
+    
+    namespace utility {
+        namespace stateelimination {
+            
+            using namespace storm::solver::stateelimination;
+            
+            bool eliminationOrderNeedsDistances(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order);
+            bool eliminationOrderNeedsForwardDistances(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order);
+            bool eliminationOrderNeedsReversedDistances(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order);
+            bool eliminationOrderIsPenaltyBased(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order);
+            bool eliminationOrderIsStatic(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder const& order);
+            
+            template<typename ValueType>
+            uint_fast64_t estimateComplexity(ValueType const& value);
+
+#ifdef STORM_HAVE_CARL
+            template<>
+            uint_fast64_t estimateComplexity(storm::RationalFunction const& value);
+#endif
+            
+            template<typename ValueType>
+            uint_fast64_t computeStatePenalty(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities);
+            
+            template<typename ValueType>
+            uint_fast64_t computeStatePenaltyRegularExpression(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& oneStepProbabilities);
+            
+            template<typename ValueType>
+            std::shared_ptr<StatePriorityQueue> createStatePriorityQueue(boost::optional<std::vector<uint_fast64_t>> const& stateDistances, storm::storage::FlexibleSparseMatrix<ValueType> const& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType>& oneStepProbabilities, storm::storage::BitVector const& states);
+            
+            std::shared_ptr<StatePriorityQueue> createNaivePriorityQueue(storm::storage::BitVector const& states);
+            
+        }
+    }
+}
\ No newline at end of file