diff --git a/src/storm/exceptions/InvalidSolverSettingsException.h b/src/storm/exceptions/InvalidSolverSettingsException.h
new file mode 100644
index 000000000..0580fb0cc
--- /dev/null
+++ b/src/storm/exceptions/InvalidSolverSettingsException.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "storm/exceptions/BaseException.h"
+#include "storm/exceptions/ExceptionMacros.h"
+
+namespace storm {
+    namespace exceptions {
+        
+        STORM_NEW_EXCEPTION(InvalidSolverSettingsException)
+        
+    } // namespace exceptions
+} // namespace storm
diff --git a/src/storm/exceptions/UnmetRequirementException.h b/src/storm/exceptions/UnmetRequirementException.h
new file mode 100644
index 000000000..3a7b70312
--- /dev/null
+++ b/src/storm/exceptions/UnmetRequirementException.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "storm/exceptions/BaseException.h"
+#include "storm/exceptions/ExceptionMacros.h"
+
+namespace storm {
+    namespace exceptions {
+        
+        STORM_NEW_EXCEPTION(UnmetRequirementException)
+        
+    } // namespace exceptions
+} // namespace storm
diff --git a/src/storm/modelchecker/prctl/helper/HybridMdpPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/HybridMdpPrctlHelper.cpp
index 5c88f9466..fd808cdae 100644
--- a/src/storm/modelchecker/prctl/helper/HybridMdpPrctlHelper.cpp
+++ b/src/storm/modelchecker/prctl/helper/HybridMdpPrctlHelper.cpp
@@ -117,7 +117,7 @@ namespace storm {
                                 STORM_LOG_DEBUG("Computing valid scheduler hint, because the solver requires it.");
                                 initialScheduler = computeValidInitialSchedulerForUntilProbabilities<ValueType>(explicitRepresentation.first, explicitRepresentation.second);
 
-                                requirements.set(storm::solver::MinMaxLinearEquationSolverRequirements::Element::ValidInitialScheduler, false);
+                                requirements.clearValidInitialScheduler();
                             }
                             STORM_LOG_THROW(requirements.empty(), storm::exceptions::UncheckedRequirementException, "Cannot establish requirements for solver.");
                         }
@@ -126,6 +126,7 @@ namespace storm {
                         if (initialScheduler) {
                             solver->setInitialScheduler(std::move(initialScheduler.get()));
                         }
+                        solver->setBounds(storm::utility::zero<ValueType>(), storm::utility::one<ValueType>());
                         solver->setRequirementsChecked();
                         solver->solveEquations(dir, x, explicitRepresentation.second);
                         
@@ -357,7 +358,7 @@ namespace storm {
                             if (requirements.requires(storm::solver::MinMaxLinearEquationSolverRequirements::Element::ValidInitialScheduler)) {
                                 STORM_LOG_DEBUG("Computing valid scheduler, because the solver requires it.");
                                 requireInitialScheduler = true;
-                                requirements.set(storm::solver::MinMaxLinearEquationSolverRequirements::Element::ValidInitialScheduler, false);
+                                requirements.clearValidInitialScheduler();
                             }
                             STORM_LOG_THROW(requirements.empty(), storm::exceptions::UncheckedRequirementException, "Cannot establish requirements for solver.");
                         }
diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp
index ae898a14d..437631a3a 100644
--- a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp
+++ b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp
@@ -207,7 +207,7 @@ namespace storm {
                     if (requirements.requires(storm::solver::MinMaxLinearEquationSolverRequirements::Element::ValidInitialScheduler)) {
                         STORM_LOG_DEBUG("Computing valid scheduler, because the solver requires it.");
                         result.schedulerHint = computeValidSchedulerHint(type, transitionMatrix, backwardTransitions, maybeStates, phiStates, targetStates);
-                        requirements.set(storm::solver::MinMaxLinearEquationSolverRequirements::Element::ValidInitialScheduler, false);
+                        requirements.clearValidInitialScheduler();
                     }
                     STORM_LOG_THROW(requirements.empty(), storm::exceptions::UncheckedRequirementException, "There are unchecked requirements of the solver.");
                 }
@@ -215,15 +215,14 @@ namespace storm {
                 bool skipEcWithinMaybeStatesCheck = dir == storm::OptimizationDirection::Minimize || (hint.isExplicitModelCheckerHint() && hint.asExplicitModelCheckerHint<ValueType>().getNoEndComponentsInMaybeStates());
                 extractHintInformationForMaybeStates(result, transitionMatrix, backwardTransitions, maybeStates, selectedChoices, hint, skipEcWithinMaybeStatesCheck);
 
-                result.lowerResultBound = storm::utility::zero<ValueType>();
-                if (type == storm::solver::EquationSystemType::UntilProbabilities) {
+                // Only set bounds if we did not obtain them from the hint.
+                if (!result.hasLowerResultBound()) {
+                    result.lowerResultBound = storm::utility::zero<ValueType>();
+                }
+                if (!result.hasUpperResultBound() && type == storm::solver::EquationSystemType::UntilProbabilities) {
                     result.upperResultBound = storm::utility::one<ValueType>();
-                } else if (type == storm::solver::EquationSystemType::ReachabilityRewards) {
-                    // Intentionally left empty.
-                } else {
-                    STORM_LOG_ASSERT(false, "Unexpected equation system type.");
                 }
-                
+
                 return result;
             }
             
diff --git a/src/storm/modelchecker/prctl/helper/SymbolicMdpPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/SymbolicMdpPrctlHelper.cpp
index 395018b6e..c6231a5eb 100644
--- a/src/storm/modelchecker/prctl/helper/SymbolicMdpPrctlHelper.cpp
+++ b/src/storm/modelchecker/prctl/helper/SymbolicMdpPrctlHelper.cpp
@@ -88,7 +88,7 @@ namespace storm {
                             if (requirements.requires(storm::solver::MinMaxLinearEquationSolverRequirements::Element::ValidInitialScheduler)) {
                                 STORM_LOG_DEBUG("Computing valid scheduler, because the solver requires it.");
                                 initialScheduler = computeValidSchedulerHint(storm::solver::EquationSystemType::UntilProbabilities, model, transitionMatrix, maybeStates, statesWithProbability01.second);
-                                requirements.set(storm::solver::MinMaxLinearEquationSolverRequirements::Element::ValidInitialScheduler, false);
+                                requirements.clearValidInitialScheduler();
                             }
                             STORM_LOG_THROW(requirements.empty(), storm::exceptions::UncheckedRequirementException, "Could not establish requirements of solver.");
                         }
@@ -247,7 +247,7 @@ namespace storm {
                             if (requirements.requires(storm::solver::MinMaxLinearEquationSolverRequirements::Element::ValidInitialScheduler)) {
                                 STORM_LOG_DEBUG("Computing valid scheduler, because the solver requires it.");
                                 initialScheduler = computeValidSchedulerHint(storm::solver::EquationSystemType::ReachabilityRewards, model, transitionMatrix, maybeStates, targetStates);
-                                requirements.set(storm::solver::MinMaxLinearEquationSolverRequirements::Element::ValidInitialScheduler, false);
+                                requirements.clearValidInitialScheduler();
                             }
                             STORM_LOG_THROW(requirements.empty(), storm::exceptions::UncheckedRequirementException, "Could not establish requirements of solver.");
                         }
diff --git a/src/storm/settings/modules/EigenEquationSolverSettings.cpp b/src/storm/settings/modules/EigenEquationSolverSettings.cpp
index ea25da11d..3047a13a4 100644
--- a/src/storm/settings/modules/EigenEquationSolverSettings.cpp
+++ b/src/storm/settings/modules/EigenEquationSolverSettings.cpp
@@ -106,6 +106,15 @@ namespace storm {
                 return true;
             }
             
+            std::ostream& operator<<(std::ostream& out, EigenEquationSolverSettings::LinearEquationMethod const& method) {
+                switch (method) {
+                    case EigenEquationSolverSettings::LinearEquationMethod::BiCGSTAB: out << "bicgstab"; break;
+                    case EigenEquationSolverSettings::LinearEquationMethod::GMRES: out << "gmres"; break;
+                    case EigenEquationSolverSettings::LinearEquationMethod::DGMRES: out << "dgmres"; break;
+                    case EigenEquationSolverSettings::LinearEquationMethod::SparseLU: out << "sparselu"; break;
+                }
+            }
+            
         } // namespace modules
     } // namespace settings
 } // namespace storm
diff --git a/src/storm/settings/modules/EigenEquationSolverSettings.h b/src/storm/settings/modules/EigenEquationSolverSettings.h
index 8ac5fa7f0..622d71764 100644
--- a/src/storm/settings/modules/EigenEquationSolverSettings.h
+++ b/src/storm/settings/modules/EigenEquationSolverSettings.h
@@ -110,6 +110,8 @@ namespace storm {
                 static const std::string restartOptionName;
             };
             
+            std::ostream& operator<<(std::ostream& out, EigenEquationSolverSettings::LinearEquationMethod const& method);
+            
         } // namespace modules
     } // namespace settings
 } // namespace storm
