diff --git a/_oasis b/_oasis index aaf751670368ed47e2cf5bbb9a63c484043428c6..61aa0cccbe1a91db969a8b89dfb3ca3437d06063 100644 --- a/_oasis +++ b/_oasis @@ -26,6 +26,7 @@ Library libcool CCOpt: -std=c++98 -x c++ CSources: gmlmip_stub.c, minisat_stub.c, + glpk_stub.c, GMLMIP-0.1/rules/sizefunctions.c, GMLMIP-0.1/rules/setofconclusions.c, GMLMIP-0.1/rules/PML_premise.c, diff --git a/src/lib/glpk_stub.c b/src/lib/glpk_stub.c index df77a01c0d54c04be9fdcaf6f8ddf776ac8f5276..82075ad5d44c21ff40425875712297daff64a6bf 100644 --- a/src/lib/glpk_stub.c +++ b/src/lib/glpk_stub.c @@ -1,6 +1,6 @@ /* * ocaml-glpk - OCaml bindings to glpk - * Copyright (C) 2004 Samuel Mimram + * Copyright (C) 2004 Samuel Mimram, 2014 Dominik Paulus * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,8 +18,6 @@ * Boston, MA 02111-1307, USA. */ -/* $Id$ */ - #include <caml/alloc.h> #include <caml/callback.h> #include <caml/custom.h> @@ -34,184 +32,187 @@ #include <glpk.h> static void raise_on_error(int ret) { + /* TODO: Do we want this semantics? */ +#if 0 switch(ret) { - case LPX_E_OK: + case glp_prob_E_OK: return; - case LPX_E_FAULT: + case glp_prob_E_FAULT: caml_raise_constant(*caml_named_value("ocaml_glpk_exn_fault")); - case LPX_E_OBJLL: + case glp_prob_E_OBJLL: caml_raise_constant(*caml_named_value("ocaml_glpk_exn_objll")); - case LPX_E_OBJUL: + case glp_prob_E_OBJUL: caml_raise_constant(*caml_named_value("ocaml_glpk_exn_objul")); - case LPX_E_NOPFS: + case glp_prob_E_NOPFS: caml_raise_constant(*caml_named_value("ocaml_glpk_exn_nopfs")); - case LPX_E_NODFS: + case glp_prob_E_NODFS: caml_raise_constant(*caml_named_value("ocaml_glpk_exn_nodfs")); - case LPX_E_ITLIM: + case glp_prob_E_ITLIM: caml_raise_constant(*caml_named_value("ocaml_glpk_exn_itlim")); - case LPX_E_TMLIM: + case glp_prob_E_TMLIM: caml_raise_constant(*caml_named_value("ocaml_glpk_exn_tmlim")); - case LPX_E_SING: + case glp_prob_E_SING: caml_raise_constant(*caml_named_value("ocaml_glpk_exn_sing")); - case LPX_E_EMPTY: + case glp_prob_E_EMPTY: caml_raise_constant(*caml_named_value("ocaml_glpk_exn_empty")); - case LPX_E_BADB: + case glp_prob_E_BADB: caml_raise_constant(*caml_named_value("ocaml_glpk_exn_badb")); - case LPX_E_NOCONV: + case glp_prob_E_NOCONV: caml_raise_constant(*caml_named_value("ocaml_glpk_exn_noconv")); default: caml_raise_constant(*caml_named_value("ocaml_glpk_exn_unknown")); } assert(0); /* TODO */ +#endif } -#define Lpx_val(v) (*((LPX**)Data_custom_val(v))) +#define Glp_val(v) (*((glp_prob**)Data_custom_val(v))) -static void finalize_lpx(value block) { - lpx_delete_prob(Lpx_val(block)); +static void finalize_glp(value block) { + glp_delete_prob(Glp_val(block)); } -static struct custom_operations lpx_ops = { - "ocaml_glpk_lpx", - finalize_lpx, +static struct custom_operations glp_ops = { + (char*) "ocaml_glpk_prob", + finalize_glp, custom_compare_default, custom_hash_default, custom_serialize_default, custom_deserialize_default }; -static value new_blp(LPX *lp) { - value block = caml_alloc_custom(&lpx_ops, sizeof(LPX *), 0, 1); - Lpx_val(block) = lp; +static value box_problem(glp_prob *lp) { + value block = caml_alloc_custom(&glp_ops, sizeof(glp_prob*), 0, 1); + Glp_val(block) = lp; return block; } CAMLprim value ocaml_glpk_new_prob(value unit) { - LPX *lp = lpx_create_prob(); - return new_blp(lp); + glp_prob *lp = glp_create_prob(); + return box_problem(lp); } CAMLprim value ocaml_glpk_set_prob_name(value blp, value name) { - LPX *lp = Lpx_val(blp); - lpx_set_prob_name(lp, String_val(name)); + glp_prob *lp = Glp_val(blp); + glp_set_prob_name(lp, String_val(name)); return Val_unit; } CAMLprim value ocaml_glpk_get_prob_name(value blp) { CAMLparam1(blp); - LPX *lp = Lpx_val(blp); - CAMLreturn(caml_copy_string(lpx_get_prob_name(lp))); + glp_prob *lp = Glp_val(blp); + CAMLreturn(caml_copy_string(glp_get_prob_name(lp))); } CAMLprim value ocaml_glpk_set_obj_name(value blp, value name) { - LPX *lp = Lpx_val(blp); - lpx_set_obj_name(lp, String_val(name)); + glp_prob *lp = Glp_val(blp); + glp_set_obj_name(lp, String_val(name)); return Val_unit; } CAMLprim value ocaml_glpk_get_obj_name(value blp) { CAMLparam1(blp); - LPX *lp = Lpx_val(blp); - CAMLreturn(caml_copy_string(lpx_get_obj_name(lp))); + glp_prob *lp = Glp_val(blp); + CAMLreturn(caml_copy_string(glp_get_obj_name(lp))); } -static int direction_table[] = {LPX_MIN, LPX_MAX}; +static int direction_table[] = {GLP_MIN, GLP_MAX}; CAMLprim value ocaml_glpk_set_direction(value blp, value direction) { - LPX *lp = Lpx_val(blp); - lpx_set_obj_dir(lp, direction_table[Int_val(direction)]); + glp_prob *lp = Glp_val(blp); + glp_set_obj_dir(lp, direction_table[Int_val(direction)]); return Val_unit; } CAMLprim value ocaml_glpk_get_direction(value blp) { - LPX *lp = Lpx_val(blp); - switch(lpx_get_obj_dir(lp)) { - case LPX_MIN: - return Val_int(0); - - case LPX_MAX: - return Val_int(1); - - default: - assert(0); + glp_prob *lp = Glp_val(blp); + switch(glp_get_obj_dir(lp)) { + case GLP_MIN: return Val_int(0); + case GLP_MAX: return Val_int(1); + default: assert(0); } } CAMLprim value ocaml_glpk_add_rows(value blp, value n) { - LPX *lp = Lpx_val(blp); - lpx_add_rows(lp, Int_val(n)); + glp_prob *lp = Glp_val(blp); + glp_add_rows(lp, Int_val(n)); return Val_unit; } CAMLprim value ocaml_glpk_set_row_name(value blp, value n, value name) { - LPX *lp = Lpx_val(blp); - lpx_set_row_name(lp, Int_val(n) + 1, String_val(name)); + glp_prob *lp = Glp_val(blp); + glp_set_row_name(lp, Int_val(n) + 1, String_val(name)); return Val_unit; } CAMLprim value ocaml_glpk_get_row_name(value blp, value n) { CAMLparam1(blp); - LPX *lp = Lpx_val(blp); - CAMLreturn(caml_copy_string(lpx_get_row_name(lp, Int_val(n) + 1))); + glp_prob *lp = Glp_val(blp); + CAMLreturn(caml_copy_string(glp_get_row_name(lp, Int_val(n) + 1))); } -static int auxvartype_table[] = {LPX_FR, LPX_LO, LPX_UP, LPX_DB, LPX_FX}; +static int auxvartype_table[] = { + GLP_FR, /* Unbound variable */ + GLP_LO, /* Lower bound */ + GLP_UP, /* Upper bound */ + GLP_DB, /* Lower and upper bound */ + GLP_FX /* Fixed value */ }; CAMLprim value ocaml_glpk_set_row_bounds(value blp, value n, value type, value lb, value ub) { - LPX *lp = Lpx_val(blp); - lpx_set_row_bnds(lp, Int_val(n) + 1, auxvartype_table[Int_val(type)], Double_val(lb), Double_val(ub)); + glp_prob *lp = Glp_val(blp); + glp_set_row_bnds(lp, Int_val(n) + 1, auxvartype_table[Int_val(type)], Double_val(lb), Double_val(ub)); return Val_unit; } CAMLprim value ocaml_glpk_add_cols(value blp, value n) { - LPX *lp = Lpx_val(blp); - lpx_add_cols(lp, Int_val(n)); + glp_prob *lp = Glp_val(blp); + glp_add_cols(lp, Int_val(n)); return Val_unit; } CAMLprim value ocaml_glpk_set_col_name(value blp, value n, value name) { - LPX *lp = Lpx_val(blp); - lpx_set_col_name(lp, Int_val(n) + 1, String_val(name)); + glp_prob *lp = Glp_val(blp); + glp_set_col_name(lp, Int_val(n) + 1, String_val(name)); return Val_unit; } CAMLprim value ocaml_glpk_get_col_name(value blp, value n) { CAMLparam1(blp); - LPX *lp = Lpx_val(blp); - CAMLreturn(caml_copy_string(lpx_get_col_name(lp, Int_val(n) + 1))); + glp_prob *lp = Glp_val(blp); + CAMLreturn(caml_copy_string(glp_get_col_name(lp, Int_val(n) + 1))); } CAMLprim value ocaml_glpk_set_col_bounds(value blp, value n, value type, value lb, value ub) { - LPX *lp = Lpx_val(blp); - lpx_set_col_bnds(lp, Int_val(n) + 1, auxvartype_table[Int_val(type)], Double_val(lb), Double_val(ub)); + glp_prob *lp = Glp_val(blp); + glp_set_col_bnds(lp, Int_val(n) + 1, auxvartype_table[Int_val(type)], Double_val(lb), Double_val(ub)); return Val_unit; } CAMLprim value ocaml_glpk_set_obj_coef(value blp, value n, value coef) { - LPX *lp = Lpx_val(blp); - lpx_set_obj_coef(lp, Int_val(n) + 1, Double_val(coef)); + glp_prob *lp = Glp_val(blp); + glp_set_obj_coef(lp, Int_val(n) + 1, Double_val(coef)); return Val_unit; } CAMLprim value ocaml_glpk_load_matrix(value blp, value matrix) { - LPX *lp = Lpx_val(blp); - int i_dim = Wosize_val(matrix), j_dim; + glp_prob *lp = Glp_val(blp); + unsigned int i_dim = Wosize_val(matrix), j_dim; int *ia, *ja; double *ar; double x; - int i, j, n; + unsigned int i, j, n; if(i_dim <= 0) return Val_unit; @@ -236,7 +237,7 @@ CAMLprim value ocaml_glpk_load_matrix(value blp, value matrix) { } } } - lpx_load_matrix(lp, n - 1, ia, ja, ar); + glp_load_matrix(lp, n - 1, ia, ja, ar); free(ia); free(ja); @@ -246,7 +247,7 @@ CAMLprim value ocaml_glpk_load_matrix(value blp, value matrix) { } CAMLprim value ocaml_glpk_load_sparse_matrix(value blp, value matrix) { - LPX *lp = Lpx_val(blp); + glp_prob *lp = Glp_val(blp); int len = Wosize_val(matrix); int *ia, *ja; double *ar; @@ -263,7 +264,7 @@ CAMLprim value ocaml_glpk_load_sparse_matrix(value blp, value matrix) { ja[i + 1] = Int_val(Field(Field(e, 0), 1)) + 1; ar[i + 1] = Double_val(Field(e, 1)); } - lpx_load_matrix(lp, len, ia, ja, ar); + glp_load_matrix(lp, len, ia, ja, ar); free(ia); free(ja); @@ -274,11 +275,11 @@ CAMLprim value ocaml_glpk_load_sparse_matrix(value blp, value matrix) { CAMLprim value ocaml_glpk_simplex(value blp) { CAMLparam1(blp); - LPX *lp = Lpx_val(blp); + glp_prob *lp = Glp_val(blp); int ret; caml_enter_blocking_section(); - ret = lpx_simplex(lp); + ret = glp_simplex(lp, NULL); caml_leave_blocking_section(); raise_on_error(ret); @@ -286,195 +287,125 @@ CAMLprim value ocaml_glpk_simplex(value blp) { } CAMLprim value ocaml_glpk_get_obj_val(value blp) { - LPX *lp = Lpx_val(blp); + glp_prob *lp = Glp_val(blp); double ans; - if(lpx_get_class(lp) == LPX_MIP) - ans = lpx_mip_obj_val(lp); - else - ans = lpx_get_obj_val(lp); + ans = glp_get_obj_val(lp); return caml_copy_double(ans); } CAMLprim value ocaml_glpk_get_col_prim(value blp, value n) { - LPX *lp = Lpx_val(blp); + glp_prob *lp = Glp_val(blp); double ans; - /* TODO: is it the right thing to do? */ - if(lpx_get_class(lp) == LPX_MIP) - ans = lpx_mip_col_val(lp, Int_val(n) + 1); - else - ans = lpx_get_col_prim(lp, Int_val(n) + 1); + ans = glp_get_col_prim(lp, Int_val(n) + 1); return caml_copy_double(ans); } CAMLprim value ocaml_glpk_get_row_prim(value blp, value n) { - LPX *lp = Lpx_val(blp); - return caml_copy_double(lpx_get_row_prim(lp, Int_val(n) + 1)); + glp_prob *lp = Glp_val(blp); + return caml_copy_double(glp_get_row_prim(lp, Int_val(n) + 1)); } CAMLprim value ocaml_glpk_get_row_dual(value blp, value n) { - LPX *lp = Lpx_val(blp); - return caml_copy_double(lpx_get_row_dual(lp, Int_val(n) + 1)); + glp_prob *lp = Glp_val(blp); + return caml_copy_double(glp_get_row_dual(lp, Int_val(n) + 1)); } CAMLprim value ocaml_glpk_get_num_rows(value blp) { - LPX *lp = Lpx_val(blp); - return Val_int(lpx_get_num_rows(lp)); + glp_prob *lp = Glp_val(blp); + return Val_int(glp_get_num_rows(lp)); } CAMLprim value ocaml_glpk_get_num_cols(value blp) { - LPX *lp = Lpx_val(blp); - return Val_int(lpx_get_num_cols(lp)); + glp_prob *lp = Glp_val(blp); + return Val_int(glp_get_num_cols(lp)); } CAMLprim value ocaml_glpk_scale_problem(value blp) { - LPX *lp = Lpx_val(blp); - lpx_scale_prob(lp); + glp_prob *lp = Glp_val(blp); + glp_scale_prob(lp, GLP_SF_AUTO); /* TODO! */ return Val_unit; } CAMLprim value ocaml_glpk_unscale_problem(value blp) { - LPX *lp = Lpx_val(blp); - lpx_unscale_prob(lp); + glp_prob *lp = Glp_val(blp); + glp_unscale_prob(lp); return Val_unit; } -/* TODO */ -/* -CAMLprim value ocaml_glpk_check_kkt(value blp, value scaled, value vkkt) -{ - -} -*/ - CAMLprim value ocaml_glpk_interior(value blp) { CAMLparam1(blp); - LPX *lp = Lpx_val(blp); + glp_prob *lp = Glp_val(blp); int ret; caml_enter_blocking_section(); - ret = lpx_interior(lp); + ret = glp_interior(lp, NULL); /* TODO! */ caml_leave_blocking_section(); raise_on_error(ret); CAMLreturn(Val_unit); } -static int class_table[] = {LPX_LP, LPX_MIP}; - -CAMLprim value ocaml_glpk_set_class(value blp, value class) { - LPX *lp = Lpx_val(blp); - lpx_set_class(lp, class_table[Int_val(class)]); - return Val_unit; -} - -CAMLprim value ocaml_glpk_get_class(value blp) { - LPX *lp = Lpx_val(blp); - switch(lpx_get_class(lp)) { - case LPX_LP: - return Val_int(0); - - case LPX_MIP: - return Val_int(1); - - default: - assert(0); - } -} - -static int kind_table[] = {LPX_CV, LPX_IV}; +static int kind_table[] = {GLP_CV, GLP_IV}; CAMLprim value ocaml_glpk_set_col_kind(value blp, value n, value kind) { - LPX *lp = Lpx_val(blp); - lpx_set_col_kind(lp, Int_val(n) + 1, kind_table[Int_val(kind)]); + glp_prob *lp = Glp_val(blp); + glp_set_col_kind(lp, Int_val(n) + 1, kind_table[Int_val(kind)]); return Val_unit; } -CAMLprim value ocaml_glpk_integer(value blp) { - CAMLparam1(blp); - LPX *lp = Lpx_val(blp); - int ret; - - caml_enter_blocking_section(); - ret = lpx_integer(lp); - caml_leave_blocking_section(); - - raise_on_error(ret); - CAMLreturn(Val_unit); -} - -CAMLprim value ocaml_glpk_intopt(value blp) { - CAMLparam1(blp); - LPX *lp = Lpx_val(blp); - int ret; - - caml_enter_blocking_section(); - ret = lpx_intopt(lp); - caml_leave_blocking_section(); - - raise_on_error(ret); - CAMLreturn(Val_unit); -} - CAMLprim value ocaml_glpk_warm_up(value blp) { - LPX *lp = Lpx_val(blp); - raise_on_error(lpx_warm_up(lp)); + glp_prob *lp = Glp_val(blp); + raise_on_error(glp_warm_up(lp)); return Val_unit; } +#if 0 + +/* TODO! */ + #define BIND_INT_PARAM(name, param) \ CAMLprim value ocaml_glpk_get_##name(value blp) \ { \ - LPX *lp = Lpx_val(blp); \ + glp_prob *lp = Glp_val(blp); \ return Val_int(lpx_get_int_parm(lp, param)); \ } \ CAMLprim value ocaml_glpk_set_##name(value blp, value n) \ { \ - LPX *lp = Lpx_val(blp); \ - lpx_set_int_parm(lp, param, Int_val(n)); \ + glp_prob *lp = Glp_val(blp); \ + glp_set_int_parm(lp, param, Int_val(n)); \ return Val_unit; \ } #define BIND_REAL_PARAM(name, param) \ CAMLprim value ocaml_glpk_get_##name(value blp) \ { \ - LPX *lp = Lpx_val(blp); \ + glp_prob *lp = Glp_val(blp); \ double ans = lpx_get_real_parm(lp, param); \ return caml_copy_double(ans); \ } \ CAMLprim value ocaml_glpk_set_##name(value blp, value n) \ { \ - LPX *lp = Lpx_val(blp); \ - lpx_set_real_parm(lp, param, Double_val(n)); \ + glp_prob *lp = Glp_val(blp); \ + glp_set_real_parm(lp, param, Double_val(n)); \ return Val_unit; \ } -BIND_INT_PARAM(message_level, LPX_K_MSGLEV); -BIND_INT_PARAM(scaling, LPX_K_SCALE); -BIND_INT_PARAM(use_dual_simplex, LPX_K_DUAL); -BIND_INT_PARAM(pricing, LPX_K_PRICE); -BIND_REAL_PARAM(relaxation, LPX_K_RELAX); +BIND_INT_PARAM(message_level, glp_prob_K_MSGLEV); +BIND_INT_PARAM(scaling, glp_prob_K_SCALE); +BIND_INT_PARAM(use_dual_simplex, glp_prob_K_DUAL); +BIND_INT_PARAM(pricing, glp_prob_K_PRICE); +BIND_REAL_PARAM(relaxation, glp_prob_K_RELAX); /* -BIND_REAL_PARAM(relative_tolerance, LPX_K_TOLBND); -BIND_REAL_PARAM(absolute_tolerance, LPX_K_TOLDJ); +BIND_REAL_PARAM(relative_tolerance, glp_prob_K_TOLBND); +BIND_REAL_PARAM(absolute_tolerance, glp_prob_K_TOLDJ); */ -BIND_INT_PARAM(solution_rounding, LPX_K_ROUND); -BIND_INT_PARAM(iteration_limit, LPX_K_ITLIM); -BIND_INT_PARAM(iteration_count, LPX_K_ITCNT); -BIND_REAL_PARAM(time_limit, LPX_K_TMLIM); -BIND_INT_PARAM(branching_heuristic, LPX_K_BRANCH); -BIND_INT_PARAM(backtracking_heuristic, LPX_K_BTRACK); -BIND_INT_PARAM(use_presolver, LPX_K_PRESOL); - -CAMLprim value ocaml_glpk_read_cplex(value fname) { - LPX *lp = lpx_read_cpxlp(String_val(fname)); - if(!lp) - caml_failwith("Error while reading data in CPLEX LP format."); - return new_blp(lp); -} - -CAMLprim value ocaml_glpk_write_cplex(value blp, value fname) { - if(lpx_write_cpxlp(Lpx_val(blp), String_val(fname))) - caml_failwith("Error while writing data in CPLEX LP format."); - return Val_unit; -} +BIND_INT_PARAM(solution_rounding, glp_prob_K_ROUND); +BIND_INT_PARAM(iteration_limit, glp_prob_K_ITLIM); +BIND_INT_PARAM(iteration_count, glp_prob_K_ITCNT); +BIND_REAL_PARAM(time_limit, glp_prob_K_TMLIM); +BIND_INT_PARAM(branching_heuristic, glp_prob_K_BRANCH); +BIND_INT_PARAM(backtracking_heuristic, glp_prob_K_BTRACK); +BIND_INT_PARAM(use_presolver, glp_prob_K_PRESOL); + +#endif