#include "storm/solver/SymbolicEliminationLinearEquationSolver.h" #include "storm/storage/dd/DdManager.h" #include "storm/storage/dd/Add.h" #include "storm/utility/dd.h" #include "storm/adapters/RationalFunctionAdapter.h" namespace storm { namespace solver { template SymbolicEliminationLinearEquationSolver::SymbolicEliminationLinearEquationSolver() : SymbolicLinearEquationSolver() { // Intentionally left empty. } template SymbolicEliminationLinearEquationSolver::SymbolicEliminationLinearEquationSolver(storm::dd::Add const& A, storm::dd::Bdd const& allRows, std::set const& rowMetaVariables, std::set const& columnMetaVariables, std::vector> const& rowColumnMetaVariablePairs) : SymbolicEliminationLinearEquationSolver(allRows, rowMetaVariables, columnMetaVariables, rowColumnMetaVariablePairs) { this->setMatrix(A); } template SymbolicEliminationLinearEquationSolver::SymbolicEliminationLinearEquationSolver(storm::dd::Bdd const& allRows, std::set const& rowMetaVariables, std::set const& columnMetaVariables, std::vector> const& rowColumnMetaVariablePairs) : SymbolicLinearEquationSolver(allRows, rowMetaVariables, columnMetaVariables, rowColumnMetaVariablePairs) { this->createInternalData(allRows, rowMetaVariables, columnMetaVariables, rowColumnMetaVariablePairs); } template storm::dd::Add SymbolicEliminationLinearEquationSolver::solveEquations(storm::dd::Add const& x, storm::dd::Add const& b) const { storm::dd::DdManager& ddManager = x.getDdManager(); // Build diagonal BDD over new meta variables. storm::dd::Bdd diagonal = storm::utility::dd::getRowColumnDiagonal(ddManager, this->rowColumnMetaVariablePairs); diagonal &= this->getAllRows(); diagonal = diagonal.swapVariables(this->oldNewMetaVariablePairs); storm::dd::Add rowsAdd = this->getAllRows().swapVariables(rowRowMetaVariablePairs).template toAdd(); storm::dd::Add diagonalAdd = diagonal.template toAdd(); // Move the matrix to the new meta variables. storm::dd::Add matrix = this->A.swapVariables(oldNewMetaVariablePairs); // Initialize solution over the new meta variables. storm::dd::Add solution = b.swapVariables(oldNewMetaVariablePairs); // As long as there are transitions, we eliminate them. uint64_t iterations = 0; while (!matrix.isZero()) { // Determine inverse loop probabilies. storm::dd::Add inverseLoopProbabilities = rowsAdd / (rowsAdd - (diagonalAdd * matrix).sumAbstract(newColumnVariables)); // Scale all transitions with the inverse loop probabilities. matrix *= inverseLoopProbabilities; solution *= inverseLoopProbabilities; // Delete diagonal elements, i.e. remove self-loops. matrix = diagonal.ite(ddManager.template getAddZero(), matrix); // Update the one-step probabilities. solution += (matrix * solution.swapVariables(newRowColumnMetaVariablePairs)).sumAbstract(newColumnVariables); // Shortcut all transitions by eliminating one intermediate step. matrix = matrix.multiplyMatrix(matrix.permuteVariables(shiftMetaVariablePairs), newColumnVariables); matrix = matrix.swapVariables(columnHelperMetaVariablePairs); ++iterations; STORM_LOG_TRACE("Completed iteration " << iterations << " of elimination process."); } STORM_LOG_INFO("Elimination completed in " << iterations << " iterations."); return solution.swapVariables(rowRowMetaVariablePairs); } template LinearEquationSolverProblemFormat SymbolicEliminationLinearEquationSolver::getEquationProblemFormat() const { return LinearEquationSolverProblemFormat::FixedPointSystem; } template void SymbolicEliminationLinearEquationSolver::createInternalData(storm::dd::Bdd const& allRows, std::set const& rowMetaVariables, std::set const& columnMetaVariables, std::vector> const& rowColumnMetaVariablePairs) { storm::dd::DdManager& ddManager = allRows.getDdManager(); // Create triple-layered meta variables for all original meta variables. We will use them later in the elimination process. for (auto const& metaVariablePair : this->rowColumnMetaVariablePairs) { auto rowVariable = metaVariablePair.first; storm::dd::DdMetaVariable const& metaVariable = ddManager.getMetaVariable(rowVariable); std::vector newMetaVariables; // Find a suitable name for the temporary variable. uint64_t counter = 0; std::string newMetaVariableName = "tmp_" + metaVariable.getName(); while (ddManager.hasMetaVariable(newMetaVariableName + std::to_string(counter))) { ++counter; } newMetaVariables = ddManager.cloneVariable(metaVariablePair.first, newMetaVariableName + std::to_string(counter), 3); newRowVariables.insert(newMetaVariables[0]); newColumnVariables.insert(newMetaVariables[1]); helperVariables.insert(newMetaVariables[2]); newRowColumnMetaVariablePairs.emplace_back(newMetaVariables[0], newMetaVariables[1]); columnHelperMetaVariablePairs.emplace_back(newMetaVariables[1], newMetaVariables[2]); rowRowMetaVariablePairs.emplace_back(metaVariablePair.first, newMetaVariables[0]); columnColumnMetaVariablePairs.emplace_back(metaVariablePair.second, newMetaVariables[1]); oldToNewMapping.emplace_back(std::move(newMetaVariables)); } oldNewMetaVariablePairs = rowRowMetaVariablePairs; for (auto const& entry : columnColumnMetaVariablePairs) { oldNewMetaVariablePairs.emplace_back(entry.first, entry.second); } shiftMetaVariablePairs = newRowColumnMetaVariablePairs; for (auto const& entry : columnHelperMetaVariablePairs) { shiftMetaVariablePairs.emplace_back(entry.first, entry.second); } } template void SymbolicEliminationLinearEquationSolver::setData(storm::dd::Bdd const& allRows, std::set const& rowMetaVariables, std::set const& columnMetaVariables, std::vector> const& rowColumnMetaVariablePairs) { // Call superclass function. SymbolicLinearEquationSolver::setData(allRows, rowMetaVariables, columnMetaVariables, rowColumnMetaVariablePairs); // Now create new variables as needed. this->createInternalData(this->getAllRows(), this->rowMetaVariables, this->columnMetaVariables, this->rowColumnMetaVariablePairs); } template std::unique_ptr> SymbolicEliminationLinearEquationSolverFactory::create() const { return std::make_unique>(); } template SymbolicEliminationLinearEquationSolverSettings& SymbolicEliminationLinearEquationSolverFactory::getSettings() { return settings; } template SymbolicEliminationLinearEquationSolverSettings const& SymbolicEliminationLinearEquationSolverFactory::getSettings() const { return settings; } template class SymbolicEliminationLinearEquationSolver; template class SymbolicEliminationLinearEquationSolver; template class SymbolicEliminationLinearEquationSolver; template class SymbolicEliminationLinearEquationSolver; template class SymbolicEliminationLinearEquationSolver; template class SymbolicEliminationLinearEquationSolverFactory; template class SymbolicEliminationLinearEquationSolverFactory; template class SymbolicEliminationLinearEquationSolverFactory; template class SymbolicEliminationLinearEquationSolverFactory; template class SymbolicEliminationLinearEquationSolverFactory; } }