diff --git a/src/storm/settings/modules/GeneralSettings.cpp b/src/storm/settings/modules/GeneralSettings.cpp
index da9a7223c..7edb76e7b 100644
--- a/src/storm/settings/modules/GeneralSettings.cpp
+++ b/src/storm/settings/modules/GeneralSettings.cpp
@@ -30,6 +30,7 @@ namespace storm {
             const std::string GeneralSettings::bisimulationOptionShortName = "bisim";
             const std::string GeneralSettings::parametricOptionName = "parametric";
             const std::string GeneralSettings::exactOptionName = "exact";
+            const std::string GeneralSettings::soundOptionName = "sound";
 
             GeneralSettings::GeneralSettings() : ModuleSettings(moduleName) {
                 this->addOption(storm::settings::OptionBuilder(moduleName, helpOptionName, false, "Shows all available options, arguments and descriptions.").setShortName(helpOptionShortName)
@@ -43,6 +44,7 @@ namespace storm {
                 this->addOption(storm::settings::OptionBuilder(moduleName, bisimulationOptionName, false, "Sets whether to perform bisimulation minimization.").setShortName(bisimulationOptionShortName).build());
                 this->addOption(storm::settings::OptionBuilder(moduleName, parametricOptionName, false, "Sets whether to enable parametric model checking.").build());
                 this->addOption(storm::settings::OptionBuilder(moduleName, exactOptionName, false, "Sets whether to enable exact model checking.").build());
+                this->addOption(storm::settings::OptionBuilder(moduleName, soundOptionName, false, "Sets whether to force sound model checking.").build());
             }
             
             bool GeneralSettings::isHelpSet() const {
@@ -86,6 +88,10 @@ namespace storm {
                 return this->getOption(exactOptionName).getHasOptionBeenSet();
             }
             
+            bool GeneralSettings::isSoundSet() const {
+                return this->getOption(soundOptionName).getHasOptionBeenSet();
+            }
+            
             void GeneralSettings::finalize() {
                 // Intentionally left empty.
             }
diff --git a/src/storm/settings/modules/GeneralSettings.h b/src/storm/settings/modules/GeneralSettings.h
index 52b519ed2..42f22fb3b 100644
--- a/src/storm/settings/modules/GeneralSettings.h
+++ b/src/storm/settings/modules/GeneralSettings.h
@@ -84,20 +84,20 @@ namespace storm {
                  * @return True iff the option was set.
                  */
                 bool isParametricSet() const;
-
+                
                 /*!
-                 * Retrieves whether a min/max equation solving technique has been set.
+                 * Retrieves whether the option enabling exact model checking is set.
                  *
-                 * @return True iff an equation solving technique has been set.
+                 * @return True iff the option was set.
                  */
-                bool isMinMaxEquationSolvingTechniqueSet() const;
+                bool isExactSet() const;
                 
                 /*!
-                 * Retrieves whether the option enabling exact model checking is set.
+                 * Retrieves whether the option forcing soundnet is set.
                  *
                  * @return True iff the option was set.
                  */
-                bool isExactSet() const;
+                bool isSoundSet() const;
 
                 bool check() const override;
                 void finalize() override;
@@ -121,8 +121,8 @@ namespace storm {
                 static const std::string bisimulationOptionName;
                 static const std::string bisimulationOptionShortName;
                 static const std::string parametricOptionName;
-
                 static const std::string exactOptionName;
+                static const std::string soundOptionName;
             };
 
         } // namespace modules
diff --git a/src/storm/settings/modules/NativeEquationSolverSettings.cpp b/src/storm/settings/modules/NativeEquationSolverSettings.cpp
index 7b17808f1..d797a968a 100644
--- a/src/storm/settings/modules/NativeEquationSolverSettings.cpp
+++ b/src/storm/settings/modules/NativeEquationSolverSettings.cpp
@@ -25,7 +25,7 @@ namespace storm {
             const std::string NativeEquationSolverSettings::powerMethodMultiplicationStyleOptionName = "powmult";
 
             NativeEquationSolverSettings::NativeEquationSolverSettings() : ModuleSettings(moduleName) {
-                std::vector<std::string> methods = { "jacobi", "gaussseidel", "sor", "walkerchae", "power", "spower" };
+                std::vector<std::string> methods = { "jacobi", "gaussseidel", "sor", "walkerchae", "power" };
                 this->addOption(storm::settings::OptionBuilder(moduleName, techniqueOptionName, true, "The method to be used for solving linear equation systems with the native engine.").addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of the method to use.").addValidatorString(ArgumentValidatorFactory::createMultipleChoiceValidator(methods)).setDefaultValueString("jacobi").build()).build());
                 
                 this->addOption(storm::settings::OptionBuilder(moduleName, maximalIterationsOptionName, false, "The maximal number of iterations to perform before iterative solving is aborted.").setShortName(maximalIterationsOptionShortName).addArgument(storm::settings::ArgumentBuilder::createUnsignedIntegerArgument("count", "The maximal iteration count.").setDefaultValueUnsignedInteger(20000).build()).build());
@@ -61,8 +61,6 @@ namespace storm {
                     return NativeEquationSolverSettings::LinearEquationMethod::WalkerChae;
                 } else if (linearEquationSystemTechniqueAsString == "power") {
                     return NativeEquationSolverSettings::LinearEquationMethod::Power;
-                } else if (linearEquationSystemTechniqueAsString == "spower") {
-                    return NativeEquationSolverSettings::LinearEquationMethod::SoundPower;
                 }
                 STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentValueException, "Unknown solution technique '" << linearEquationSystemTechniqueAsString << "' selected.");
             }
@@ -114,6 +112,16 @@ namespace storm {
                 return true;
             }
             
+            std::ostream& operator<<(std::ostream& out, NativeEquationSolverSettings::LinearEquationMethod const& method) {
+                switch (method) {
+                    case NativeEquationSolverSettings::LinearEquationMethod::Jacobi: out << "jacobi"; break;
+                    case NativeEquationSolverSettings::LinearEquationMethod::GaussSeidel: out << "gaussseidel"; break;
+                    case NativeEquationSolverSettings::LinearEquationMethod::SOR: out << "sor"; break;
+                    case NativeEquationSolverSettings::LinearEquationMethod::WalkerChae: out << "walkerchae"; break;
+                    case NativeEquationSolverSettings::LinearEquationMethod::Power: out << "power"; break;
+                }
+            }
+            
         } // namespace modules
     } // namespace settings
 } // namespace storm
diff --git a/src/storm/settings/modules/NativeEquationSolverSettings.h b/src/storm/settings/modules/NativeEquationSolverSettings.h
index ccedfbdc6..6f70db06a 100644
--- a/src/storm/settings/modules/NativeEquationSolverSettings.h
+++ b/src/storm/settings/modules/NativeEquationSolverSettings.h
@@ -15,7 +15,7 @@ namespace storm {
             class NativeEquationSolverSettings : public ModuleSettings {
             public:
                 // An enumeration of all available methods for solving linear equations.
-                enum class LinearEquationMethod { Jacobi, GaussSeidel, SOR, WalkerChae, Power, SoundPower };
+                enum class LinearEquationMethod { Jacobi, GaussSeidel, SOR, WalkerChae, Power };
                 
                 // An enumeration of all available convergence criteria.
                 enum class ConvergenceCriterion { Absolute, Relative };
@@ -118,6 +118,8 @@ namespace storm {
                 static const std::string powerMethodMultiplicationStyleOptionName;
             };
             
+            std::ostream& operator<<(std::ostream& out, NativeEquationSolverSettings::LinearEquationMethod const& method);
+            
         } // namespace modules
     } // namespace settings
 } // namespace storm
diff --git a/src/storm/solver/EigenLinearEquationSolver.cpp b/src/storm/solver/EigenLinearEquationSolver.cpp
index 5f0a001a9..002352d88 100644
--- a/src/storm/solver/EigenLinearEquationSolver.cpp
+++ b/src/storm/solver/EigenLinearEquationSolver.cpp
@@ -3,6 +3,7 @@
 #include "storm/adapters/EigenAdapter.h"
 
 #include "storm/settings/SettingsManager.h"
+#include "storm/settings/modules/GeneralSettings.h"
 #include "storm/settings/modules/EigenEquationSolverSettings.h"
 
 #include "storm/utility/vector.h"
@@ -16,12 +17,7 @@ namespace storm {
         EigenLinearEquationSolverSettings<ValueType>::EigenLinearEquationSolverSettings() {
             // Get the settings object to customize linear solving.
             storm::settings::modules::EigenEquationSolverSettings const& settings = storm::settings::getModule<storm::settings::modules::EigenEquationSolverSettings>();
-            
-            // Get appropriate settings.
-            maximalNumberOfIterations = settings.getMaximalIterationCount();
-            precision = settings.getPrecision();
-            restart = settings.getRestartIterationCount();
-            
+
             // Determine the method to be used.
             storm::settings::modules::EigenEquationSolverSettings::LinearEquationMethod methodAsSetting = settings.getLinearEquationSystemMethod();
             if (methodAsSetting == storm::settings::modules::EigenEquationSolverSettings::LinearEquationMethod::BiCGSTAB) {
@@ -33,7 +29,7 @@ namespace storm {
             } else if (methodAsSetting == storm::settings::modules::EigenEquationSolverSettings::LinearEquationMethod::GMRES) {
                 method = SolutionMethod::GMRES;
             }
-            
+        
             // Check which preconditioner to use.
             storm::settings::modules::EigenEquationSolverSettings::PreconditioningMethod preconditionAsSetting = settings.getPreconditioningMethod();
             if (preconditionAsSetting == storm::settings::modules::EigenEquationSolverSettings::PreconditioningMethod::Ilu) {
@@ -43,11 +39,22 @@ namespace storm {
             } else if (preconditionAsSetting == storm::settings::modules::EigenEquationSolverSettings::PreconditioningMethod::None) {
                 preconditioner = Preconditioner::None;
             }
+
+            // Get appropriate settings.
+            maximalNumberOfIterations = settings.getMaximalIterationCount();
+            precision = settings.getPrecision();
+            restart = settings.getRestartIterationCount();
+
+            // Finally force soundness and potentially overwrite some other settings.
+            this->setForceSoundness(storm::settings::getModule<storm::settings::modules::GeneralSettings>().isSoundSet());
         }
         
         template<typename ValueType>
         void EigenLinearEquationSolverSettings<ValueType>::setSolutionMethod(SolutionMethod const& method) {
             this->method = method;
+            
+            // Make sure we switch the method if we have to guarantee soundness.
+            this->setForceSoundness(forceSoundness);
         }
         
         template<typename ValueType>
@@ -69,6 +76,15 @@ namespace storm {
         void EigenLinearEquationSolverSettings<ValueType>::setNumberOfIterationsUntilRestart(uint64_t restart) {
             this->restart = restart;
         }
+            
+        template<typename ValueType>
+        void EigenLinearEquationSolverSettings<ValueType>::setForceSoundness(bool value) {
+            forceSoundness = value;
+            if (value) {
+                STORM_LOG_WARN_COND(method != SolutionMethod::SparseLU, "To guarantee soundness, the equation solving technique has been switched to '" << storm::settings::modules::EigenEquationSolverSettings::  LinearEquationMethod::SparseLU << "'.");
+                method = SolutionMethod::SparseLU;
+            }
+        }
         
         template<typename ValueType>
         typename EigenLinearEquationSolverSettings<ValueType>::SolutionMethod EigenLinearEquationSolverSettings<ValueType>::getSolutionMethod() const {
@@ -95,6 +111,11 @@ namespace storm {
             return restart;
         }
         
+        template<typename ValueType>
+        bool EigenLinearEquationSolverSettings<ValueType>::getForceSoundness() const {
+            return forceSoundness;
+        }
+        
 #ifdef STORM_HAVE_CARL
         EigenLinearEquationSolverSettings<storm::RationalNumber>::EigenLinearEquationSolverSettings() {
             // Intentionally left empty.
@@ -135,7 +156,7 @@ namespace storm {
         }
         
         template<typename ValueType>
-        bool EigenLinearEquationSolver<ValueType>::solveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const {
+        bool EigenLinearEquationSolver<ValueType>::internalSolveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const {
             // Map the input vectors to Eigen's format.
             auto eigenX = StormEigen::Matrix<ValueType, StormEigen::Dynamic, 1>::Map(x.data(), x.size());
             auto eigenB = StormEigen::Matrix<ValueType, StormEigen::Dynamic, 1>::Map(b.data(), b.size());
@@ -306,7 +327,7 @@ namespace storm {
         
         template<typename ValueType>
         LinearEquationSolverProblemFormat EigenLinearEquationSolver<ValueType>::getEquationProblemFormat() const {
-            LinearEquationSolverProblemFormat::EquationSystem;
+            return LinearEquationSolverProblemFormat::EquationSystem;
         }
         
         template<typename ValueType>
@@ -327,7 +348,7 @@ namespace storm {
 #ifdef STORM_HAVE_CARL
         // Specialization for storm::RationalNumber
         template<>
-        bool EigenLinearEquationSolver<storm::RationalNumber>::solveEquations(std::vector<storm::RationalNumber>& x, std::vector<storm::RationalNumber> const& b) const {
+        bool EigenLinearEquationSolver<storm::RationalNumber>::internalSolveEquations(std::vector<storm::RationalNumber>& x, std::vector<storm::RationalNumber> const& b) const {
             STORM_LOG_INFO("Solving linear equation system (" << x.size() << " rows) with with rational numbers using LU factorization (Eigen library).");
 
             // Map the input vectors to Eigen's format.
@@ -342,7 +363,7 @@ namespace storm {
         
         // Specialization for storm::RationalFunction
         template<>
-        bool EigenLinearEquationSolver<storm::RationalFunction>::solveEquations(std::vector<storm::RationalFunction>& x, std::vector<storm::RationalFunction> const& b) const {
+        bool EigenLinearEquationSolver<storm::RationalFunction>::internalSolveEquations(std::vector<storm::RationalFunction>& x, std::vector<storm::RationalFunction> const& b) const {
             STORM_LOG_INFO("Solving linear equation system (" << x.size() << " rows) with rational functions using LU factorization (Eigen library).");
 
             // Map the input vectors to Eigen's format.
diff --git a/src/storm/solver/EigenLinearEquationSolver.h b/src/storm/solver/EigenLinearEquationSolver.h
index 951258a76..0bfadd7ca 100644
--- a/src/storm/solver/EigenLinearEquationSolver.h
+++ b/src/storm/solver/EigenLinearEquationSolver.h
@@ -25,14 +25,17 @@ namespace storm {
             void setPrecision(ValueType precision);
             void setMaximalNumberOfIterations(uint64_t maximalNumberOfIterations);
             void setNumberOfIterationsUntilRestart(uint64_t restart);
-
+            void setForceSoundness(bool value);
+            
             SolutionMethod getSolutionMethod() const;
             Preconditioner getPreconditioner() const;
             ValueType getPrecision() const;
             uint64_t getMaximalNumberOfIterations() const;
             uint64_t getNumberOfIterationsUntilRestart() const;
+            bool getForceSoundness() const;
             
         private:
+            bool forceSoundness;
             SolutionMethod method;
             Preconditioner preconditioner;
             double precision;
@@ -67,14 +70,16 @@ namespace storm {
             virtual void setMatrix(storm::storage::SparseMatrix<ValueType> const& A) override;
             virtual void setMatrix(storm::storage::SparseMatrix<ValueType>&& A) override;
             
-            virtual bool solveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const override;
             virtual void multiply(std::vector<ValueType>& x, std::vector<ValueType> const* b, std::vector<ValueType>& result) const override;
 
             EigenLinearEquationSolverSettings<ValueType>& getSettings();
             EigenLinearEquationSolverSettings<ValueType> const& getSettings() const;
             
             virtual LinearEquationSolverProblemFormat getEquationProblemFormat() const override;
-            
+
+        protected:
+            virtual bool internalSolveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const override;
+
         private:
             virtual uint64_t getMatrixRowCount() const override;
             virtual uint64_t getMatrixColumnCount() const override;
diff --git a/src/storm/solver/EliminationLinearEquationSolver.cpp b/src/storm/solver/EliminationLinearEquationSolver.cpp
index 94aba88f5..7bb12d4bd 100644
--- a/src/storm/solver/EliminationLinearEquationSolver.cpp
+++ b/src/storm/solver/EliminationLinearEquationSolver.cpp
@@ -63,9 +63,9 @@ namespace storm {
         }
         
         template<typename ValueType>
-        bool EliminationLinearEquationSolver<ValueType>::solveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const {
+        bool EliminationLinearEquationSolver<ValueType>::internalSolveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const {
             // FIXME: This solver will not work for all input systems. More concretely, the current implementation will
-            // not work for systems that have a 0 on the diagonal. This is not a restriction of this technique in general
+            // not work for systems that have a 1 on the diagonal. This is not a restriction of this technique in general
             // but arbitrary matrices require pivoting, which is not currently implemented.
             
             STORM_LOG_INFO("Solving linear equation system (" << x.size() << " rows) with elimination");
diff --git a/src/storm/solver/EliminationLinearEquationSolver.h b/src/storm/solver/EliminationLinearEquationSolver.h
index 30d0277b0..b99485ce1 100644
--- a/src/storm/solver/EliminationLinearEquationSolver.h
+++ b/src/storm/solver/EliminationLinearEquationSolver.h
@@ -33,13 +33,15 @@ namespace storm {
             virtual void setMatrix(storm::storage::SparseMatrix<ValueType> const& A) override;
             virtual void setMatrix(storm::storage::SparseMatrix<ValueType>&& A) override;
             
-            virtual bool solveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const override;
             virtual void multiply(std::vector<ValueType>& x, std::vector<ValueType> const* b, std::vector<ValueType>& result) const override;
 
             EliminationLinearEquationSolverSettings<ValueType>& getSettings();
             EliminationLinearEquationSolverSettings<ValueType> const& getSettings() const;
             
             virtual LinearEquationSolverProblemFormat getEquationProblemFormat() const override;
+
+        protected:
+            virtual bool internalSolveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const override;
             
         private:
             void initializeSettings();
diff --git a/src/storm/solver/GmmxxLinearEquationSolver.cpp b/src/storm/solver/GmmxxLinearEquationSolver.cpp
index f7aea79a9..2708d0a68 100644
--- a/src/storm/solver/GmmxxLinearEquationSolver.cpp
+++ b/src/storm/solver/GmmxxLinearEquationSolver.cpp
@@ -3,17 +3,19 @@
 #include <cmath>
 #include <utility>
 
+#include "storm/settings/SettingsManager.h"
+#include "storm/settings/modules/GeneralSettings.h"
+#include "storm/settings/modules/GmmxxEquationSolverSettings.h"
+
 #include "storm/adapters/GmmxxAdapter.h"
 
 #include "storm/solver/GmmxxMultiplier.h"
+#include "storm/solver/NativeLinearEquationSolver.h"
 
-#include "storm/settings/SettingsManager.h"
 #include "storm/utility/vector.h"
 #include "storm/utility/constants.h"
 #include "storm/exceptions/InvalidStateException.h"
-#include "storm/settings/modules/GmmxxEquationSolverSettings.h"
-
-#include "storm/solver/NativeLinearEquationSolver.h"
+#include "storm/exceptions/InvalidSolverSettingsException.h"
 
 #include "storm/utility/gmm.h"
 #include "storm/utility/vector.h"
@@ -49,11 +51,17 @@ namespace storm {
             } else if (preconditionAsSetting == storm::settings::modules::GmmxxEquationSolverSettings::PreconditioningMethod::None) {
                 preconditioner = Preconditioner::None;
             }
+            
+            // Finally force soundness and potentially overwrite some other settings.
+            this->setForceSoundness(storm::settings::getModule<storm::settings::modules::GeneralSettings>().isSoundSet());
         }
         
         template<typename ValueType>
         void GmmxxLinearEquationSolverSettings<ValueType>::setSolutionMethod(SolutionMethod const& method) {
             this->method = method;
+            
+            // Make sure we switch the method if we have to guarantee soundness.
+            this->setForceSoundness(forceSoundness);
         }
         
         template<typename ValueType>
@@ -76,6 +84,12 @@ namespace storm {
             this->restart = restart;
         }
         
+        template<typename ValueType>
+        void GmmxxLinearEquationSolverSettings<ValueType>::setForceSoundness(bool value) {
+            STORM_LOG_THROW(!value, storm::exceptions::InvalidSolverSettingsException, "Solver cannot guarantee soundness, please choose a different equation solver.");
+            forceSoundness = value;
+        }
+        
         template<typename ValueType>
         typename GmmxxLinearEquationSolverSettings<ValueType>::SolutionMethod GmmxxLinearEquationSolverSettings<ValueType>::getSolutionMethod() const {
             return method;
@@ -101,6 +115,11 @@ namespace storm {
             return restart;
         }
         
+        template<typename ValueType>
+        bool GmmxxLinearEquationSolverSettings<ValueType>::getForceSoundness() const {
+            return forceSoundness;
+        }
+        
         template<typename ValueType>
         GmmxxLinearEquationSolver<ValueType>::GmmxxLinearEquationSolver(GmmxxLinearEquationSolverSettings<ValueType> const& settings) : settings(settings) {
             // Intentionally left empty.
@@ -129,7 +148,7 @@ namespace storm {
         }
         
         template<typename ValueType>
-        bool GmmxxLinearEquationSolver<ValueType>::solveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const {
+        bool GmmxxLinearEquationSolver<ValueType>::internalSolveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const {
             auto method = this->getSettings().getSolutionMethod();
             auto preconditioner = this->getSettings().getPreconditioner();
             STORM_LOG_INFO("Solving linear equation system (" << x.size() << " rows) with Gmmxx linear equation solver with method '" << method << "' and preconditioner '" << preconditioner << "' (max. " << this->getSettings().getMaximalNumberOfIterations() << " iterations).");
diff --git a/src/storm/solver/GmmxxLinearEquationSolver.h b/src/storm/solver/GmmxxLinearEquationSolver.h
index 95cb10757..453a841e4 100644
--- a/src/storm/solver/GmmxxLinearEquationSolver.h
+++ b/src/storm/solver/GmmxxLinearEquationSolver.h
@@ -19,7 +19,6 @@ namespace storm {
             enum class Preconditioner {
                 Ilu, Diagonal, None
             };
-
             
             friend std::ostream& operator<<(std::ostream& out, Preconditioner const& preconditioner) {
                 switch (preconditioner) {
@@ -51,14 +50,19 @@ namespace storm {
             void setPrecision(ValueType precision);
             void setMaximalNumberOfIterations(uint64_t maximalNumberOfIterations);
             void setNumberOfIterationsUntilRestart(uint64_t restart);
+            void setForceSoundness(bool value);
          
             SolutionMethod getSolutionMethod() const;
             Preconditioner getPreconditioner() const;
             ValueType getPrecision() const;
             uint64_t getMaximalNumberOfIterations() const;
             uint64_t getNumberOfIterationsUntilRestart() const;
+            bool getForceSoundness() const;
             
         private:
+            // Whether or not we are forced to be sound.
+            bool forceSoundness;
+            
             // The method to use for solving linear equation systems.
             SolutionMethod method;
             
@@ -88,7 +92,6 @@ namespace storm {
             virtual void setMatrix(storm::storage::SparseMatrix<ValueType> const& A) override;
             virtual void setMatrix(storm::storage::SparseMatrix<ValueType>&& A) override;
             
-            virtual bool solveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const override;
             virtual void multiply(std::vector<ValueType>& x, std::vector<ValueType> const* b, std::vector<ValueType>& result) const override;
             virtual void multiplyAndReduce(OptimizationDirection const& dir, std::vector<uint64_t> const& rowGroupIndices, std::vector<ValueType>& x, std::vector<ValueType> const* b, std::vector<ValueType>& result, std::vector<uint_fast64_t>* choices = nullptr) const override;
             virtual bool supportsGaussSeidelMultiplication() const override;
@@ -102,6 +105,9 @@ namespace storm {
             
             virtual void clearCache() const override;
 
+        protected:
+            virtual bool internalSolveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const override;
+            
         private:
             virtual uint64_t getMatrixRowCount() const override;
             virtual uint64_t getMatrixColumnCount() const override;
diff --git a/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp b/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp
index 6abfaf270..99561bcfd 100644
--- a/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp
+++ b/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp
@@ -1,12 +1,14 @@
 #include "storm/solver/IterativeMinMaxLinearEquationSolver.h"
 
 #include "storm/settings/SettingsManager.h"
+#include "storm/settings/modules/GeneralSettings.h"
 #include "storm/settings/modules/MinMaxEquationSolverSettings.h"
 
 #include "storm/utility/vector.h"
 #include "storm/utility/macros.h"
 #include "storm/exceptions/InvalidSettingsException.h"
 #include "storm/exceptions/InvalidStateException.h"
+#include "storm/exceptions/UnmetRequirementException.h"
 
 namespace storm {
     namespace solver {
@@ -22,6 +24,9 @@ namespace storm {
             valueIterationMultiplicationStyle = minMaxSettings.getValueIterationMultiplicationStyle();
             
             setSolutionMethod(minMaxSettings.getMinMaxEquationSolvingMethod());
+            
+            // Finally force soundness and potentially overwrite some other settings.
+            this->setForceSoundness(storm::settings::getModule<storm::settings::modules::GeneralSettings>().isSoundSet());
         }
         
         template<typename ValueType>
@@ -60,6 +65,11 @@ namespace storm {
             this->valueIterationMultiplicationStyle = value;
         }
         
+        template<typename ValueType>
+        void IterativeMinMaxLinearEquationSolverSettings<ValueType>::setForceSoundness(bool value) {
+            this->forceSoundness = value;
+        }
+        
         template<typename ValueType>
         typename IterativeMinMaxLinearEquationSolverSettings<ValueType>::SolutionMethod const& IterativeMinMaxLinearEquationSolverSettings<ValueType>::getSolutionMethod() const {
             return solutionMethod;
@@ -84,6 +94,11 @@ namespace storm {
         MultiplicationStyle IterativeMinMaxLinearEquationSolverSettings<ValueType>::getValueIterationMultiplicationStyle() const {
             return valueIterationMultiplicationStyle;
         }
+        
+        template<typename ValueType>
+        bool IterativeMinMaxLinearEquationSolverSettings<ValueType>::getForceSoundness() const {
+            return forceSoundness;
+        }
     
         template<typename ValueType>
         IterativeMinMaxLinearEquationSolver<ValueType>::IterativeMinMaxLinearEquationSolver(std::unique_ptr<LinearEquationSolverFactory<ValueType>>&& linearEquationSolverFactory, IterativeMinMaxLinearEquationSolverSettings<ValueType> const& settings) : StandardMinMaxLinearEquationSolver<ValueType>(std::move(linearEquationSolverFactory)), settings(settings) {
@@ -104,7 +119,11 @@ namespace storm {
         bool IterativeMinMaxLinearEquationSolver<ValueType>::internalSolveEquations(OptimizationDirection dir, std::vector<ValueType>& x, std::vector<ValueType> const& b) const {
             switch (this->getSettings().getSolutionMethod()) {
                 case IterativeMinMaxLinearEquationSolverSettings<ValueType>::SolutionMethod::ValueIteration:
-                    return solveEquationsValueIteration(dir, x, b);
+                    if (this->getSettings().getForceSoundness()) {
+                        return solveEquationsSoundValueIteration(dir, x, b);
+                    } else {
+                        return solveEquationsValueIteration(dir, x, b);
+                    }
                 case IterativeMinMaxLinearEquationSolverSettings<ValueType>::SolutionMethod::PolicyIteration:
                     return solveEquationsPolicyIteration(dir, x, b);
                 case IterativeMinMaxLinearEquationSolverSettings<ValueType>::SolutionMethod::Acyclic:
@@ -229,20 +248,32 @@ namespace storm {
         
         template<typename ValueType>
         MinMaxLinearEquationSolverRequirements IterativeMinMaxLinearEquationSolver<ValueType>::getRequirements(EquationSystemType const& equationSystemType, boost::optional<storm::solver::OptimizationDirection> const& direction) const {
-            MinMaxLinearEquationSolverRequirements requirements;
+            // Start by copying the requirements of the linear equation solver.
+            MinMaxLinearEquationSolverRequirements requirements(this->linearEquationSolverFactory->getRequirements());
             
+            // If we will use sound value iteration, we require no ECs and an upper bound.
+            if (this->getSettings().getSolutionMethod() == IterativeMinMaxLinearEquationSolverSettings<ValueType>::SolutionMethod::ValueIteration && this->getSettings().getForceSoundness()) {
+                requirements.requireNoEndComponents();
+                requirements.requireGlobalUpperBound();
+            }
+            
+            // Then add our requirements on top of that.
             if (equationSystemType == EquationSystemType::UntilProbabilities) {
                 if (this->getSettings().getSolutionMethod() == IterativeMinMaxLinearEquationSolverSettings<ValueType>::SolutionMethod::PolicyIteration) {
                     if (!direction || direction.get() == OptimizationDirection::Maximize) {
-                        requirements.set(MinMaxLinearEquationSolverRequirements::Element::ValidInitialScheduler);
+                        requirements.requireValidInitialScheduler();
                     }
                 }
             } else if (equationSystemType == EquationSystemType::ReachabilityRewards) {
                 if (!direction || direction.get() == OptimizationDirection::Minimize) {
-                    requirements.set(MinMaxLinearEquationSolverRequirements::Element::ValidInitialScheduler);
+                    requirements.requireValidInitialScheduler();
                 }
             }
             
+            if (this->getSettings().getSolutionMethod() == IterativeMinMaxLinearEquationSolverSettings<ValueType>::SolutionMethod::ValueIteration && this->getSettings().getForceSoundness()) {
+                requirements.requireGlobalUpperBound();
+            }
+            
             return requirements;
         }
 
@@ -330,6 +361,105 @@ namespace storm {
             return status == Status::Converged || status == Status::TerminatedEarly;
         }
         
+        template<typename ValueType>
+        bool IterativeMinMaxLinearEquationSolver<ValueType>::solveEquationsSoundValueIteration(OptimizationDirection dir, std::vector<ValueType>& x, std::vector<ValueType> const& b) const {
+            STORM_LOG_THROW(this->hasUpperBound(), storm::exceptions::UnmetRequirementException, "Solver requires upper bound, but none was given.");
+
+            if (!this->linEqSolverA) {
+                this->linEqSolverA = this->linearEquationSolverFactory->create(*this->A);
+                this->linEqSolverA->setCachingEnabled(true);
+            }
+            
+            if (!auxiliaryRowGroupVector) {
+                auxiliaryRowGroupVector = std::make_unique<std::vector<ValueType>>(this->A->getRowGroupCount());
+            }
+            
+            if (this->hasInitialScheduler()) {
+                // Resolve the nondeterminism according to the initial scheduler.
+                bool convertToEquationSystem = this->linearEquationSolverFactory->getEquationProblemFormat() == LinearEquationSolverProblemFormat::EquationSystem;
+                storm::storage::SparseMatrix<ValueType> submatrix = this->A->selectRowsFromRowGroups(this->getInitialScheduler(), convertToEquationSystem);
+                if (convertToEquationSystem) {
+                    submatrix.convertToEquationSystem();
+                }
+                storm::utility::vector::selectVectorValues<ValueType>(*auxiliaryRowGroupVector, this->getInitialScheduler(), this->A->getRowGroupIndices(), b);
+                
+                // Solve the resulting equation system.
+                auto submatrixSolver = this->linearEquationSolverFactory->create(std::move(submatrix));
+                submatrixSolver->setCachingEnabled(true);
+                if (this->lowerBound) {
+                    submatrixSolver->setLowerBound(this->lowerBound.get());
+                }
+                if (this->upperBound) {
+                    submatrixSolver->setUpperBound(this->upperBound.get());
+                }
+                submatrixSolver->solveEquations(x, *auxiliaryRowGroupVector);
+            }
+            
+            // Allow aliased multiplications.
+            bool useGaussSeidelMultiplication = this->linEqSolverA->supportsGaussSeidelMultiplication() && settings.getValueIterationMultiplicationStyle() == storm::solver::MultiplicationStyle::GaussSeidel;
+            
+            std::vector<ValueType>* lowerX = &x;
+            std::vector<ValueType>* upperX = this->auxiliaryRowGroupVector.get();
+            std::vector<ValueType>* tmp;
+            if (!useGaussSeidelMultiplication) {
+                auxiliaryRowGroupVector2 = std::make_unique<std::vector<ValueType>>(lowerX->size());
+                tmp = auxiliaryRowGroupVector2.get();
+            }
+            
+            // Proceed with the iterations as long as the method did not converge or reach the maximum number of iterations.
+            uint64_t iterations = 0;
+            
+            Status status = Status::InProgress;
+            while (status == Status::InProgress && iterations < this->getSettings().getMaximalNumberOfIterations()) {
+                // Compute x' = min/max(A*x + b).
+                if (useGaussSeidelMultiplication) {
+                    this->linEqSolverA->multiplyAndReduceGaussSeidel(dir, this->A->getRowGroupIndices(), *lowerX, &b);
+                    this->linEqSolverA->multiplyAndReduceGaussSeidel(dir, this->A->getRowGroupIndices(), *upperX, &b);
+                } else {
+                    this->linEqSolverA->multiplyAndReduce(dir, this->A->getRowGroupIndices(), *lowerX, &b, *tmp);
+                    std::swap(lowerX, tmp);
+                    this->linEqSolverA->multiplyAndReduce(dir, this->A->getRowGroupIndices(), *upperX, &b, *tmp);
+                    std::swap(upperX, tmp);
+                }
+                
+                // Determine whether the method converged.
+                if (storm::utility::vector::equalModuloPrecision<ValueType>(*lowerX, *upperX, storm::utility::convertNumber<ValueType>(2.0) * this->getSettings().getPrecision(), false)) {
+                    status = Status::Converged;
+                }
+                
+                // Update environment variables.
+                ++iterations;
+            }
+            
+            if (status != Status::Converged) {
+                status = Status::MaximalIterationsExceeded;
+            }
+            
+            reportStatus(status, iterations);
+            
+            // We take the means of the lower and upper bound so we guarantee the desired precision.
+            storm::utility::vector::applyPointwise(*lowerX, *upperX, *lowerX, [] (ValueType const& a, ValueType const& b) { return (a + b) / storm::utility::convertNumber<ValueType>(2.0); });
+            
+            // Since we shuffled the pointer around, we need to write the actual results to the input/output vector x.
+            if (&x == tmp) {
+                std::swap(x, *tmp);
+            } else if (&x == this->auxiliaryRowGroupVector.get()) {
+                std::swap(x, *this->auxiliaryRowGroupVector);
+            }
+            
+            // If requested, we store the scheduler for retrieval.
+            if (this->isTrackSchedulerSet()) {
+                this->schedulerChoices = std::vector<uint_fast64_t>(this->A->getRowGroupCount());
+                this->linEqSolverA->multiplyAndReduce(dir, this->A->getRowGroupIndices(), x, &b, *this->auxiliaryRowGroupVector, &this->schedulerChoices.get());
+            }
+            
+            if (!this->isCachingEnabled()) {
+                clearCache();
+            }
+            
+            return status == Status::Converged;
+        }
+        
         template<typename ValueType>
         bool IterativeMinMaxLinearEquationSolver<ValueType>::solveEquationsAcyclic(OptimizationDirection dir, std::vector<ValueType>& x, std::vector<ValueType> const& b) const {
             uint64_t numGroups = this->A->getRowGroupCount();
@@ -473,6 +603,7 @@ namespace storm {
         template<typename ValueType>
         void IterativeMinMaxLinearEquationSolver<ValueType>::clearCache() const {
             auxiliaryRowGroupVector.reset();
+            auxiliaryRowGroupVector2.reset();
             rowGroupOrdering.reset();
             StandardMinMaxLinearEquationSolver<ValueType>::clearCache();
         }
diff --git a/src/storm/solver/IterativeMinMaxLinearEquationSolver.h b/src/storm/solver/IterativeMinMaxLinearEquationSolver.h
index 81b2d722f..b2b10ef29 100644
--- a/src/storm/solver/IterativeMinMaxLinearEquationSolver.h
+++ b/src/storm/solver/IterativeMinMaxLinearEquationSolver.h
@@ -23,14 +23,17 @@ namespace storm {
             void setRelativeTerminationCriterion(bool value);
             void setPrecision(ValueType precision);
             void setValueIterationMultiplicationStyle(MultiplicationStyle value);
-
+            void setForceSoundness(bool value);
+            
             SolutionMethod const& getSolutionMethod() const;
             uint64_t getMaximalNumberOfIterations() const;
             ValueType getPrecision() const;
             bool getRelativeTerminationCriterion() const;
             MultiplicationStyle getValueIterationMultiplicationStyle() const;
+            bool getForceSoundness() const;
             
         private:
+            bool forceSoundness;
             SolutionMethod solutionMethod;
             uint64_t maximalNumberOfIterations;
             ValueType precision;
@@ -60,6 +63,7 @@ namespace storm {
         private:
             bool solveEquationsPolicyIteration(OptimizationDirection dir, std::vector<ValueType>& x, std::vector<ValueType> const& b) const;
             bool solveEquationsValueIteration(OptimizationDirection dir, std::vector<ValueType>& x, std::vector<ValueType> const& b) const;
+            bool solveEquationsSoundValueIteration(OptimizationDirection dir, std::vector<ValueType>& x, std::vector<ValueType> const& b) const;
             bool solveEquationsAcyclic(OptimizationDirection dir, std::vector<ValueType>& x, std::vector<ValueType> const& b) const;
 
             bool valueImproved(OptimizationDirection dir, ValueType const& value1, ValueType const& value2) const;
@@ -72,6 +76,7 @@ namespace storm {
             
             // possibly cached data
             mutable std::unique_ptr<std::vector<ValueType>> auxiliaryRowGroupVector; // A.rowGroupCount() entries
+            mutable std::unique_ptr<std::vector<ValueType>> auxiliaryRowGroupVector2; // A.rowGroupCount() entries
             mutable std::unique_ptr<std::vector<uint64_t>> rowGroupOrdering; // A.rowGroupCount() entries
             
             Status updateStatusIfNotConverged(Status status, std::vector<ValueType> const& x, uint64_t iterations) const;
diff --git a/src/storm/solver/LinearEquationSolver.cpp b/src/storm/solver/LinearEquationSolver.cpp
index 2efc90f8f..f9da0758d 100644
--- a/src/storm/solver/LinearEquationSolver.cpp
+++ b/src/storm/solver/LinearEquationSolver.cpp
@@ -23,6 +23,11 @@ namespace storm {
             // Intentionally left empty.
         }
         
+        template<typename ValueType>
+        bool LinearEquationSolver<ValueType>::solveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const {
+            return this->internalSolveEquations(x, b);
+        }
+        
         template<typename ValueType>
         void LinearEquationSolver<ValueType>::repeatedMultiply(std::vector<ValueType>& x, std::vector<ValueType> const* b, uint_fast64_t n) const {
             if (!cachedRowVector) {
@@ -101,6 +106,11 @@ namespace storm {
             STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "This solver does not support the function 'multiplyAndReduceGaussSeidel'.");
         }
         
+        template<typename ValueType>
+        LinearEquationSolverRequirements LinearEquationSolver<ValueType>::getRequirements() const {
+            return LinearEquationSolverRequirements();
+        }
+        
         template<typename ValueType>
         void LinearEquationSolver<ValueType>::setCachingEnabled(bool value) const {
             if(cachingEnabled && !value) {
@@ -136,6 +146,26 @@ namespace storm {
             setUpperBound(upper);
         }
         
+        template<typename ValueType>
+        bool LinearEquationSolver<ValueType>::hasLowerBound() const {
+            return static_cast<bool>(lowerBound);
+        }
+        
+        template<typename ValueType>
+        bool LinearEquationSolver<ValueType>::hasUpperBound() const {
+            return static_cast<bool>(upperBound);
+        }
+        
+        template<typename ValueType>
+        ValueType const& LinearEquationSolver<ValueType>::getLowerBound() const {
+            return lowerBound.get();
+        }
+        
+        template<typename ValueType>
+        ValueType const& LinearEquationSolver<ValueType>::getUpperBound() const {
+            return upperBound.get();
+        }
+        
         template<typename ValueType>
         std::unique_ptr<LinearEquationSolver<ValueType>> LinearEquationSolverFactory<ValueType>::create(storm::storage::SparseMatrix<ValueType> const& matrix) const {
             std::unique_ptr<LinearEquationSolver<ValueType>> solver = this->create();
@@ -155,6 +185,11 @@ namespace storm {
             return this->create()->getEquationProblemFormat();
         }
         
+        template<typename ValueType>
+        LinearEquationSolverRequirements LinearEquationSolverFactory<ValueType>::getRequirements() const {
+            return this->create()->getRequirements();
+        }
+        
         template<typename ValueType>
         std::unique_ptr<LinearEquationSolver<ValueType>> GeneralLinearEquationSolverFactory<ValueType>::create() const {
             EquationSolverType equationSolver = storm::settings::getModule<storm::settings::modules::CoreSettings>().getEquationSolver();
diff --git a/src/storm/solver/LinearEquationSolver.h b/src/storm/solver/LinearEquationSolver.h
index aa14226bf..1aa0a0fa4 100644
--- a/src/storm/solver/LinearEquationSolver.h
+++ b/src/storm/solver/LinearEquationSolver.h
@@ -7,6 +7,7 @@
 #include "storm/solver/AbstractEquationSolver.h"
 #include "storm/solver/MultiplicationStyle.h"
 #include "storm/solver/LinearEquationSolverProblemFormat.h"
+#include "storm/solver/LinearEquationSolverRequirements.h"
 #include "storm/solver/OptimizationDirection.h"
 
 #include "storm/utility/VectorHelper.h"
@@ -47,7 +48,7 @@ namespace storm {
              *
              * @return true
              */
-            virtual bool solveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const = 0;
+            bool solveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const;
 
             /*!
              * Performs on matrix-vector multiplication x' = A*x + b.
@@ -127,6 +128,12 @@ namespace storm {
              */
             virtual LinearEquationSolverProblemFormat getEquationProblemFormat() const = 0;
             
+            /*!
+             * Retrieves the requirements of the solver under the current settings. Note that these requirements only
+             * apply to solving linear equations and not to the matrix vector multiplications.
+             */
+            virtual LinearEquationSolverRequirements getRequirements() const;
+            
             /*!
              * Sets whether some of the generated data during solver calls should be cached.
              * This possibly increases the runtime of subsequent calls but also increases memory consumption.
@@ -153,12 +160,34 @@ namespace storm {
              */
             void setUpperBound(ValueType const& value);
 
+            /*!
+             * Retrieves the lower bound (if there is any).
+             */
+            ValueType const& getLowerBound() const;
+            
+            /*!
+             * Retrieves the lower bound (if there is any).
+             */
+            ValueType const& getUpperBound() const;
+            
+            /*!
+             * Retrieves whether this solver has a lower bound.
+             */
+            bool hasLowerBound() const;
+
+            /*!
+             * Retrieves whether this solver has an upper bound.
+             */
+            bool hasUpperBound() const;
+
             /*!
              * Sets bounds for the solution that can potentially be used by the solver.
              */
             void setBounds(ValueType const& lower, ValueType const& upper);
 
         protected:
+            virtual bool internalSolveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const = 0;
+            
             // auxiliary storage. If set, this vector has getMatrixRowCount() entries.
             mutable std::unique_ptr<std::vector<ValueType>> cachedRowVector;
             
@@ -220,6 +249,12 @@ namespace storm {
              * Retrieves the problem format that the solver expects if it was created with the current settings.
              */
             virtual LinearEquationSolverProblemFormat getEquationProblemFormat() const;
+            
+            /*!
+             * Retrieves the requirements of the solver if it was created with the current settings. Note that these
+             * requirements only apply to solving linear equations and not to the matrix vector multiplications.
+             */
+            LinearEquationSolverRequirements getRequirements() const;
         };
 
         template<typename ValueType>
diff --git a/src/storm/solver/LinearEquationSolverRequirements.cpp b/src/storm/solver/LinearEquationSolverRequirements.cpp
new file mode 100644
index 000000000..3d1b34ee9
--- /dev/null
+++ b/src/storm/solver/LinearEquationSolverRequirements.cpp
@@ -0,0 +1,48 @@
+#include "storm/solver/LinearEquationSolverRequirements.h"
+
+namespace storm {
+    namespace solver {
+        
+        LinearEquationSolverRequirements::LinearEquationSolverRequirements() : globalLowerBound(false), globalUpperBound(false) {
+            // Intentionally left empty.
+        }
+        
+        LinearEquationSolverRequirements& LinearEquationSolverRequirements::requireGlobalLowerBound() {
+            globalLowerBound = true;
+            return *this;
+        }
+        
+        LinearEquationSolverRequirements& LinearEquationSolverRequirements::requireGlobalUpperBound() {
+            globalUpperBound = true;
+            return *this;
+        }
+        
+        bool LinearEquationSolverRequirements::requiresGlobalLowerBound() const {
+            return globalLowerBound;
+        }
+        
+        bool LinearEquationSolverRequirements::requiresGlobalUpperBound() const {
+            return globalUpperBound;
+        }
+        
+        bool LinearEquationSolverRequirements::requires(Element const& element) const {
+            switch (element) {
+                case Element::GlobalLowerBound: return globalLowerBound; break;
+                case Element::GlobalUpperBound: return globalUpperBound; break;
+            }
+        }
+        
+        void LinearEquationSolverRequirements::clearGlobalLowerBound() {
+            globalLowerBound = false;
+        }
+        
+        void LinearEquationSolverRequirements::clearGlobalUpperBound() {
+            globalUpperBound = false;
+        }
+        
+        bool LinearEquationSolverRequirements::empty() const {
+            return !globalLowerBound && !globalUpperBound;
+        }
+        
+    }
+}
diff --git a/src/storm/solver/LinearEquationSolverRequirements.h b/src/storm/solver/LinearEquationSolverRequirements.h
new file mode 100644
index 000000000..d07c6a764
--- /dev/null
+++ b/src/storm/solver/LinearEquationSolverRequirements.h
@@ -0,0 +1,35 @@
+#pragma once
+
+namespace storm {
+    namespace solver {
+        
+        class LinearEquationSolverRequirements {
+        public:
+            // The different requirements a solver can have.
+            enum class Element {
+                // Requirements that are related to bounds for the actual solution.
+                GlobalLowerBound,
+                GlobalUpperBound
+            };
+            
+            LinearEquationSolverRequirements();
+            
+            LinearEquationSolverRequirements& requireGlobalLowerBound();
+            LinearEquationSolverRequirements& requireGlobalUpperBound();
+            
+            bool requiresGlobalLowerBound() const;
+            bool requiresGlobalUpperBound() const;
+            bool requires(Element const& element) const;
+            
+            void clearGlobalLowerBound();
+            void clearGlobalUpperBound();
+            
+            bool empty() const;
+            
+        private:
+            bool globalLowerBound;
+            bool globalUpperBound;
+        };
+        
+    }
+}
diff --git a/src/storm/solver/MinMaxLinearEquationSolver.cpp b/src/storm/solver/MinMaxLinearEquationSolver.cpp
index 5fb4fe38b..a61307047 100644
--- a/src/storm/solver/MinMaxLinearEquationSolver.cpp
+++ b/src/storm/solver/MinMaxLinearEquationSolver.cpp
@@ -127,6 +127,26 @@ namespace storm {
             setUpperBound(upper);
         }
         
+        template<typename ValueType>
+        bool MinMaxLinearEquationSolver<ValueType>::hasUpperBound() const {
+            return static_cast<bool>(upperBound);
+        }
+        
+        template<typename ValueType>
+        bool MinMaxLinearEquationSolver<ValueType>::hasLowerBound() const {
+            return static_cast<bool>(lowerBound);
+        }
+
+        template<typename ValueType>
+        ValueType const& MinMaxLinearEquationSolver<ValueType>::getUpperBound() const {
+            return upperBound.get();
+        }
+        
+        template<typename ValueType>
+        ValueType const& MinMaxLinearEquationSolver<ValueType>::getLowerBound() const {
+            return lowerBound.get();
+        }
+        
         template<typename ValueType>
         void MinMaxLinearEquationSolver<ValueType>::setInitialScheduler(std::vector<uint_fast64_t>&& choices) {
             initialScheduler = std::move(choices);
diff --git a/src/storm/solver/MinMaxLinearEquationSolver.h b/src/storm/solver/MinMaxLinearEquationSolver.h
index 2d8ee350d..c05b2f13f 100644
--- a/src/storm/solver/MinMaxLinearEquationSolver.h
+++ b/src/storm/solver/MinMaxLinearEquationSolver.h
@@ -150,7 +150,27 @@ namespace storm {
              * Sets bounds for the solution that can potentially used by the solver.
              */
             void setBounds(ValueType const& lower, ValueType const& upper);
+
+            /*!
+             * Retrieves whether the solver has an upper bound.
+             */
+            bool hasUpperBound() const;
+            
+            /*!
+             * Retrieves whether the solver has a lower bound.
+             */
+            bool hasLowerBound() const;
+
+            /*!
+             * Retrieves the upper bound (if this solver has any).
+             */
+            ValueType const& getUpperBound() const;
             
+            /*!
+             * Retrieves the upper bound (if this solver has any).
+             */
+            ValueType const& getLowerBound() const;
+
             /*!
              * Sets a valid initial scheduler that is required by some solvers (see requirements of solvers).
              */
diff --git a/src/storm/solver/MinMaxLinearEquationSolverRequirements.cpp b/src/storm/solver/MinMaxLinearEquationSolverRequirements.cpp
index 07560601d..a90907ff8 100644
--- a/src/storm/solver/MinMaxLinearEquationSolverRequirements.cpp
+++ b/src/storm/solver/MinMaxLinearEquationSolverRequirements.cpp
@@ -3,58 +3,74 @@
 namespace storm {
     namespace solver {
         
-        MinMaxLinearEquationSolverRequirements::MinMaxLinearEquationSolverRequirements() : noEndComponents(false), noZeroRewardEndComponents(false), validInitialScheduler(false), globalLowerBound(false), globalUpperBound(false) {
+        MinMaxLinearEquationSolverRequirements::MinMaxLinearEquationSolverRequirements(LinearEquationSolverRequirements const& linearEquationSolverRequirements) : noEndComponents(false), validInitialScheduler(false), globalLowerBound(linearEquationSolverRequirements.requiresGlobalLowerBound()), globalUpperBound(linearEquationSolverRequirements.requiresGlobalUpperBound()) {
             // Intentionally left empty.
         }
         
-        MinMaxLinearEquationSolverRequirements& MinMaxLinearEquationSolverRequirements::setNoEndComponents(bool value) {
-            noEndComponents = value;
+        MinMaxLinearEquationSolverRequirements& MinMaxLinearEquationSolverRequirements::requireNoEndComponents() {
+            noEndComponents = true;
             return *this;
         }
         
-        MinMaxLinearEquationSolverRequirements& MinMaxLinearEquationSolverRequirements::setNoZeroRewardEndComponents(bool value) {
-            noZeroRewardEndComponents = value;
+        MinMaxLinearEquationSolverRequirements& MinMaxLinearEquationSolverRequirements::requireValidInitialScheduler() {
+            validInitialScheduler = true;
             return *this;
         }
         
-        MinMaxLinearEquationSolverRequirements& MinMaxLinearEquationSolverRequirements::setValidInitialScheduler(bool value) {
-            validInitialScheduler = value;
+        MinMaxLinearEquationSolverRequirements& MinMaxLinearEquationSolverRequirements::requireGlobalLowerBound() {
+            globalLowerBound = true;
             return *this;
         }
         
-        MinMaxLinearEquationSolverRequirements& MinMaxLinearEquationSolverRequirements::setGlobalLowerBound(bool value) {
-            globalLowerBound = value;
+        MinMaxLinearEquationSolverRequirements& MinMaxLinearEquationSolverRequirements::requireGlobalUpperBound() {
+            globalUpperBound = true;
             return *this;
         }
         
-        MinMaxLinearEquationSolverRequirements& MinMaxLinearEquationSolverRequirements::setGlobalUpperBound(bool value) {
-            globalUpperBound = value;
-            return *this;
+        bool MinMaxLinearEquationSolverRequirements::requiresNoEndComponents() const {
+            return noEndComponents;
         }
         
-        MinMaxLinearEquationSolverRequirements& MinMaxLinearEquationSolverRequirements::set(Element const& element, bool value) {
-            switch (element) {
-                case Element::NoEndComponents: noEndComponents = value; break;
-                case Element::NoZeroRewardEndComponents: noZeroRewardEndComponents = value; break;
-                case Element::ValidInitialScheduler: validInitialScheduler = value; break;
-                case Element::GlobalLowerBound: globalLowerBound = value; break;
-                case Element::GlobalUpperBound: globalUpperBound = value; break;
-            }
-            return *this;
+        bool MinMaxLinearEquationSolverRequirements::requiresValidIntialScheduler() const {
+            return validInitialScheduler;
+        }
+        
+        bool MinMaxLinearEquationSolverRequirements::requiresGlobalLowerBound() const {
+            return globalLowerBound;
+        }
+        
+        bool MinMaxLinearEquationSolverRequirements::requiresGlobalUpperBound() const {
+            return globalUpperBound;
         }
         
-        bool MinMaxLinearEquationSolverRequirements::requires(Element const& element) {
+        bool MinMaxLinearEquationSolverRequirements::requires(Element const& element) const {
             switch (element) {
                 case Element::NoEndComponents: return noEndComponents; break;
-                case Element::NoZeroRewardEndComponents: return noZeroRewardEndComponents; break;
                 case Element::ValidInitialScheduler: return validInitialScheduler; break;
                 case Element::GlobalLowerBound: return globalLowerBound; break;
                 case Element::GlobalUpperBound: return globalUpperBound; break;
             }
         }
         
+        void MinMaxLinearEquationSolverRequirements::clearNoEndComponents() {
+            noEndComponents = false;
+            validInitialScheduler = false;
+        }
+        
+        void MinMaxLinearEquationSolverRequirements::clearValidInitialScheduler() {
+            validInitialScheduler = false;
+        }
+        
+        void MinMaxLinearEquationSolverRequirements::clearGlobalLowerBound() {
+            globalLowerBound = false;
+        }
+        
+        void MinMaxLinearEquationSolverRequirements::clearGlobalUpperBound() {
+            globalUpperBound = false;
+        }
+        
         bool MinMaxLinearEquationSolverRequirements::empty() const {
-            return !noEndComponents && !noZeroRewardEndComponents && !validInitialScheduler && !globalLowerBound && !globalUpperBound;
+            return !noEndComponents && !validInitialScheduler && !globalLowerBound && !globalUpperBound;
         }
         
     }
diff --git a/src/storm/solver/MinMaxLinearEquationSolverRequirements.h b/src/storm/solver/MinMaxLinearEquationSolverRequirements.h
index 6cb4e025c..4dfb9f2aa 100644
--- a/src/storm/solver/MinMaxLinearEquationSolverRequirements.h
+++ b/src/storm/solver/MinMaxLinearEquationSolverRequirements.h
@@ -1,30 +1,47 @@
 #pragma once
 
+#include "storm/solver/LinearEquationSolverRequirements.h"
+
 namespace storm {
     namespace solver {
         
         class MinMaxLinearEquationSolverRequirements {
         public:
+            // The different requirements a solver can have.
             enum class Element {
-                NoEndComponents, NoZeroRewardEndComponents, ValidInitialScheduler, GlobalLowerBound, GlobalUpperBound
+                // Requirements that are related to the graph structure of the system. Note that the requirements in this
+                // category are to be interpreted incrementally in the following sense: whenever the system has no end
+                // components then automatically both requirements are fulfilled.
+                NoEndComponents,
+                ValidInitialScheduler,
+                
+                // Requirements that are related to bounds for the actual solution.
+                GlobalLowerBound,
+                GlobalUpperBound
             };
             
-            MinMaxLinearEquationSolverRequirements();
+            MinMaxLinearEquationSolverRequirements(LinearEquationSolverRequirements const& linearEquationSolverRequirements = LinearEquationSolverRequirements());
             
-            MinMaxLinearEquationSolverRequirements& setNoEndComponents(bool value = true);
-            MinMaxLinearEquationSolverRequirements& setNoZeroRewardEndComponents(bool value = true);
-            MinMaxLinearEquationSolverRequirements& setValidInitialScheduler(bool value = true);
-            MinMaxLinearEquationSolverRequirements& setGlobalLowerBound(bool value = true);
-            MinMaxLinearEquationSolverRequirements& setGlobalUpperBound(bool value = true);
-            MinMaxLinearEquationSolverRequirements& set(Element const& element, bool value = true);
+            MinMaxLinearEquationSolverRequirements& requireNoEndComponents();
+            MinMaxLinearEquationSolverRequirements& requireValidInitialScheduler();
+            MinMaxLinearEquationSolverRequirements& requireGlobalLowerBound();
+            MinMaxLinearEquationSolverRequirements& requireGlobalUpperBound();
+
+            bool requiresNoEndComponents() const;
+            bool requiresValidIntialScheduler() const;
+            bool requiresGlobalLowerBound() const;
+            bool requiresGlobalUpperBound() const;
+            bool requires(Element const& element) const;
             
-            bool requires(Element const& element);
+            void clearNoEndComponents();
+            void clearValidInitialScheduler();
+            void clearGlobalLowerBound();
+            void clearGlobalUpperBound();
             
             bool empty() const;
             
         private:
             bool noEndComponents;
-            bool noZeroRewardEndComponents;
             bool validInitialScheduler;
             bool globalLowerBound;
             bool globalUpperBound;
diff --git a/src/storm/solver/NativeLinearEquationSolver.cpp b/src/storm/solver/NativeLinearEquationSolver.cpp
index fa2dbc237..30fe62228 100644
--- a/src/storm/solver/NativeLinearEquationSolver.cpp
+++ b/src/storm/solver/NativeLinearEquationSolver.cpp
@@ -3,12 +3,14 @@
 #include <utility>
 
 #include "storm/settings/SettingsManager.h"
+#include "storm/settings/modules/GeneralSettings.h"
 #include "storm/settings/modules/NativeEquationSolverSettings.h"
 
 #include "storm/utility/constants.h"
 #include "storm/utility/vector.h"
 #include "storm/exceptions/InvalidStateException.h"
 #include "storm/exceptions/InvalidSettingsException.h"
+#include "storm/exceptions/UnmetRequirementException.h"
 
 namespace storm {
     namespace solver {
@@ -28,22 +30,26 @@ namespace storm {
                 method = SolutionMethod::WalkerChae;
             } else if (methodAsSetting == storm::settings::modules::NativeEquationSolverSettings::LinearEquationMethod::Power) {
                 method = SolutionMethod::Power;
-            } else if (methodAsSetting == storm::settings::modules::NativeEquationSolverSettings::LinearEquationMethod::SoundPower) {
-                method = SolutionMethod::SoundPower;
             } else {
                 STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "The selected solution technique is invalid for this solver.");
             }
-            
+        
             maximalNumberOfIterations = settings.getMaximalIterationCount();
             precision = settings.getPrecision();
             relative = settings.getConvergenceCriterion() == storm::settings::modules::NativeEquationSolverSettings::ConvergenceCriterion::Relative;
             omega = settings.getOmega();
             multiplicationStyle = settings.getPowerMethodMultiplicationStyle();
+                                    
+            // Finally force soundness and potentially overwrite some other settings.
+            this->setForceSoundness(storm::settings::getModule<storm::settings::modules::GeneralSettings>().isSoundSet());
         }
         
         template<typename ValueType>
         void NativeLinearEquationSolverSettings<ValueType>::setSolutionMethod(SolutionMethod const& method) {
             this->method = method;
+            
+            // Make sure we switch the method if we have to guarantee soundness.
+            this->setForceSoundness(forceSoundness);
         }
         
         template<typename ValueType>
@@ -71,6 +77,15 @@ namespace storm {
             this->multiplicationStyle = value;
         }
         
+        template<typename ValueType>
+        void NativeLinearEquationSolverSettings<ValueType>::setForceSoundness(bool value) {
+            forceSoundness = value;
+            if (forceSoundness) {
+                STORM_LOG_WARN_COND(method != SolutionMethod::Power, "To guarantee soundness, the equation solving technique has been switched to '" << storm::settings::modules::NativeEquationSolverSettings::LinearEquationMethod::Power << "'.");
+                method = SolutionMethod::Power;
+            }
+        }
+        
         template<typename ValueType>
         typename NativeLinearEquationSolverSettings<ValueType>::SolutionMethod NativeLinearEquationSolverSettings<ValueType>::getSolutionMethod() const {
             return method;
@@ -101,6 +116,11 @@ namespace storm {
             return multiplicationStyle;
         }
 
+        template<typename ValueType>
+        bool NativeLinearEquationSolverSettings<ValueType>::getForceSoundness() const {
+            return forceSoundness;
+        }
+        
         template<typename ValueType>
         NativeLinearEquationSolver<ValueType>::NativeLinearEquationSolver(NativeLinearEquationSolverSettings<ValueType> const& settings) : localA(nullptr), A(nullptr), settings(settings) {
             // Intentionally left empty.
@@ -410,11 +430,69 @@ namespace storm {
         
         template<typename ValueType>
         bool NativeLinearEquationSolver<ValueType>::solveEquationsSoundPower(std::vector<ValueType>& x, std::vector<ValueType> const& b) const {
-            // TODO
+            STORM_LOG_THROW(this->hasUpperBound(), storm::exceptions::UnmetRequirementException, "Solver requires upper bound, but none was given.");
+            STORM_LOG_INFO("Solving linear equation system (" << x.size() << " rows) with NativeLinearEquationSolver (SoundPower)");
+            
+            std::vector<ValueType>* lowerX = &x;
+            if (!this->cachedRowVector) {
+                this->cachedRowVector = std::make_unique<std::vector<ValueType>>(getMatrixRowCount(), this->getUpperBound());
+            }
+            std::vector<ValueType>* upperX = this->cachedRowVector.get();
+            
+            bool useGaussSeidelMultiplication = this->getSettings().getPowerMethodMultiplicationStyle() == storm::solver::MultiplicationStyle::GaussSeidel;
+            std::vector<ValueType>* tmp;
+            if (!useGaussSeidelMultiplication) {
+                cachedRowVector2 = std::make_unique<std::vector<ValueType>>(x.size());
+                tmp = cachedRowVector2.get();
+            }
+            
+            bool converged = false;
+            uint64_t iterations = 0;
+            while (!converged && iterations < this->getSettings().getMaximalNumberOfIterations()) {
+                if (useGaussSeidelMultiplication) {
+                    this->multiplier.multAddGaussSeidelBackward(*this->A, *lowerX, &b);
+                    this->multiplier.multAddGaussSeidelBackward(*this->A, *upperX, &b);
+                } else {
+                    this->multiplier.multAdd(*this->A, *lowerX, &b, *tmp);
+                    std::swap(tmp, lowerX);
+                    this->multiplier.multAdd(*this->A, *upperX, &b, *tmp);
+                    std::swap(tmp, upperX);
+                }
+                
+                // Now check if the process already converged within our precision. Note that we double the target
+                // precision here. Doing so, we need to take the means of the lower and upper values later to guarantee
+                // the original precision.
+                converged = storm::utility::vector::equalModuloPrecision<ValueType>(*lowerX, *upperX, storm::utility::convertNumber<ValueType>(2.0) * static_cast<ValueType>(this->getSettings().getPrecision()), false);
+                
+                // Set up next iteration.
+                ++iterations;
+            }
+            
+            // We take the means of the lower and upper bound so we guarantee the desired precision.
+            storm::utility::vector::applyPointwise(*lowerX, *upperX, *lowerX, [] (ValueType const& a, ValueType const& b) { return (a + b) / storm::utility::convertNumber<ValueType>(2.0); });
+
+            // Since we shuffled the pointer around, we need to write the actual results to the input/output vector x.
+            if (&x == tmp) {
+                std::swap(x, *tmp);
+            } else if (&x == this->cachedRowVector.get()) {
+                std::swap(x, *this->cachedRowVector);
+            }
+            
+            if (!this->isCachingEnabled()) {
+                clearCache();
+            }
+            
+            if (converged) {
+                STORM_LOG_INFO("Iterative solver converged in " << iterations << " iterations.");
+            } else {
+                STORM_LOG_WARN("Iterative solver did not converge in " << iterations << " iterations.");
+            }
+            
+            return converged;
         }
         
         template<typename ValueType>
-        bool NativeLinearEquationSolver<ValueType>::solveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const {
+        bool NativeLinearEquationSolver<ValueType>::internalSolveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const {
             if (this->getSettings().getSolutionMethod() == NativeLinearEquationSolverSettings<ValueType>::SolutionMethod::SOR || this->getSettings().getSolutionMethod() == NativeLinearEquationSolverSettings<ValueType>::SolutionMethod::GaussSeidel) {
                 return this->solveEquationsSOR(x, b, this->getSettings().getSolutionMethod() == NativeLinearEquationSolverSettings<ValueType>::SolutionMethod::SOR ? this->getSettings().getOmega() : storm::utility::one<ValueType>());
             } else if (this->getSettings().getSolutionMethod() == NativeLinearEquationSolverSettings<ValueType>::SolutionMethod::Jacobi) {
@@ -422,7 +500,11 @@ namespace storm {
             } else if (this->getSettings().getSolutionMethod() == NativeLinearEquationSolverSettings<ValueType>::SolutionMethod::WalkerChae) {
                 return this->solveEquationsWalkerChae(x, b);
             } else if (this->getSettings().getSolutionMethod() == NativeLinearEquationSolverSettings<ValueType>::SolutionMethod::Power) {
-                return this->solveEquationsPower(x, b);
+                if (this->getSettings().getForceSoundness()) {
+                    return this->solveEquationsSoundPower(x, b);
+                } else {
+                    return this->solveEquationsPower(x, b);
+                }
             }
             
             STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "Unknown solving technique.");
@@ -495,7 +577,7 @@ namespace storm {
         
         template<typename ValueType>
         LinearEquationSolverProblemFormat NativeLinearEquationSolver<ValueType>::getEquationProblemFormat() const {
-            if (this->getSettings().getSolutionMethod() == NativeLinearEquationSolverSettings<ValueType>::SolutionMethod::Power || this->getSettings().getSolutionMethod() == NativeLinearEquationSolverSettings<ValueType>::SolutionMethod::SoundPower) {
+            if (this->getSettings().getSolutionMethod() == NativeLinearEquationSolverSettings<ValueType>::SolutionMethod::Power) {
                 return LinearEquationSolverProblemFormat::FixedPointSystem;
             } else {
                 return LinearEquationSolverProblemFormat::EquationSystem;
@@ -505,6 +587,7 @@ namespace storm {
         template<typename ValueType>
         void NativeLinearEquationSolver<ValueType>::clearCache() const {
             jacobiDecomposition.reset();
+            cachedRowVector2.reset();
             walkerChaeData.reset();
             LinearEquationSolver<ValueType>::clearCache();
         }
diff --git a/src/storm/solver/NativeLinearEquationSolver.h b/src/storm/solver/NativeLinearEquationSolver.h
index 678aab555..c252b86b3 100644
--- a/src/storm/solver/NativeLinearEquationSolver.h
+++ b/src/storm/solver/NativeLinearEquationSolver.h
@@ -14,7 +14,7 @@ namespace storm {
         class NativeLinearEquationSolverSettings {
         public:
             enum class SolutionMethod {
-                Jacobi, GaussSeidel, SOR, WalkerChae, Power, SoundPower
+                Jacobi, GaussSeidel, SOR, WalkerChae, Power
             };
 
             NativeLinearEquationSolverSettings();
@@ -25,15 +25,18 @@ namespace storm {
             void setRelativeTerminationCriterion(bool value);
             void setOmega(ValueType omega);
             void setPowerMethodMultiplicationStyle(MultiplicationStyle value);
-
+            void setForceSoundness(bool value);
+            
             SolutionMethod getSolutionMethod() const;
             ValueType getPrecision() const;
             uint64_t getMaximalNumberOfIterations() const;
             uint64_t getRelativeTerminationCriterion() const;
             ValueType getOmega() const;
             MultiplicationStyle getPowerMethodMultiplicationStyle() const;
+            bool getForceSoundness() const;
 
         private:
+            bool forceSoundness;
             SolutionMethod method;
             double precision;
             bool relative;
@@ -55,7 +58,6 @@ namespace storm {
             virtual void setMatrix(storm::storage::SparseMatrix<ValueType> const& A) override;
             virtual void setMatrix(storm::storage::SparseMatrix<ValueType>&& A) override;
             
-            virtual bool solveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const override;
             virtual void multiply(std::vector<ValueType>& x, std::vector<ValueType> const* b, std::vector<ValueType>& result) const override;
             virtual void multiplyAndReduce(OptimizationDirection const& dir, std::vector<uint64_t> const& rowGroupIndices, std::vector<ValueType>& x, std::vector<ValueType> const* b, std::vector<ValueType>& result, std::vector<uint_fast64_t>* choices = nullptr) const override;
             virtual bool supportsGaussSeidelMultiplication() const override;
@@ -69,6 +71,9 @@ namespace storm {
 
             virtual void clearCache() const override;
 
+        protected:
+            virtual bool internalSolveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const override;
+            
         private:
             virtual uint64_t getMatrixRowCount() const override;
             virtual uint64_t getMatrixColumnCount() const override;
@@ -95,6 +100,7 @@ namespace storm {
 
             // cached auxiliary data
             mutable std::unique_ptr<std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<ValueType>>> jacobiDecomposition;
+            mutable std::unique_ptr<std::vector<ValueType>> cachedRowVector2; // A.getRowCount() rows
             
             struct WalkerChaeData {
                 WalkerChaeData(storm::storage::SparseMatrix<ValueType> const& originalMatrix, std::vector<ValueType> const& originalB);
diff --git a/src/storm/solver/SymbolicMinMaxLinearEquationSolver.cpp b/src/storm/solver/SymbolicMinMaxLinearEquationSolver.cpp
index b4449c45b..03f603337 100644
--- a/src/storm/solver/SymbolicMinMaxLinearEquationSolver.cpp
+++ b/src/storm/solver/SymbolicMinMaxLinearEquationSolver.cpp
@@ -263,12 +263,12 @@ namespace storm {
             if (equationSystemType == EquationSystemType::UntilProbabilities) {
                 if (this->getSettings().getSolutionMethod() == SymbolicMinMaxLinearEquationSolverSettings<ValueType>::SolutionMethod::PolicyIteration) {
                     if (!direction || direction.get() == OptimizationDirection::Maximize) {
-                        requirements.set(MinMaxLinearEquationSolverRequirements::Element::ValidInitialScheduler);
+                        requirements.requireValidInitialScheduler();
                     }
                 }
             } else if (equationSystemType == EquationSystemType::ReachabilityRewards) {
                 if (!direction || direction.get() == OptimizationDirection::Minimize) {
-                    requirements.set(MinMaxLinearEquationSolverRequirements::Element::ValidInitialScheduler);
+                    requirements.requireValidInitialScheduler();
                 }
             }