Hi,

I don't know whether this can be of any help to anybody
but I wrote a GLPK -> GUROBI -> GLPK  kind of wrapper
which uses GLPK to parse a MathProg model with data files, generates an mps file, solve it with Gurobi,
and uses the post solve features of GLPK.

motivations:
- with somewhat complex models, GLPK is not effective as GUROBI.
- MathProg is wonderful for fast prototyping and post solve features.
- AMPL is too expensive :).

compiling:

assume you have glpk and gurobi properly installed and GUROBI is a env variable where gurobi is

#: gcc -std=c99 -O2 -o wrapper_GLPK_GUROBI -I$GUROBI/include/ wrapper_gurobi.c -L$GUROBI/lib/ -lm -lgurobi40 -lpthread -lglpk

usage:

#: ./wrapper_GLPK_GUROBI -m mod8.m -d mod8.d
#: ./wrapper_GLPK_GUROBI -m mod8.m -d mod8.d --glpk_out
#: ./wrapper_GLPK_GUROBI -m mod8.m -d mod8.d --glpk_out --grb_out

most of the glpsol options can be passed via command line (I am now addressing with the -y option)
and most of the parameters can be set via command line too.

Enjoy,
Matteo

--
*Matteo Salani*
IDSIA
Galleria 2
6928 Manno-Lugano Switzerland
Web: http://www.idsia.ch/~salani <http://www.idsia.ch/%7Esalani>
Email: [email protected] <mailto:[email protected]>
Phone: +41 58 666 66 71
/***************************************************************************
                          wrapper.c  -  description
                             -------------------
    begin                : May 2010
    copyright            : Matteo Salani
    email                : [email protected]
    description          : This is a wrapper to process a MILP model 
                           written in GNU - MathProg (http://www.gnu.org/software/glpk/)
                           solve it with Gurobi (http://gurobi.com/)
                           post-process the output with GLPK
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

/** please, have GLPK and GUROBI installed **/
#include "glpk.h"
#include "gurobi_c.h"

#define GRB_INT 0
#define GRB_DB 1

/** GLPK: data structures **/
glp_prob *mip = NULL;
glp_tran *tran = NULL;
glp_smcp *parm;
glp_iocp *iparm;
int ret, col_index;
double glpk_iparm_mip_gap = 10E-4;
double glpk_iparm_tol_int = 10E-4;
double glpk_iparm_tol_obj = 10E-4;

/** GUROBI: data structures **/
GRBenv   *env   = NULL; 
GRBenv   *mipenv = NULL;
GRBmodel *model = NULL;
int      numvars, j, retGRB, GRB_IsMIP, GRB_noMIP;
double   db_tmp, bound;
char * nameGRB;
char type;
double grb_feasibilityTol = 10E-6;
double grb_intFeasTol = 10E-5;
double grb_mipGap = 10E-4;

/** GUROBI: user defined parameters **/
typedef struct _grb_udef {
  char * name;
  char type;
  double db_value;
  int int_value;
  struct _grb_udef * next;
} grb_udef;

grb_udef * grb_user_def_params;

/** execution flags **/
char GRB_out, GLPK_out, verbose;

int keep_tmp_mps;

void freeMem(){
grb_udef * tmp;

  /** GLPK: free user defined parameters **/
  while (grb_user_def_params != NULL){
    tmp = grb_user_def_params;
    grb_user_def_params = grb_user_def_params->next;
    free(tmp);
  }

  /** GLPK: free structures **/
  if (tran) glp_mpl_free_wksp(tran);
  if (mip) glp_delete_prob(mip);

  if (retGRB) printf("ERROR: %s\n", GRBgeterrormsg(env));

  /** GUROBI: free structures **/
  if (model) GRBfreemodel(model);
  if (env) GRBfreeenv(env);

  printf("ERRORS OCCURRED.\nGLPK -> GUROBI -> GLPK wrapper v0.2 (2010)\n");

  exit(1);
}

