17 changed files with 676 additions and 102 deletions
			
			
		- 
					4src/storm/environment/SubEnvironment.cpp
 - 
					4src/storm/environment/solver/MinMaxSolverEnvironment.cpp
 - 
					2src/storm/environment/solver/MinMaxSolverEnvironment.h
 - 
					12src/storm/environment/solver/SolverEnvironment.cpp
 - 
					10src/storm/environment/solver/SolverEnvironment.h
 - 
					37src/storm/environment/solver/TopologicalLinearEquationSolverEnvironment.cpp
 - 
					24src/storm/environment/solver/TopologicalLinearEquationSolverEnvironment.h
 - 
					56src/storm/environment/solver/TopologicalSolverEnvironment.cpp
 - 
					31src/storm/environment/solver/TopologicalSolverEnvironment.h
 - 
					2src/storm/solver/MinMaxLinearEquationSolver.cpp
 - 
					20src/storm/solver/TopologicalLinearEquationSolver.cpp
 - 
					434src/storm/solver/TopologicalMinMaxLinearEquationSolver.cpp
 - 
					73src/storm/solver/TopologicalMinMaxLinearEquationSolver.h
 - 
					4src/test/storm/modelchecker/DtmcPrctlModelCheckerTest.cpp
 - 
					39src/test/storm/modelchecker/MdpPrctlModelCheckerTest.cpp
 - 
					4src/test/storm/solver/LinearEquationSolverTest.cpp
 - 
					4src/test/storm/solver/MinMaxLinearEquationSolverTest.cpp
 
@ -1,37 +0,0 @@ | 
			
		|||||
#include "storm/environment/solver/TopologicalLinearEquationSolverEnvironment.h"
 | 
				 | 
			
		||||
 | 
				 | 
			
		||||
#include "storm/settings/SettingsManager.h"
 | 
				 | 
			
		||||
#include "storm/settings/modules/TopologicalEquationSolverSettings.h"
 | 
				 | 
			
		||||
#include "storm/utility/macros.h"
 | 
				 | 
			
		||||
 | 
				 | 
			
		||||
#include "storm/exceptions/InvalidArgumentException.h"
 | 
				 | 
			
		||||
 | 
				 | 
			
		||||
namespace storm { | 
				 | 
			
		||||
     | 
				 | 
			
		||||
    TopologicalLinearEquationSolverEnvironment::TopologicalLinearEquationSolverEnvironment() { | 
				 | 
			
		||||
        auto const& topologicalSettings = storm::settings::getModule<storm::settings::modules::TopologicalEquationSolverSettings>(); | 
				 | 
			
		||||
        underlyingSolverType = topologicalSettings.getUnderlyingEquationSolverType(); | 
				 | 
			
		||||
        underlyingSolverTypeSetFromDefault = topologicalSettings.isUnderlyingEquationSolverTypeSetFromDefaultValue(); | 
				 | 
			
		||||
    } | 
				 | 
			
		||||
 | 
				 | 
			
		||||
    TopologicalLinearEquationSolverEnvironment::~TopologicalLinearEquationSolverEnvironment() { | 
				 | 
			
		||||
        // Intentionally left empty
 | 
				 | 
			
		||||
    } | 
				 | 
			
		||||
     | 
				 | 
			
		||||
    storm::solver::EquationSolverType const& TopologicalLinearEquationSolverEnvironment::getUnderlyingSolverType() const { | 
				 | 
			
		||||
        return underlyingSolverType; | 
				 | 
			
		||||
    } | 
				 | 
			
		||||
     | 
				 | 
			
		||||
    bool const& TopologicalLinearEquationSolverEnvironment::isUnderlyingSolverTypeSetFromDefault() const { | 
				 | 
			
		||||
        return underlyingSolverTypeSetFromDefault; | 
				 | 
			
		||||
    } | 
				 | 
			
		||||
     | 
				 | 
			
		||||
    void TopologicalLinearEquationSolverEnvironment::setUnderlyingSolverType(storm::solver::EquationSolverType value) { | 
				 | 
			
		||||
        STORM_LOG_THROW(value != storm::solver::EquationSolverType::Topological, storm::exceptions::InvalidArgumentException, "Can not use the topological solver as underlying solver of the topological solver."); | 
				 | 
			
		||||
        underlyingSolverTypeSetFromDefault = false; | 
				 | 
			
		||||
        underlyingSolverType = value; | 
				 | 
			
		||||
    } | 
				 | 
			
		||||
     | 
				 | 
			
		||||
 | 
				 | 
			
		||||
 | 
				 | 
			
		||||
} | 
				 | 
			
		||||
@ -1,24 +0,0 @@ | 
			
		|||||
#pragma once | 
				 | 
			
		||||
 | 
				 | 
			
		||||
#include "storm/environment/solver/SolverEnvironment.h" | 
				 | 
			
		||||
 | 
				 | 
			
		||||
#include "storm/solver/SolverSelectionOptions.h" | 
				 | 
			
		||||
 | 
				 | 
			
		||||
namespace storm { | 
				 | 
			
		||||
     | 
				 | 
			
		||||
    class TopologicalLinearEquationSolverEnvironment { | 
				 | 
			
		||||
    public: | 
				 | 
			
		||||
         | 
				 | 
			
		||||
        TopologicalLinearEquationSolverEnvironment(); | 
				 | 
			
		||||
        ~TopologicalLinearEquationSolverEnvironment(); | 
				 | 
			
		||||
         | 
				 | 
			
		||||
        storm::solver::EquationSolverType const& getUnderlyingSolverType() const; | 
				 | 
			
		||||
        bool const& isUnderlyingSolverTypeSetFromDefault() const; | 
				 | 
			
		||||
        void setUnderlyingSolverType(storm::solver::EquationSolverType value); | 
				 | 
			
		||||
         | 
				 | 
			
		||||
    private: | 
				 | 
			
		||||
        storm::solver::EquationSolverType underlyingSolverType; | 
				 | 
			
