Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the ?mip_gap parameter that allows unoptimized solutions to be returned #40

Merged
merged 1 commit into from
Apr 28, 2023
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
2 changes: 2 additions & 0 deletions src/abstract_solver.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ class abstract_solver {
virtual int solve() { return 0; };
virtual int solve(int timeout) { return 0; };

virtual void set_mip_gap(double) = 0;

// ******************************************************************
// abort should, if possible, do something which causes solve to
// terminate.
Expand Down
7 changes: 7 additions & 0 deletions src/glpk_solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ void glpk_solver::abort(void) {
return;
}

void glpk_solver::set_mip_gap(double mip_gap) {
this->mip_gap = mip_gap;
}

// solve the current lp problem
int glpk_solver::solve(int timeout) {
int status = 0, nb_objectives = objectives.size();
Expand All @@ -85,6 +89,7 @@ int glpk_solver::solve(int timeout) {
this->mip_params.presolve = GLP_ON;
this->mip_params.binarize = GLP_ON;
this->mip_params.tm_lim = timeout;
this->mip_params.mip_gap = this->mip_gap;
this->mip_params.msg_lev = (verbosity > 1) ? GLP_MSG_ON : GLP_MSG_OFF;
// one of GLP_MSG_OFF GLP_MSG_ERR GLP_MSG_ON GLP_MSG_ALL

Expand Down Expand Up @@ -129,8 +134,10 @@ int glpk_solver::solve(int timeout) {
close(save_stdout);
}
switch (status) {
case GLP_EMIPGAP:
case 0: {
switch (glp_mip_status(lp)) {
case GLP_FEAS:
case GLP_OPT: return 1;
case GLP_NOFEAS: return 0;
default: return -1;
Expand Down
3 changes: 3 additions & 0 deletions src/glpk_solver.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class glpk_solver: public abstract_solver, public scoeff_solver<double, 1, 1> {
// Allocate some columns for integer variables
int set_intvar_range(int rank, CUDFcoefficient lower, CUDFcoefficient upper);

void set_mip_gap(double);

// Write the lp on a file
// int writelp(const char *filename);

Expand Down Expand Up @@ -97,6 +99,7 @@ class glpk_solver: public abstract_solver, public scoeff_solver<double, 1, 1> {
private:
glp_iocp mip_params;
bool aborted;
double mip_gap;

};

Expand Down
2 changes: 2 additions & 0 deletions src/lp_solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ int lp_solver::init_solver(CUDFVersionedPackageList *all_versioned_packages, int
// write the problem into a file
int lp_solver::writelp(const char *filename) { return 0; }

void lp_solver::set_mip_gap(double mip_gap) {} // TODO ?

// solve the current problem
int lp_solver::solve() {
int status = 0;
Expand Down
2 changes: 2 additions & 0 deletions src/lp_solver.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ class lp_solver: public abstract_solver, public scoeff_solver<CUDFcoefficient, 0
// Write the lp on a file
int writelp(const char *filename);

void set_mip_gap(double);

// Solve the problem
int solve();
int solve(int timeout);
Expand Down
6 changes: 3 additions & 3 deletions src/mccs.ml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ external set_problem_request: problem -> request -> unit
= "set_problem_request"

external call_solver:
solver_backend -> string -> int -> problem -> Cudf.package list option
solver_backend -> string -> int -> float -> problem -> Cudf.package list option
= "call_solver"

external backends_list:
Expand All @@ -75,15 +75,15 @@ let problem_of_cudf cudf =
pb

let resolve_cudf
?(verbosity=0) ?timeout ?(solver=default_solver)
?(verbosity=0) ?timeout ?(mip_gap=0.0) ?(solver=default_solver)
criteria (preamble, _, _ as cudf) =
let timeout = match timeout with
| None -> 0
| Some f -> int_of_float (1000. *. f)
in
set_verbosity (max 0 verbosity);
let pb = problem_of_cudf cudf in
match call_solver solver criteria timeout pb with
match call_solver solver criteria timeout mip_gap pb with
| None -> None
| Some sol ->
let univ = Cudf.load_universe sol in
Expand Down
2 changes: 1 addition & 1 deletion src/mccs.mli
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type solver_backend = [ `GLPK | `LP of string | `COIN_CLP | `COIN_CBC | `COIN_SY
(** Resolve the given problem. The timeout is in seconds, default is to never
time out. *)
val resolve_cudf:
?verbosity:int -> ?timeout:float -> ?solver:solver_backend ->
?verbosity:int -> ?timeout:float -> ?mip_gap:float -> ?solver:solver_backend ->
string -> Cudf.cudf -> Cudf.solution option

(** Deprecated, corresponds to the default solver backend selection only *)
Expand Down
10 changes: 5 additions & 5 deletions src/mccs_stubs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -657,11 +657,11 @@ void restore_sigint_handler() {
#endif

// Allow C-c to interrupt the solver
Solver_return call_mccs_protected(Solver solver, char *criteria, int timeout, CUDFproblem* cpb) {
Solver_return call_mccs_protected(Solver solver, char *criteria, int timeout, double mip_gap, CUDFproblem* cpb) {
Solver_return ret = { 0, "", cpb, NULL };
try {
install_sigint_handler();
ret = call_mccs(solver, criteria, timeout, cpb, &mccs_current_solver);
ret = call_mccs(solver, criteria, timeout, mip_gap, cpb, &mccs_current_solver);
mccs_current_solver = NULL;
restore_sigint_handler();
} catch (...) {
Expand All @@ -672,9 +672,9 @@ Solver_return call_mccs_protected(Solver solver, char *criteria, int timeout, CU
}

extern "C" value call_solver
(value ml_solver_backend, value ml_criteria, value ml_timeout, value ml_problem)
(value ml_solver_backend, value ml_criteria, value ml_timeout, value mip_gap, value ml_problem)
{
CAMLparam3(ml_criteria, ml_timeout, ml_problem);
CAMLparam4(ml_criteria, ml_timeout, mip_gap, ml_problem);
CAMLlocal2(results, pkg);
problem * pb = Problem_pt(ml_problem);
CUDFproblem * cpb = pb->pb_cudf_problem;
Expand All @@ -689,7 +689,7 @@ extern "C" value call_solver
strcat(criteria, "]");

// caml_release_runtime_system ();
ret = call_mccs_protected(solver, criteria, Int_val(ml_timeout), cpb);
ret = call_mccs_protected(solver, criteria, Int_val(ml_timeout), Double_val(mip_gap), cpb);
// caml_acquire_runtime_system ();
delete[] criteria;
switch (ret.success) {
Expand Down
7 changes: 4 additions & 3 deletions src/mccscudf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,12 +285,12 @@ CriteriaList *get_criteria(char *crit_descr, bool first_level, vector<abstract_c
return process_criteria(crit_descr, pos, first_level, criteria_with_property);
}

Solver_return call_mccs(Solver solver_arg, char *criteria_arg, int timeout, CUDFproblem* the_problem) {
Solver_return call_mccs(Solver solver_arg, char *criteria_arg, int timeout, double mip_gap, CUDFproblem* the_problem) {
abstract_solver *solver;
return call_mccs(solver_arg, criteria_arg, timeout, the_problem, &solver);
return call_mccs(solver_arg, criteria_arg, timeout, mip_gap, the_problem, &solver);
}

Solver_return call_mccs(Solver solver_arg, char *criteria_arg, int timeout, CUDFproblem* the_problem, abstract_solver **solver_ptr) {
Solver_return call_mccs(Solver solver_arg, char *criteria_arg, int timeout, double mip_gap, CUDFproblem* the_problem, abstract_solver **solver_ptr) {
CUDFproblem *problem = the_problem;
vector<abstract_criteria *> criteria_with_property;
CriteriaList *criteria = get_criteria(criteria_arg, false, &criteria_with_property);
Expand Down Expand Up @@ -377,6 +377,7 @@ Solver_return call_mccs(Solver solver_arg, char *criteria_arg, int timeout, CUDF
if (verbosity > 0) PRINT_OUT("========\nConstraint generation error.\n");
no_solution = true;
}
solver->set_mip_gap(mip_gap);
if (! no_solution) {
int s = (timeout > 0) ? solver->solve(timeout) : solver->solve();
if (s <= 0) {
Expand Down
4 changes: 2 additions & 2 deletions src/mccscudf.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ typedef struct {
abstract_solver * solution; // May be NULL with success == 1 for unsatisfiable problems
} Solver_return;

Solver_return call_mccs(Solver solver_arg, char *criteria_arg, int timeout, CUDFproblem* the_problem);
Solver_return call_mccs(Solver solver_arg, char *criteria_arg, int timeout, CUDFproblem* the_problem, abstract_solver **solver);
Solver_return call_mccs(Solver solver_arg, char *criteria_arg, int timeout, double mip_gap, CUDFproblem* the_problem);
Solver_return call_mccs(Solver solver_arg, char *criteria_arg, int timeout, double mip_gap, CUDFproblem* the_problem, abstract_solver **solver);

int has_backend(Solver_backend backend);

Expand Down