Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion lib/coek/coek/solvers/gurobi/coek_gurobi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,17 @@ class GurobiSolver : public SolverRepn {
std::unordered_map<size_t, GRBVar> x;
std::shared_ptr<SolverResults> results;

enum class gurobi_license_status { available, error, unknown };
gurobi_license_status license_status;

public:
GurobiSolver() : SolverRepn(), env(0), gmodel(0) {}
GurobiSolver() : SolverRepn(), env(0), gmodel(0), license_status(gurobi_license_status::unknown)
{
}
~GurobiSolver();

bool available();

std::shared_ptr<SolverResults> resolve();
std::shared_ptr<SolverResults> solve(Model&);
#ifdef COEK_WITH_COMPACT_MODEL
Expand Down
45 changes: 39 additions & 6 deletions lib/coek/coek/solvers/gurobi/gurobi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,24 @@ GurobiSolver::~GurobiSolver()
}
}

bool GurobiSolver::available()
{
if (license_status == gurobi_license_status::available)
return true;

try {
auto _env = new GRBEnv(true);
_env->start();
license_status = gurobi_license_status::available;
delete _env;
}
catch (GRBException e) {
license_status = gurobi_license_status::error;
}

return license_status == gurobi_license_status::available;
}

void GurobiSolver::set_gurobi_options()
{
// All options are converted to strings for Gurobi
Expand All @@ -161,12 +179,19 @@ void GurobiSolver::pre_solve()
results->tic();

if (initial_solve()) {
env = new GRBEnv(true);
auto it = integer_options().find("OutputFlag");
if (it != integer_options().end())
env->set(GRB_IntParam_OutputFlag, it->second);
env->start();
gmodel = new GRBModel(*env);
try {
env = new GRBEnv(true);
auto it = integer_options().find("OutputFlag");
if (it != integer_options().end())
env->set(GRB_IntParam_OutputFlag, it->second);
env->start();
}
catch (GRBException e) {
license_status = gurobi_license_status::error;
results->termination_condition = TerminationCondition::license_problems;
}
if (available())
gmodel = new GRBModel(*env);
}
}

