diff --git a/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp b/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp index 82590e31e..580ea9c69 100644 --- a/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp +++ b/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp @@ -1,8 +1,8 @@ -#include "src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.h" +// #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; -}); \ No newline at end of file +//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; +//}); diff --git a/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.h b/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.h index aab76f807..8a924ba47 100644 --- a/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.h +++ b/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.h @@ -428,7 +428,7 @@ namespace storm { */ static ValueType computeLraForMaximalEndComponent(bool min, storm::storage::SparseMatrix const& transitionMatrix, std::vector const& nondeterministicChoiceIndices, storm::storage::BitVector const& markovianStates, std::vector const& exitRates, storm::storage::BitVector const& goalStates, storm::storage::MaximalEndComponent const& mec, uint_fast64_t mecIndex = 0) { std::shared_ptr solver = storm::utility::solver::getLpSolver("LRA for MEC"); - solver->setModelSense(min ? storm::solver::LpSolver::MAXIMIZE : storm::solver::LpSolver::MINIMIZE); + solver->setModelSense(min ? storm::solver::LpSolver::ModelSense::Maximize : storm::solver::LpSolver::ModelSense::Minimize); // First, we need to create the variables for the problem. std::map stateToVariableIndexMap; diff --git a/src/solver/GlpkLpSolver.cpp b/src/solver/GlpkLpSolver.cpp index 1cffa1a18..2a9eec7f6 100644 --- a/src/solver/GlpkLpSolver.cpp +++ b/src/solver/GlpkLpSolver.cpp @@ -21,7 +21,7 @@ bool GlpkLpSolverOptionsRegistered = storm::settings::Settings::registerNewModul namespace storm { namespace solver { - GlpkLpSolver::GlpkLpSolver(std::string const& name, ModelSense const& modelSense) : LpSolver(modelSense), lp(nullptr), variableNameToIndexMap(), nextVariableIndex(0), nextConstraintIndex(0), modelContainsIntegerVariables(false), isInfeasibleFlag(false), isUnboundedFlag(false), rowIndices(), columnIndices(), coefficientValues() { + GlpkLpSolver::GlpkLpSolver(std::string const& name, ModelSense const& modelSense) : LpSolver(modelSense), lp(nullptr), variableNameToIndexMap(), nextVariableIndex(1), nextConstraintIndex(1), modelContainsIntegerVariables(false), isInfeasibleFlag(false), isUnboundedFlag(false), rowIndices(), columnIndices(), coefficientValues() { // Create the LP problem for glpk. lp = glp_create_prob(); @@ -37,11 +37,11 @@ namespace storm { coefficientValues.push_back(0); } - GlpkLpSolver::GlpkLpSolver(std::string const& name) : GlpkLpSolver(name, ModelSense::MINIMIZE) { + GlpkLpSolver::GlpkLpSolver(std::string const& name) : GlpkLpSolver(name, ModelSense::Minimize) { // Intentionally left empty. } - GlpkLpSolver::GlpkLpSolver() : GlpkLpSolver("", ModelSense::MINIMIZE) { + GlpkLpSolver::GlpkLpSolver() : GlpkLpSolver("", ModelSense::Minimize) { // Intentionally left empty. } @@ -56,98 +56,65 @@ namespace storm { } void GlpkLpSolver::addBoundedContinuousVariable(std::string const& name, double lowerBound, double upperBound, double objectiveFunctionCoefficient) { - glp_add_cols(this->lp, 1); - glp_set_col_name(this->lp, nextVariableIndex, name.c_str()); - glp_set_col_bnds(lp, nextVariableIndex, GLP_DB, lowerBound, upperBound); - glp_set_col_kind(this->lp, nextVariableIndex, GLP_CV); - glp_set_obj_coef(this->lp, nextVariableIndex, objectiveFunctionCoefficient); - this->variableNameToIndexMap.emplace(name, this->nextVariableIndex); - ++this->nextVariableIndex; + this->addVariable(name, GLP_CV, GLP_DB, lowerBound, upperBound, objectiveFunctionCoefficient); } void GlpkLpSolver::addLowerBoundedContinuousVariable(std::string const& name, double lowerBound, double objectiveFunctionCoefficient) { - glp_add_cols(this->lp, 1); - glp_set_col_name(this->lp, nextVariableIndex, name.c_str()); - glp_set_col_bnds(lp, nextVariableIndex, GLP_LO, lowerBound, 0); - glp_set_col_kind(this->lp, nextVariableIndex, GLP_CV); - glp_set_obj_coef(this->lp, nextVariableIndex, objectiveFunctionCoefficient); - this->variableNameToIndexMap.emplace(name, this->nextVariableIndex); - ++this->nextVariableIndex; + this->addVariable(name, GLP_CV, GLP_LO, lowerBound, 0, objectiveFunctionCoefficient); } void GlpkLpSolver::addUpperBoundedContinuousVariable(std::string const& name, double upperBound, double objectiveFunctionCoefficient) { - glp_add_cols(this->lp, 1); - glp_set_col_name(this->lp, nextVariableIndex, name.c_str()); - glp_set_col_bnds(lp, nextVariableIndex, GLP_UP, 0, upperBound); - glp_set_col_kind(this->lp, nextVariableIndex, GLP_CV); - glp_set_obj_coef(this->lp, nextVariableIndex, objectiveFunctionCoefficient); - this->variableNameToIndexMap.emplace(name, this->nextVariableIndex); - ++this->nextVariableIndex; + this->addVariable(name, GLP_CV, GLP_UP, 0, upperBound, objectiveFunctionCoefficient); } void GlpkLpSolver::addUnboundedContinuousVariable(std::string const& name, double objectiveFunctionCoefficient) { - glp_add_cols(this->lp, 1); - glp_set_col_name(this->lp, nextVariableIndex, name.c_str()); - glp_set_col_bnds(lp, nextVariableIndex, GLP_FR, 0, 0); - glp_set_col_kind(this->lp, nextVariableIndex, GLP_CV); - glp_set_obj_coef(this->lp, nextVariableIndex, objectiveFunctionCoefficient); - this->variableNameToIndexMap.emplace(name, this->nextVariableIndex); - ++this->nextVariableIndex; + this->addVariable(name, GLP_CV, GLP_FR, 0, 0, objectiveFunctionCoefficient); } void GlpkLpSolver::addBoundedIntegerVariable(std::string const& name, double lowerBound, double upperBound, double objectiveFunctionCoefficient) { - glp_add_cols(this->lp, 1); - glp_set_col_name(this->lp, nextVariableIndex, name.c_str()); - glp_set_col_bnds(lp, nextVariableIndex, GLP_DB, lowerBound, upperBound); - glp_set_col_kind(this->lp, nextVariableIndex, GLP_IV); - glp_set_obj_coef(this->lp, nextVariableIndex, objectiveFunctionCoefficient); - this->variableNameToIndexMap.emplace(name, this->nextVariableIndex); - ++this->nextVariableIndex; + this->addVariable(name, GLP_IV, GLP_DB, lowerBound, upperBound, objectiveFunctionCoefficient); this->modelContainsIntegerVariables = true; } void GlpkLpSolver::addLowerBoundedIntegerVariable(std::string const& name, double lowerBound, double objectiveFunctionCoefficient) { - glp_add_cols(this->lp, 1); - glp_set_col_name(this->lp, nextVariableIndex, name.c_str()); - glp_set_col_bnds(lp, nextVariableIndex, GLP_LO, lowerBound, 0); - glp_set_col_kind(this->lp, nextVariableIndex, GLP_IV); - glp_set_obj_coef(this->lp, nextVariableIndex, objectiveFunctionCoefficient); - this->variableNameToIndexMap.emplace(name, this->nextVariableIndex); - ++this->nextVariableIndex; + this->addVariable(name, GLP_IV, GLP_LO, lowerBound, 0, objectiveFunctionCoefficient); this->modelContainsIntegerVariables = true; } void GlpkLpSolver::addUpperBoundedIntegerVariable(std::string const& name, double upperBound, double objectiveFunctionCoefficient) { - glp_add_cols(this->lp, 1); - glp_set_col_name(this->lp, nextVariableIndex, name.c_str()); - glp_set_col_bnds(lp, nextVariableIndex, GLP_UP, 0, upperBound); - glp_set_col_kind(this->lp, nextVariableIndex, GLP_IV); - glp_set_obj_coef(this->lp, nextVariableIndex, objectiveFunctionCoefficient); - this->variableNameToIndexMap.emplace(name, this->nextVariableIndex); - ++this->nextVariableIndex; + this->addVariable(name, GLP_IV, GLP_UP, 0, upperBound, objectiveFunctionCoefficient); this->modelContainsIntegerVariables = true; } void GlpkLpSolver::addUnboundedIntegerVariable(std::string const& name, double objectiveFunctionCoefficient) { - glp_add_cols(this->lp, 1); - glp_set_col_name(this->lp, nextVariableIndex, name.c_str()); - glp_set_col_bnds(lp, nextVariableIndex, GLP_FR, 0, 0); - glp_set_col_kind(this->lp, nextVariableIndex, GLP_IV); - glp_set_obj_coef(this->lp, nextVariableIndex, objectiveFunctionCoefficient); - this->variableNameToIndexMap.emplace(name, this->nextVariableIndex); - ++this->nextVariableIndex; + this->addVariable(name, GLP_IV, GLP_FR, 0, 0, objectiveFunctionCoefficient); this->modelContainsIntegerVariables = true; } void GlpkLpSolver::addBinaryVariable(std::string const& name, double objectiveFunctionCoefficient) { + this->addVariable(name, GLP_BV, GLP_FR, 0, 0, objectiveFunctionCoefficient); + this->modelContainsIntegerVariables = true; + } + + void GlpkLpSolver::addVariable(std::string const& name, int variableType, int boundType, double lowerBound, double upperBound, double objectiveFunctionCoefficient) { + // Check whether variable already exists. + auto nameIndexPair = this->variableNameToIndexMap.find(name); + LOG_THROW(nameIndexPair == this->variableNameToIndexMap.end(), storm::exceptions::InvalidArgumentException, "Variable '" << nameIndexPair->first << "' already exists."); + + // Check for valid variable type. + LOG_ASSERT(variableType == GLP_CV || variableType == GLP_IV || variableType == GLP_BV, "Illegal type '" << variableType << "' for glpk variable."); + + // Check for valid bound type. + LOG_ASSERT(boundType == GLP_FR || boundType == GLP_UP || boundType == GLP_LO || boundType == GLP_DB, "Illegal bound type for variable '" << name << "'."); + + // Finally, create the actual variable. glp_add_cols(this->lp, 1); glp_set_col_name(this->lp, nextVariableIndex, name.c_str()); - glp_set_col_bnds(lp, nextVariableIndex, GLP_FR, 0, 0); - glp_set_col_kind(this->lp, nextVariableIndex, GLP_BV); + glp_set_col_bnds(lp, nextVariableIndex, boundType, lowerBound, upperBound); + glp_set_col_kind(this->lp, nextVariableIndex, variableType); glp_set_obj_coef(this->lp, nextVariableIndex, objectiveFunctionCoefficient); this->variableNameToIndexMap.emplace(name, this->nextVariableIndex); ++this->nextVariableIndex; - this->modelContainsIntegerVariables = true; } void GlpkLpSolver::update() const { @@ -219,7 +186,7 @@ namespace storm { this->isUnboundedFlag = false; // Start by setting the model sense. - glp_set_obj_dir(this->lp, this->getModelSense() == LpSolver::ModelSense::MINIMIZE ? GLP_MIN : GLP_MAX); + glp_set_obj_dir(this->lp, this->getModelSense() == LpSolver::ModelSense::Minimize ? GLP_MIN : GLP_MAX); glp_load_matrix(this->lp, rowIndices.size() - 1, rowIndices.data(), columnIndices.data(), coefficientValues.data()); diff --git a/src/solver/GlpkLpSolver.h b/src/solver/GlpkLpSolver.h index 0045ced73..1f6d7bd2a 100644 --- a/src/solver/GlpkLpSolver.h +++ b/src/solver/GlpkLpSolver.h @@ -92,17 +92,29 @@ namespace storm { virtual void writeModelToFile(std::string const& filename) const override; private: + /*! + * Adds a variable with the given name, type, lower and upper bound and objective function coefficient. + * + * @param name The name of the variable. + * @param variableType The type of the variable in terms of glpk's constants. + * @param boundType A glpk flag indicating which bounds apply to the variable. + * @param lowerBound The lower bound of the range of the variable. + * @param upperBound The upper bound of the range of the variable. + * @param objectiveFunctionCoefficient The coefficient of the variable in the objective function. + */ + void addVariable(std::string const& name, int variableType, int boundType, double lowerBound, double upperBound, double objectiveFunctionCoefficient); + // The glpk LP problem. glp_prob* lp; // A mapping from variable names to their indices. - std::map variableNameToIndexMap; + std::map variableNameToIndexMap; // A counter used for getting the next variable index. - uint_fast64_t nextVariableIndex; + int nextVariableIndex; // A counter used for getting the next constraint index. - uint_fast64_t nextConstraintIndex; + int nextConstraintIndex; // A flag storing whether the model is an LP or an MILP. bool modelContainsIntegerVariables; diff --git a/src/solver/GurobiLpSolver.cpp b/src/solver/GurobiLpSolver.cpp index 75a0d5a7e..676867ecb 100644 --- a/src/solver/GurobiLpSolver.cpp +++ b/src/solver/GurobiLpSolver.cpp @@ -3,13 +3,12 @@ #ifdef STORM_HAVE_GUROBI #include -#include "src/exceptions/InvalidStateException.h" -#include "src/settings/Settings.h" +#include "src/storage/expressions/LinearCoefficientVisitor.h" -#include "log4cplus/logger.h" -#include "log4cplus/loggingmacros.h" - -extern log4cplus::Logger logger; +#include "src/settings/Settings.h" +#include "src/exceptions/ExceptionMacros.h" +#include "src/exceptions/InvalidStateException.h" +#include "src/exceptions/InvalidAccessException.h" bool GurobiLpSolverOptionsRegistered = storm::settings::Settings::registerNewModule([] (storm::settings::Settings* instance) -> bool { instance->addOption(storm::settings::OptionBuilder("GurobiLpSolver", "gurobithreads", "", "The number of threads that may be used by Gurobi.").addArgument(storm::settings::ArgumentBuilder::createUnsignedIntegerArgument("count", "The number of threads.").setDefaultValueUnsignedInteger(1).build()).build()); @@ -43,7 +42,7 @@ namespace storm { } } - GurobiLpSolver::GurobiLpSolver(std::string const& name) : GurobiLpSolver(name, MINIMIZE) { + GurobiLpSolver::GurobiLpSolver(std::string const& name) : GurobiLpSolver(name, ModelSense::Minimize) { // Intentionally left empty. } @@ -51,7 +50,7 @@ namespace storm { // Intentionally left empty. } - GurobiLpSolver::GurobiLpSolver() : GurobiLpSolver("", MINIMIZE) { + GurobiLpSolver::GurobiLpSolver() : GurobiLpSolver("", ModelSense::Minimize) { // Intentionally left empty. } @@ -66,145 +65,124 @@ namespace storm { // Enable the following line to only print the output of Gurobi if the debug flag is set. error = GRBsetintparam(env, "OutputFlag", storm::settings::Settings::getInstance()->isSet("debug") || storm::settings::Settings::getInstance()->isSet("gurobioutput") ? 1 : 0); - if (error) { - LOG4CPLUS_ERROR(logger, "Unable to set Gurobi Parameter OutputFlag (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to set Gurobi Parameter OutputFlag (" << GRBgeterrormsg(env) << ", error code " << error << ")."; - } + LOG_THROW(error == 0, storm::exceptions::InvalidStateException, "Unable to set Gurobi Parameter OutputFlag (" << GRBgeterrormsg(env) << ", error code " << error << ")."); // Enable the following line to restrict Gurobi to one thread only. error = GRBsetintparam(env, "Threads", storm::settings::Settings::getInstance()->getOptionByLongName("gurobithreads").getArgument(0).getValueAsUnsignedInteger()); - if (error) { - LOG4CPLUS_ERROR(logger, "Unable to set Gurobi Parameter Threads (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to set Gurobi Parameter Threads (" << GRBgeterrormsg(env) << ", error code " << error << ")."; - } + LOG_THROW(error == 0, storm::exceptions::InvalidStateException, "Unable to set Gurobi Parameter Threads (" << GRBgeterrormsg(env) << ", error code " << error << ")."); // Enable the following line to force Gurobi to be as precise about the binary variables as required by the given precision option. error = GRBsetdblparam(env, "IntFeasTol", storm::settings::Settings::getInstance()->getOptionByLongName("gurobiinttol").getArgument(0).getValueAsDouble()); - if (error) { - LOG4CPLUS_ERROR(logger, "Unable to set Gurobi Parameter IntFeasTol (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to set Gurobi Parameter IntFeasTol (" << GRBgeterrormsg(env) << ", error code " << error << ")."; - } + LOG_THROW(error == 0, storm::exceptions::InvalidStateException, "Unable to set Gurobi Parameter IntFeasTol (" << GRBgeterrormsg(env) << ", error code " << error << ")."); } void GurobiLpSolver::update() const { int error = GRBupdatemodel(model); - if (error) { - LOG4CPLUS_ERROR(logger, "Unable to update Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to update Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."; - } + LOG_THROW(error == 0, storm::exceptions::InvalidStateException, "Unable to update Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); // Since the model changed, we erase the optimality flag. this->currentModelHasBeenOptimized = false; } - uint_fast64_t GurobiLpSolver::createContinuousVariable(std::string const& name, VariableType const& variableType, double lowerBound, double upperBound, double objectiveFunctionCoefficient) { - int error = 0; - switch (variableType) { - case LpSolver::BOUNDED: - error = GRBaddvar(model, 0, nullptr, nullptr, objectiveFunctionCoefficient, lowerBound, upperBound, GRB_CONTINUOUS, name.c_str()); - break; - case LpSolver::UNBOUNDED: - error = GRBaddvar(model, 0, nullptr, nullptr, objectiveFunctionCoefficient, -GRB_INFINITY, GRB_INFINITY, GRB_CONTINUOUS, name.c_str()); - break; - case LpSolver::UPPER_BOUND: - error = GRBaddvar(model, 0, nullptr, nullptr, objectiveFunctionCoefficient, -GRB_INFINITY, upperBound, GRB_CONTINUOUS, name.c_str()); - break; - case LpSolver::LOWER_BOUND: - error = GRBaddvar(model, 0, nullptr, nullptr, objectiveFunctionCoefficient, lowerBound, GRB_INFINITY, GRB_CONTINUOUS, name.c_str()); - break; - } - - if (error) { - LOG4CPLUS_ERROR(logger, "Could not create binary Gurobi variable (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Could not create binary Gurobi variable (" << GRBgeterrormsg(env) << ", error code " << error << ")."; - } - ++nextVariableIndex; - return nextVariableIndex - 1; + void GurobiLpSolver::addBoundedContinuousVariable(std::string const& name, double lowerBound, double upperBound, double objectiveFunctionCoefficient) { + this->addVariable(name, GRB_CONTINUOUS, lowerBound, upperBound, objectiveFunctionCoefficient); } - uint_fast64_t GurobiLpSolver::createIntegerVariable(std::string const& name, VariableType const& variableType, double lowerBound, double upperBound, double objectiveFunctionCoefficient) { - int error = 0; - switch (variableType) { - case LpSolver::BOUNDED: - error = GRBaddvar(model, 0, nullptr, nullptr, objectiveFunctionCoefficient, lowerBound, upperBound, GRB_INTEGER, name.c_str()); - break; - case LpSolver::UNBOUNDED: - error = GRBaddvar(model, 0, nullptr, nullptr, objectiveFunctionCoefficient, -GRB_INFINITY, GRB_INFINITY, GRB_INTEGER, name.c_str()); - break; - case LpSolver::UPPER_BOUND: - error = GRBaddvar(model, 0, nullptr, nullptr, objectiveFunctionCoefficient, -GRB_INFINITY, upperBound, GRB_INTEGER, name.c_str()); - break; - case LpSolver::LOWER_BOUND: - error = GRBaddvar(model, 0, nullptr, nullptr, objectiveFunctionCoefficient, lowerBound, GRB_INFINITY, GRB_INTEGER, name.c_str()); - break; - } + void GurobiLpSolver::addLowerBoundedContinuousVariable(std::string const& name, double lowerBound, double objectiveFunctionCoefficient) { + this->addVariable(name, GRB_CONTINUOUS, lowerBound, GRB_INFINITY, objectiveFunctionCoefficient); + } - if (error) { - LOG4CPLUS_ERROR(logger, "Could not create binary Gurobi variable (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Could not create binary Gurobi variable (" << GRBgeterrormsg(env) << ", error code " << error << ")."; - } - ++nextVariableIndex; - return nextVariableIndex - 1; + void GurobiLpSolver::addUpperBoundedContinuousVariable(std::string const& name, double upperBound, double objectiveFunctionCoefficient) { + this->addVariable(name, GRB_CONTINUOUS, -GRB_INFINITY, upperBound, objectiveFunctionCoefficient); + } + + void GurobiLpSolver::addUnboundedContinuousVariable(std::string const& name, double objectiveFunctionCoefficient) { + this->addVariable(name, GRB_CONTINUOUS, -GRB_INFINITY, GRB_INFINITY, objectiveFunctionCoefficient); } - uint_fast64_t GurobiLpSolver::createBinaryVariable(std::string const& name, double objectiveFunctionCoefficient) { - int error = GRBaddvar(model, 0, nullptr, nullptr, objectiveFunctionCoefficient, 0.0, 1.0, GRB_BINARY, name.c_str()); - if (error) { - LOG4CPLUS_ERROR(logger, "Could not create binary Gurobi variable (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Could not create binary Gurobi variable (" << GRBgeterrormsg(env) << ", error code " << error << ")."; - } - ++nextVariableIndex; - return nextVariableIndex - 1; + void GurobiLpSolver::addBoundedIntegerVariable(std::string const& name, double lowerBound, double upperBound, double objectiveFunctionCoefficient) { + this->addVariable(name, GRB_INTEGER, lowerBound, upperBound, objectiveFunctionCoefficient); } - void GurobiLpSolver::addConstraint(std::string const& name, std::vector const& variables, std::vector 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."; - } + void GurobiLpSolver::addLowerBoundedIntegerVariable(std::string const& name, double lowerBound, double objectiveFunctionCoefficient) { + this->addVariable(name, GRB_INTEGER, lowerBound, GRB_INFINITY, objectiveFunctionCoefficient); + } + + void GurobiLpSolver::addUpperBoundedIntegerVariable(std::string const& name, double upperBound, double objectiveFunctionCoefficient) { + this->addVariable(name, GRB_INTEGER, -GRB_INFINITY, upperBound, objectiveFunctionCoefficient); + } + + void GurobiLpSolver::addUnboundedIntegerVariable(std::string const& name, double objectiveFunctionCoefficient) { + this->addVariable(name, GRB_INTEGER, -GRB_INFINITY, GRB_INFINITY, objectiveFunctionCoefficient); + } + + void GurobiLpSolver::addBinaryVariable(std::string const& name, double objectiveFunctionCoefficient) { + this->addVariable(name, GRB_BINARY, 0, 1, objectiveFunctionCoefficient); + } + + void GurobiLpSolver::addVariable(std::string const& name, char variableType, double lowerBound, double upperBound, double objectiveFunctionCoefficient) { + // Check whether variable already exists. + auto nameIndexPair = this->variableNameToIndexMap.find(name); + LOG_THROW(nameIndexPair == this->variableNameToIndexMap.end(), storm::exceptions::InvalidArgumentException, "Variable '" << nameIndexPair->first << "' already exists."); - // As Gurobi requires the indices to be unique, we now explicitly make them unique. For this, we sort the - // variables and coefficients and eliminated duplicates by adding the coefficients. + // Check for valid variable type. + LOG_ASSERT(variableType == GRB_CONTINUOUS || variableType == GRB_INTEGER || variableType == GRB_BINARY, "Illegal type '" << variableType << "' for Gurobi variable."); - // We start by sorting both vectors. - std::vector sortedVariables(variables); - std::vector sortedCoefficients(coefficients); - std::vector permutation(variables.size()); - std::iota(permutation.begin(), permutation.end(), 0); - std::sort(permutation.begin(), permutation.end(), [&] (uint_fast64_t i, uint_fast64_t j) { return variables[i] < variables[j]; } ); - std::transform(permutation.begin(), permutation.end(), sortedVariables.begin(), [&] (uint_fast64_t i) { return variables[i]; } ); - std::transform(permutation.begin(), permutation.end(), sortedCoefficients.begin(), [&] (uint_fast64_t i) { return coefficients[i]; } ); + // Finally, create the actual variable. + int error = 0; + error = GRBaddvar(model, 0, nullptr, nullptr, objectiveFunctionCoefficient, lowerBound, upperBound, variableType, name.c_str()); + LOG_THROW(error == 0, storm::exceptions::InvalidStateException, "Could not create binary Gurobi variable (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + this->variableNameToIndexMap.emplace(name, nextVariableIndex); + ++nextVariableIndex; + } + + void GurobiLpSolver::addConstraint(std::string const& name, storm::expressions::Expression const& constraint) { + LOG_THROW(constraint.isRelationalExpression(), storm::exceptions::InvalidArgumentException, "Illegal constraint is not a relational expression."); + LOG_THROW(constraint.getOperator() != storm::expressions::OperatorType::NotEqual, storm::exceptions::InvalidArgumentException, "Illegal constraint uses inequality operator."); - // Now we perform the duplicate elimination step. - std::vector uniqueVariables; - std::vector uniqueCoefficients; - for (uint_fast64_t i = 0; i < sortedVariables.size(); ++i) { - if (!uniqueVariables.empty() && uniqueVariables.back() == sortedVariables[i]) { - uniqueCoefficients.back() += sortedCoefficients[i]; + std::pair leftCoefficients = storm::expressions::LinearCoefficientVisitor().getLinearCoefficients(constraint.getOperand(0)); + std::pair rightCoefficients = storm::expressions::LinearCoefficientVisitor().getLinearCoefficients(constraint.getOperand(1)); + for (auto const& identifier : rightCoefficients.first.getDoubleIdentifiers()) { + if (leftCoefficients.first.containsDoubleIdentifier(identifier)) { + leftCoefficients.first.setDoubleValue(identifier, leftCoefficients.first.getDoubleValue(identifier) - rightCoefficients.first.getDoubleValue(identifier)); } else { - uniqueVariables.push_back(static_cast(sortedVariables[i])); - uniqueCoefficients.push_back(sortedCoefficients[i]); + leftCoefficients.first.addDoubleIdentifier(identifier, -rightCoefficients.first.getDoubleValue(identifier)); } } + rightCoefficients.second -= leftCoefficients.second; - bool strictBound = boundType == LESS || boundType == GREATER; - char sense = boundType == LESS || boundType == LESS_EQUAL ? GRB_LESS_EQUAL : boundType == EQUAL ? GRB_EQUAL : GRB_GREATER_EQUAL; - - // If the constraint enforces a strict bound, we need to do some tweaking of the right-hand side value, because Gurobi only supports - // non-strict bounds. - if (strictBound) { - if (boundType == LESS) { - rightHandSideValue -= storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble(); - } else if (boundType == GREATER) { - rightHandSideValue += storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble(); - } + // Now we need to transform the coefficients to the vector representation. + std::vector variables; + std::vector coefficients; + for (auto const& identifier : leftCoefficients.first.getDoubleIdentifiers()) { + auto identifierIndexPair = this->variableNameToIndexMap.find(identifier); + LOG_THROW(identifierIndexPair != this->variableNameToIndexMap.end(), storm::exceptions::InvalidArgumentException, "Constraint contains illegal identifier '" << identifier << "'."); + variables.push_back(identifierIndexPair->second); + coefficients.push_back(leftCoefficients.first.getDoubleValue(identifier)); } - int error = GRBaddconstr(model, uniqueVariables.size(), uniqueVariables.data(), uniqueCoefficients.data(), sense, rightHandSideValue, name == "" ? nullptr : name.c_str()); - if (error) { - LOG4CPLUS_ERROR(logger, "Unable to assert Gurobi constraint (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to assert Gurobi constraint (" << GRBgeterrormsg(env) << ", error code " << error << ")."; + // Determine the type of the constraint and add it properly. + int error = 0; + switch (constraint.getOperator()) { + case storm::expressions::OperatorType::Less: + error = GRBaddconstr(model, variables.size(), variables.data(), coefficients.data(), GRB_LESS_EQUAL, rightCoefficients.second - storm::settings::Settings::getInstance()->getOptionByLongName("gurobiinttol").getArgument(0).getValueAsDouble(), name == "" ? nullptr : name.c_str()); + break; + case storm::expressions::OperatorType::LessOrEqual: + error = GRBaddconstr(model, variables.size(), variables.data(), coefficients.data(), GRB_LESS_EQUAL, rightCoefficients.second, name == "" ? nullptr : name.c_str()); + break; + case storm::expressions::OperatorType::Greater: + error = GRBaddconstr(model, variables.size(), variables.data(), coefficients.data(), GRB_GREATER_EQUAL, rightCoefficients.second + storm::settings::Settings::getInstance()->getOptionByLongName("gurobiinttol").getArgument(0).getValueAsDouble(), name == "" ? nullptr : name.c_str()); + break; + case storm::expressions::OperatorType::GreaterOrEqual: + error = GRBaddconstr(model, variables.size(), variables.data(), coefficients.data(), GRB_GREATER_EQUAL, rightCoefficients.second, name == "" ? nullptr : name.c_str()); + break; + case storm::expressions::OperatorType::Equal: + error = GRBaddconstr(model, variables.size(), variables.data(), coefficients.data(), GRB_EQUAL, rightCoefficients.second, name == "" ? nullptr : name.c_str()); + break; + default: + LOG_ASSERT(false, "Illegal operator in LP solver constraint."); } + LOG_THROW(error == 0, storm::exceptions::InvalidStateException, "Could not assert constraint (" << GRBgeterrormsg(env) << ", error code " << error << ")."); } void GurobiLpSolver::optimize() const { @@ -212,18 +190,12 @@ namespace storm { this->update(); // Set the most recently set model sense. - int error = GRBsetintattr(model, "ModelSense", this->getModelSense() == MINIMIZE ? 1 : -1); - if (error) { - LOG4CPLUS_ERROR(logger, "Unable to set Gurobi model sense (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to set Gurobi model sense (" << GRBgeterrormsg(env) << ", error code " << error << ")."; - } + int error = GRBsetintattr(model, "ModelSense", this->getModelSense() == ModelSense::Minimize ? 1 : -1); + LOG_THROW(error == 0, storm::exceptions::InvalidStateException, "Unable to set Gurobi model sense (" << GRBgeterrormsg(env) << ", error code " << error << ")."); // Then we actually optimize the model. error = GRBoptimize(model); - if (error) { - LOG4CPLUS_ERROR(logger, "Unable to optimize Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to optimize Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."; - } + LOG_THROW(error == 0, storm::exceptions::InvalidStateException, "Unable to optimize Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); this->currentModelHasBeenOptimized = true; } @@ -236,34 +208,21 @@ namespace storm { int optimalityStatus = 0; int error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimalityStatus); - if (error) { - LOG4CPLUS_ERROR(logger, "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."; - } + LOG_THROW(error == 0, storm::exceptions::InvalidStateException, "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); // By default, Gurobi may tell us only that the model is either infeasible or unbounded. To decide which one // it is, we need to perform an extra step. if (optimalityStatus == GRB_INF_OR_UNBD) { - std::cout << "here" << std::endl; error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_DUALREDUCTIONS, 0); - if (error) { - LOG4CPLUS_ERROR(logger, "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ", error code " << error << ")."; - } + LOG_THROW(error == 0, storm::exceptions::InvalidStateException, "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ", error code " << error << ")."); this->optimize(); error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimalityStatus); - if (error) { - LOG4CPLUS_ERROR(logger, "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."; - } + LOG_THROW(error == 0, storm::exceptions::InvalidStateException, "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_DUALREDUCTIONS, 1); - if (error) { - LOG4CPLUS_ERROR(logger, "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ", error code " << error << ")."; - } + LOG_THROW(error == 0, storm::exceptions::InvalidStateException, "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ", error code " << error << ")."); } return optimalityStatus == GRB_INFEASIBLE; @@ -277,33 +236,21 @@ namespace storm { int optimalityStatus = 0; int error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimalityStatus); - if (error) { - LOG4CPLUS_ERROR(logger, "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."; - } + LOG_THROW(error == 0, storm::exceptions::InvalidStateException, "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); // By default, Gurobi may tell us only that the model is either infeasible or unbounded. To decide which one // it is, we need to perform an extra step. if (optimalityStatus == GRB_INF_OR_UNBD) { error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_DUALREDUCTIONS, 0); - if (error) { - LOG4CPLUS_ERROR(logger, "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ", error code " << error << ")."; - } + LOG_THROW(error == 0, storm::exceptions::InvalidStateException, "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ", error code " << error << ")."); this->optimize(); error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimalityStatus); - if (error) { - LOG4CPLUS_ERROR(logger, "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."; - } + LOG_THROW(error == 0, storm::exceptions::InvalidStateException, "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_DUALREDUCTIONS, 1); - if (error) { - LOG4CPLUS_ERROR(logger, "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ", error code " << error << ")."; - } + LOG_THROW(error == 0, storm::exceptions::InvalidStateException, "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ", error code " << error << ")."); } return optimalityStatus == GRB_UNBOUNDED; @@ -316,120 +263,79 @@ namespace storm { int optimalityStatus = 0; int error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimalityStatus); - if (error) { - LOG4CPLUS_ERROR(logger, "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."; - } + LOG_THROW(error == 0, storm::exceptions::InvalidStateException, "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); return optimalityStatus == GRB_OPTIMAL; } - int_fast64_t GurobiLpSolver::getIntegerValue(uint_fast64_t variableIndex) const { + double GurobiLpSolver::getContinuousValue(std::string const& name) const { if (!this->isOptimal()) { - if (this->isInfeasible()) { - LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution from infeasible model (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution from infeasible model (" << GRBgeterrormsg(env) << ")."; - } else if (this->isUnbounded()) { - LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution from unbounded model (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution from unbounded model (" << GRBgeterrormsg(env) << ")."; - } else { - LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(env) << ")."; - } + LOG_THROW(!this->isInfeasible(), storm::exceptions::InvalidAccessException, "Unable to get Gurobi solution from infeasible model (" << GRBgeterrormsg(env) << ")."); + LOG_THROW(!this->isUnbounded(), storm::exceptions::InvalidAccessException, "Unable to get Gurobi solution from unbounded model (" << GRBgeterrormsg(env) << ")."); + LOG_THROW(false, storm::exceptions::InvalidAccessException, "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(env) << ")."); } - double value = 0; - int error = GRBgetdblattrelement(model, GRB_DBL_ATTR_X, variableIndex, &value); - if (error) { - LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ", error code " << error << ")."; - } + auto variableIndexPair = this->variableNameToIndexMap.find(name); + LOG_THROW(variableIndexPair != this->variableNameToIndexMap.end(), storm::exceptions::InvalidAccessException, "Accessing value of unknown variable '" << name << "'."); - if (std::abs(value - static_cast(value)) <= storm::settings::Settings::getInstance()->getOptionByLongName("gurobiinttol").getArgument(0).getValueAsDouble()) { - // Nothing to do in this case. - } else if (std::abs(value) > storm::settings::Settings::getInstance()->getOptionByLongName("gurobiinttol").getArgument(0).getValueAsDouble()) { - LOG4CPLUS_ERROR(logger, "Illegal value for integer variable in Gurobi solution (" << value << ")."); - throw storm::exceptions::InvalidStateException() << "Illegal value for integer variable in Gurobi solution (" << value << ")."; - } + double value = 0; + int error = GRBgetdblattrelement(model, GRB_DBL_ATTR_X, variableIndexPair->second, &value); + LOG_THROW(error == 0, storm::exceptions::InvalidStateException, "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - return static_cast(value); + return value; } - bool GurobiLpSolver::getBinaryValue(uint_fast64_t variableIndex) const { + int_fast64_t GurobiLpSolver::getIntegerValue(std::string const& name) const { if (!this->isOptimal()) { - if (this->isInfeasible()) { - LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution from infeasible model (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution from infeasible model (" << GRBgeterrormsg(env) << ")."; - } else if (this->isUnbounded()) { - LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution from unbounded model (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution from unbounded model (" << GRBgeterrormsg(env) << ")."; - } else { - LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(env) << ")."; - } - } - - double value = 0; - int error = GRBgetdblattrelement(model, GRB_DBL_ATTR_X, variableIndex, &value); - if (error) { - LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ", error code " << error << ")."; + LOG_THROW(!this->isInfeasible(), storm::exceptions::InvalidAccessException, "Unable to get Gurobi solution from infeasible model (" << GRBgeterrormsg(env) << ")."); + LOG_THROW(!this->isUnbounded(), storm::exceptions::InvalidAccessException, "Unable to get Gurobi solution from unbounded model (" << GRBgeterrormsg(env) << ")."); + LOG_THROW(false, storm::exceptions::InvalidAccessException, "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(env) << ")."); } - if (std::abs(value - 1) <= storm::settings::Settings::getInstance()->getOptionByLongName("gurobiinttol").getArgument(0).getValueAsDouble()) { - // Nothing to do in this case. - } else if (std::abs(value) > storm::settings::Settings::getInstance()->getOptionByLongName("gurobiinttol").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 << ")."; - } + auto variableIndexPair = this->variableNameToIndexMap.find(name); + LOG_THROW(variableIndexPair != this->variableNameToIndexMap.end(), storm::exceptions::InvalidAccessException, "Accessing value of unknown variable '" << name << "'."); - return static_cast(value); + double value = 0; + int error = GRBgetdblattrelement(model, GRB_DBL_ATTR_X, variableIndexPair->second, &value); + LOG_THROW(error == 0, storm::exceptions::InvalidStateException, "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + LOG_THROW(std::abs(static_cast(value) - value) <= storm::settings::Settings::getInstance()->getOptionByLongName("gurobiinttol").getArgument(0).getValueAsDouble(), storm::exceptions::InvalidStateException, "Illegal value for integer variable in Gurobi solution (" << value << ")."); + + return static_cast(value); } - double GurobiLpSolver::getContinuousValue(uint_fast64_t variableIndex) const { + bool GurobiLpSolver::getBinaryValue(std::string const& name) const { if (!this->isOptimal()) { - if (this->isInfeasible()) { - LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution from infeasible model (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution from infeasible model (" << GRBgeterrormsg(env) << ")."; - } else if (this->isUnbounded()) { - LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution from unbounded model (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution from unbounded model (" << GRBgeterrormsg(env) << ")."; - } else { - LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(env) << ")."; - } + LOG_THROW(!this->isInfeasible(), storm::exceptions::InvalidAccessException, "Unable to get Gurobi solution from infeasible model (" << GRBgeterrormsg(env) << ")."); + LOG_THROW(!this->isUnbounded(), storm::exceptions::InvalidAccessException, "Unable to get Gurobi solution from unbounded model (" << GRBgeterrormsg(env) << ")."); + LOG_THROW(false, storm::exceptions::InvalidAccessException, "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(env) << ")."); } + auto variableIndexPair = this->variableNameToIndexMap.find(name); + LOG_THROW(variableIndexPair != this->variableNameToIndexMap.end(), storm::exceptions::InvalidAccessException, "Accessing value of unknown variable '" << name << "'."); + double value = 0; - int error = GRBgetdblattrelement(model, GRB_DBL_ATTR_X, variableIndex, &value); - if (error) { - LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ", error code " << error << ")."; + int error = GRBgetdblattrelement(model, GRB_DBL_ATTR_X, variableIndexPair->second, &value); + LOG_THROW(error == 0, storm::exceptions::InvalidStateException, "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + + if (value > 0.5) { + LOG_THROW(std::abs(static_cast(value) - 1) <= storm::settings::Settings::getInstance()->getOptionByLongName("gurobiinttol").getArgument(0).getValueAsDouble(), storm::exceptions::InvalidStateException, "Illegal value for integer variable in Gurobi solution (" << value << ")."); + } else { + LOG_THROW(value <= storm::settings::Settings::getInstance()->getOptionByLongName("gurobiinttol").getArgument(0).getValueAsDouble(), storm::exceptions::InvalidStateException, "Illegal value for integer variable in Gurobi solution (" << value << ")."); } - return value; + return static_cast(value); } double GurobiLpSolver::getObjectiveValue() const { if (!this->isOptimal()) { - if (this->isInfeasible()) { - LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution from infeasible model (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution from infeasible model (" << GRBgeterrormsg(env) << ")."; - } else if (this->isUnbounded()) { - LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution from unbounded model (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution from unbounded model (" << GRBgeterrormsg(env) << ")."; - } else { - LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(env) << ")."; - } + LOG_THROW(!this->isInfeasible(), storm::exceptions::InvalidAccessException, "Unable to get Gurobi solution from infeasible model (" << GRBgeterrormsg(env) << ")."); + LOG_THROW(!this->isUnbounded(), storm::exceptions::InvalidAccessException, "Unable to get Gurobi solution from unbounded model (" << GRBgeterrormsg(env) << ")."); + LOG_THROW(false, storm::exceptions::InvalidAccessException, "Unable to get Gurobi solution from unoptimized model (" << GRBgeterrormsg(env) << ")."); } double value = 0; int error = GRBgetdblattr(model, GRB_DBL_ATTR_OBJVAL, &value); - if (error) { - LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ", error code " << error << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ", error code " << error << ")."; - } + LOG_THROW(error == 0, storm::exceptions::InvalidStateException, "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ", error code " << error << ")."); return value; } diff --git a/src/solver/GurobiLpSolver.h b/src/solver/GurobiLpSolver.h index 27ac66c52..e9eac0e85 100644 --- a/src/solver/GurobiLpSolver.h +++ b/src/solver/GurobiLpSolver.h @@ -102,14 +102,28 @@ namespace storm { */ void setGurobiEnvironmentProperties() const; + /*! + * Adds a variable with the given name, type, lower and upper bound and objective function coefficient. + * + * @param name The name of the variable. + * @param variableType The type of the variable in terms of Gurobi's constants. + * @param lowerBound The lower bound of the range of the variable. + * @param upperBound The upper bound of the range of the variable. + * @param objectiveFunctionCoefficient The coefficient of the variable in the objective function. + */ + void addVariable(std::string const& name, char variableType, double lowerBound, double upperBound, double objectiveFunctionCoefficient); + // The Gurobi environment. GRBenv* env; // The Gurobi model. GRBmodel* model; + // The index of the next variable. + int nextVariableIndex; + // A mapping from variable names to their indices. - std::map variableNameToIndexMap; + std::map variableNameToIndexMap; }; #else // If Gurobi is not available, we provide a stub implementation that emits an error if any of its methods is called. diff --git a/src/solver/LpSolver.h b/src/solver/LpSolver.h index f775f2829..5e7a5f76e 100644 --- a/src/solver/LpSolver.h +++ b/src/solver/LpSolver.h @@ -16,14 +16,14 @@ namespace storm { public: // An enumeration to represent whether the objective function is to be minimized or maximized. enum class ModelSense { - MINIMIZE, - MAXIMIZE + Minimize, + Maximize }; /*! * Creates an empty LP solver. By default the objective function is assumed to be minimized. */ - LpSolver() : currentModelHasBeenOptimized(false), modelSense(ModelSense::MINIMIZE) { + LpSolver() : currentModelHasBeenOptimized(false), modelSense(ModelSense::Minimize) { // Intentionally left empty. } diff --git a/src/storage/expressions/Expression.cpp b/src/storage/expressions/Expression.cpp index 762ed07bf..e8de2af62 100644 --- a/src/storage/expressions/Expression.cpp +++ b/src/storage/expressions/Expression.cpp @@ -17,27 +17,27 @@ namespace storm { } Expression Expression::substitute(std::map const& identifierToExpressionMap) const { - return SubstitutionVisitor>(identifierToExpressionMap).substitute(this); + return SubstitutionVisitor>(identifierToExpressionMap).substitute(*this); } Expression Expression::substitute(std::unordered_map const& identifierToExpressionMap) const { - return SubstitutionVisitor>(identifierToExpressionMap).substitute(this); + return SubstitutionVisitor>(identifierToExpressionMap).substitute(*this); } Expression Expression::substitute(std::map const& identifierToIdentifierMap) const { - return IdentifierSubstitutionVisitor>(identifierToIdentifierMap).substitute(this); + return IdentifierSubstitutionVisitor>(identifierToIdentifierMap).substitute(*this); } Expression Expression::substitute(std::unordered_map const& identifierToIdentifierMap) const { - return IdentifierSubstitutionVisitor>(identifierToIdentifierMap).substitute(this); + return IdentifierSubstitutionVisitor>(identifierToIdentifierMap).substitute(*this); } void Expression::check(std::map const& identifierToTypeMap) const { - return TypeCheckVisitor>(identifierToTypeMap).check(this); + return TypeCheckVisitor>(identifierToTypeMap).check(*this); } void Expression::check(std::unordered_map const& identifierToTypeMap) const { - return TypeCheckVisitor>(identifierToTypeMap).check(this); + return TypeCheckVisitor>(identifierToTypeMap).check(*this); } bool Expression::evaluateAsBool(Valuation const* valuation) const { diff --git a/src/storage/expressions/LinearCoefficientVisitor.cpp b/src/storage/expressions/LinearCoefficientVisitor.cpp index f59804927..7525d6dde 100644 --- a/src/storage/expressions/LinearCoefficientVisitor.cpp +++ b/src/storage/expressions/LinearCoefficientVisitor.cpp @@ -28,7 +28,7 @@ namespace storm { std::pair& rightResult = resultStack.top(); // Now add the left result to the right result. - for (auto const& identifier : leftResult.first.Valuation::getDoubleIdentifiers()) { + for (auto const& identifier : leftResult.first.getDoubleIdentifiers()) { if (rightResult.first.containsDoubleIdentifier(identifier)) { rightResult.first.setDoubleValue(identifier, leftResult.first.getDoubleValue(identifier) + rightResult.first.getDoubleValue(identifier)); } else { @@ -52,7 +52,7 @@ namespace storm { rightResult.first.setDoubleValue(identifier, leftResult.first.getDoubleValue(identifier)); } } - for (auto const& identifier : rightResult.first.Valuation::getDoubleIdentifiers()) { + for (auto const& identifier : rightResult.first.getDoubleIdentifiers()) { if (!leftResult.first.containsDoubleIdentifier(identifier)) { rightResult.first.setDoubleValue(identifier, -rightResult.first.getDoubleValue(identifier)); } diff --git a/src/storage/expressions/Valuation.h b/src/storage/expressions/Valuation.h index baf39462f..f7ab3c985 100644 --- a/src/storage/expressions/Valuation.h +++ b/src/storage/expressions/Valuation.h @@ -94,7 +94,6 @@ namespace storm { */ virtual std::set getDoubleIdentifiers() const = 0; - }; } } diff --git a/test/functional/solver/GlpkLpSolverTest.cpp b/test/functional/solver/GlpkLpSolverTest.cpp index 30c3e10f9..a6410611d 100644 --- a/test/functional/solver/GlpkLpSolverTest.cpp +++ b/test/functional/solver/GlpkLpSolverTest.cpp @@ -3,34 +3,34 @@ #include "src/solver/GlpkLpSolver.h" #include "src/exceptions/InvalidStateException.h" +#include "src/exceptions/InvalidAccessException.h" #include "src/settings/Settings.h" TEST(GlpkLpSolver, LPOptimizeMax) { #ifdef STORM_HAVE_GLPK - storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::MAXIMIZE); - uint_fast64_t xIndex; - ASSERT_NO_THROW(xIndex = solver.createContinuousVariable("x", storm::solver::LpSolver::VariableType::BOUNDED, 0, 1, -1)); - uint_fast64_t yIndex; - ASSERT_NO_THROW(yIndex = solver.createContinuousVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2)); - uint_fast64_t zIndex; - ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1)); - - ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::EQUAL, 5)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); - + storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize); + ASSERT_NO_THROW(solver.addBoundedContinuousVariable("x", 0, 1, -1)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("y", 0, 2)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1)); + ASSERT_NO_THROW(solver.update()); + + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleLiteral(0.5) * storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") - storm::expressions::Expression::createDoubleVariable("x") == storm::expressions::Expression::createDoubleLiteral(5))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5))); + ASSERT_NO_THROW(solver.update()); + ASSERT_NO_THROW(solver.optimize()); ASSERT_TRUE(solver.isOptimal()); ASSERT_FALSE(solver.isUnbounded()); ASSERT_FALSE(solver.isInfeasible()); double xValue = 0; - ASSERT_NO_THROW(xValue = solver.getContinuousValue(xIndex)); + ASSERT_NO_THROW(xValue = solver.getContinuousValue("x")); ASSERT_LT(std::abs(xValue - 1), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); double yValue = 0; - ASSERT_NO_THROW(yValue = solver.getContinuousValue(yIndex)); + ASSERT_NO_THROW(yValue = solver.getContinuousValue("y")); ASSERT_LT(std::abs(yValue - 6.5), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); double zValue = 0; - ASSERT_NO_THROW(zValue = solver.getContinuousValue(zIndex)); + ASSERT_NO_THROW(zValue = solver.getContinuousValue("z")); ASSERT_LT(std::abs(zValue - 2.75), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); double objectiveValue = 0; ASSERT_NO_THROW(objectiveValue = solver.getObjectiveValue()); @@ -42,30 +42,29 @@ TEST(GlpkLpSolver, LPOptimizeMax) { TEST(GlpkLpSolver, LPOptimizeMin) { #ifdef STORM_HAVE_GLPK - storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::MINIMIZE); - uint_fast64_t xIndex; - ASSERT_NO_THROW(xIndex = solver.createContinuousVariable("x", storm::solver::LpSolver::VariableType::BOUNDED, 0, 1, -1)); - uint_fast64_t yIndex; - ASSERT_NO_THROW(yIndex = solver.createContinuousVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2)); - uint_fast64_t zIndex; - ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::BOUNDED, 1, 5.7, -1)); - - ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); - + storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::ModelSense::Minimize); + ASSERT_NO_THROW(solver.addBoundedContinuousVariable("x", 0, 1, -1)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("y", 0, 2)); + ASSERT_NO_THROW(solver.addBoundedContinuousVariable("z", 1, 5.7, -1)); + ASSERT_NO_THROW(solver.update()); + + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleLiteral(0.5) * storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5))); + ASSERT_NO_THROW(solver.update()); + ASSERT_NO_THROW(solver.optimize()); ASSERT_TRUE(solver.isOptimal()); ASSERT_FALSE(solver.isUnbounded()); ASSERT_FALSE(solver.isInfeasible()); double xValue = 0; - ASSERT_NO_THROW(xValue = solver.getContinuousValue(xIndex)); + ASSERT_NO_THROW(xValue = solver.getContinuousValue("x")); ASSERT_LT(std::abs(xValue - 1), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); double yValue = 0; - ASSERT_NO_THROW(yValue = solver.getContinuousValue(yIndex)); + ASSERT_NO_THROW(yValue = solver.getContinuousValue("y")); ASSERT_LT(std::abs(yValue - 0), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); double zValue = 0; - ASSERT_NO_THROW(zValue = solver.getContinuousValue(zIndex)); + ASSERT_NO_THROW(zValue = solver.getContinuousValue("z")); ASSERT_LT(std::abs(zValue - 5.7), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); double objectiveValue = 0; ASSERT_NO_THROW(objectiveValue = solver.getObjectiveValue()); @@ -77,30 +76,29 @@ TEST(GlpkLpSolver, LPOptimizeMin) { TEST(GlpkLpSolver, MILPOptimizeMax) { #ifdef STORM_HAVE_GLPK - storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::MAXIMIZE); - uint_fast64_t xIndex; - ASSERT_NO_THROW(xIndex = solver.createBinaryVariable("x", -1)); - uint_fast64_t yIndex; - ASSERT_NO_THROW(yIndex = solver.createIntegerVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2)); - uint_fast64_t zIndex; - ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1)); - - ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::EQUAL, 5)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); - + storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize); + ASSERT_NO_THROW(solver.addBinaryVariable("x", -1)); + ASSERT_NO_THROW(solver.addLowerBoundedIntegerVariable("y", 0, 2)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1)); + ASSERT_NO_THROW(solver.update()); + + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleLiteral(0.5) * storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") - storm::expressions::Expression::createDoubleVariable("x") == storm::expressions::Expression::createDoubleLiteral(5))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5))); + ASSERT_NO_THROW(solver.update()); + ASSERT_NO_THROW(solver.optimize()); ASSERT_TRUE(solver.isOptimal()); ASSERT_FALSE(solver.isUnbounded()); ASSERT_FALSE(solver.isInfeasible()); bool xValue = false; - ASSERT_NO_THROW(xValue = solver.getBinaryValue(xIndex)); + ASSERT_NO_THROW(xValue = solver.getBinaryValue("x")); ASSERT_EQ(true, xValue); int_fast64_t yValue = 0; - ASSERT_NO_THROW(yValue = solver.getIntegerValue(yIndex)); + ASSERT_NO_THROW(yValue = solver.getIntegerValue("y")); ASSERT_EQ(6, yValue); double zValue = 0; - ASSERT_NO_THROW(zValue = solver.getContinuousValue(zIndex)); + ASSERT_NO_THROW(zValue = solver.getContinuousValue("z")); ASSERT_LT(std::abs(zValue - 3), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); double objectiveValue = 0; ASSERT_NO_THROW(objectiveValue = solver.getObjectiveValue()); @@ -112,30 +110,29 @@ TEST(GlpkLpSolver, MILPOptimizeMax) { TEST(GlpkLpSolver, MILPOptimizeMin) { #ifdef STORM_HAVE_GLPK - storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::MINIMIZE); - uint_fast64_t xIndex; - ASSERT_NO_THROW(xIndex = solver.createBinaryVariable("x", -1)); - uint_fast64_t yIndex; - ASSERT_NO_THROW(yIndex = solver.createContinuousVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2)); - uint_fast64_t zIndex; - ASSERT_NO_THROW(zIndex = solver.createIntegerVariable("z", storm::solver::LpSolver::VariableType::BOUNDED, 0, 5, -1)); - - ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); - + storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::ModelSense::Minimize); + ASSERT_NO_THROW(solver.addBinaryVariable("x", -1)); + ASSERT_NO_THROW(solver.addLowerBoundedIntegerVariable("y", 0, 2)); + ASSERT_NO_THROW(solver.addBoundedContinuousVariable("z", 0, 5, -1)); + ASSERT_NO_THROW(solver.update()); + + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleLiteral(0.5) * storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5))); + ASSERT_NO_THROW(solver.update()); + ASSERT_NO_THROW(solver.optimize()); ASSERT_TRUE(solver.isOptimal()); ASSERT_FALSE(solver.isUnbounded()); ASSERT_FALSE(solver.isInfeasible()); bool xValue = false; - ASSERT_NO_THROW(xValue = solver.getBinaryValue(xIndex)); + ASSERT_NO_THROW(xValue = solver.getBinaryValue("x")); ASSERT_EQ(true, xValue); int_fast64_t yValue = 0; - ASSERT_NO_THROW(yValue = solver.getIntegerValue(yIndex)); + ASSERT_NO_THROW(yValue = solver.getIntegerValue("y")); ASSERT_EQ(0, yValue); double zValue = 0; - ASSERT_NO_THROW(zValue = solver.getContinuousValue(zIndex)); + ASSERT_NO_THROW(zValue = solver.getContinuousValue("z")); ASSERT_LT(std::abs(zValue - 5), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); double objectiveValue = 0; ASSERT_NO_THROW(objectiveValue = solver.getObjectiveValue()); @@ -147,31 +144,30 @@ TEST(GlpkLpSolver, MILPOptimizeMin) { TEST(GlpkLpSolver, LPInfeasible) { #ifdef STORM_HAVE_GLPK - storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::MAXIMIZE); - uint_fast64_t xIndex; - ASSERT_NO_THROW(xIndex = solver.createContinuousVariable("x", storm::solver::LpSolver::VariableType::BOUNDED, 0, 1, -1)); - uint_fast64_t yIndex; - ASSERT_NO_THROW(yIndex = solver.createContinuousVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2)); - uint_fast64_t zIndex; - ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1)); - - ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::EQUAL, 5)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex}, {1}, storm::solver::LpSolver::BoundType::GREATER_EQUAL, 7)); - + storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize); + ASSERT_NO_THROW(solver.addBoundedContinuousVariable("x", 0, 1, -1)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("y", 0, 2)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1)); + ASSERT_NO_THROW(solver.update()); + + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleLiteral(0.5) * storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") - storm::expressions::Expression::createDoubleVariable("x") == storm::expressions::Expression::createDoubleLiteral(5))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") > storm::expressions::Expression::createDoubleLiteral(7))); + ASSERT_NO_THROW(solver.update()); + ASSERT_NO_THROW(solver.optimize()); ASSERT_FALSE(solver.isOptimal()); ASSERT_FALSE(solver.isUnbounded()); ASSERT_TRUE(solver.isInfeasible()); double xValue = 0; - ASSERT_THROW(xValue = solver.getContinuousValue(xIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(xValue = solver.getContinuousValue("x"), storm::exceptions::InvalidAccessException); double yValue = 0; - ASSERT_THROW(yValue = solver.getContinuousValue(yIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(yValue = solver.getContinuousValue("y"), storm::exceptions::InvalidAccessException); double zValue = 0; - ASSERT_THROW(zValue = solver.getContinuousValue(zIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(zValue = solver.getContinuousValue("z"), storm::exceptions::InvalidAccessException); double objectiveValue = 0; - ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidStateException); + ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidAccessException); #else ASSERT_TRUE(false) << "StoRM built without glpk support."; #endif @@ -179,31 +175,30 @@ TEST(GlpkLpSolver, LPInfeasible) { TEST(GlpkLpSolver, MILPInfeasible) { #ifdef STORM_HAVE_GLPK - storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::MAXIMIZE); - uint_fast64_t xIndex; - ASSERT_NO_THROW(xIndex = solver.createBinaryVariable("x", -1)); - uint_fast64_t yIndex; - ASSERT_NO_THROW(yIndex = solver.createIntegerVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2)); - uint_fast64_t zIndex; - ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1)); - - ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::EQUAL, 5)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex}, {1}, storm::solver::LpSolver::BoundType::GREATER_EQUAL, 7)); - + storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize); + ASSERT_NO_THROW(solver.addBinaryVariable("x", -1)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("y", 0, 2)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1)); + ASSERT_NO_THROW(solver.update()); + + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleLiteral(0.5) * storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") - storm::expressions::Expression::createDoubleVariable("x") == storm::expressions::Expression::createDoubleLiteral(5))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") > storm::expressions::Expression::createDoubleLiteral(7))); + ASSERT_NO_THROW(solver.update()); + ASSERT_NO_THROW(solver.optimize()); ASSERT_FALSE(solver.isOptimal()); ASSERT_FALSE(solver.isUnbounded()); ASSERT_TRUE(solver.isInfeasible()); bool xValue = false; - ASSERT_THROW(xValue = solver.getBinaryValue(xIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(xValue = solver.getBinaryValue("x"), storm::exceptions::InvalidAccessException); int_fast64_t yValue = 0; - ASSERT_THROW(yValue = solver.getIntegerValue(yIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(yValue = solver.getIntegerValue("y"), storm::exceptions::InvalidAccessException); double zValue = 0; - ASSERT_THROW(zValue = solver.getContinuousValue(zIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(zValue = solver.getContinuousValue("z"), storm::exceptions::InvalidAccessException); double objectiveValue = 0; - ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidStateException); + ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidAccessException); #else ASSERT_TRUE(false) << "StoRM built without glpk support."; #endif @@ -211,29 +206,28 @@ TEST(GlpkLpSolver, MILPInfeasible) { TEST(GlpkLpSolver, LPUnbounded) { #ifdef STORM_HAVE_GLPK - storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::MAXIMIZE); - uint_fast64_t xIndex; - ASSERT_NO_THROW(xIndex = solver.createContinuousVariable("x", storm::solver::LpSolver::VariableType::BOUNDED, 0, 1, -1)); - uint_fast64_t yIndex; - ASSERT_NO_THROW(yIndex = solver.createContinuousVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2)); - uint_fast64_t zIndex; - ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1)); - - ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); - + storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize); + ASSERT_NO_THROW(solver.addBoundedContinuousVariable("x", 0, 1, -1)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("y", 0, 2)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1)); + ASSERT_NO_THROW(solver.update()); + + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5))); + ASSERT_NO_THROW(solver.update()); + ASSERT_NO_THROW(solver.optimize()); ASSERT_FALSE(solver.isOptimal()); ASSERT_TRUE(solver.isUnbounded()); ASSERT_FALSE(solver.isInfeasible()); double xValue = 0; - ASSERT_THROW(xValue = solver.getContinuousValue(xIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(xValue = solver.getContinuousValue("x"), storm::exceptions::InvalidAccessException); double yValue = 0; - ASSERT_THROW(yValue = solver.getContinuousValue(yIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(yValue = solver.getContinuousValue("y"), storm::exceptions::InvalidAccessException); double zValue = 0; - ASSERT_THROW(zValue = solver.getContinuousValue(zIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(zValue = solver.getContinuousValue("z"), storm::exceptions::InvalidAccessException); double objectiveValue = 0; - ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidStateException); + ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidAccessException); #else ASSERT_TRUE(false) << "StoRM built without glpk support."; #endif @@ -241,30 +235,29 @@ TEST(GlpkLpSolver, LPUnbounded) { TEST(GlpkLpSolver, MILPUnbounded) { #ifdef STORM_HAVE_GLPK - storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::MAXIMIZE); - uint_fast64_t xIndex; - ASSERT_NO_THROW(xIndex = solver.createBinaryVariable("x", -1)); - uint_fast64_t yIndex; - ASSERT_NO_THROW(yIndex = solver.createIntegerVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2)); - uint_fast64_t zIndex; - ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1)); - - ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); - + storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize); + ASSERT_NO_THROW(solver.addBinaryVariable("x", -1)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("y", 0, 2)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1)); + ASSERT_NO_THROW(solver.update()); + + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5))); + ASSERT_NO_THROW(solver.update()); + ASSERT_NO_THROW(solver.optimize()); ASSERT_FALSE(solver.isOptimal()); ASSERT_TRUE(solver.isUnbounded()); ASSERT_FALSE(solver.isInfeasible()); bool xValue = false; - ASSERT_THROW(xValue = solver.getBinaryValue(xIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(xValue = solver.getBinaryValue("x"), storm::exceptions::InvalidAccessException); int_fast64_t yValue = 0; - ASSERT_THROW(yValue = solver.getIntegerValue(yIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(yValue = solver.getIntegerValue("y"), storm::exceptions::InvalidAccessException); double zValue = 0; - ASSERT_THROW(zValue = solver.getContinuousValue(zIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(zValue = solver.getContinuousValue("z"), storm::exceptions::InvalidAccessException); double objectiveValue = 0; - ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidStateException); + ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidAccessException); #else ASSERT_TRUE(false) << "StoRM built without glpk support."; #endif -} \ No newline at end of file +} diff --git a/test/functional/solver/GurobiLpSolverTest.cpp b/test/functional/solver/GurobiLpSolverTest.cpp index 1ca524d8e..ee0ebfa03 100644 --- a/test/functional/solver/GurobiLpSolverTest.cpp +++ b/test/functional/solver/GurobiLpSolverTest.cpp @@ -3,36 +3,34 @@ #include "src/solver/GurobiLpSolver.h" #include "src/exceptions/InvalidStateException.h" +#include "src/exceptions/InvalidAccessException.h" #include "src/settings/Settings.h" TEST(GurobiLpSolver, LPOptimizeMax) { #ifdef STORM_HAVE_GUROBI - storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::MAXIMIZE); - uint_fast64_t xIndex; - ASSERT_NO_THROW(xIndex = solver.createContinuousVariable("x", storm::solver::LpSolver::VariableType::BOUNDED, 0, 1, -1)); - uint_fast64_t yIndex; - ASSERT_NO_THROW(yIndex = solver.createContinuousVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2)); - uint_fast64_t zIndex; - ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1)); - - ASSERT_NO_THROW(solver.update()); - - ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::EQUAL, 5)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); + storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize); + ASSERT_NO_THROW(solver.addBoundedContinuousVariable("x", 0, 1, -1)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("y", 0, 2)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1)); + ASSERT_NO_THROW(solver.update()); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleLiteral(0.5) * storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") - storm::expressions::Expression::createDoubleVariable("x") == storm::expressions::Expression::createDoubleLiteral(5))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5))); + ASSERT_NO_THROW(solver.update()); + ASSERT_NO_THROW(solver.optimize()); ASSERT_TRUE(solver.isOptimal()); ASSERT_FALSE(solver.isUnbounded()); ASSERT_FALSE(solver.isInfeasible()); double xValue = 0; - ASSERT_NO_THROW(xValue = solver.getContinuousValue(xIndex)); + ASSERT_NO_THROW(xValue = solver.getContinuousValue("x")); ASSERT_LT(std::abs(xValue - 1), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); double yValue = 0; - ASSERT_NO_THROW(yValue = solver.getContinuousValue(yIndex)); + ASSERT_NO_THROW(yValue = solver.getContinuousValue("y")); ASSERT_LT(std::abs(yValue - 6.5), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); double zValue = 0; - ASSERT_NO_THROW(zValue = solver.getContinuousValue(zIndex)); + ASSERT_NO_THROW(zValue = solver.getContinuousValue("z")); ASSERT_LT(std::abs(zValue - 2.75), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); double objectiveValue = 0; ASSERT_NO_THROW(objectiveValue = solver.getObjectiveValue()); @@ -44,32 +42,29 @@ TEST(GurobiLpSolver, LPOptimizeMax) { TEST(GurobiLpSolver, LPOptimizeMin) { #ifdef STORM_HAVE_GUROBI - storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::MINIMIZE); - uint_fast64_t xIndex; - ASSERT_NO_THROW(xIndex = solver.createContinuousVariable("x", storm::solver::LpSolver::VariableType::BOUNDED, 0, 1, -1)); - uint_fast64_t yIndex; - ASSERT_NO_THROW(yIndex = solver.createContinuousVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2)); - uint_fast64_t zIndex; - ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::BOUNDED, 1, 5.7, -1)); - - ASSERT_NO_THROW(solver.update()); + storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::ModelSense::Minimize); + ASSERT_NO_THROW(solver.addBoundedContinuousVariable("x", 0, 1, -1)); + ASSERT_NO_THROW(solver.addLowerBoundedIntegerVariable("y", 0, 2)); + ASSERT_NO_THROW(solver.addBoundedContinuousVariable("z", 1, 5.7, -1)); + ASSERT_NO_THROW(solver.update()); + + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleLiteral(0.5) * storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5))); + ASSERT_NO_THROW(solver.update()); - ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); - ASSERT_NO_THROW(solver.optimize()); ASSERT_TRUE(solver.isOptimal()); ASSERT_FALSE(solver.isUnbounded()); ASSERT_FALSE(solver.isInfeasible()); double xValue = 0; - ASSERT_NO_THROW(xValue = solver.getContinuousValue(xIndex)); + ASSERT_NO_THROW(xValue = solver.getContinuousValue("x")); ASSERT_LT(std::abs(xValue - 1), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); double yValue = 0; - ASSERT_NO_THROW(yValue = solver.getContinuousValue(yIndex)); + ASSERT_NO_THROW(yValue = solver.getContinuousValue("y")); ASSERT_LT(std::abs(yValue - 0), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); double zValue = 0; - ASSERT_NO_THROW(zValue = solver.getContinuousValue(zIndex)); + ASSERT_NO_THROW(zValue = solver.getContinuousValue("z")); ASSERT_LT(std::abs(zValue - 5.7), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); double objectiveValue = 0; ASSERT_NO_THROW(objectiveValue = solver.getObjectiveValue()); @@ -81,32 +76,29 @@ TEST(GurobiLpSolver, LPOptimizeMin) { TEST(GurobiLpSolver, MILPOptimizeMax) { #ifdef STORM_HAVE_GUROBI - storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::MAXIMIZE); - uint_fast64_t xIndex; - ASSERT_NO_THROW(xIndex = solver.createBinaryVariable("x", -1)); - uint_fast64_t yIndex; - ASSERT_NO_THROW(yIndex = solver.createIntegerVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2)); - uint_fast64_t zIndex; - ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1)); - - ASSERT_NO_THROW(solver.update()); + storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize); + ASSERT_NO_THROW(solver.addBinaryVariable("x", -1)); + ASSERT_NO_THROW(solver.addLowerBoundedIntegerVariable("y", 0, 2)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1)); + ASSERT_NO_THROW(solver.update()); + + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleLiteral(0.5) * storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") - storm::expressions::Expression::createDoubleVariable("x") == storm::expressions::Expression::createDoubleLiteral(5))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5))); + ASSERT_NO_THROW(solver.update()); - ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::EQUAL, 5)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); - ASSERT_NO_THROW(solver.optimize()); ASSERT_TRUE(solver.isOptimal()); ASSERT_FALSE(solver.isUnbounded()); ASSERT_FALSE(solver.isInfeasible()); bool xValue = false; - ASSERT_NO_THROW(xValue = solver.getBinaryValue(xIndex)); + ASSERT_NO_THROW(xValue = solver.getBinaryValue("x")); ASSERT_EQ(true, xValue); int_fast64_t yValue = 0; - ASSERT_NO_THROW(yValue = solver.getIntegerValue(yIndex)); + ASSERT_NO_THROW(yValue = solver.getIntegerValue("y")); ASSERT_EQ(6, yValue); double zValue = 0; - ASSERT_NO_THROW(zValue = solver.getContinuousValue(zIndex)); + ASSERT_NO_THROW(zValue = solver.getContinuousValue("z")); ASSERT_LT(std::abs(zValue - 3), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); double objectiveValue = 0; ASSERT_NO_THROW(objectiveValue = solver.getObjectiveValue()); @@ -118,32 +110,29 @@ TEST(GurobiLpSolver, MILPOptimizeMax) { TEST(GurobiLpSolver, MILPOptimizeMin) { #ifdef STORM_HAVE_GUROBI - storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::MINIMIZE); - uint_fast64_t xIndex; - ASSERT_NO_THROW(xIndex = solver.createBinaryVariable("x", -1)); - uint_fast64_t yIndex; - ASSERT_NO_THROW(yIndex = solver.createContinuousVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2)); - uint_fast64_t zIndex; - ASSERT_NO_THROW(zIndex = solver.createIntegerVariable("z", storm::solver::LpSolver::VariableType::BOUNDED, 0, 5.7, -1)); - - ASSERT_NO_THROW(solver.update()); + storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::ModelSense::Minimize); + ASSERT_NO_THROW(solver.addBinaryVariable("x", -1)); + ASSERT_NO_THROW(solver.addLowerBoundedIntegerVariable("y", 0, 2)); + ASSERT_NO_THROW(solver.addBoundedContinuousVariable("z", 0, 5, -1)); + ASSERT_NO_THROW(solver.update()); + + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleLiteral(0.5) * storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5))); + ASSERT_NO_THROW(solver.update()); - ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); - ASSERT_NO_THROW(solver.optimize()); ASSERT_TRUE(solver.isOptimal()); ASSERT_FALSE(solver.isUnbounded()); ASSERT_FALSE(solver.isInfeasible()); bool xValue = false; - ASSERT_NO_THROW(xValue = solver.getBinaryValue(xIndex)); + ASSERT_NO_THROW(xValue = solver.getBinaryValue("x")); ASSERT_EQ(true, xValue); int_fast64_t yValue = 0; - ASSERT_NO_THROW(yValue = solver.getIntegerValue(yIndex)); + ASSERT_NO_THROW(yValue = solver.getIntegerValue("y")); ASSERT_EQ(0, yValue); double zValue = 0; - ASSERT_NO_THROW(zValue = solver.getContinuousValue(zIndex)); + ASSERT_NO_THROW(zValue = solver.getContinuousValue("z")); ASSERT_LT(std::abs(zValue - 5), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); double objectiveValue = 0; ASSERT_NO_THROW(objectiveValue = solver.getObjectiveValue()); @@ -155,33 +144,30 @@ TEST(GurobiLpSolver, MILPOptimizeMin) { TEST(GurobiLpSolver, LPInfeasible) { #ifdef STORM_HAVE_GUROBI - storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::MAXIMIZE); - uint_fast64_t xIndex; - ASSERT_NO_THROW(xIndex = solver.createContinuousVariable("x", storm::solver::LpSolver::VariableType::BOUNDED, 0, 1, -1)); - uint_fast64_t yIndex; - ASSERT_NO_THROW(yIndex = solver.createContinuousVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2)); - uint_fast64_t zIndex; - ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1)); - - ASSERT_NO_THROW(solver.update()); + storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize); + ASSERT_NO_THROW(solver.addBoundedContinuousVariable("x", 0, 1, -1)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("y", 0, 2)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1)); + ASSERT_NO_THROW(solver.update()); + + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleLiteral(0.5) * storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") - storm::expressions::Expression::createDoubleVariable("x") == storm::expressions::Expression::createDoubleLiteral(5))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") > storm::expressions::Expression::createDoubleLiteral(7))); + ASSERT_NO_THROW(solver.update()); - ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::EQUAL, 5)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex}, {1}, storm::solver::LpSolver::BoundType::GREATER_EQUAL, 7)); - ASSERT_NO_THROW(solver.optimize()); ASSERT_FALSE(solver.isOptimal()); ASSERT_FALSE(solver.isUnbounded()); ASSERT_TRUE(solver.isInfeasible()); double xValue = 0; - ASSERT_THROW(xValue = solver.getContinuousValue(xIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(xValue = solver.getContinuousValue("x"), storm::exceptions::InvalidAccessException); double yValue = 0; - ASSERT_THROW(yValue = solver.getContinuousValue(yIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(yValue = solver.getContinuousValue("y"), storm::exceptions::InvalidAccessException); double zValue = 0; - ASSERT_THROW(zValue = solver.getContinuousValue(zIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(zValue = solver.getContinuousValue("z"), storm::exceptions::InvalidAccessException); double objectiveValue = 0; - ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidStateException); + ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidAccessException); #else ASSERT_TRUE(false) << "StoRM built without Gurobi support."; #endif @@ -189,33 +175,30 @@ TEST(GurobiLpSolver, LPInfeasible) { TEST(GurobiLpSolver, MILPInfeasible) { #ifdef STORM_HAVE_GUROBI - storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::MAXIMIZE); - uint_fast64_t xIndex; - ASSERT_NO_THROW(xIndex = solver.createBinaryVariable("x", -1)); - uint_fast64_t yIndex; - ASSERT_NO_THROW(yIndex = solver.createIntegerVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2)); - uint_fast64_t zIndex; - ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1)); - - ASSERT_NO_THROW(solver.update()); + storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize); + ASSERT_NO_THROW(solver.addBinaryVariable("x", -1)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("y", 0, 2)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1)); + ASSERT_NO_THROW(solver.update()); + + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleLiteral(0.5) * storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") - storm::expressions::Expression::createDoubleVariable("x") == storm::expressions::Expression::createDoubleLiteral(5))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") > storm::expressions::Expression::createDoubleLiteral(7))); + ASSERT_NO_THROW(solver.update()); - ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::EQUAL, 5)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex}, {1}, storm::solver::LpSolver::BoundType::GREATER_EQUAL, 7)); - ASSERT_NO_THROW(solver.optimize()); ASSERT_FALSE(solver.isOptimal()); ASSERT_FALSE(solver.isUnbounded()); ASSERT_TRUE(solver.isInfeasible()); bool xValue = false; - ASSERT_THROW(xValue = solver.getBinaryValue(xIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(xValue = solver.getBinaryValue("x"), storm::exceptions::InvalidAccessException); int_fast64_t yValue = 0; - ASSERT_THROW(yValue = solver.getIntegerValue(yIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(yValue = solver.getIntegerValue("y"), storm::exceptions::InvalidAccessException); double zValue = 0; - ASSERT_THROW(zValue = solver.getContinuousValue(zIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(zValue = solver.getContinuousValue("z"), storm::exceptions::InvalidAccessException); double objectiveValue = 0; - ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidStateException); + ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidAccessException); #else ASSERT_TRUE(false) << "StoRM built without Gurobi support."; #endif @@ -223,31 +206,28 @@ TEST(GurobiLpSolver, MILPInfeasible) { TEST(GurobiLpSolver, LPUnbounded) { #ifdef STORM_HAVE_GUROBI - storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::MAXIMIZE); - uint_fast64_t xIndex; - ASSERT_NO_THROW(xIndex = solver.createContinuousVariable("x", storm::solver::LpSolver::VariableType::BOUNDED, 0, 1, -1)); - uint_fast64_t yIndex; - ASSERT_NO_THROW(yIndex = solver.createContinuousVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2)); - uint_fast64_t zIndex; - ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1)); - - ASSERT_NO_THROW(solver.update()); + storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize); + ASSERT_NO_THROW(solver.addBoundedContinuousVariable("x", 0, 1, -1)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("y", 0, 2)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1)); + ASSERT_NO_THROW(solver.update()); + + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5))); + ASSERT_NO_THROW(solver.update()); - ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); - ASSERT_NO_THROW(solver.optimize()); ASSERT_FALSE(solver.isOptimal()); ASSERT_TRUE(solver.isUnbounded()); ASSERT_FALSE(solver.isInfeasible()); double xValue = 0; - ASSERT_THROW(xValue = solver.getContinuousValue(xIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(xValue = solver.getContinuousValue("x"), storm::exceptions::InvalidAccessException); double yValue = 0; - ASSERT_THROW(yValue = solver.getContinuousValue(yIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(yValue = solver.getContinuousValue("y"), storm::exceptions::InvalidAccessException); double zValue = 0; - ASSERT_THROW(zValue = solver.getContinuousValue(zIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(zValue = solver.getContinuousValue("z"), storm::exceptions::InvalidAccessException); double objectiveValue = 0; - ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidStateException); + ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidAccessException); #else ASSERT_TRUE(false) << "StoRM built without Gurobi support."; #endif @@ -255,32 +235,28 @@ TEST(GurobiLpSolver, LPUnbounded) { TEST(GurobiLpSolver, MILPUnbounded) { #ifdef STORM_HAVE_GUROBI - storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::MAXIMIZE); - uint_fast64_t xIndex; - ASSERT_NO_THROW(xIndex = solver.createBinaryVariable("x", -1)); - uint_fast64_t yIndex; - ASSERT_NO_THROW(yIndex = solver.createIntegerVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2)); - uint_fast64_t zIndex; - ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1)); - - ASSERT_NO_THROW(solver.update()); + storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize); + ASSERT_NO_THROW(solver.addBinaryVariable("x", -1)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("y", 0, 2)); + ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1)); + ASSERT_NO_THROW(solver.update()); - ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12))); + ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5))); ASSERT_NO_THROW(solver.optimize()); ASSERT_FALSE(solver.isOptimal()); ASSERT_TRUE(solver.isUnbounded()); ASSERT_FALSE(solver.isInfeasible()); bool xValue = false; - ASSERT_THROW(xValue = solver.getBinaryValue(xIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(xValue = solver.getBinaryValue("x"), storm::exceptions::InvalidAccessException); int_fast64_t yValue = 0; - ASSERT_THROW(yValue = solver.getIntegerValue(yIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(yValue = solver.getIntegerValue("y"), storm::exceptions::InvalidAccessException); double zValue = 0; - ASSERT_THROW(zValue = solver.getContinuousValue(zIndex), storm::exceptions::InvalidStateException); + ASSERT_THROW(zValue = solver.getContinuousValue("z"), storm::exceptions::InvalidAccessException); double objectiveValue = 0; - ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidStateException); + ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidAccessException); #else ASSERT_TRUE(false) << "StoRM built without Gurobi support."; #endif -} \ No newline at end of file +}