#include "src/solver/EliminationLinearEquationSolver.h" #include #include "src/settings/SettingsManager.h" #include "src/solver/stateelimination/StatePriorityQueue.h" #include "src/solver/stateelimination/PrioritizedStateEliminator.h" #include "src/utility/graph.h" #include "src/utility/macros.h" #include "src/utility/vector.h" #include "src/utility/stateelimination.h" namespace storm { namespace solver { using namespace stateelimination; using namespace storm::utility::stateelimination; template EliminationLinearEquationSolverSettings::EliminationLinearEquationSolverSettings() { order = storm::settings::getModule().getEliminationOrder(); } template void EliminationLinearEquationSolverSettings::setEliminationOrder(storm::settings::modules::EliminationSettings::EliminationOrder const& order) { this->order = order; } template storm::settings::modules::EliminationSettings::EliminationOrder EliminationLinearEquationSolverSettings::getEliminationOrder() const { return order; } template EliminationLinearEquationSolver::EliminationLinearEquationSolver(storm::storage::SparseMatrix const& A, EliminationLinearEquationSolverSettings const& settings) : localA(nullptr), A(nullptr), settings(settings) { this->setMatrix(A); } template EliminationLinearEquationSolver::EliminationLinearEquationSolver(storm::storage::SparseMatrix&& A, EliminationLinearEquationSolverSettings const& settings) : localA(nullptr), A(nullptr), settings(settings) { this->setMatrix(std::move(A)); } template void EliminationLinearEquationSolver::setMatrix(storm::storage::SparseMatrix const& A) { this->A = &A; localA.reset(); } template void EliminationLinearEquationSolver::setMatrix(storm::storage::SparseMatrix&& A) { localA = std::make_unique>(std::move(A)); this->A = localA.get(); } template void EliminationLinearEquationSolver::solveEquations(std::vector& x, std::vector 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 // but arbitrary matrices require pivoting, which is not currently implemented. STORM_LOG_DEBUG("Solving equation system using elimination."); // We need to revert the transformation into an equation system matrix, because the elimination procedure // and the distance computation is based on the probability matrix instead. storm::storage::SparseMatrix locallyConvertedMatrix; if (localA) { localA->convertToEquationSystem(); } else { locallyConvertedMatrix = *A; locallyConvertedMatrix.convertToEquationSystem(); } storm::storage::SparseMatrix const& transitionMatrix = localA ? *localA : locallyConvertedMatrix; storm::storage::SparseMatrix backwardTransitions = transitionMatrix.transpose(); // Initialize the solution to the right-hand side of the equation system. x = b; // Translate the matrix and its transpose into the flexible format. storm::storage::FlexibleSparseMatrix flexibleMatrix(transitionMatrix, false); storm::storage::FlexibleSparseMatrix flexibleBackwardTransitions(backwardTransitions, true); boost::optional> distanceBasedPriorities; auto order = this->getSettings().getEliminationOrder(); if (eliminationOrderNeedsDistances(order)) { // Since we have no initial states at this point, we determine a representative of every BSCC regarding // the backward transitions, because this means that every row is reachable from this set of rows, which // we require to make sure we cover every row. storm::storage::BitVector initialRows = storm::utility::graph::getBsccCover(backwardTransitions); distanceBasedPriorities = getDistanceBasedPriorities(transitionMatrix, backwardTransitions, initialRows, b, eliminationOrderNeedsForwardDistances(order), eliminationOrderNeedsReversedDistances(order)); } std::shared_ptr priorityQueue = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, b, storm::storage::BitVector(x.size(), true)); // Create a state eliminator to perform the actual elimination. PrioritizedStateEliminator eliminator(flexibleMatrix, flexibleBackwardTransitions, priorityQueue, x); // Eliminate all states. while (priorityQueue->hasNext()) { auto state = priorityQueue->pop(); eliminator.eliminateState(state, false); } // After having solved the system, we need to revert the transition system if we kept it local. if (localA) { localA->convertToEquationSystem(); }; } template void EliminationLinearEquationSolver::multiply(std::vector& x, std::vector const* b, std::vector& result) const { if (&x != &result) { A->multiplyWithVector(x, result); if (b != nullptr) { storm::utility::vector::addVectors(result, *b, result); } } else { // If the two vectors are aliases, we need to create a temporary. std::vector tmp(result.size()); A->multiplyWithVector(x, tmp); if (b != nullptr) { storm::utility::vector::addVectors(tmp, *b, result); } } } template EliminationLinearEquationSolverSettings& EliminationLinearEquationSolver::getSettings() { return settings; } template EliminationLinearEquationSolverSettings const& EliminationLinearEquationSolver::getSettings() const { return settings; } template uint64_t EliminationLinearEquationSolver::getMatrixRowCount() const { return this->A->getRowCount(); } template uint64_t EliminationLinearEquationSolver::getMatrixColumnCount() const { return this->A->getColumnCount(); } template std::unique_ptr> EliminationLinearEquationSolverFactory::create(storm::storage::SparseMatrix const& matrix) const { return std::make_unique>(matrix, settings); } template std::unique_ptr> EliminationLinearEquationSolverFactory::create(storm::storage::SparseMatrix&& matrix) const { return std::make_unique>(std::move(matrix), settings); } template EliminationLinearEquationSolverSettings& EliminationLinearEquationSolverFactory::getSettings() { return settings; } template EliminationLinearEquationSolverSettings const& EliminationLinearEquationSolverFactory::getSettings() const { return settings; } template std::unique_ptr> EliminationLinearEquationSolverFactory::clone() const { return std::make_unique>(*this); } template class EliminationLinearEquationSolverSettings; template class EliminationLinearEquationSolver; template class EliminationLinearEquationSolverFactory; #ifdef STORM_HAVE_CARL template class EliminationLinearEquationSolverSettings; template class EliminationLinearEquationSolverSettings; template class EliminationLinearEquationSolver; template class EliminationLinearEquationSolver; template class EliminationLinearEquationSolverFactory; template class EliminationLinearEquationSolverFactory; #endif } }