irgmod: Pass the new inputs to turn_into_tuple() instead of initialising them with...
[libfirm] / ir / lpp / lpp_gurobi.c
index 13c34c2..6b043e4 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <math.h>
 
 #include "obst.h"
 
@@ -42,6 +43,7 @@ static char gurobi_var_encoding[4] = { 0, 0, GRB_CONTINUOUS, GRB_BINARY };
 typedef struct _gurobi_t {
        lpp_t *lpp;
        GRBenv *env;
+       GRBenv *modelenv;
        GRBmodel *model;
 } gurobi_t;
 
@@ -58,16 +60,28 @@ static gurobi_t *new_gurobi(lpp_t *lpp)
 
        gurobi_t *grb = XMALLOCZ(gurobi_t);
        grb->lpp = lpp;
-       error = GRBloadenv(&grb->env, NULL);
-       check_gurobi_error(grb, error);
-       error = GRBsetlogfile(grb->env, lpp->log);
+       /* /tmp/firm_gurobi.log is a hack (see below) */
+       error = GRBloadenv(&grb->env, "/tmp/firm_gurobi.log");
        check_gurobi_error(grb, error);
+       /* Matze: do not set the FILE* for logging output. Because:
+        *  a) the function is deprecated
+        *  b) gurobi closes the FILE handle when it is done, which leads to
+        *     very unexpected effects when you pass stdout or stderr as logging
+        *     output.
+        * The only thing gurobi sanely supports is giving a string with a filename
+        * :-( ...so we use /tmp/firm_gurobi.log as a temporary measure...
+        */
+       if (lpp->log != stdout && lpp->log != stderr) {
+               error = GRBsetintparam(grb->env, GRB_INT_PAR_OUTPUTFLAG, 0);
+               check_gurobi_error(grb, error);
+       }
 
        return grb;
 }
 
 static void free_gurobi(gurobi_t *grb)
 {
+       GRBfreemodel(grb->model);
        GRBfreeenv(grb->env);
        free(grb);
 }
@@ -78,19 +92,18 @@ static void free_gurobi(gurobi_t *grb)
  */
 static void gurobi_construct(gurobi_t *grb)
 {
-       const matrix_elem_t *elem;
-       int                  i, o;
-       //int                  sv_cnt;
-       //int                 *indices;
-       //double              *startv;
-       int                  numcols, numrows, numentries;
-       int                  objsen, *matbeg, *matcnt, *matind;
-       double               *obj, *rhs, *matval, *lb;
-       char                 *sense, *vartype;
-       char                 **colname, **rowname;
-       struct obstack       obst;
-       lpp_t                *lpp = grb->lpp;
-       int                  error;
+       int            i, o;
+       //int            sv_cnt;
+       //int           *indices;
+       //double        *startv;
+       int            numcols, numrows, numentries;
+       int            objsen, *matbeg, *matcnt, *matind;
+       double        *obj, *rhs, *matval, *lb;
+       char          *sense, *vartype;
+       char         **colname, **rowname;
+       struct obstack obst;
+       lpp_t         *lpp = grb->lpp;
+       int            error;
 
        numcols    = lpp->var_next-1;
        numrows    = lpp->cst_next-1;
@@ -124,14 +137,6 @@ static void gurobi_construct(gurobi_t *grb)
                colname[i] = (char*) curr_var->name;
                vartype[i] = gurobi_var_encoding[curr_var->type.var_type];
 
-#if 0
-               if (curr_var->value_kind == lpp_value_start) {
-                       panic("start values not supported in gurobi yet");
-                       indices[sv_cnt]  = i;
-                       startv[sv_cnt++] = curr_var->value;
-               }
-#endif
-
                matbeg[i] = o;
                matcnt[i] = 0;
                matrix_foreach_in_col(lpp->m, 1 + i, elem) {
@@ -157,9 +162,10 @@ static void gurobi_construct(gurobi_t *grb)
                             objsen, 0, obj, sense, rhs, matbeg, matcnt, matind,
                             matval, lb, NULL, vartype, colname, rowname);
        check_gurobi_error(grb, error);
+       grb->modelenv = GRBgetenv(grb->model);
 
        obstack_free(&obst, NULL);
-       free_lpp_matrix(lpp);
+       lpp_free_matrix(lpp);
 }
 
 static void gurobi_solve(gurobi_t *grb)
