#include "storm/solver/MinMaxLinearEquationSolver.h" #include #include "storm/solver/LinearEquationSolver.h" #include "storm/solver/IterativeMinMaxLinearEquationSolver.h" #include "storm/solver/TopologicalMinMaxLinearEquationSolver.h" #include "storm/solver/TopologicalCudaMinMaxLinearEquationSolver.h" #include "storm/solver/LpMinMaxLinearEquationSolver.h" #include "storm/solver/AcyclicMinMaxLinearEquationSolver.h" #include "storm/environment/solver/MinMaxSolverEnvironment.h" #include "storm/utility/macros.h" #include "storm/exceptions/NotImplementedException.h" #include "storm/exceptions/InvalidSettingsException.h" #include "storm/exceptions/IllegalFunctionCallException.h" namespace storm { namespace solver { template MinMaxLinearEquationSolver::MinMaxLinearEquationSolver(OptimizationDirectionSetting direction) : direction(direction), trackScheduler(false), uniqueSolution(false), noEndComponents(false), cachingEnabled(false), requirementsChecked(false) { // Intentionally left empty. } template MinMaxLinearEquationSolver::~MinMaxLinearEquationSolver() { // Intentionally left empty. } template bool MinMaxLinearEquationSolver::solveEquations(Environment const& env, OptimizationDirection d, std::vector& x, std::vector const& b) const { STORM_LOG_WARN_COND_DEBUG(this->isRequirementsCheckedSet(), "The requirements of the solver have not been marked as checked. Please provide the appropriate check or mark the requirements as checked (if applicable)."); return internalSolveEquations(env, d, x, b); } template void MinMaxLinearEquationSolver::solveEquations(Environment const& env, std::vector& x, std::vector const& b) const { STORM_LOG_THROW(isSet(this->direction), storm::exceptions::IllegalFunctionCallException, "Optimization direction not set."); solveEquations(env, convert(this->direction), x, b); } template void MinMaxLinearEquationSolver::setOptimizationDirection(OptimizationDirection d) { direction = convert(d); } template void MinMaxLinearEquationSolver::unsetOptimizationDirection() { direction = OptimizationDirectionSetting::Unset; } template void MinMaxLinearEquationSolver::setHasUniqueSolution(bool value) { uniqueSolution = value; } template bool MinMaxLinearEquationSolver::hasUniqueSolution() const { return uniqueSolution || noEndComponents; } template void MinMaxLinearEquationSolver::setHasNoEndComponents(bool value) { noEndComponents = value; } template bool MinMaxLinearEquationSolver::hasNoEndComponents() const { return noEndComponents; } template void MinMaxLinearEquationSolver::setTrackScheduler(bool trackScheduler) { this->trackScheduler = trackScheduler; if (!this->trackScheduler) { schedulerChoices = boost::none; } } template bool MinMaxLinearEquationSolver::isTrackSchedulerSet() const { return this->trackScheduler; } template bool MinMaxLinearEquationSolver::hasScheduler() const { return static_cast(schedulerChoices); } template storm::storage::Scheduler MinMaxLinearEquationSolver::computeScheduler() const { STORM_LOG_THROW(hasScheduler(), storm::exceptions::IllegalFunctionCallException, "Cannot retrieve scheduler, because none was generated."); storm::storage::Scheduler result(schedulerChoices->size()); uint_fast64_t state = 0; for (auto const& schedulerChoice : schedulerChoices.get()) { result.setChoice(schedulerChoice, state); ++state; } return result; } template std::vector const& MinMaxLinearEquationSolver::getSchedulerChoices() const { STORM_LOG_THROW(hasScheduler(), storm::exceptions::IllegalFunctionCallException, "Cannot retrieve scheduler choices, because they were not generated."); return schedulerChoices.get(); } template void MinMaxLinearEquationSolver::setCachingEnabled(bool value) { if(cachingEnabled && !value) { // caching will be turned off. Hence we clear the cache at this point clearCache(); } cachingEnabled = value; } template bool MinMaxLinearEquationSolver::isCachingEnabled() const { return cachingEnabled; } template void MinMaxLinearEquationSolver::clearCache() const { // Intentionally left empty. } template void MinMaxLinearEquationSolver::setInitialScheduler(std::vector&& choices) { initialScheduler = std::move(choices); } template bool MinMaxLinearEquationSolver::hasInitialScheduler() const { return static_cast(initialScheduler); } template std::vector const& MinMaxLinearEquationSolver::getInitialScheduler() const { return initialScheduler.get(); } template MinMaxLinearEquationSolverRequirements MinMaxLinearEquationSolver::getRequirements(Environment const&, boost::optional const& direction, bool const& hasInitialScheduler) const { return MinMaxLinearEquationSolverRequirements(); } template void MinMaxLinearEquationSolver::setRequirementsChecked(bool value) { this->requirementsChecked = value; } template bool MinMaxLinearEquationSolver::isRequirementsCheckedSet() const { return requirementsChecked; } template MinMaxLinearEquationSolverFactory::MinMaxLinearEquationSolverFactory() : requirementsChecked(false) { // Intentionally left empty } template void MinMaxLinearEquationSolverFactory::setRequirementsChecked(bool value) { this->requirementsChecked = value; } template bool MinMaxLinearEquationSolverFactory::isRequirementsCheckedSet() const { return this->requirementsChecked; } template MinMaxLinearEquationSolverRequirements MinMaxLinearEquationSolverFactory::getRequirements(Environment const& env, bool hasUniqueSolution, bool hasNoEndComponents, boost::optional const& direction, bool hasInitialScheduler, bool trackScheduler) const { // Create dummy solver and ask it for requirements. std::unique_ptr> solver = this->create(env); solver->setTrackScheduler(trackScheduler); solver->setHasUniqueSolution(hasUniqueSolution); solver->setHasNoEndComponents(hasNoEndComponents); return solver->getRequirements(env, direction, hasInitialScheduler); } template std::unique_ptr> MinMaxLinearEquationSolverFactory::create(Environment const& env, storm::storage::SparseMatrix const& matrix) const { std::unique_ptr> solver = this->create(env); solver->setMatrix(matrix); return solver; } template std::unique_ptr> MinMaxLinearEquationSolverFactory::create(Environment const& env, storm::storage::SparseMatrix&& matrix) const { std::unique_ptr> solver = this->create(env); solver->setMatrix(std::move(matrix)); return solver; } template GeneralMinMaxLinearEquationSolverFactory::GeneralMinMaxLinearEquationSolverFactory() : MinMaxLinearEquationSolverFactory() { // Intentionally left empty. } template std::unique_ptr> GeneralMinMaxLinearEquationSolverFactory::create(Environment const& env) const { std::unique_ptr> result; auto method = env.solver().minMax().getMethod(); if (method == MinMaxMethod::ValueIteration || method == MinMaxMethod::PolicyIteration || method == MinMaxMethod::RationalSearch || method == MinMaxMethod::IntervalIteration || method == MinMaxMethod::SoundValueIteration || method == MinMaxMethod::OptimisticValueIteration || method == MinMaxMethod::ViToPi) { result = std::make_unique>(std::make_unique>()); } else if (method == MinMaxMethod::Topological) { result = std::make_unique>(); } else if (method == MinMaxMethod::TopologicalCuda) { result = std::make_unique>(); } else if (method == MinMaxMethod::LinearProgramming) { result = std::make_unique>(std::make_unique>()); } else if (method == MinMaxMethod::Acyclic) { result = std::make_unique>(); } else { STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "Unsupported technique."); } result->setRequirementsChecked(this->isRequirementsCheckedSet()); return result; } template<> std::unique_ptr> GeneralMinMaxLinearEquationSolverFactory::create(Environment const& env) const { std::unique_ptr> result; auto method = env.solver().minMax().getMethod(); if (method == MinMaxMethod::ValueIteration || method == MinMaxMethod::PolicyIteration || method == MinMaxMethod::RationalSearch || method == MinMaxMethod::IntervalIteration || method == MinMaxMethod::SoundValueIteration || method == MinMaxMethod::OptimisticValueIteration || method == MinMaxMethod::ViToPi) { result = std::make_unique>(std::make_unique>()); } else if (method == MinMaxMethod::LinearProgramming) { result = std::make_unique>(std::make_unique>()); } else if (method == MinMaxMethod::Acyclic) { result = std::make_unique>(); } else if (method == MinMaxMethod::Topological) { result = std::make_unique>(); } else { STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "Unsupported technique."); } result->setRequirementsChecked(this->isRequirementsCheckedSet()); return result; } template class MinMaxLinearEquationSolver; template class MinMaxLinearEquationSolver; template class MinMaxLinearEquationSolverFactory; template class GeneralMinMaxLinearEquationSolverFactory; #ifdef STORM_HAVE_CARL template class MinMaxLinearEquationSolver; template class MinMaxLinearEquationSolverFactory; template class GeneralMinMaxLinearEquationSolverFactory; #endif } }