Expand All @@ -183,6 +208,9 @@ void GurobiSolver::post_solve()
std::shared_ptr<SolverResults> GurobiSolver::solve(Model& model)
{
pre_solve();
if (not available())
return results;

auto _model = model.repn.get();
results->model_name = _model->name;

Expand Down Expand Up @@ -281,6 +309,9 @@ std::shared_ptr<SolverResults> GurobiSolver::solve(Model& model)
std::shared_ptr<SolverResults> GurobiSolver::solve(CompactModel& compact_model)
{
pre_solve();
if (not available())
return results;

results->model_name = compact_model.name();

// Add Gurobi variables
Expand Down Expand Up @@ -395,6 +426,8 @@ std::shared_ptr<SolverResults> GurobiSolver::solve(CompactModel& compact_model)
std::shared_ptr<SolverResults> GurobiSolver::resolve()
{
pre_solve();
if (not available())
return results;

auto _model = model.repn.get();
results->model_name = _model->name;
Expand Down
4 changes: 2 additions & 2 deletions lib/coek/coek/solvers/solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ void Solver::initialize(std::string name_)
name = name_;
}

bool Solver::available() const { return repn.get(); }
bool Solver::available() { return repn.get() and repn->available(); }

std::shared_ptr<SolverResults> Solver::solve(Model& model)
{
Expand Down Expand Up @@ -71,7 +71,7 @@ void NLPSolver::initialize(std::string name_)
name = name_;
}

bool NLPSolver::available() const { return repn.get() && repn->available(); }
bool NLPSolver::available() { return repn.get() and repn->available(); }

std::shared_ptr<SolverResults> NLPSolver::solve(NLPModel& model)
{
Expand Down
4 changes: 2 additions & 2 deletions lib/coek/coek/solvers/solver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class Solver : public OptionCache {
void initialize(std::string solver);

/** \returns \c true if the solver is available */
bool available() const;
virtual bool available();

/** Optimize the specified model
*
Expand Down Expand Up @@ -74,7 +74,7 @@ class NLPSolver : public OptionCache {
void initialize(std::string solver);

/** \returns \c true if the solver is available */
bool available() const;
bool available();

/** Optimize the specified model
*
Expand Down
2 changes: 2 additions & 0 deletions lib/coek/coek/solvers/solver_repn.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ class SolverRepn : public SolverCache, public OptionCache {
virtual std::shared_ptr<SolverResults> resolve() = 0;

void find_updated_coefs();

virtual bool available() { return true; }
};

SolverRepn* create_solver(std::string& name, OptionCache& options);
Expand Down
4 changes: 2 additions & 2 deletions lib/coek/coek/solvers/solver_results.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ std::string to_string(TerminationCondition tc)
case TerminationCondition::interrupted:
return "interrupted";

case TerminationCondition::licensing_problems:
return "licensing_problems";
case TerminationCondition::license_problems:
return "license_problems";

case TerminationCondition::solver_not_available:
return "solver_not_available";
Expand Down
6 changes: 3 additions & 3 deletions lib/coek/coek/solvers/solver_results.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ enum class TerminationCondition {
// The solver was interrupted while running.
interrupted,

// The solver experienced issues with licensing. This could be that no license was found, the
// The solver experienced issues with license. This could be that no license was found, the
// license is of the wrong type for the problem (e.g., problem is too big for type of license),
// or there was an issue contacting a licensing server.
licensing_problems,
// or there was an issue contacting a license server.
license_problems,

// The solver cannot be found. This could be a problem the installation of the solver, the
// solver link library may not be found, or the solver executable may not be found.
Expand Down
8 changes: 7 additions & 1 deletion lib/coek/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,16 @@ TARGET_LINK_LIBRARIES(coek_micro_test PUBLIC coek ${coek_link_libraries})
TARGET_COMPILE_OPTIONS(coek_micro_test PUBLIC ${coek_compile_options})
target_compile_definitions(coek_micro_test PUBLIC COEK_TEST_DIR="${CMAKE_CURRENT_SOURCE_DIR}/")

# gurobi
add_executable(gurobi_test coek_gurobi_test.cpp solver/TestModels.cpp)
TARGET_LINK_LIBRARIES(gurobi_test PUBLIC coek ${coek_link_libraries} ${coek_test_libraries})
TARGET_COMPILE_OPTIONS(gurobi_test PUBLIC ${coek_compile_options})
target_compile_definitions(gurobi_test PUBLIC COEK_TEST_DIR="${CMAKE_CURRENT_SOURCE_DIR}/")


# testing
add_custom_target(test_coek
COMMAND ${CMAKE_CTEST_COMMAND})
COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure)
add_custom_target(test_coek_verbose
COMMAND ${CMAKE_CTEST_COMMAND} --verbose)
add_custom_target(test_coek_memcheck
Expand Down
139 changes: 139 additions & 0 deletions lib/coek/test/coek_gurobi_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// #include "catch2/catch_test_macros.hpp"
// #include "catch2/catch_approx.hpp"
// #include "catch2/generators/catch_generators.hpp"

#include <cassert>
#include "coek/coek.hpp"
#include "test/solver/TestModel.hpp"

coek::Solver test_solver()
{
coek::Solver solver("gurobi");
solver.set_option("OutputFlag", 0);
return solver;
}

int main()
{
//
// Gurobi Checks
//

auto solver = test_solver();
if (solver.available()) {
// SECTION("empty")
{
std::cout << "empty" << std::endl;
auto solver = test_solver();
auto test = test::model("empty");
auto m = test->model;
assert(m.name() == "empty");
auto res = solver.solve(m);
assert(res->termination_condition == coek::TerminationCondition::empty_model);
}
// SECTION("rosenbr")
{
std::cout << "rosenbr" << std::endl;
auto solver = test_solver();
auto test = test::model("rosenbr");
auto m = test->model;
assert(m.name() == "rosenbr");
auto res = solver.solve(m);
assert(res->termination_condition
== coek::TerminationCondition::invalid_model_for_solver);
}
// SECTION("simplelp1")
{
std::cout << "simplelp1" << std::endl;
auto solver = test_solver();
auto test = test::model("simplelp1");
auto m = test->model;
assert(m.name() == "simplelp1");
auto res = solver.solve(m);
assert(test->check_results(m, res) == true);
}
// SECTION("simpleqp1")
{
std::cout << "simpleqp1" << std::endl;
auto solver = test_solver();
auto test = test::model("simpleqp1");
auto m = test->model;
assert(m.name() == "simpleqp1");
auto res = solver.solve(m);
assert(test->check_results(m, res) == true);
}
// SECTION("simpleqp2")
{
std::cout << "simpleqp2" << std::endl;
auto solver = test_solver();
auto test = test::model("simpleqp2");
auto m = test->model;
assert(m.name() == "simpleqp2");
auto res = solver.solve(m);
assert(test->check_results(m, res) == true);
}
// SECTION("simpleqp3")
{
std::cout << "simpleqp3" << std::endl;
auto solver = test_solver();
auto test = test::model("simpleqp3");
auto m = test->model;
assert(m.name() == "simpleqp3");
auto res = solver.solve(m);
assert(test->check_results(m, res) == true);
}
// SECTION("simpleqp4")
{
std::cout << "simpleqp4" << std::endl;
auto solver = test_solver();
auto test = test::model("simpleqp4");
auto m = test->model;
assert(m.name() == "simpleqp4");
auto res = solver.solve(m);
assert(test->check_results(m, res) == true);
}
// SECTION("lp_bounds1")
{
std::cout << "lp_bounds" << std::endl;
auto solver = test_solver();
auto test = test::model("lp_bounds1");
auto m = test->model;
assert(m.name() == "lp_bounds1");
auto res = solver.solve(m);
assert(test->check_results(m, res) == true);
}
// SECTION("lp_bounds2")
{
std::cout << "lp_bounds2" << std::endl;
auto solver = test_solver();
auto test = test::model("lp_bounds2");
auto m = test->model;
assert(m.name() == "lp_bounds2");
auto res = solver.solve(m);
assert(test->check_results(m, res) == true);
}
// SECTION("qp_bounds")
{
std::cout << "qp_bounds" << std::endl;
auto solver = test_solver();
auto test = test::model("qp_bounds");
auto m = test->model;
assert(m.name() == "qp_bounds");
auto res = solver.solve(m);
assert(test->check_results(m, res) == true);
}
}
else {
// SECTION("simplelp1")
{
std::cout << "simplelp1" << std::endl;
auto solver = test_solver();
auto test = test::model("simplelp1");
auto m = test->model;
assert(m.name() == "simplelp1");
auto res = solver.solve(m);
assert((res->termination_condition == coek::TerminationCondition::solver_not_available)
or (res->termination_condition == coek::TerminationCondition::license_problems));
}
}
}
Loading