@@ -172,40 +178,12 @@ static void gurobi_solve(gurobi_t *grb)
        double *values;
        double  iterations;
 
-       /* set performance parameters */
-       // CPXsetintparam(grb->env, CPX_PARAM_MIPSTART, CPX_ON);
-       //CPXsetintparam(grb->env, CPX_PARAM_MIPORDTYPE, CPX_MIPORDER_COST);
-       /* output every search tree node */
-       // CPXsetintparam(grb->env, CPX_PARAM_MIPINTERVAL, 1);
-
-       /* experimental switches */
-       // CPXsetintparam(grb->env, CPX_PARAM_VARSEL, CPX_VARSEL_STRONG);
-       // CPXsetdblparam(grb->env, CPX_PARAM_BTTOL, 1.0);
-       // CPXsetintparam(grb->env, CPX_PARAM_BRDIR, CPX_BRDIR_UP);
-
        /* Set the time limit appropriately */
        if(lpp->time_limit_secs > 0.0) {
-               error = GRBsetdblparam(grb->env, GRB_DBL_PAR_TIMELIMIT, lpp->time_limit_secs);
+               error = GRBsetdblparam(grb->modelenv, GRB_DBL_PAR_TIMELIMIT, lpp->time_limit_secs);
                check_gurobi_error(grb, error);
        }
 
-       /*
-        * If we have enough time, we instruct cplex to imply some
-        * of its higher order magic to pursue the best solution
-        */
-       if(lpp->emphasis) {
-               /* not implemented */
-       }
-
-       /*
-        * If a bound of the objective function is supplied,
-        * set it accordingly, dependign on minimization or maximization.
-        */
-       if(lpp->set_bound) {
-               //panic("bound not implemented yet");
-               fprintf(stderr, "Warning: gurobi bound not implemented yet\n");
-       }
-
        /* solve */
        error = GRBoptimize(grb->model);
        check_gurobi_error(grb, error);
@@ -223,20 +201,26 @@ static void gurobi_solve(gurobi_t *grb)
        default:                    lpp->sol_state = lpp_feasible; break;
        }
 
-       /* get variable solution values */
-       values = alloca(numcols * sizeof(*values));
-       error = GRBgetdblattrarray(grb->model, GRB_DBL_ATTR_X, 0, numcols, values);
-       check_gurobi_error(grb, error);
-       for(i=0; i<numcols; ++i) {
-               lpp->vars[1+i]->value      = values[i];
-               lpp->vars[1+i]->value_kind = lpp_value_solution;
-       }
+       if (lpp->sol_state >= lpp_feasible) {
+               /* get variable solution values */
+               values = alloca(numcols * sizeof(*values));
+               error = GRBgetdblattrarray(grb->model, GRB_DBL_ATTR_X, 0, numcols,
+                                          values);
+               check_gurobi_error(grb, error);
+               for(i=0; i<numcols; ++i) {
+                       lpp->vars[1+i]->value      = values[i];
+                       lpp->vars[1+i]->value_kind = lpp_value_solution;
+               }
 
-       /* Get the value of the objective function. */
-       error = GRBgetdblattr(grb->model, GRB_DBL_ATTR_OBJVAL, &lpp->objval);
-       check_gurobi_error(grb, error);
-       error = GRBgetdblattr(grb->model , GRB_DBL_ATTR_OBJBOUND, &lpp->best_bound);
-       check_gurobi_error(grb, error);
+               /* Get the value of the objective function. */
+               error = GRBgetdblattr(grb->model, GRB_DBL_ATTR_OBJVAL, &lpp->objval);
+               check_gurobi_error(grb, error);
+               error = GRBgetdblattr(grb->model , GRB_DBL_ATTR_OBJBOUND,
+                                     &lpp->best_bound);
+               if (error != 0) {
+                       lpp->best_bound = FP_NAN;
+               }
+       }
 
        /* get some statistics */
        error = GRBgetdblattr(grb->model, GRB_DBL_ATTR_ITERCOUNT, &iterations);