void usage(){
    fprintf(stderr, "GLPK -> GUROBI -> GLPK wrapper v0.2 (2010)\nby Matteo Salani ([email protected])\n\n"
                    "Usage: \n"
                    "wrapper_GLPK_GUROBI [OPTIONS] -m <model.mod> -d <data.dat>\n"
                    "with OPTIONS:\n"
                    "--glpk_out (enable GLPK output, default disabled)\n"
                    "--grb_out (enable GRB output, default disabled)\n"
                    "--glpk_mip_gap <value> GLPK mip gap (default 10E-4)\n"
                    "--glpk_tol_int <value> GLPK integer tolerance (default 10E-4)\n"
                    "--glpk_tol_obj <value> GLPK objective tolerance (default 10E-4)\n"
                    "--grb_feas_tol <value> GUROBI feasibility tolerance (default 10E-6)\n"
                    "--grb_int_tol <value> GUROBI integer tolerance (default 10E-5)\n"
                    "--grb_set_db_para <parameter name> <value> Set GUROBI double paramenter (example --grb_set_db_para IntFeasTol 10E-5)\n"
                    "--grb_set_int_para <parameter name> <value> Set GUROBI integer paramenter (example --grb_set_int_para ModelSense -1)\n"
                    "--grb_nomip tells Gurobi to solve the linear relaxation only \n"
                    "--keep_tmp_files Keep the temporary mps file\n");
}

