dehnert
11 years ago
29 changed files with 1415 additions and 705 deletions
-
20CMakeLists.txt
-
11src/counterexamples/MILPMinimalLabelSetGenerator.h
-
2src/counterexamples/PathBasedSubsystemGenerator.h
-
14src/counterexamples/SMTMinimalCommandSetGenerator.h
-
8src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp
-
442src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.h
-
148src/modelchecker/prctl/SparseMdpPrctlModelChecker.h
-
2src/models/AtomicPropositionsLabeling.h
-
4src/models/Dtmc.h
-
8src/models/MarkovAutomaton.h
-
76src/solver/AbstractNondeterministicLinearEquationSolver.h
-
172src/solver/GlpkLpSolver.cpp
-
113src/solver/GlpkLpSolver.h
-
47src/solver/GmmxxNondeterministicLinearEquationSolver.h
-
1src/solver/GurobiLpSolver.cpp
-
4src/storage/BitVector.h
-
73src/storage/SparseMatrix.cpp
-
160src/storage/SparseMatrix.h
-
25src/storm.cpp
-
13src/utility/StormOptions.cpp
-
102src/utility/graph.h
-
36src/utility/solver.cpp
-
12src/utility/solver.h
-
600src/utility/vector.h
-
3storm-config.h.in
-
8test/functional/modelchecker/GmmxxMdpPrctlModelCheckerTest.cpp
-
8test/functional/modelchecker/SparseMdpPrctlModelCheckerTest.cpp
-
4test/performance/modelchecker/GmmxxMdpPrctModelCheckerTest.cpp
-
4test/performance/modelchecker/SparseMdpPrctlModelCheckerTest.cpp
@ -0,0 +1,8 @@ |
|||
#include "src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.h"
|
|||
|
|||
bool SparseMarkovAutomatonCslModelCheckerOptionsRegistered = storm::settings::Settings::registerNewModule([] (storm::settings::Settings* instance) -> bool { |
|||
|
|||
instance->addOption(storm::settings::OptionBuilder("GmmxxLinearEquationSolver", "digiprecision", "", "Precision used for iterative solving of linear equation systems").addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("precision value", "Precision").setDefaultValueDouble(1e-4).addValidationFunctionDouble(storm::settings::ArgumentValidators::doubleRangeValidatorExcluding(0.0, 1.0)).build()).build()); |
|||
|
|||
return true; |
|||
}); |
@ -0,0 +1,172 @@ |
|||
#include "src/solver/GlpkLpSolver.h"
|
|||
|
|||
#ifdef STORM_HAVE_GLPK
|
|||
|
|||
#include <iostream>
|
|||
|
|||
#include "src/exceptions/InvalidStateException.h"
|
|||
#include "src/settings/Settings.h"
|
|||
|
|||
#include "log4cplus/logger.h"
|
|||
#include "log4cplus/loggingmacros.h"
|
|||
|
|||
extern log4cplus::Logger logger; |
|||
|
|||
namespace storm { |
|||
namespace solver { |
|||
GlpkLpSolver::GlpkLpSolver(std::string const& name, ModelSense const& modelSense) : LpSolver(modelSense), lp(nullptr), nextVariableIndex(1), nextConstraintIndex(1), isOptimal(false), rowIndices(), columnIndices(), coefficientValues() { |
|||
// Create the LP problem for glpk.
|
|||
lp = glp_create_prob(); |
|||
|
|||
// Set its name and model sense.
|
|||
glp_set_prob_name(lp, name.c_str()); |
|||
this->setModelSense(modelSense); |
|||
|
|||
// Because glpk uses 1-based indexing (wtf!?), we need to put dummy elements into the matrix vectors.
|
|||
rowIndices.push_back(0); |
|||
columnIndices.push_back(0); |
|||
coefficientValues.push_back(0); |
|||
} |
|||
|
|||
GlpkLpSolver::GlpkLpSolver(std::string const& name) : GlpkLpSolver(name, MINIMIZE) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
GlpkLpSolver::~GlpkLpSolver() { |
|||
glp_delete_prob(this->lp); |
|||
glp_free_env(); |
|||
} |
|||
|
|||
uint_fast64_t GlpkLpSolver::createContinuousVariable(std::string const& name, VariableType const& variableType, double lowerBound, double upperBound, double objectiveFunctionCoefficient) { |
|||
glp_add_cols(this->lp, 1); |
|||
glp_set_col_name(this->lp, nextVariableIndex, name.c_str()); |
|||
switch (variableType) { |
|||
case LpSolver::BOUNDED: |
|||
glp_set_col_bnds(lp, nextVariableIndex, GLP_DB, lowerBound, upperBound); |
|||
break; |
|||
case LpSolver::UNBOUNDED: |
|||
glp_set_col_bnds(lp, nextVariableIndex, GLP_FR, 0, 0); |
|||
break; |
|||
case LpSolver::UPPER_BOUND: |
|||
glp_set_col_bnds(lp, nextVariableIndex, GLP_UP, 0, upperBound); |
|||
break; |
|||
case LpSolver::LOWER_BOUND: |
|||
glp_set_col_bnds(lp, nextVariableIndex, GLP_LO, lowerBound, 0); |
|||
break; |
|||
} |
|||
glp_set_col_kind(this->lp, nextVariableIndex, GLP_CV); |
|||
glp_set_obj_coef(this->lp, nextVariableIndex, objectiveFunctionCoefficient); |
|||
++nextVariableIndex; |
|||
|
|||
this->isOptimal = false; |
|||
|
|||
return nextVariableIndex - 1; |
|||
} |
|||
|
|||
uint_fast64_t GlpkLpSolver::createIntegerVariable(std::string const& name, VariableType const& variableType, double lowerBound, double upperBound, double objectiveFunctionCoefficient) { |
|||
uint_fast64_t index = this->createContinuousVariable(name, variableType, lowerBound, upperBound, objectiveFunctionCoefficient); |
|||
glp_set_col_kind(this->lp, index, GLP_IV); |
|||
return index; |
|||
} |
|||
|
|||
uint_fast64_t GlpkLpSolver::createBinaryVariable(std::string const& name, double objectiveFunctionCoefficient) { |
|||
uint_fast64_t index = this->createContinuousVariable(name, UNBOUNDED, 0, 1, objectiveFunctionCoefficient); |
|||
glp_set_col_kind(this->lp, index, GLP_BV); |
|||
return index; |
|||
} |
|||
|
|||
void GlpkLpSolver::addConstraint(std::string const& name, std::vector<uint_fast64_t> const& variables, std::vector<double> const& coefficients, BoundType const& boundType, double rightHandSideValue) { |
|||
if (variables.size() != coefficients.size()) { |
|||
LOG4CPLUS_ERROR(logger, "Sizes of variable indices vector and coefficients vector do not match."); |
|||
throw storm::exceptions::InvalidStateException() << "Sizes of variable indices vector and coefficients vector do not match."; |
|||
} |
|||
|
|||
// Add the row that will represent this constraint.
|
|||
glp_add_rows(this->lp, 1); |
|||
glp_set_row_name(this->lp, nextConstraintIndex, name.c_str()); |
|||
|
|||
// Determine the type of the constraint and add it properly.
|
|||
bool isUpperBound = boundType == LESS || boundType == LESS_EQUAL; |
|||
bool isStrict = boundType == LESS || boundType == GREATER; |
|||
switch (boundType) { |
|||
case LESS: |
|||
glp_set_row_bnds(this->lp, nextConstraintIndex, GLP_UP, 0, rightHandSideValue - storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
break; |
|||
case LESS_EQUAL: |
|||
glp_set_row_bnds(this->lp, nextConstraintIndex, GLP_UP, 0, rightHandSideValue); |
|||
break; |
|||
case GREATER: |
|||
glp_set_row_bnds(this->lp, nextConstraintIndex, GLP_LO, rightHandSideValue + storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble(), 0); |
|||
break; |
|||
case GREATER_EQUAL: |
|||
glp_set_row_bnds(this->lp, nextConstraintIndex, GLP_LO, rightHandSideValue, 0); |
|||
break; |
|||
case EQUAL: |
|||
glp_set_row_bnds(this->lp, nextConstraintIndex, GLP_FX, rightHandSideValue, rightHandSideValue); |
|||
break; |
|||
} |
|||
|
|||
// Record the variables and coefficients in the coefficient matrix.
|
|||
rowIndices.insert(rowIndices.end(), variables.size(), nextConstraintIndex); |
|||
columnIndices.insert(columnIndices.end(), variables.begin(), variables.end()); |
|||
coefficientValues.insert(coefficientValues.end(), coefficients.begin(), coefficients.end()); |
|||
|
|||
++nextConstraintIndex; |
|||
this->isOptimal = false; |
|||
} |
|||
|
|||
void GlpkLpSolver::setModelSense(ModelSense const& newModelSense) { |
|||
glp_set_obj_dir(this->lp, newModelSense == MINIMIZE ? GLP_MIN : GLP_MAX); |
|||
this->isOptimal = false; |
|||
} |
|||
|
|||
void GlpkLpSolver::optimize() const { |
|||
glp_load_matrix(this->lp, rowIndices.size() - 1, rowIndices.data(), columnIndices.data(), coefficientValues.data()); |
|||
int error = glp_simplex(this->lp, nullptr); |
|||
|
|||
if (error != 0) { |
|||
LOG4CPLUS_ERROR(logger, "Unable to optimize glpk model (" << error << ")."); |
|||
throw storm::exceptions::InvalidStateException() << "Unable to optimize glpk model (" << error << ")."; |
|||
} |
|||
|
|||
this->isOptimal = true; |
|||
} |
|||
|
|||
int_fast64_t GlpkLpSolver::getIntegerValue(uint_fast64_t variableIndex) const { |
|||
double value = glp_get_col_prim(this->lp, static_cast<int>(variableIndex)); |
|||
|
|||
if (std::abs(value - static_cast<int>(value)) <= storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()) { |
|||
// Nothing to do in this case.
|
|||
} else if (std::abs(value) > storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()) { |
|||
LOG4CPLUS_ERROR(logger, "Illegal value for integer variable in glpk solution (" << value << ")."); |
|||
throw storm::exceptions::InvalidStateException() << "Illegal value for integer variable in glpk solution (" << value << ")."; |
|||
} |
|||
|
|||
return static_cast<int_fast64_t>(value); |
|||
} |
|||
|
|||
bool GlpkLpSolver::getBinaryValue(uint_fast64_t variableIndex) const { |
|||
double value = glp_get_col_prim(this->lp, static_cast<int>(variableIndex)); |
|||
|
|||
if (std::abs(value - 1) <= storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()) { |
|||
// Nothing to do in this case.
|
|||
} else if (std::abs(value) > storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()) { |
|||
LOG4CPLUS_ERROR(logger, "Illegal value for binary variable in Gurobi solution (" << value << ")."); |
|||
throw storm::exceptions::InvalidStateException() << "Illegal value for binary variable in Gurobi solution (" << value << ")."; |
|||
} |
|||
|
|||
return static_cast<bool>(value); |
|||
} |
|||
|
|||
double GlpkLpSolver::getContinuousValue(uint_fast64_t variableIndex) const { |
|||
return glp_get_col_prim(this->lp, static_cast<int>(variableIndex)); |
|||
} |
|||
|
|||
void GlpkLpSolver::writeModelToFile(std::string const& filename) const { |
|||
glp_load_matrix(this->lp, rowIndices.size() - 1, rowIndices.data(), columnIndices.data(), coefficientValues.data()); |
|||
glp_write_lp(this->lp, 0, filename.c_str()); |
|||
} |
|||
} |
|||
} |
|||
|
|||
#endif
|
@ -0,0 +1,113 @@ |
|||
#ifndef STORM_SOLVER_GLPKLPSOLVER_H_ |
|||
#define STORM_SOLVER_GLPKLPSOLVER_H_ |
|||
|
|||
#include "src/solver/LpSolver.h" |
|||
#include "src/exceptions/NotImplementedException.h" |
|||
|
|||
// To detect whether the usage of glpk is possible, this include is neccessary. |
|||
#include "storm-config.h" |
|||
|
|||
#ifdef STORM_HAVE_GLPK |
|||
#include <glpk.h> |
|||
#endif |
|||
|
|||
namespace storm { |
|||
namespace solver { |
|||
#ifdef STORM_HAVE_GLPK |
|||
class GlpkLpSolver : public LpSolver { |
|||
public: |
|||
GlpkLpSolver(std::string const& name, ModelSense const& modelSense); |
|||
GlpkLpSolver(std::string const& name); |
|||
virtual ~GlpkLpSolver(); |
|||
|
|||
virtual uint_fast64_t createContinuousVariable(std::string const& name, VariableType const& variableType, double lowerBound, double upperBound, double objectiveFunctionCoefficient) override; |
|||
virtual uint_fast64_t createIntegerVariable(std::string const& name, VariableType const& variableType, double lowerBound, double upperBound, double objectiveFunctionCoefficient) override; |
|||
virtual uint_fast64_t createBinaryVariable(std::string const& name, double objectiveFunctionCoefficient) override; |
|||
|
|||
virtual void addConstraint(std::string const& name, std::vector<uint_fast64_t> const& variables, std::vector<double> const& coefficients, BoundType const& boundType, double rightHandSideValue) override; |
|||
|
|||
virtual void setModelSense(ModelSense const& newModelSense) override; |
|||
virtual void optimize() const override; |
|||
|
|||
virtual int_fast64_t getIntegerValue(uint_fast64_t variableIndex) const override; |
|||
virtual bool getBinaryValue(uint_fast64_t variableIndex) const override; |
|||
virtual double getContinuousValue(uint_fast64_t variableIndex) const override; |
|||
|
|||
virtual void writeModelToFile(std::string const& filename) const override; |
|||
|
|||
private: |
|||
// The glpk LP problem. |
|||
glp_prob* lp; |
|||
|
|||
// A counter that keeps track of the next free variable index. |
|||
uint_fast64_t nextVariableIndex; |
|||
|
|||
// A counter that keeps track of the next free constraint index. |
|||
uint_fast64_t nextConstraintIndex; |
|||
|
|||
// A flag that stores whether the model was optimized properly. |
|||
mutable bool isOptimal; |
|||
|
|||
// The arrays that store the coefficient matrix of the problem. |
|||
std::vector<int> rowIndices; |
|||
std::vector<int> columnIndices; |
|||
std::vector<double> coefficientValues; |
|||
}; |
|||
#else |
|||
// If glpk is not available, we provide a stub implementation that emits an error if any of its methods is called. |
|||
class GlpkLpSolver : public LpSolver { |
|||
public: |
|||
|
|||
GlpkLpSolver(std::string const& name) : LpSolver(MINIMIZE) { |
|||
throw storm::exceptions::NotImplementedException() << "This version of StoRM was compiled without support for glpk. Yet, a method was called that requires this support. Please choose a version of support with glpk support."; |
|||
} |
|||
|
|||
virtual ~GlpkLpSolver() { |
|||
throw storm::exceptions::NotImplementedException() << "This version of StoRM was compiled without support for glpk. Yet, a method was called that requires this support. Please choose a version of support with glpk support."; |
|||
} |
|||
|
|||
virtual uint_fast64_t createContinuousVariable(std::string const& name, VariableType const& variableType, double lowerBound, double upperBound, double objectiveFunctionCoefficient) override { |
|||
throw storm::exceptions::NotImplementedException() << "This version of StoRM was compiled without support for glpk. Yet, a method was called that requires this support. Please choose a version of support with glpk support."; |
|||
} |
|||
|
|||
virtual uint_fast64_t createIntegerVariable(std::string const& name, VariableType const& variableType, double lowerBound, double upperBound, double objectiveFunctionCoefficient) override { |
|||
throw storm::exceptions::NotImplementedException() << "This version of StoRM was compiled without support for glpk. Yet, a method was called that requires this support. Please choose a version of support with glpk support."; |
|||
} |
|||
|
|||
virtual uint_fast64_t createBinaryVariable(std::string const& name, double objectiveFunctionCoefficient) override { |
|||
throw storm::exceptions::NotImplementedException() << "This version of StoRM was compiled without support for glpk. Yet, a method was called that requires this support. Please choose a version of support with glpk support."; |
|||
} |
|||
|
|||
virtual void addConstraint(std::string const& name, std::vector<uint_fast64_t> const& variables, std::vector<double> const& coefficients, BoundType const& boundType, double rightHandSideValue) override { |
|||
throw storm::exceptions::NotImplementedException() << "This version of StoRM was compiled without support for glpk. Yet, a method was called that requires this support. Please choose a version of support with glpk support."; |
|||
} |
|||
|
|||
virtual void setModelSense(ModelSense const& newModelSense) { |
|||
throw storm::exceptions::NotImplementedException() << "This version of StoRM was compiled without support for glpk. Yet, a method was called that requires this support. Please choose a version of support with glpk support."; |
|||
} |
|||
|
|||
virtual void optimize() const override { |
|||
throw storm::exceptions::NotImplementedException() << "This version of StoRM was compiled without support for glpk. Yet, a method was called that requires this support. Please choose a version of support with glpk support."; |
|||
} |
|||
|
|||
virtual int_fast64_t getIntegerValue(uint_fast64_t variableIndex) const override { |
|||
throw storm::exceptions::NotImplementedException() << "This version of StoRM was compiled without support for glpk. Yet, a method was called that requires this support. Please choose a version of support with glpk support."; |
|||
} |
|||
|
|||
virtual bool getBinaryValue(uint_fast64_t variableIndex) const override { |
|||
throw storm::exceptions::NotImplementedException() << "This version of StoRM was compiled without support for glpk. Yet, a method was called that requires this support. Please choose a version of support with glpk support."; |
|||
} |
|||
|
|||
virtual double getContinuousValue(uint_fast64_t variableIndex) const override { |
|||
throw storm::exceptions::NotImplementedException() << "This version of StoRM was compiled without support for glpk. Yet, a method was called that requires this support. Please choose a version of support with glpk support."; |
|||
} |
|||
|
|||
virtual void writeModelToFile(std::string const& filename) const override { |
|||
throw storm::exceptions::NotImplementedException() << "This version of StoRM was compiled without support for glpk. Yet, a method was called that requires this support. Please choose a version of support with glpk support."; |
|||
} |
|||
}; |
|||
#endif |
|||
} |
|||
} |
|||
|
|||
#endif /* STORM_SOLVER_GLPKLPSOLVER_H_ */ |
@ -0,0 +1,36 @@ |
|||
#include "src/utility/solver.h"
|
|||
|
|||
#include "src/solver/GmmxxNondeterministicLinearEquationSolver.h"
|
|||
#include "src/solver/GurobiLpSolver.h"
|
|||
#include "src/solver/GlpkLpSolver.h"
|
|||
|
|||
namespace storm { |
|||
namespace utility { |
|||
namespace solver { |
|||
std::shared_ptr<storm::solver::LpSolver> getLpSolver(std::string const& name) { |
|||
std::string const& lpSolver = storm::settings::Settings::getInstance()->getOptionByLongName("lpSolver").getArgument(0).getValueAsString(); |
|||
if (lpSolver == "gurobi") { |
|||
return std::shared_ptr<storm::solver::LpSolver>(new storm::solver::GurobiLpSolver(name)); |
|||
} else if (lpSolver == "glpk") { |
|||
return std::shared_ptr<storm::solver::LpSolver>(new storm::solver::GlpkLpSolver(name)); |
|||
} |
|||
|
|||
throw storm::exceptions::InvalidSettingsException() << "No suitable LP-solver selected."; |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
std::shared_ptr<storm::solver::AbstractNondeterministicLinearEquationSolver<ValueType>> getNondeterministicLinearEquationSolver() { |
|||
std::string const& matrixLibrary = storm::settings::Settings::getInstance()->getOptionByLongName("matrixLibrary").getArgument(0).getValueAsString(); |
|||
if (matrixLibrary == "gmm++") { |
|||
return std::shared_ptr<storm::solver::AbstractNondeterministicLinearEquationSolver<ValueType>>(new storm::solver::GmmxxNondeterministicLinearEquationSolver<ValueType>()); |
|||
} else if (matrixLibrary == "native") { |
|||
return std::shared_ptr<storm::solver::AbstractNondeterministicLinearEquationSolver<ValueType>>(new storm::solver::AbstractNondeterministicLinearEquationSolver<ValueType>()); |
|||
} |
|||
|
|||
throw storm::exceptions::InvalidSettingsException() << "No suitable nondeterministic linear equation solver selected."; |
|||
} |
|||
|
|||
template std::shared_ptr<storm::solver::AbstractNondeterministicLinearEquationSolver<double>> getNondeterministicLinearEquationSolver(); |
|||
} |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue