X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Flpp%2Flpp_gurobi.c;h=6b043e456bbf8dc3f1b2b358ced5774d0abb5024;hb=4f25f9ca1fd1d53303f277a140a1aa657782aeba;hp=d7c942c68738ffd129e03d5a2a31e5168ae3ef71;hpb=61c624c67d9ef82f06584a9f7cedb2268991bbac;p=libfirm diff --git a/ir/lpp/lpp_gurobi.c b/ir/lpp/lpp_gurobi.c index d7c942c68..6b043e456 100644 --- a/ir/lpp/lpp_gurobi.c +++ b/ir/lpp/lpp_gurobi.c @@ -1,25 +1,34 @@ +/* + * Copyright (C) 2005-2011 University of Karlsruhe. All right reserved. + * + * This file is part of libFirm. + * + * This file may be distributed and/or modified under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation and appearing in the file LICENSE.GPL included in the + * packaging of this file. + * + * Licensees holding valid libFirm Professional Edition licenses may use + * this file in accordance with the libFirm Commercial License. + * Agreement provided with the Software. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE. + */ + /** - * Author: Matthias Braun - * Copyright: (c) Universitaet Karlsruhe - * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. + * @file + * @author Matthias Braun */ #include "config.h" +#ifdef WITH_GUROBI #include "lpp_gurobi.h" #include #include - -#ifdef WITH_GUROBI - - -#ifdef _WIN32 -#include -#else -#include -#include -#endif -#include +#include #include "obst.h" @@ -31,19 +40,10 @@ static char gurobi_cst_encoding[4] = { 0, GRB_EQUAL, GRB_LESS_EQUAL, GRB_GREATER_EQUAL }; static char gurobi_var_encoding[4] = { 0, 0, GRB_CONTINUOUS, GRB_BINARY }; -#define my_timersub(tvp, uvp, vvp) \ - do { \ - (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ - (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ - if ((vvp)->tv_usec < 0) { \ - (vvp)->tv_sec--; \ - (vvp)->tv_usec += 1000000; \ - } \ - } while (0) - typedef struct _gurobi_t { lpp_t *lpp; GRBenv *env; + GRBenv *modelenv; GRBmodel *model; } gurobi_t; @@ -60,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); } @@ -80,16 +92,18 @@ static void free_gurobi(gurobi_t *grb) */ static void gurobi_construct(gurobi_t *grb) { - const matrix_elem_t *elem; - int i, o, sv_cnt; - int numcols, numrows, numentries; - int objsen, *matbeg, *matcnt, *matind, *indices; - double *obj, *rhs, *matval, *lb, *startv; - 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; @@ -102,8 +116,8 @@ static void gurobi_construct(gurobi_t *grb) colname = obstack_alloc(&obst, numcols * sizeof(*colname)); rowname = obstack_alloc(&obst, numrows * sizeof(*rowname)); vartype = obstack_alloc(&obst, numcols * sizeof(*vartype)); - indices = obstack_alloc(&obst, numcols * sizeof(*indices)); - startv = obstack_alloc(&obst, numcols * sizeof(*startv)); + //indices = obstack_alloc(&obst, numcols * sizeof(*indices)); + //startv = obstack_alloc(&obst, numcols * sizeof(*startv)); matbeg = obstack_alloc(&obst, numcols * sizeof(*matbeg)); matcnt = obstack_alloc(&obst, numcols * sizeof(*matcnt)); matind = obstack_alloc(&obst, numentries * sizeof(*matind)); @@ -112,7 +126,7 @@ static void gurobi_construct(gurobi_t *grb) sense = obstack_alloc(&obst, numrows * sizeof(*sense)); o = 0; - sv_cnt = 0; + //sv_cnt = 0; /* fill the CPLEX matrix*/ for (i = 0; i < numcols; ++i) { lpp_name_t *curr_var = lpp->vars[1+i]; @@ -123,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) { @@ -156,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) @@ -169,48 +176,17 @@ static void gurobi_solve(gurobi_t *grb) int error; int numcols = lpp->var_next-1; double *values; - struct timeval tvb, tva, tvdiff; - 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); + double iterations; /* 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 */ - gettimeofday(&tvb, NULL); error = GRBoptimize(grb->model); check_gurobi_error(grb, error); - gettimeofday(&tva, NULL); /* get solution status */ error = GRBgetintattr(grb->model, GRB_INT_ATTR_STATUS, &optimstatus); @@ -225,27 +201,34 @@ 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; ivars[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; ivars[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 */ - my_timersub(&tva, &tvb, &tvdiff); - lpp->sol_time = tvdiff.tv_sec + tvdiff.tv_usec / 1e6; error = GRBgetdblattr(grb->model, GRB_DBL_ATTR_ITERCOUNT, &iterations); check_gurobi_error(grb, error); lpp->iterations = (unsigned) iterations; + + error = GRBgetdblattr(grb->model, GRB_DBL_ATTR_RUNTIME, &lpp->sol_time); + check_gurobi_error(grb, error); } void lpp_solve_gurobi(lpp_t *lpp)