int main(int argc, char *argv[]){
char * file_model;
char * file_data;
char * file_output;
grb_udef * tmp;

  if (argc < 5){
    usage();
    exit(1);
  }

  printf("GLPK -> GUROBI -> GLPK wrapper v0.2 (2010)\n\n");

  grb_user_def_params = NULL;
  file_model = file_data = NULL;
  GRB_out = GLPK_out = GRB_noMIP = verbose = keep_tmp_mps = 0;

  for(int i=1 ; i<=argc-1 ; i++){
    if (strcmp(argv[i],"-m")==0) file_model = argv[i+1];
    if (strcmp(argv[i],"-d")==0) file_data = argv[i+1];
    if (strcmp(argv[i],"-y")==0) file_output = argv[i+1];
    if (strcmp(argv[i],"-v")==0) verbose = 1;
    if (strcmp(argv[i],"--keep_tmp_files")==0) keep_tmp_mps = 1;
    if (strcmp(argv[i],"--glpk_out")==0) GLPK_out = 1;
    if (strcmp(argv[i],"--grb_out")==0) GRB_out = 1;
    if (strcmp(argv[i],"--glpk_mip_gap")==0) glpk_iparm_mip_gap = atof(argv[i+1]);
    if (strcmp(argv[i],"--glpk_tol_int")==0) glpk_iparm_tol_int = atof(argv[i+1]);
    if (strcmp(argv[i],"--glpk_tol_obj")==0) glpk_iparm_tol_obj = atof(argv[i+1]);
    if (strcmp(argv[i],"--grb_feas_tol")==0) grb_feasibilityTol =  atof(argv[i+1]);
    if (strcmp(argv[i],"--grb_int_tol")==0) grb_intFeasTol =  atof(argv[i+1]);
    if (strcmp(argv[i],"--grb_mip_gap")==0) grb_mipGap = atof(argv[i+1]) ;
    if (strcmp(argv[i],"--grb_set_db_para")==0) {
      grb_udef * tmp = (grb_udef *) malloc(sizeof(grb_udef));
      tmp->name = argv[i+1];
      tmp->type = GRB_DB;
      tmp->db_value = atof(argv[i+2]);
      tmp->next = grb_user_def_params; 
      grb_user_def_params = tmp;
    }
    if (strcmp(argv[i],"--grb_set_int_para")==0) {
      grb_udef * tmp = (grb_udef *) malloc(sizeof(grb_udef));
      tmp->name = argv[i+1];
      tmp->type = GRB_INT;
      tmp->int_value = atoi(argv[i+2]);
      tmp->next = grb_user_def_params; 
      grb_user_def_params = tmp;
    }
    if (strcmp(argv[i],"--grb_nomip")==0) GRB_noMIP = 1;
  } 

  if ((file_model==NULL) || (file_data == NULL)){ 
    usage();
    fprintf(stderr, "Error no model or data files provided\n");
    freeMem();
  }

  printf("Wrapper parameters:\n");
  printf("  model: %s\n", file_model);
  printf("  data: %s\n", file_data);
  printf("  verbosity level: %s\n", verbose ? "quiet" : "verbose");
  printf("  keep temporary files: %s\n", keep_tmp_mps ? "on" : "off");
  printf("  GLPK parameters:\n");
  printf("    GLPK output: %s\n", GLPK_out ? "on" : "off");
  printf("    GLPK Mip Gap: %lf\n", glpk_iparm_mip_gap);
  printf("    GLPK Int Tolerance: %lf\n", glpk_iparm_tol_int);
  printf("    GLPK Objective Tolerance: %lf\n", glpk_iparm_tol_obj);
  printf("  GUROBI parameters:\n");
  printf("    GUROBI output: %s\n", GRB_out ? "on" : "off");
  printf("    GUROBI Feasibility tolerance: %lf\n", grb_feasibilityTol);
  printf("    GUROBI Integer Feasibility tolerance: %lf\n", grb_intFeasTol);
  if (grb_user_def_params != NULL){
    printf("  USER DEF GUROBI parameters:\n");
    tmp = grb_user_def_params;
    while (tmp != NULL){
      if (tmp->type == GRB_INT){
        printf("    GUROBI %s : %d\n", tmp->name, tmp->int_value);
      }
      else if (tmp->type == GRB_DB){
        printf("    GUROBI %s : %lf\n", tmp->name, tmp->db_value);
      }
      tmp = tmp->next;
    }
  }
  printf("\n\n");

  /** GLPK: Open environment **/
  mip = glp_create_prob();
  tran = glp_mpl_alloc_wksp();

  glp_term_out(GLPK_out?GLP_ON:GLP_OFF);

  /** GLPK: Read model written in MathProg **/
  ret = glp_mpl_read_model(tran, file_model, 1);

  if (ret){ 
    fprintf(stderr, "Error on translating model\n");
    freeMem();
  }
  
  /** GLPK: Read data for MathProg **/
  ret = glp_mpl_read_data(tran, file_data);
  if (ret){ 
    fprintf(stderr, "Error on translating data\n");
    freeMem();
  }

  /** GLPK: Generate model (merge data an model) **/
  ret = glp_mpl_generate(tran, NULL);
  if (ret){ 
    fprintf(stderr, "Error on generating model\n");
    freeMem();
  }

  /** GLPK: Generate Build Model **/
  glp_mpl_build_prob(tran, mip);
          
  /** GLPK: Generate Variable indexing **/
  glp_create_index(mip);

  /** GLPK: Generate LP **/
  glp_write_mps(mip, GLP_MPS_FILE, NULL, "model.mps");


  /************/
  /** GUROBI **/
  /************/

  retGRB = GRBloadenv(&env, NULL);
  if (retGRB || env == NULL)
  {
    fprintf(stderr, "Error: could not create environment\n");
    exit(1);
  }

  retGRB = GRBsetintparam(env, "OutputFlag", GRB_out?1:0);
  if (retGRB) freeMem();

  /** GUROBI: Read model **/
  retGRB = GRBreadmodel(env, "model.mps", &model);
  if (retGRB) freeMem();

  /** Remove utility files from disk **/
  if (!keep_tmp_mps) remove("model.mps");

  /** GUROBI: Get environment **/
  mipenv = GRBgetenv(model);
  if (!mipenv) freeMem();

  /** GUROBI: Set parameters **/

  /** GUROBI: Ask for more precision **/
  retGRB = GRBsetdblparam(mipenv, "FeasibilityTol", grb_feasibilityTol);
  if (retGRB) freeMem();
  retGRB = GRBsetdblparam(mipenv, "IntFeasTol", grb_intFeasTol);
  if (retGRB) freeMem();
  retGRB = GRBsetdblparam(mipenv, "MIPgap", grb_mipGap);
  if (retGRB) freeMem();

  /** Set other user-defined parameters for Gurobi **/
  tmp = grb_user_def_params;
  while (tmp != NULL){
    if (tmp->type == GRB_INT){
      retGRB = GRBsetintparam(mipenv, tmp->name, tmp->int_value);
      if (retGRB) freeMem();
    }
    else if (tmp->type == GRB_DB){
      retGRB = GRBsetdblparam(mipenv, tmp->name, tmp->db_value);
      if (retGRB) freeMem();
    }
    tmp = tmp->next;
  }

  /** GUROBI: get numvars and numrows **/
  retGRB = GRBgetintattr(model, "NumVars", &numvars);
  if (retGRB) freeMem();

  /** GUROBI: get model type **/
  retGRB = GRBgetintattr(model, "IsMIP", &GRB_IsMIP);
  if (retGRB) freeMem();

  /** GUROBI: Solve the linear relaxation **/
  if (GRB_noMIP){
    int numintvars; int j; char vtype;
    /* Collect integer variables and relax them */
    retGRB = GRBgetintattr(model, "NumIntVars", &numintvars);
    if (retGRB) freeMem();
    for (j = 0; j < numintvars; ++j)
    {
      retGRB = GRBgetcharattrelement(model, "VType", j, &vtype);
      if (retGRB) freeMem();
      if (vtype != GRB_CONTINUOUS)
      {
        retGRB = GRBsetcharattrelement(model, "VType", j, GRB_CONTINUOUS);
        if (retGRB) freeMem();
      }
    }
  }

  /** GUROBI: Optimize model **/
  retGRB = GRBoptimize(model);
  if (retGRB) freeMem();

  /** GUROBI: Retreive the optimization status **/
  GRBgetintattr(model, "Status", &retGRB);
  switch(retGRB){
    case GRB_OPTIMAL:
        break;
    case GRB_INFEASIBLE :
        fprintf(stderr, "Error GRB optimization failed with code GRB_INFEASIBLE\n");
    case GRB_INF_OR_UNBD :
        fprintf(stderr, "Error GRB optimization failed with code GRB_INF_OR_UNBD \n");
    case GRB_UNBOUNDED :
        fprintf(stderr, "Error GRB optimization failed with code GRB_UNBOUNDED \n");
    case GRB_CUTOFF :
        fprintf(stderr, "Error GRB optimization failed with code GRB_CUTOFF \n");
    case GRB_ITERATION_LIMIT :
        fprintf(stderr, "Error GRB optimization failed with code GRB_ITERATION_LIMIT \n");
    case GRB_NODE_LIMIT :
        fprintf(stderr, "Error GRB optimization failed with code GRB_NODE_LIMIT \n");
    case GRB_TIME_LIMIT :
        fprintf(stderr, "Error GRB optimization failed with code GRB_TIME_LIMIT \n");
    case GRB_SOLUTION_LIMIT :
        fprintf(stderr, "Error GRB optimization failed with code GRB_SOLUTION_LIMIT \n");
    case GRB_INTERRUPTED :
        fprintf(stderr, "Error GRB optimization failed with code GRB_INTERRUPTED \n");
    case GRB_SUBOPTIMAL :
        fprintf(stderr, "Error GRB optimization failed with code GRB_SUBOPTIMAL \n");
    case GRB_NUMERIC :
        fprintf(stderr, "Error GRB optimization failed with code GRB_NUMERIC \n");

    /** GUROBI: Quit in any case non optimal **/
    freeMem();
  }

  /** GUROBI: Get obj function value **/
  if (!GRB_noMIP){
    retGRB = GRBgetdblattr(model, "IntVio", &db_tmp);
    if (retGRB) freeMem();

    retGRB = GRBgetdblattr(model, "ObjBound", &bound);
    if (retGRB) freeMem();
  }

  retGRB = GRBgetdblattr(model, "ObjVal", &db_tmp);
  if (retGRB) freeMem();
  
  if (verbose) printf ("Objective %lf\n", db_tmp);
  if (verbose) printf ("Best bound %lf\n", bound);
  if (verbose) printf ("Absolute gap %lf\n", fabs(db_tmp - bound));

  /** GUROBI: Get variable values **/
  for (j = 0; j < numvars; ++j){

    retGRB = GRBgetdblattrelement(model, "X", j, &db_tmp);
    if (retGRB) freeMem();

    retGRB = GRBgetstrattrelement(model, "VarName", j, &nameGRB);
    if (retGRB) freeMem();

    retGRB = GRBgetcharattrelement(model, "VType", j, &type);
    if (retGRB) freeMem();

    /** GLPK search variable index by name **/
    col_index = glp_find_col(mip, nameGRB);

    if (col_index != 0){ 
      /** GLPK set variable bounds **/
      if ((type == 'B') || (type == 'I')){
        if (verbose) printf ("Variable %s is of type %c value %lf fixed to %lf\n", nameGRB, type, db_tmp, round(db_tmp));
        glp_set_col_bnds(mip, col_index, GLP_FX, round(db_tmp), round(db_tmp));
      }
      else{
        if (verbose) printf ("Variable %s is of type %c value %lf fixed to %lf\n", nameGRB, type, db_tmp, db_tmp);
        glp_set_col_bnds(mip, col_index, GLP_FX, db_tmp, db_tmp);
      }
    }
  }

  if ((GRB_IsMIP) && (!GRB_noMIP)){
          
    /** GLPK initialize parameters **/
    iparm = (glp_iocp*) malloc(sizeof(glp_iocp));
    glp_init_iocp(iparm);
    iparm->presolve = GLP_ON;
    iparm->mip_gap = glpk_iparm_mip_gap;
    iparm->tol_int = glpk_iparm_tol_int;
    iparm->tol_obj = glpk_iparm_tol_obj;

    /** GLPK get the optimal integer solution **/
    ret = glp_intopt(mip, iparm);
    if (ret){ 
      fprintf(stderr, "glp_intopt, Error on optimizing the model : %d \n", ret);
      freeMem();
    }

    ret = glp_mip_status(mip);
    switch (ret){
            case GLP_OPT:
            break;
            case GLP_FEAS:
              fprintf(stderr, "Error GLPK simplex is not optimal, GLP_FEAS, code %d\n", ret);
              freeMem();
            case GLP_NOFEAS:
              fprintf(stderr, "Error GLPK simplex is not optimal, GLP_NOFEAS, code %d\n", ret);
              freeMem();
            case GLP_UNDEF:
              fprintf(stderr, "Error GLPK simplex is not optimal, GLP_UNDEF, code %d\n", ret);
              freeMem();
    }
  }
  else{

    /** GLPK initialize parameters **/
    parm = (glp_smcp*) malloc(sizeof(glp_smcp));
    glp_init_smcp(parm);
    parm->meth = GLP_DUALP;
    parm->tol_bnd = 10E-4;
    parm->tol_dj = 10E-4;
  
    /** GLPK get the optimal basis **/
    //ret = glp_simplex(mip, parm);
    if (ret){ 
     fprintf(stderr, "glp_simplex, Error on optimizing the model : %d \n", ret);
     freeMem();
    }
    ret = glp_get_status(mip);
    switch (ret){
            case GLP_OPT:
            break;
              case GLP_FEAS:
              fprintf(stderr, "Error GLPK simplex is not optimal, GLP_FEAS, code %d\n", ret);
              freeMem();
            case GLP_INFEAS:
              fprintf(stderr, "Error GLPK simplex is not optimal, GLP_INFEAS, code %d\n", ret);
              freeMem();
            case GLP_NOFEAS:
              fprintf(stderr, "Error GLPK simplex is not optimal, GLP_NOFEAS, code %d\n", ret);
              freeMem();
            case GLP_UNBND:
              fprintf(stderr, "Error GLPK simplex is not optimal, GLP_UNBND, code %d\n", ret);
              freeMem();
            case GLP_UNDEF:
              fprintf(stderr, "Error GLPK simplex is not optimal, GLP_UNDEF, code %d\n", ret);
              freeMem();
    }
  }

  /** GLPK: Perform postprocessing **/
  ret = glp_mpl_postsolve(tran, mip, GLP_MIP);
  if (ret != 0) fprintf(stderr, "Error on postsolving model\n");

  /** GLPK: free structures **/
  if (tran) glp_mpl_free_wksp(tran);
  if (mip) glp_delete_prob(mip);

  if (retGRB) printf("ERROR: %s\n", GRBgeterrormsg(env));

  /** GUROBI: free structures **/
  if (model) GRBfreemodel(model);
  if (env) GRBfreeenv(env);

  printf("Done.\nGLPK -> GUROBI -> GLPK wrapper v0.2 (2010)\n");

  exit(0);
}
_______________________________________________
Help-glpk mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/help-glpk

Reply via email to