		||||
        bool underlyingSolverTypeSetFromDefault; | 
				 | 
			
		||||
    }; | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
@ -0,0 +1,56 @@ | 
			
		|||||
 | 
				#include "storm/environment/solver/TopologicalSolverEnvironment.h"
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				#include "storm/settings/SettingsManager.h"
 | 
			
		||||
 | 
				#include "storm/settings/modules/TopologicalEquationSolverSettings.h"
 | 
			
		||||
 | 
				#include "storm/utility/macros.h"
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				#include "storm/exceptions/InvalidArgumentException.h"
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				namespace storm { | 
			
		||||
 | 
				     | 
			
		||||
 | 
				    TopologicalSolverEnvironment::TopologicalSolverEnvironment() { | 
			
		||||
 | 
				        auto const& topologicalSettings = storm::settings::getModule<storm::settings::modules::TopologicalEquationSolverSettings>(); | 
			
		||||
 | 
				        underlyingEquationSolverType = topologicalSettings.getUnderlyingEquationSolverType(); | 
			
		||||
 | 
				        underlyingEquationSolverTypeSetFromDefault = topologicalSettings.isUnderlyingEquationSolverTypeSetFromDefaultValue(); | 
			
		||||
 | 
				         | 
			
		||||
 | 
				        std::cout << "Get topo env minmax from settings!!" << std::endl; | 
			
		||||
 | 
				        underlyingMinMaxMethod = storm::solver::MinMaxMethod::ValueIteration; | 
			
		||||
 | 
				        underlyingEquationSolverTypeSetFromDefault = false; | 
			
		||||
 | 
				         | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    TopologicalSolverEnvironment::~TopologicalSolverEnvironment() { | 
			
		||||
 | 
				        // Intentionally left empty
 | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				     | 
			
		||||
 | 
				    storm::solver::EquationSolverType const& TopologicalSolverEnvironment::getUnderlyingEquationSolverType() const { | 
			
		||||
 | 
				        return underlyingEquationSolverType; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				     | 
			
		||||
 | 
				    bool const& TopologicalSolverEnvironment::isUnderlyingEquationSolverTypeSetFromDefault() const { | 
			
		||||
 | 
				        return underlyingEquationSolverTypeSetFromDefault; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				     | 
			
		||||
 | 
				    void TopologicalSolverEnvironment::setUnderlyingEquationSolverType(storm::solver::EquationSolverType value) { | 
			
		||||
 | 
				        STORM_LOG_THROW(value != storm::solver::EquationSolverType::Topological, storm::exceptions::InvalidArgumentException, "Can not use the topological solver as underlying solver of the topological solver."); | 
			
		||||
 | 
				        underlyingEquationSolverTypeSetFromDefault = false; | 
			
		||||
 | 
				        underlyingEquationSolverType = value; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				     | 
			
		||||
 | 
				    storm::solver::MinMaxMethod const& TopologicalSolverEnvironment::getUnderlyingMinMaxMethod() const { | 
			
		||||
 | 
				        return underlyingMinMaxMethod; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				     | 
			
		||||
 | 
				    bool const& TopologicalSolverEnvironment::isUnderlyingMinMaxMethodSetFromDefault() const { | 
			
		||||
 | 
				        return underlyingMinMaxMethodSetFromDefault; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				     | 
			
		||||
 | 
				    void TopologicalSolverEnvironment::setUnderlyingMinMaxMethod(storm::solver::MinMaxMethod value) { | 
			
		||||
 | 
				        STORM_LOG_THROW(value != storm::solver::MinMaxMethod::Topological, storm::exceptions::InvalidArgumentException, "Can not use the topological solver as underlying solver of the topological solver."); | 
			
		||||
 | 
				        underlyingMinMaxMethodSetFromDefault = false; | 
			
		||||
 | 
				        underlyingMinMaxMethod = value; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				     | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				} | 
			
		||||
@ -0,0 +1,31 @@ | 
			
		|||||
 | 
				#pragma once | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				#include "storm/environment/solver/SolverEnvironment.h" | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				#include "storm/solver/SolverSelectionOptions.h" | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				namespace storm { | 
			
		||||
 | 
				     | 
			
		||||
 | 
				    class TopologicalSolverEnvironment { | 
			
		||||
 | 
				    public: | 
			
		||||
 | 
				         | 
			
		||||
 | 
				        TopologicalSolverEnvironment(); | 
			
		||||
 | 
				        ~TopologicalSolverEnvironment(); | 
			
		||||
 | 
				         | 
			
		||||
 | 
				        storm::solver::EquationSolverType const& getUnderlyingEquationSolverType() const; | 
			
		||||
 | 
				        bool const& isUnderlyingEquationSolverTypeSetFromDefault() const; | 
			
		||||
 | 
				        void setUnderlyingEquationSolverType(storm::solver::EquationSolverType value); | 
			
		||||
 | 
				         | 
			
		||||
 | 
				        storm::solver::MinMaxMethod const& getUnderlyingMinMaxMethod() const; | 
			
		||||
 | 
				        bool const& isUnderlyingMinMaxMethodSetFromDefault() const; | 
			
		||||
 | 
				        void setUnderlyingMinMaxMethod(storm::solver::MinMaxMethod value); | 
			
		||||
 | 
				         | 
			
		||||
 | 
				    private: | 
			
		||||
 | 
				        storm::solver::EquationSolverType underlyingEquationSolverType; | 
			
		||||
 | 
				        bool underlyingEquationSolverTypeSetFromDefault; | 
			
		||||
 | 
				         | 
			
		||||
 | 
				        storm::solver::MinMaxMethod underlyingMinMaxMethod; | 
			
		||||
 | 
				        bool underlyingMinMaxMethodSetFromDefault; | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
@ -0,0 +1,434 @@ | 
			
		|||||
 | 
				#include "storm/solver/TopologicalMinMaxLinearEquationSolver.h"
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				#include "storm/environment/solver/MinMaxSolverEnvironment.h"
 | 
			
		||||
 | 
				#include "storm/environment/solver/TopologicalSolverEnvironment.h"
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				#include "storm/utility/constants.h"
 | 
			
		||||
 | 
				#include "storm/utility/vector.h"
 | 
			
		||||
 | 
				#include "storm/exceptions/InvalidStateException.h"
 | 
			
		||||
 | 
				#include "storm/exceptions/InvalidEnvironmentException.h"
 | 
			
		||||
 | 
				#include "storm/exceptions/UnexpectedException.h"
 | 
			
		||||
 | 
				#include "storm/exceptions/UnmetRequirementException.h"
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				namespace storm { | 
			
		||||
 | 
				    namespace solver { | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        template<typename ValueType> | 
			
		||||
 | 
				        TopologicalMinMaxLinearEquationSolver<ValueType>::TopologicalMinMaxLinearEquationSolver() : localA(nullptr), A(nullptr) { | 
			
		||||
 | 
				            // Intentionally left empty.
 | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        template<typename ValueType> | 
			
		||||
 | 
				        TopologicalMinMaxLinearEquationSolver<ValueType>::TopologicalMinMaxLinearEquationSolver(storm::storage::SparseMatrix<ValueType> const& A) : localA(nullptr), A(nullptr) { | 
			
		||||
 | 
				            this->setMatrix(A); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        template<typename ValueType> | 
			
		||||
 | 
				        TopologicalMinMaxLinearEquationSolver<ValueType>::TopologicalMinMaxLinearEquationSolver(storm::storage::SparseMatrix<ValueType>&& A) : localA(nullptr), A(nullptr) { | 
			
		||||
 | 
				            this->setMatrix(std::move(A)); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				         | 
			
		||||
 | 
				        template<typename ValueType> | 
			
		||||
 | 
				        void TopologicalMinMaxLinearEquationSolver<ValueType>::setMatrix(storm::storage::SparseMatrix<ValueType> const& A) { | 
			
		||||
 | 
				            localA.reset(); | 
			
		||||
 | 
				            this->A = &A; | 
			
		||||
 | 
				            clearCache(); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        template<typename ValueType> | 
			
		||||
 | 
				        void TopologicalMinMaxLinearEquationSolver<ValueType>::setMatrix(storm::storage::SparseMatrix<ValueType>&& A) { | 
			
		||||
 | 
				            localA = std::make_unique<storm::storage::SparseMatrix<ValueType>>(std::move(A)); | 
			
		||||
 | 
				            this->A = localA.get(); | 
			
		||||
 | 
				            clearCache(); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				         | 
			
		||||
 | 
				        template<typename ValueType> | 
			
		||||
 | 
				        storm::Environment TopologicalMinMaxLinearEquationSolver<ValueType>::getEnvironmentForUnderlyingSolver(storm::Environment const& env, bool adaptPrecision) const { | 
			
		||||
 | 
				            storm::Environment subEnv(env); | 
			
		||||
 | 
				            subEnv.solver().minMax().setMethod(env.solver().topological().getUnderlyingMinMaxMethod(), env.solver().topological().isUnderlyingMinMaxMethodSetFromDefault()); | 
			
		||||
 | 
				            if (adaptPrecision) { | 
			
		||||
 | 
				                STORM_LOG_ASSERT(this->longestSccChainSize, "Did not compute the longest SCC chain size although it is needed."); | 
			
		||||
 | 
				                storm::RationalNumber subEnvPrec = subEnv.solver().minMax().getPrecision() / storm::utility::convertNumber<storm::RationalNumber>(this->longestSccChainSize.get()); | 
			
		||||
 | 
				                subEnv.solver().minMax().setPrecision(subEnvPrec); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				            return subEnv; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        template<typename ValueType> | 
			
		||||
 | 
				        bool TopologicalMinMaxLinearEquationSolver<ValueType>::internalSolveEquations(Environment const& env, OptimizationDirection dir, std::vector<ValueType>& x, std::vector<ValueType> const& b) const { | 
			
		||||
 | 
				            STORM_LOG_ASSERT(x.size() == this->A->getRowGroupCount(), "Provided x-vector has invalid size."); | 
			
		||||
 | 
				            STORM_LOG_ASSERT(b.size() == this->A->getRowCount(), "Provided b-vector has invalid size."); | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            //std::cout << "Solving equation system with fixpoint characterization " << std::endl;
 | 
			
		||||
 | 
				            //std::cout << *this->A << std::endl;
 | 
			
		||||
 | 
				            //std::cout << storm::utility::vector::toString(b) << std::endl;
 | 
			
		||||
 | 
				            //std::cout << "Initial solution vector: " << std::endl;
 | 
			
		||||
 | 
				            //std::cout << storm::utility::vector::toString(x) << std::endl;
 | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            // For sound computations we need to increase the precision in each SCC
 | 
			
		||||
 | 
				            bool needAdaptPrecision = env.solver().isForceSoundness(); | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            if (!this->sortedSccDecomposition || (needAdaptPrecision && !this->longestSccChainSize)) { | 
			
		||||
 | 
				                STORM_LOG_TRACE("Creating SCC decomposition."); | 
			
		||||
 | 
				                createSortedSccDecomposition(needAdaptPrecision); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            //std::cout << "Sorted SCC decomposition: " << std::endl;
 | 
			
		||||
 | 
				            //for (auto const& scc : *this->sortedSccDecomposition) {
 | 
			
		||||
 | 
				                //std::cout << "SCC: ";
 | 
			
		||||
 | 
				              //  for (auto const& row : scc) {
 | 
			
		||||
 | 
				                    //std::cout << row << "  ";
 | 
			
		||||
 | 
				               // }
 | 
			
		||||
 | 
				                //std::cout << std::endl;
 | 
			
		||||
 | 
				            //}
 | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            // We do not need to adapt the precision if all SCCs are trivial (i.e., the system is acyclic)
 | 
			
		||||
 | 
				            needAdaptPrecision = needAdaptPrecision && (this->sortedSccDecomposition->size() != this->A->getRowGroupCount()); | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            storm::Environment sccSolverEnvironment = getEnvironmentForUnderlyingSolver(env, needAdaptPrecision); | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            std::cout << "Found " << this->sortedSccDecomposition->size() << "SCCs. Average size is " << static_cast<double>(this->A->getRowGroupCount()) / static_cast<double>(this->sortedSccDecomposition->size()) << "." << std::endl; | 
			
		||||
 | 
				            if (this->longestSccChainSize) { | 
			
		||||
 | 
				                std::cout << "Longest SCC chain size is " << this->longestSccChainSize.get() << std::endl; | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            bool returnValue = true; | 
			
		||||
 | 
				            if (this->sortedSccDecomposition->size() == 1) { | 
			
		||||
 | 
				                // Handle the case where there is just one large SCC
 | 
			
		||||
 | 
				                returnValue = solveFullyConnectedEquationSystem(sccSolverEnvironment, dir, x, b); | 
			
		||||
 | 
				            } else { | 
			
		||||
 | 
				                if (this->isTrackSchedulerSet()) { | 
			
		||||
 | 
				                    if (this->schedulerChoices) { | 
			
		||||
 | 
				                        this->schedulerChoices.get().resize(x.size()); | 
			
		||||
 | 
				                    } else { | 
			
		||||
 | 
				                        this->schedulerChoices = std::vector<uint64_t>(x.size()); | 
			
		||||
 | 
				                    } | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				                storm::storage::BitVector sccRowGroupsAsBitVector(x.size(), false); | 
			
		||||
 | 
				                storm::storage::BitVector sccRowsAsBitVector(b.size(), false); | 
			
		||||
 | 
				                for (auto const& scc : *this->sortedSccDecomposition) { | 
			
		||||
 | 
				                    if (scc.isTrivial()) { | 
			
		||||
 | 
				                        returnValue = solveTrivialScc(*scc.begin(), dir, x, b) && returnValue; | 
			
		||||
 | 
				                    } else { | 
			
		||||
 | 
				                        sccRowGroupsAsBitVector.clear(); | 
			
		||||
 | 
				                        sccRowsAsBitVector.clear(); | 
			
		||||
 | 
				                        for (auto const& group : scc) { | 
			
		||||
 | 
				                            sccRowGroupsAsBitVector.set(group, true); | 
			
		||||
 | 
				                            for (uint64_t row = this->A->getRowGroupIndices()[group]; row < this->A->getRowGroupIndices()[group + 1]; ++row) { | 
			
		||||
 | 
				                                sccRowsAsBitVector.set(row, true); | 
			
		||||
 | 
				                            } | 
			
		||||
 | 
				                        } | 
			
		||||
 | 
				                        returnValue = solveScc(sccSolverEnvironment, dir, sccRowGroupsAsBitVector, sccRowsAsBitVector, x, b) && returnValue; | 
			
		||||
 | 
				                    } | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				                 | 
			
		||||
 | 
				                // If requested, we store the scheduler for retrieval.
 | 
			
		||||
 | 
				                if (this->isTrackSchedulerSet()) { | 
			
		||||
 | 
				                    if (!auxiliaryRowGroupVector) { | 
			
		||||
 | 
				                        auxiliaryRowGroupVector = std::make_unique<std::vector<ValueType>>(this->A->getRowGroupCount()); | 
			
		||||
 | 
				                    } | 
			
		||||
 | 
				                    this->schedulerChoices = std::vector<uint_fast64_t>(this->A->getRowGroupCount()); | 
			
		||||
 | 
				                    this->A->multiplyAndReduce(dir, this->A->getRowGroupIndices(), x, &b, *auxiliaryRowGroupVector.get(), &this->schedulerChoices.get()); | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            if (!this->isCachingEnabled()) { | 
			
		||||
 | 
				                clearCache(); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            return returnValue; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				         | 
			
		||||
 | 
				        template<typename ValueType> | 
			
		||||
 | 
				        void TopologicalMinMaxLinearEquationSolver<ValueType>::createSortedSccDecomposition(bool needLongestChainSize) const { | 
			
		||||
 | 
				            // Obtain the scc decomposition
 | 
			
		||||
 | 
				            auto sccDecomposition = storm::storage::StronglyConnectedComponentDecomposition<ValueType>(*this->A); | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            // Get a mapping from matrix row to the corresponding scc
 | 
			
		||||
 | 
				            STORM_LOG_THROW(sccDecomposition.size() < std::numeric_limits<uint32_t>::max(), storm::exceptions::UnexpectedException, "The number of SCCs is too large."); | 
			
		||||
 | 
				            std::vector<uint32_t> sccIndices(this->A->getRowCount(), std::numeric_limits<uint32_t>::max()); | 
			
		||||
 | 
				            uint32_t sccIndex = 0; | 
			
		||||
 | 
				            for (auto const& scc : sccDecomposition) { | 
			
		||||
 | 
				                for (auto const& row : scc) { | 
			
		||||
 | 
				                    sccIndices[row] = sccIndex; | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				                ++sccIndex; | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            // Prepare the resulting set of sorted sccs
 | 
			
		||||
 | 
				            this->sortedSccDecomposition = std::make_unique<std::vector<storm::storage::StronglyConnectedComponent>>(); | 
			
		||||
 | 
				            std::vector<storm::storage::StronglyConnectedComponent>& sortedSCCs = *this->sortedSccDecomposition; | 
			
		||||
 | 
				            sortedSCCs.reserve(sccDecomposition.size()); | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            // Find a topological sort via DFS.
 | 
			
		||||
 | 
				            storm::storage::BitVector unsortedSCCs(sccDecomposition.size(), true); | 
			
		||||
 | 
				            std::vector<uint32_t> sccStack, chainSizes; | 
			
		||||
 | 
				            if (needLongestChainSize) { | 
			
		||||
 | 
				                chainSizes.resize(sccDecomposition.size(), 1u); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				            uint32_t longestChainSize = 0; | 
			
		||||
 | 
				            uint32_t const token = std::numeric_limits<uint32_t>::max(); | 
			
		||||
 | 
				            std::set<uint64_t> successorSCCs; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            for (uint32_t firstUnsortedScc = 0; firstUnsortedScc < unsortedSCCs.size(); firstUnsortedScc = unsortedSCCs.getNextSetIndex(firstUnsortedScc + 1)) { | 
			
		||||
 | 
				                 | 
			
		||||
 | 
				                sccStack.push_back(firstUnsortedScc); | 
			
		||||
 | 
				                while (!sccStack.empty()) { | 
			
		||||
 | 
				                    uint32_t currentSccIndex = sccStack.back(); | 
			
		||||
 | 
				                    if (currentSccIndex != token) { | 
			
		||||
 | 
				                        // Check whether the SCC is still unprocessed
 | 
			
		||||
 | 
				                        if (unsortedSCCs.get(currentSccIndex)) { | 
			
		||||
 | 
				                            // Explore the successors of the scc.
 | 
			
		||||
 | 
				                            storm::storage::StronglyConnectedComponent const& currentScc = sccDecomposition.getBlock(currentSccIndex); | 
			
		||||
 | 
				                            // We first push a token on the stack in order to recognize later when all successors of this SCC have been explored already.
 | 
			
		||||
 | 
				                            sccStack.push_back(token); | 
			
		||||
 | 
				                            // Now add all successors that are not already sorted.
 | 
			
		||||
 | 
				                            // Successors should only be added once, so we first prepare a set of them and add them afterwards.
 | 
			
		||||
 | 
				                            successorSCCs.clear(); | 
			
		||||
 | 
				                            for (auto const& row : currentScc) { | 
			
		||||
 | 
				                                for (auto const& entry : this->A->getRow(row)) { | 
			
		||||
 | 
				                                    auto const& successorSCC = sccIndices[entry.getColumn()]; | 
			
		||||
 | 
				                                    if (successorSCC != currentSccIndex && unsortedSCCs.get(successorSCC)) { | 
			
		||||
 | 
				                                        successorSCCs.insert(successorSCC); | 
			
		||||
 | 
				                                    } | 
			
		||||
 | 
				                                } | 
			
		||||
 | 
				                            } | 
			
		||||
 | 
				                            sccStack.insert(sccStack.end(), successorSCCs.begin(), successorSCCs.end()); | 
			
		||||
 | 
				                             | 
			
		||||
 | 
				                        } | 
			
		||||
 | 
				                    } else { | 
			
		||||
 | 
				                        // all successors of the current scc have already been explored.
 | 
			
		||||
 | 
				                        sccStack.pop_back(); // pop the token
 | 
			
		||||
 | 
				                         | 
			
		||||
 | 
				                        currentSccIndex = sccStack.back(); | 
			
		||||
 | 
				                        storm::storage::StronglyConnectedComponent& scc = sccDecomposition.getBlock(currentSccIndex); | 
			
		||||
 | 
				                         | 
			
		||||
 | 
				                        // Compute the longest chain size for this scc
 | 
			
		||||
 | 
				                        if (needLongestChainSize) { | 
			
		||||
 | 
				                            uint32_t& currentChainSize = chainSizes[currentSccIndex]; | 
			
		||||
 | 
				                            for (auto const& row : scc) { | 
			
		||||
 | 
				                                for (auto const& entry : this->A->getRow(row)) { | 
			
		||||
 | 
				                                    auto const& successorSCC = sccIndices[entry.getColumn()]; | 
			
		||||
 | 
				                                    if (successorSCC != currentSccIndex) { | 
			
		||||
 | 
				                                        currentChainSize = std::max(currentChainSize, chainSizes[successorSCC] + 1); | 
			
		||||
 | 
				                                    } | 
			
		||||
 | 
				                                } | 
			
		||||
 | 
				                            } | 
			
		||||
 | 
				                            longestChainSize = std::max(longestChainSize, currentChainSize); | 
			
		||||
 | 
				                        } | 
			
		||||
 | 
				                         | 
			
		||||
 | 
				                        unsortedSCCs.set(currentSccIndex, false); | 
			
		||||
 | 
				                        sccStack.pop_back(); // pop the current scc index
 | 
			
		||||
 | 
				                        sortedSCCs.push_back(std::move(scc)); | 
			
		||||
 | 
				                    } | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            if (longestChainSize > 0) { | 
			
		||||
 | 
				                this->longestSccChainSize = longestChainSize; | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				         | 
			
		||||
 | 
				        template<typename ValueType> | 
			
		||||
 | 
				        bool TopologicalMinMaxLinearEquationSolver<ValueType>::solveTrivialScc(uint64_t const& sccState, OptimizationDirection dir, std::vector<ValueType>& globalX, std::vector<ValueType> const& globalB) const { | 
			
		||||
 | 
				            ValueType& xi = globalX[sccState]; | 
			
		||||
 | 
				            bool firstRow = true; | 
			
		||||
 | 
				            uint64_t bestRow; | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            for (uint64_t row = this->A->getRowGroupIndices()[sccState]; row < this->A->getRowGroupIndices()[sccState + 1]; ++row) { | 
			
		||||
 | 
				                ValueType rowValue = globalB[sccState]; | 
			
		||||
 | 
				                bool hasDiagonalEntry = false; | 
			
		||||
 | 
				                ValueType denominator; | 
			
		||||
 | 
				                for (auto const& entry : this->A->getRow(sccState)) { | 
			
		||||
 | 
				                    if (entry.getColumn() == sccState) { | 
			
		||||
 | 
				                        STORM_LOG_ASSERT(!storm::utility::isOne(entry.getValue()), "Diagonal entry of fix point system has value 1."); | 
			
		||||
 | 
				                        hasDiagonalEntry = true; | 
			
		||||
 | 
				                        denominator = storm::utility::one<ValueType>() - entry.getValue(); | 
			
		||||
 | 
				                    } else { | 
			
		||||
 | 
				                        rowValue += entry.getValue() * globalX[entry.getColumn()]; | 
			
		||||
 | 
				                    } | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				                if (hasDiagonalEntry) { | 
			
		||||
 | 
				                    rowValue /= denominator; | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				                if (firstRow) { | 
			
		||||
 | 
				                    xi = std::move(rowValue); | 
			
		||||
 | 
				                    bestRow = row; | 
			
		||||
 | 
				                    firstRow = false; | 
			
		||||
 | 
				                } else { | 
			
		||||
 | 
				                    if (minimize(dir)) { | 
			
		||||
 | 
				                        if (rowValue < xi) { | 
			
		||||
 | 
				                            xi = std::move(rowValue); | 
			
		||||
 | 
				                            bestRow = row; | 
			
		||||
 | 
				                        } | 
			
		||||
 | 
				                    } else { | 
			
		||||
 | 
				                        if (rowValue > xi) { | 
			
		||||
 | 
				                            xi = std::move(rowValue); | 
			
		||||
 | 
				                            bestRow = row; | 
			
		||||
 | 
				                        } | 
			
		||||
 | 
				                    } | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				            if (this->isTrackSchedulerSet()) { | 
			
		||||
 | 
				                this->schedulerChoices.get()[sccState] = bestRow - this->A->getRowGroupIndices()[sccState]; | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				            //std::cout << "Solved trivial scc " << sccState << " with result " << globalX[sccState] << std::endl;
 | 
			
		||||
 | 
				            return true; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				         | 
			
		||||
 | 
				        template<typename ValueType> | 
			
		||||
 | 
				        bool TopologicalMinMaxLinearEquationSolver<ValueType>::solveFullyConnectedEquationSystem(storm::Environment const& sccSolverEnvironment, OptimizationDirection dir, std::vector<ValueType>& x, std::vector<ValueType> const& b) const { | 
			
		||||
 | 
				            if (!this->sccSolver) { | 
			
		||||
 | 
				                this->sccSolver = GeneralMinMaxLinearEquationSolverFactory<ValueType>().create(sccSolverEnvironment); | 
			
		||||
 | 
				                this->sccSolver->setCachingEnabled(true); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				            this->sccSolver->setMatrix(*this->A); | 
			
		||||
 | 
				            this->sccSolver->setHasUniqueSolution(this->hasUniqueSolution()); | 
			
		||||
 | 
				            this->sccSolver->setBoundsFromOtherSolver(*this); | 
			
		||||
 | 
				            this->sccSolver->setTrackScheduler(this->isTrackSchedulerSet()); | 
			
		||||
 | 
				            if (this->hasInitialScheduler()) { | 
			
		||||
 | 
				                auto choices = this->getInitialScheduler(); | 
			
		||||
 | 
				                this->sccSolver->setInitialScheduler(std::move(choices)); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				            auto req = this->sccSolver->getRequirements(sccSolverEnvironment, dir); | 
			
		||||
 | 
				            if (req.requiresUpperBounds() && this->hasUpperBound()) { | 
			
		||||
 | 
				                req.clearUpperBounds(); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				            if (req.requiresLowerBounds() && this->hasLowerBound()) { | 
			
		||||
 | 
				                req.clearLowerBounds(); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				            STORM_LOG_THROW(req.empty(), storm::exceptions::UnmetRequirementException, "Requirements of underlying solver not met."); | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            bool res = this->sccSolver->solveEquations(sccSolverEnvironment, dir, x, b); | 
			
		||||
 | 
				            if (this->isTrackSchedulerSet()) { | 
			
		||||
 | 
				                this->schedulerChoices = this->sccSolver->getSchedulerChoices(); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				            return res; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				         | 
			
		||||
 | 
				        template<typename ValueType> | 
			
		||||
 | 
				        bool TopologicalMinMaxLinearEquationSolver<ValueType>::solveScc(storm::Environment const& sccSolverEnvironment, OptimizationDirection dir, storm::storage::BitVector const& sccRowGroups, storm::storage::BitVector const& sccRows, std::vector<ValueType>& globalX, std::vector<ValueType> const& globalB) const { | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            // Set up the SCC solver
 | 
			
		||||
 | 
				            if (!this->sccSolver) { | 
			
		||||
 | 
				                this->sccSolver = GeneralMinMaxLinearEquationSolverFactory<ValueType>().create(sccSolverEnvironment); | 
			
		||||
 | 
				                this->sccSolver->setCachingEnabled(true); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				            this->sccSolver->setHasUniqueSolution(this->hasUniqueSolution()); | 
			
		||||
 | 
				            this->sccSolver->setTrackScheduler(this->isTrackSchedulerSet()); | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            // Requirements
 | 
			
		||||
 | 
				            auto req = this->sccSolver->getRequirements(sccSolverEnvironment, dir); | 
			
		||||
 | 
				            if (req.requiresUpperBounds() && this->hasUpperBound()) { | 
			
		||||
 | 
				                req.clearUpperBounds(); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				            if (req.requiresLowerBounds() && this->hasLowerBound()) { | 
			
		||||
 | 
				                req.clearLowerBounds(); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				            if (req.requiresValidInitialScheduler() && this->hasInitialScheduler()) { | 
			
		||||
 | 
				                req.clearValidInitialScheduler(); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				            STORM_LOG_THROW(req.empty(), storm::exceptions::UnmetRequirementException, "Requirements of underlying solver not met."); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            // SCC Matrix
 | 
			
		||||
 | 
				            storm::storage::SparseMatrix<ValueType> sccA = this->A->getSubmatrix(true, sccRowGroups, sccRowGroups); | 
			
		||||
 | 
				            this->sccSolver->setMatrix(std::move(sccA)); | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            // x Vector
 | 
			
		||||
 | 
				            auto sccX = storm::utility::vector::filterVector(globalX, sccRowGroups); | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            // b Vector
 | 
			
		||||
 | 
				            std::vector<ValueType> sccB; | 
			
		||||
 | 
				            sccB.reserve(sccRows.getNumberOfSetBits()); | 
			
		||||
 | 
				            for (auto const& row : sccRows) { | 
			
		||||
 | 
				                ValueType bi = globalB[row]; | 
			
		||||
 | 
				                for (auto const& entry : this->A->getRow(row)) { | 
			
		||||
 | 
				                    if (!sccRowGroups.get(entry.getColumn())) { | 
			
		||||
 | 
				                        bi += entry.getValue() * globalX[entry.getColumn()]; | 
			
		||||
 | 
				                    } | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				                sccB.push_back(std::move(bi)); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            // initial scheduler
 | 
			
		||||
 | 
				            if (this->hasInitialScheduler()) { | 
			
		||||
 | 
				                auto sccInitChoices = storm::utility::vector::filterVector(this->getInitialScheduler(), sccRowGroups); | 
			
		||||
 | 
				                this->sccSolver->setInitialScheduler(std::move(sccInitChoices)); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            // lower/upper bounds
 | 
			
		||||
 | 
				            if (this->hasLowerBound(storm::solver::AbstractEquationSolver<ValueType>::BoundType::Global)) { | 
			
		||||
 | 
				                this->sccSolver->setLowerBound(this->getLowerBound()); | 
			
		||||
 | 
				            } else if (this->hasLowerBound(storm::solver::AbstractEquationSolver<ValueType>::BoundType::Local)) { | 
			
		||||
 | 
				                this->sccSolver->setLowerBounds(storm::utility::vector::filterVector(this->getLowerBounds(), sccRowGroups)); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				            if (this->hasUpperBound(storm::solver::AbstractEquationSolver<ValueType>::BoundType::Global)) { | 
			
		||||
 | 
				                this->sccSolver->setUpperBound(this->getUpperBound()); | 
			
		||||
 | 
				            } else if (this->hasUpperBound(storm::solver::AbstractEquationSolver<ValueType>::BoundType::Local)) { | 
			
		||||
 | 
				                this->sccSolver->setUpperBounds(storm::utility::vector::filterVector(this->getUpperBounds(), sccRowGroups)); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            // Invoke scc solver
 | 
			
		||||
 | 
				            bool res = this->sccSolver->solveEquations(sccSolverEnvironment, dir, sccX, sccB); | 
			
		||||
 | 
				            //std::cout << "rhs is " << storm::utility::vector::toString(sccB) << std::endl;
 | 
			
		||||
 | 
				            //std::cout << "x is " << storm::utility::vector::toString(sccX) << std::endl;
 | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            // Set Scheduler choices
 | 
			
		||||
 | 
				            if (this->isTrackSchedulerSet()) { | 
			
		||||
 | 
				                storm::utility::vector::setVectorValues(this->schedulerChoices.get(), sccRowGroups, this->sccSolver->getSchedulerChoices()); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            // Set solution
 | 
			
		||||
 | 
				            storm::utility::vector::setVectorValues(globalX, sccRowGroups, sccX); | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            return res; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				         | 
			
		||||
 | 
				        template<typename ValueType> | 
			
		||||
 | 
				        void TopologicalMinMaxLinearEquationSolver<ValueType>::repeatedMultiply(Environment const& env, OptimizationDirection d, std::vector<ValueType>& x, std::vector<ValueType> const* b, uint_fast64_t n) const { | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            storm::Environment sccSolverEnvironment = getEnvironmentForUnderlyingSolver(env); | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            // Set up the SCC solver
 | 
			
		||||
 | 
				            if (!this->sccSolver) { | 
			
		||||
 | 
				                this->sccSolver = GeneralMinMaxLinearEquationSolverFactory<ValueType>().create(sccSolverEnvironment); | 
			
		||||
 | 
				                this->sccSolver->setCachingEnabled(true); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				            this->sccSolver->setMatrix(*this->A); | 
			
		||||
 | 
				            this->sccSolver->repeatedMultiply(sccSolverEnvironment, d, x, b, n); | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            if (!this->isCachingEnabled()) { | 
			
		||||
 | 
				                clearCache(); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        template<typename ValueType> | 
			
		||||
 | 
				        MinMaxLinearEquationSolverRequirements TopologicalMinMaxLinearEquationSolver<ValueType>::getRequirements(Environment const& env, boost::optional<storm::solver::OptimizationDirection> const& direction, bool const& assumeNoInitialScheduler) const { | 
			
		||||
 | 
				            // Return the requirements of the underlying solver
 | 
			
		||||
 | 
				            return GeneralMinMaxLinearEquationSolverFactory<ValueType>().getRequirements(getEnvironmentForUnderlyingSolver(env), this->hasUniqueSolution(), direction, assumeNoInitialScheduler); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				         | 
			
		||||
 | 
				        template<typename ValueType> | 
			
		||||
 | 
				        void TopologicalMinMaxLinearEquationSolver<ValueType>::clearCache() const { | 
			
		||||
 | 
				            sortedSccDecomposition.reset(); | 
			
		||||
 | 
				            longestSccChainSize = boost::none; | 
			
		||||
 | 
				            sccSolver.reset(); | 
			
		||||
 | 
				            auxiliaryRowGroupVector.reset(); | 
			
		||||
 | 
				            MinMaxLinearEquationSolver<ValueType>::clearCache(); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				         | 
			
		||||
 | 
				        template<typename ValueType> | 
			
		||||
 | 
				        std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType>> TopologicalMinMaxLinearEquationSolverFactory<ValueType>::create(Environment const& env) const { | 
			
		||||
 | 
				            return std::make_unique<storm::solver::TopologicalMinMaxLinearEquationSolver<ValueType>>(); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				         | 
			
		||||
 | 
				        // Explicitly instantiate the min max linear equation solver.
 | 
			
		||||
 | 
				        template class TopologicalMinMaxLinearEquationSolver<double>; | 
			
		||||
 | 
				        template class TopologicalMinMaxLinearEquationSolverFactory<double>; | 
			
		||||
 | 
				         | 
			
		||||
 | 
				#ifdef STORM_HAVE_CARL
 | 
			
		||||
 | 
				        template class TopologicalMinMaxLinearEquationSolver<storm::RationalNumber>; | 
			
		||||
 | 
				        template class TopologicalMinMaxLinearEquationSolverFactory<storm::RationalNumber>; | 
			
		||||
 | 
				#endif
 | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				} | 
			
		||||
@ -0,0 +1,73 @@ | 
			
		|||||
 | 
				#pragma once | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				#include "storm/solver/MinMaxLinearEquationSolver.h" | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				#include "storm/solver/SolverSelectionOptions.h" | 
			
		||||
 | 
				#include "storm/storage/StronglyConnectedComponentDecomposition.h" | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				namespace storm { | 
			
		||||
 | 
				     | 
			
		||||
 | 
				    class Environment; | 
			
		||||
 | 
				     | 
			
		||||
 | 
				    namespace solver { | 
			
		||||
 | 
				         | 
			
		||||
 | 
				        template<typename ValueType> | 
			
		||||
 | 
				        class TopologicalMinMaxLinearEquationSolver : public MinMaxLinearEquationSolver<ValueType> { | 
			
		||||
 | 
				        public: | 
			
		||||
 | 
				            TopologicalMinMaxLinearEquationSolver(); | 
			
		||||
 | 
				            TopologicalMinMaxLinearEquationSolver(storm::storage::SparseMatrix<ValueType> const& A); | 
			
		||||
 | 
				            TopologicalMinMaxLinearEquationSolver(storm::storage::SparseMatrix<ValueType>&& A); | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            virtual void setMatrix(storm::storage::SparseMatrix<ValueType> const& A) override; | 
			
		||||
 | 
				            virtual void setMatrix(storm::storage::SparseMatrix<ValueType>&& A) override; | 
			
		||||
 | 
				             | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            virtual void clearCache() const override; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            virtual void repeatedMultiply(Environment const& env, OptimizationDirection d, std::vector<ValueType>& x, std::vector<ValueType> const* b, uint_fast64_t n = 1) const override; | 
			
		||||
 | 
				            virtual MinMaxLinearEquationSolverRequirements getRequirements(Environment const& env, boost::optional<storm::solver::OptimizationDirection> const& direction = boost::none, bool const& assumeNoInitialScheduler = false) const override ; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        protected: | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            virtual bool internalSolveEquations(storm::Environment const& env, OptimizationDirection d, std::vector<ValueType>& x, std::vector<ValueType> const& b) const override; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        private: | 
			
		||||
 | 
				            storm::Environment getEnvironmentForUnderlyingSolver(storm::Environment const& env, bool adaptPrecision = false) const; | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            // Creates an SCC decomposition and sorts the SCCs according to a topological sort. | 
			
		||||
 | 
				            void createSortedSccDecomposition(bool needLongestChainSize) const; | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            // Solves the SCC with the given index | 
			
		||||
 | 
				            // ... for the case that the SCC is trivial | 
			
		||||
 | 
				            bool solveTrivialScc(uint64_t const& sccState, OptimizationDirection d, std::vector<ValueType>& globalX, std::vector<ValueType> const& globalB) const; | 
			
		||||
 | 
				            // ... for the case that there is just one large SCC | 
			
		||||
 | 
				            bool solveFullyConnectedEquationSystem(storm::Environment const& sccSolverEnvironment, OptimizationDirection d, std::vector<ValueType>& x, std::vector<ValueType> const& b) const; | 
			
		||||
 | 
				            // ... for the remaining cases (1 < scc.size() < x.size()) | 
			
		||||
 | 
				            bool solveScc(storm::Environment const& sccSolverEnvironment, OptimizationDirection d, storm::storage::BitVector const& sccRowGroups, storm::storage::BitVector const& sccRows, std::vector<ValueType>& globalX, std::vector<ValueType> const& globalB) const; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            // If the solver takes posession of the matrix, we store the moved matrix in this member, so it gets deleted | 
			
		||||
 | 
				            // when the solver is destructed. | 
			
		||||
 | 
				            std::unique_ptr<storm::storage::SparseMatrix<ValueType>> localA; | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            // A pointer to the original sparse matrix given to this solver. If the solver takes posession of the matrix | 
			
		||||
 | 
				            // the pointer refers to localA. | 
			
		||||
 | 
				            storm::storage::SparseMatrix<ValueType> const* A; | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            // cached auxiliary data | 
			
		||||
 | 
				            mutable std::unique_ptr<std::vector<storm::storage::StronglyConnectedComponent>> sortedSccDecomposition; | 
			
		||||
 | 
				            mutable boost::optional<uint64_t> longestSccChainSize; | 
			
		||||
 | 
				            mutable std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType>> sccSolver; | 
			
		||||
 | 
				            mutable std::unique_ptr<std::vector<ValueType>> auxiliaryRowGroupVector; // A.rowGroupCount() entries | 
			
		||||
 | 
				        }; | 
			
		||||
 | 
				         | 
			
		||||
 | 
				        template<typename ValueType> | 
			
		||||
 | 
				        class TopologicalMinMaxLinearEquationSolverFactory : public MinMaxLinearEquationSolverFactory<ValueType> { | 
			
		||||
 | 
				        public: | 
			
		||||
 | 
				            using MinMaxLinearEquationSolverFactory<ValueType>::create; | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            virtual std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType>> create(Environment const& env) const override; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        }; | 
			
		||||
 | 
				         | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				} | 
			
		||||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue