00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "EGlib.h"
00025 #include "MTgomory.h"
00026 #include <signal.h>
00027
00028
00029
00030
00031
00032
00033
00034
00035 static char options[1024]="cplex.opt";
00036
00037 static char problem[1024] = "";
00038
00039 static CPXENVptr env = 0;
00040
00041 static CPXLPptr lp = 0;
00042
00043 static int max_cuts_per_node = 1000;
00044
00045 static int max_cuts_per_round = 10;
00046
00047 static int cuts_at_root_only = 1;
00048
00049 static MTcutSelection_t cut_selection = MTcsDefault;
00050
00051 static int cut_dominance = 0;
00052
00053 static int max_tableau_rows = 5;
00054
00055 static int use_cuts = 1;
00056
00057 static int use_solve_cbk = 0;
00058
00059 static int cut_style = 1;
00060
00061 static double max_rtime = INT_MAX;
00062
00063 static unsigned long memlimit = UINT_MAX;
00064
00065
00066 static void sighandler(int s)
00067 {
00068 switch(s)
00069 {
00070 case SIGXCPU:
00071 fprintf(stderr,"TIME_LIMIT_REACHED (ending now)\n");
00072 exit(EXIT_FAILURE);
00073 default:
00074 fprintf(stderr,"Unknown signal %d (ending now)\n",s);
00075 exit(EXIT_FAILURE);
00076 }
00077 }
00078
00079
00080 static int mem_limits(void)
00081 {
00082 int rval = 0;
00083 struct rlimit mlim;
00084 rval = getrlimit(RLIMIT_CPU,&mlim);
00085 CHECKRVAL(rval);
00086 fprintf(stderr, "Cur rtime limit %ld, trying to set to %lg\n", mlim.rlim_cur, max_rtime);
00087 if(max_rtime > mlim.rlim_max) max_rtime = (double)mlim.rlim_max;
00088 mlim.rlim_cur = (rlim_t)max_rtime;
00089 rval = setrlimit(RLIMIT_CPU,&mlim);
00090 TESTERRNOIF(rval);
00091 fprintf(stderr, "New rtime limit %ld (%.3lg)\n", mlim.rlim_cur, max_rtime);
00092 rval = getrlimit(RLIMIT_DATA,&mlim);
00093 TESTERRNOIF(rval);
00094 fprintf(stderr, "Cur data limit %ld,%ld (soft,hard)\n", mlim.rlim_cur,
00095 mlim.rlim_max);
00096 mlim.rlim_cur = memlimit;
00097 rval = setrlimit(RLIMIT_DATA,&mlim);
00098 TESTERRNOIF(rval);
00099 rval = getrlimit(RLIMIT_DATA,&mlim);
00100 TESTERRNOIF(rval);
00101 fprintf(stderr, "New data limit %ld,%ld (soft,hard)\n", mlim.rlim_cur,
00102 mlim.rlim_max);
00103 rval = getrlimit(RLIMIT_AS,&mlim);
00104 TESTERRNOIF(rval);
00105 fprintf(stderr, "Cur address space limit %ld,%ld (soft,hard)\n",
00106 mlim.rlim_cur, mlim.rlim_max);
00107 mlim.rlim_cur = memlimit;
00108 rval = setrlimit(RLIMIT_AS,&mlim);
00109 TESTERRNOIF(rval);
00110 rval = getrlimit(RLIMIT_AS,&mlim);
00111 TESTERRNOIF(rval);
00112 fprintf(stderr, "New address space limit %ld,%ld (soft,hard)\n",
00113 mlim.rlim_cur, mlim.rlim_max);
00114 mlim.rlim_cur = 0;
00115 rval = setrlimit(RLIMIT_CORE,&mlim);
00116 TESTERRNOIF(rval);
00117 rval = getrlimit(RLIMIT_CORE,&mlim);
00118 TESTERRNOIF(rval);
00119 fprintf(stderr, "New core dump space limit %ld,%ld (soft,hard)\n",
00120 mlim.rlim_cur, mlim.rlim_max);
00121
00122 signal(SIGXCPU,sighandler);
00123 return rval;
00124 }
00125
00126
00127 void usage(char*const prog)
00128 {
00129 fprintf(stderr,"Usage: %s [options]\n",prog);
00130 fprintf(stderr,"Options:\n");
00131 fprintf(stderr,"\t-c n Choose cut-generation procedure: 0 = none, \n"
00132 "\t 1 = MTgomory, 2 = T1, 3 = T2. Default %d\n",
00133 use_cuts);
00134 fprintf(stderr,"\t-d n enable (=1) or not (=0) cut dominance check,\n"
00135 "\t default %d\n", cut_dominance);
00136 fprintf(stderr,"\t-f s file name of the problem to be optimized\n");
00137 fprintf(stderr,"\t-h print this help and exit\n");
00138 fprintf(stderr,"\t-m n maximum memory usage allowed, default %lu\n",
00139 memlimit);
00140 fprintf(stderr,"\t-n n maximum number of cuts to add at a given node in the\n"
00141 "\t B&B tree, default %d\n", max_cuts_per_node);
00142 fprintf(stderr,"\t-N n maximum number of cuts to add per round, default %d\n",
00143 max_cuts_per_round);
00144 fprintf(stderr,"\t-o s file name of the cplex option file, default %s\n",
00145 "cplex.opt");
00146 fprintf(stderr,"\t-r n add cuts only at the root node, default %d\n",
00147 cuts_at_root_only);
00148 fprintf(stderr,"\t-R n maximum running time allowed, default %lf\n",
00149 max_rtime);
00150 fprintf(stderr,"\t-s n cut selection strategy, %d for violation, %d for \n"
00151 "\t 1/L_inf, %d for 1/L_2, %d for raw score, default %d\n",
00152 MTcsVIOL, MTcsINVLINF, MTcsINVL2, MTcsRAW, cut_selection);
00153 fprintf(stderr,"\t-S n use (1) solve callback or not (0), default %d\n",
00154 use_solve_cbk);
00155 fprintf(stderr,"\t-T n cut generation style 0 for one round, 1 for multiple\n"
00156 "\t rounds on the same set of best tableau rows, default %d\n",
00157 cut_style);
00158 fprintf(stderr,"\t-t n maximum number of tableau to use while generating \n"
00159 "\t MTgomory cuts, default %d\n", max_tableau_rows);
00160 }
00161
00162
00163 int parseargs(int argc,char**argv)
00164 {
00165 int has_problem=0;
00166 int c,rval;
00167 FILE* infile = 0;
00168 while((c=getopt(argc,argv,"f:ho:c:d:T:t:r:R:m:n:N:s:S:")) != EOF)
00169 {
00170 switch(c)
00171 {
00172 case 'h':
00173 usage(argv[0]);
00174 exit(0);
00175 break;
00176 case 'S':
00177 use_solve_cbk = atoi(optarg);
00178 break;
00179 case 's':
00180 cut_selection = atoi(optarg);
00181 break;
00182 case 'r':
00183 cuts_at_root_only = atoi(optarg);
00184 break;
00185 case 'R':
00186 max_rtime = strtod(optarg,0);
00187 break;
00188 case 'o':
00189 strncpy(options,optarg,(size_t)1023);
00190 break;
00191 case 'm':
00192 memlimit = strtoul(optarg,0,10);
00193 break;
00194 case 'n':
00195 max_cuts_per_node = atoi(optarg);
00196 break;
00197 case 'N':
00198 max_cuts_per_round = atoi(optarg);
00199 break;
00200 case 'T':
00201 cut_style = atoi(optarg);
00202 break;
00203 case 't':
00204 max_tableau_rows = atoi(optarg);
00205 break;
00206 case 'f':
00207 strncpy(problem,optarg,(size_t)1023);
00208 has_problem=1;
00209 break;
00210 case 'd':
00211 cut_dominance = atoi(optarg);
00212 break;
00213 case 'c':
00214 use_cuts = atoi(optarg);
00215 break;
00216 default:
00217 usage(argv[0]);
00218 return 1;
00219 }
00220 }
00221 FTESTG((rval = !has_problem),CLEANUP,"Should provide a problem name");
00222
00223 fprintf(stderr,"\tCplex option file : %s\n",options);
00224 fprintf(stderr,"\tProblem file : %s\n",problem);
00225 fprintf(stderr,"\tUsing multi-tableau cuts : %s\n",use_cuts == 1? "gomory": (use_cuts==2? "T1":(use_cuts==3 ? "T2":(use_cuts==4? "SL":"no"))));
00226 fprintf(stderr,"\tMax tableau : %d\n",max_tableau_rows);
00227 fprintf(stderr,"\tMax cuts per node : %d\n",max_cuts_per_node);
00228 fprintf(stderr,"\tMax cuts per round : %d\n",max_cuts_per_round);
00229 fprintf(stderr,"\tCuts only at root : %s\n",cuts_at_root_only ? "yes":"no");
00230 fprintf(stderr,"\tCuts Style : %d\n",cut_style);
00231 fprintf(stderr,"\tCuts Selection Strategy : %d\n",cut_selection);
00232 fprintf(stderr,"\tCut dominance check : %d\n",cut_dominance);
00233 fprintf(stderr,"\tUse Solve Callback : %s\n",use_solve_cbk ? "yes":"no");
00234
00235 infile = EGsfopen(options,"r");
00236 rval = MTread_cplex_options(env,infile);
00237 CHECKRVALG(rval,CLEANUP);
00238 fclose(infile);
00239
00240 rval = mem_limits();
00241 CHECKRVALG(rval,CLEANUP);
00242
00243 CLEANUP:
00244 if(rval) usage(argv[0]);
00245 return rval;
00246 }
00247
00248
00249
00250 int main (int argc, char**argv)
00251 {
00252 int rval = 0;
00253 int solstat;
00254 double objval,objbound;
00255 MTgomory_ccbk_t data;
00256 MTns_ccbk_t ns_data;
00257 EGtimer_t timer;
00258
00259 EGtimerReset(&timer);
00260 EGtimerStart(&timer);
00261 env = CPXopenCPLEX (&rval);
00262 MTcplexCHECKRVALG(env,rval,CLEANUP);
00263 MTgomory_ccbk_init(&data);
00264 MTns_ccbk_init(&ns_data);
00265
00266 rval = parseargs(argc,argv);
00267 CHECKRVALG(rval,CLEANUP);
00268 MTccbkSetCuts(&data,use_cuts);
00269 MTccbkSetCutsAtRoot(&data,cuts_at_root_only);
00270 MTccbkSetCutDominance(&data,cut_dominance);
00271 MTccbkSetCutSel(&data,cut_selection);
00272 MTccbkSetCutStyle(&data,cut_style);
00273 MTccbkSetMaxNodeCuts(&data,max_cuts_per_node);
00274 MTccbkSetMaxRows(&data,max_tableau_rows);
00275 MTccbkSetMaxRoundCuts(&data,max_cuts_per_round);
00276
00277 lp = CPXcreateprob (env, &rval, problem);
00278 MTcplexCHECKRVALG(env,rval,CLEANUP);
00279 rval = CPXreadcopyprob (env, lp, problem, 0);
00280 MTcplexCHECKRVALG(env,rval,CLEANUP);
00281
00282 if(use_solve_cbk)
00283 {
00284 rval = CPXsetsolvecallbackfunc(env,MTnode_solve,&ns_data);
00285 MTcplexCHECKRVALG(env,rval,CLEANUP);
00286 }
00287
00288 switch(use_cuts)
00289 {
00290 case 1:
00291 rval = CPXsetcutcallbackfunc(env,MTgomory_ccbk,&data);
00292 MTcplexCHECKRVALG(env,rval,CLEANUP);
00293 break;
00294 case 2:
00295 rval = CPXsetcutcallbackfunc(env,MTt1_ccbk,&data);
00296 MTcplexCHECKRVALG(env,rval,CLEANUP);
00297 break;
00298 case 3:
00299 rval = CPXsetcutcallbackfunc(env,MTt2_ccbk,&data);
00300 MTcplexCHECKRVALG(env,rval,CLEANUP);
00301 break;
00302 case 4:
00303 rval = CPXsetcutcallbackfunc(env,MTsl_ccbk,&data);
00304 MTcplexCHECKRVALG(env,rval,CLEANUP);
00305 break;
00306 case 0:
00307 rval = CPXsetcutcallbackfunc(env,MTgomory_ccbk,&data);
00308 MTcplexCHECKRVALG(env,rval,CLEANUP);
00309 break;
00310 default:
00311 FTESTG((rval=1),CLEANUP,"Unknown cut selection %d",use_cuts);
00312 usage(argv[0]);
00313 break;
00314 }
00315
00316 rval = CPXmipopt (env, lp);
00317 EGtimerStop(&timer);
00318 MTcplexCHECKRVALG(env,rval,CLEANUP);
00319 solstat = CPXgetstat (env, lp);
00320 fprintf (stderr,"Solution status %d.\n", solstat);
00321 rval = CPXgetbestobjval (env, lp, &objbound);
00322 MTcplexCHECKRVALG(env,rval,CLEANUP);
00323 if(solstat == CPXMIP_OPTIMAL || solstat == CPXMIP_OPTIMAL_TOL)
00324 {
00325 rval = CPXgetobjval (env, lp, &objval);
00326 MTcplexCHECKRVALG(env,rval,CLEANUP);
00327 }
00328 else objval = objbound;
00329 fprintf (stderr,"Objective value %.10lg bound %.10lg GAP %10lg\nTime %.2lf\n", objval,objbound,100*fabs((objval-objbound)/(fabs(objbound)<1.0?1.0:objbound)), timer.time);
00330 MTccbk_info_display(&(data.info),stderr);
00331 MTccbk_display_sumary(stderr);
00332 if(use_solve_cbk) MTns_ccbk_display(&ns_data);
00333 CLEANUP:
00334
00335
00336 MTgomory_ccbk_clear(&data);
00337 MTns_ccbk_clear(&ns_data);
00338
00339 if(lp)
00340 {
00341 rval = CPXfreeprob(env,&lp);
00342 lp = 0;
00343 MTcplexCHECKRVALG(env,rval,CLEANUP);
00344 }
00345 if(env)
00346 {
00347 rval = CPXcloseCPLEX(&env);
00348 env=0;
00349 MTcplexCHECKRVALG(env,rval,CLEANUP);
00350 }
00351 return rval;
00352
00353 }
00354
00355
00356
00357