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 <math.h>
00025 #include "cplex.h"
00026 #include "mt_cplex_cbk.h"
00027 #include "mt_gomory.h"
00028 #include "EGlib.h"
00029
00030
00031
00032
00033
00034 int MTcheckTabrow(
00035 const MTlp_t*const lp,
00036 const double*tableau,
00037 int*const status,
00038 double*const ratio,
00039 int*const etnz)
00040 {
00041 const int nrows = lp->nrows;
00042 const int ncols = lp->ncols;
00043 const char*const ctype = lp->ctype;
00044 const char*const rtype = lp->rtype;
00045 const int*const cstat = lp->cstat;
00046 const int*const rstat = lp->rstat;
00047 register int j;
00048 int nbasic, fail_tableau, tnz=0, rval=0;
00049 double absval, absmin=DBL_MAX, absmax=0, dtmp;
00050 *status = 0;
00051
00052 for( j = ncols, nbasic = 0, fail_tableau = 0, tnz = 0 ; j-- ; )
00053 {
00054 dtmp = tableau[j];
00055 absval = EGabs(dtmp);
00056 if(absval < MT_ZERO_TOL) continue;
00057 if(absval > absmax) absmax = absval;
00058 if(absval < absmin) absmin = absval;
00059 if(cstat[j] == CPX_BASIC)
00060 {
00061 rval = (ctype[j] != CPX_BINARY && ctype[j] != CPX_INTEGER);
00062 #if MT_CCBK_USE_NAMES
00063 WARNINGL(MT_VERB_LVL+5, rval, "Imposible!, variable %s is basic,"
00064 " but type %c", lp->colnames[j], ctype[j]);
00065 #else
00066 WARNINGL(MT_VERB_LVL+5, rval, "Imposible!, variable %d is basic,"
00067 " but type %c", j, ctype[j]);
00068 #endif
00069 if(rval)
00070 {
00071 MTccbk_fail_tableau_btype++;
00072 fail_tableau = 1;
00073 rval = 0;
00074 WARNINGL(MT_VERB_LVL,1, "Found faulty tableau, |basic_coeff| = %.9lg, zero tol %lg ", absval, MT_ZERO_TOL);
00075 if(MT_VERB_LVL < DEBUG)
00076 {
00077 MTcplex_display_tableau(stderr,lp,tableau);
00078 fprintf(stderr,"\n");
00079 }
00080 break;
00081 }
00082 rval = ((absval < 1 - MT_ZERO_TOL) || (absval > 1+MT_ZERO_TOL));
00083 #if MT_CCBK_USE_NAMES
00084 WARNINGL(MT_VERB_LVL+5, rval, "Imposible!, basic variable %s"
00085 " has tableau value %.3lg/%.3lg", lp->colnames[j],
00086 dtmp, tableau[j]);
00087 #else
00088 WARNINGL(MT_VERB_LVL+5, rval, "Imposible!, basic variable %d"
00089 " has tableau value %.3lg/%.3lg", j, dtmp, tableau[j]);
00090 #endif
00091 if(rval)
00092 {
00093 MTccbk_fail_tableau_coeff++;
00094 fail_tableau = 1;
00095 rval = 0;
00096 WARNINGL(MT_VERB_LVL,1, "Found faulty tableau, |basic_coeff| = %.9lg, zero tol %lg ", absval, MT_ZERO_TOL);
00097 if(MT_VERB_LVL < DEBUG)
00098 {
00099 MTcplex_display_tableau(stderr,lp,tableau);
00100 fprintf(stderr,"\n");
00101 }
00102 break;
00103 }
00104 nbasic++;
00105 }
00106 if(cstat[j] == CPX_BASIC) continue;
00107
00108 if(ctype[j] == CPX_BINARY || ctype[j] == CPX_INTEGER)
00109 {
00110 dtmp -= floor(dtmp);
00111 if(dtmp >= 1 - MT_ZERO_TOL) dtmp = 0;
00112 }
00113
00114 if(EGabs(dtmp) < MT_ZERO_TOL) continue;
00115 MESSAGE(MT_VERB_LVL+9,"Var %d in tableau",j);
00116 tnz++;
00117 }
00118 if(fail_tableau) goto CLEANUP;;
00119 if( nbasic != 1)
00120 {
00121 MTccbk_fail_tableau_nbasic++;
00122 fail_tableau = 1;
00123 WARNINGL(MT_VERB_LVL,1, "Found faulty tableau, nbasic = %d, expected 1", nbasic);
00124 if(MT_VERB_LVL < DEBUG)
00125 {
00126 MTcplex_display_tableau(stderr,lp,tableau);
00127 fprintf(stderr,"\n");
00128 }
00129 }
00130 if(fail_tableau) goto CLEANUP;
00131
00132 tableau += ncols;
00133 for( j = nrows ; j-- ; )
00134 {
00135 dtmp = tableau[j];
00136 absval = EGabs(dtmp);
00137 if(absval < MT_ZERO_TOL) continue;
00138 if(absval > absmax) absmax = absval;
00139 if(absval < absmin) absmin = absval;
00140 if(rstat[j] == CPX_BASIC)
00141 {
00142 MTccbk_fail_tableau_nbasic++;
00143 nbasic++;
00144 WARNINGL(MT_VERB_LVL,1, "Found faulty tableau, nbasic = %d, expected 1", nbasic);
00145 if(MT_VERB_LVL<DEBUG)
00146 {
00147 MTcplex_display_tableau(stderr,lp,tableau-ncols);
00148 fprintf(stderr,"\n");
00149 }
00150 fail_tableau = 1;
00151 break;
00152 }
00153 if(rtype[j] == CPX_INTEGER || rtype[j] == CPX_BINARY)
00154 {
00155 dtmp -= floor(dtmp);
00156 if(dtmp >= 1- MT_ZERO_TOL) dtmp = 0;
00157 }
00158 if(EGabs(dtmp) < MT_ZERO_TOL) continue;
00159 MESSAGE(MT_VERB_LVL+9,"Logical %d in tableau",j);
00160 tnz++;
00161 }
00162 tableau -= ncols;
00163 if(fail_tableau) goto CLEANUP;
00164
00165 if(absmin/absmax < MT_CCBK_MIN_TABLEAU_RATIO)
00166 {
00167 MTccbk_fail_tableau_ratio++;
00168 WARNINGL(MT_VERB_LVL, 1, "Tableau row with ratio %.9lf < %.9lf",
00169 absmin/absmax, MT_CCBK_MIN_TABLEAU_RATIO);
00170 fail_tableau = 1;
00171 goto CLEANUP;
00172 }
00173 CLEANUP:
00174 if(fail_tableau) *status = 1;
00175 if(ratio) *ratio = absmin/absmax;
00176 if(etnz) *etnz = tnz;
00177 return rval;
00178 }
00179
00180
00181
00182 #define UPDATE_F_AND_VAL(__f,__cstat,__bound,__val) do{\
00183 if((__cstat) == CPX_AT_LOWER){\
00184 (__f) -= (__val) * (__bound);}\
00185 else if((__cstat) == CPX_AT_UPPER){\
00186 (__f) -= (__val) * (__bound);\
00187 (__val) = -1*(__val);}\
00188 else{TESTG((rval=1),CLEANUP,"Imposible!, cstat is %d", (__cstat));}}while(0)
00189
00190 int MTcompressTabRow(
00191 const MTlp_t*const lp,
00192 const MTsol_t*const sol,
00193 double*rowval,
00194 int*rowind,
00195 double*const rhs,
00196 int*const nz)
00197 {
00198 const double*const x = sol->x;
00199 const double*const slack = sol->slack;
00200 const int nrows = lp->nrows;
00201 const int ncols = lp->ncols;
00202 const char*const ctype = lp->ctype;
00203 const char*const rtype = lp->rtype;
00204 const int*const cstat = lp->cstat;
00205 const int*const rstat = lp->rstat;
00206 register int j;
00207 double dtmp;
00208 int tnz=0, rval=0;
00209 for( j = tnz = 0; j < ncols ; j++)
00210 {
00211 dtmp = rowval[j];
00212 if(cstat[j] == CPX_BASIC) continue;
00213 if(ctype[j] == CPX_BINARY || ctype[j] == CPX_INTEGER)
00214 {
00215 dtmp -= floor(dtmp);
00216 if(dtmp >= 1 - MT_ZERO_TOL) dtmp = 0;
00217 }
00218 if(EGabs(dtmp) < MT_ZERO_TOL) continue;
00219 if( (ctype[j] == CPX_BINARY || ctype[j] == CPX_INTEGER) && dtmp >0.5)
00220 dtmp -= 1.0;
00221 UPDATE_F_AND_VAL(*rhs, cstat[j], x[j], dtmp);
00222 MESSAGE(MT_VERB_LVL+9,"Var %d in tableau",j);
00223 rowind[tnz] = j;
00224 rowval[tnz++] = dtmp;
00225 }
00226 for( j = 0 ; j < nrows ; j++)
00227 {
00228 dtmp = rowval[j+ncols];
00229 if(rtype[j] == CPX_BINARY || rtype[j] == CPX_INTEGER)
00230 {
00231 dtmp -= floor(dtmp);
00232 if(dtmp >= 1 - MT_ZERO_TOL) dtmp = 0;
00233 }
00234 if(EGabs(dtmp) < MT_ZERO_TOL) continue;
00235 if( (rtype[j] == CPX_BINARY || rtype[j] == CPX_INTEGER) && dtmp >0.5)
00236 dtmp -= 1.0;
00237 UPDATE_F_AND_VAL(*rhs, rstat[j], slack[j], dtmp);
00238 MESSAGE(MT_VERB_LVL+9,"Logical %d in tableau",j);
00239 rowind[tnz] = j+ncols;
00240 rowval[tnz++] = dtmp;
00241 }
00242 if(MT_VERB_LVL+8 <= DEBUG)
00243 {
00244 fprintf(stderr,"Compress (and complemented) tableau:");
00245 MTcplex_display_compress_tableau(stderr, lp, rowval, rowind, tnz);
00246 fprintf(stderr," = %.3lf\n", *rhs);
00247 }
00248 CLEANUP:
00249 *nz = tnz;
00250 return rval;
00251 }
00252
00253
00254
00255
00256
00257
00258
00259 static inline void MTlp_rsz(MTlp_t*const MTlp,
00260 const int rsz,
00261 const int csz,
00262 const int tsz)
00263 {
00264 if(MTlp->rspace < rsz)
00265 {
00266 MTlp->rspace = rsz;
00267 EGfree(MTlp->sense);
00268 EGfree(MTlp->rhs);
00269 EGfree(MTlp->matbeg);
00270 EGfree(MTlp->rtype);
00271 EGfree(MTlp->rstat);
00272 #if MT_CCBK_USE_NAMES
00273 EGfree(MTlp->rownames);
00274 MTlp->rownames = EGsMalloc(char*,rsz);
00275 #endif
00276 MTlp->sense = EGsMalloc(char,rsz);
00277 MTlp->rhs = EGsMalloc(double,rsz);
00278 MTlp->matbeg = EGsMalloc(int,rsz+1);
00279 MTlp->rtype = EGsMalloc(char,rsz);
00280 MTlp->rstat = EGsMalloc(int,rsz);
00281 }
00282 if(MTlp->cspace < csz)
00283 {
00284 MTlp->cspace = csz;
00285 EGfree(MTlp->ctype);
00286 EGfree(MTlp->cstat);
00287 EGfree(MTlp->ub);
00288 EGfree(MTlp->lb);
00289 #if MT_CCBK_USE_NAMES
00290 EGfree(MTlp->colnames);
00291 MTlp->colnames = EGsMalloc(char*,csz);
00292 #endif
00293 MTlp->ctype = EGsMalloc(char,csz);
00294 MTlp->cstat = EGsMalloc(int,csz);
00295 MTlp->lb = EGsMalloc(double,csz);
00296 MTlp->ub = EGsMalloc(double,csz);
00297 }
00298 if(MTlp->nzspace < tsz)
00299 {
00300 MTlp->nzspace = tsz;
00301 EGfree(MTlp->matind);
00302 EGfree(MTlp->matval);
00303 MTlp->matind = EGsMalloc(int,tsz);
00304 MTlp->matval = EGsMalloc(double,tsz);
00305 }
00306 return;
00307 }
00308
00309 int MTcompute_integer_vars(const MTlp_t*const lp,
00310 const double*const x,
00311 int*const intvars,
00312 int*const nint,
00313 const double intgap)
00314 {
00315 const char*const ctype = lp->ctype;
00316 register int i = lp->ncols;
00317 int n=0;
00318 double dtmp=0;
00319 for( ; i-- ; )
00320 {
00321
00322 if(ctype[i] != CPX_BINARY && ctype[i] != CPX_INTEGER) continue;
00323 dtmp = fabs(x[i] - round(x[i]));
00324 if(dtmp <= intgap)
00325 {
00326 intvars[n++] = i;
00327 #if MT_CCBK_USE_NAMES
00328 MESSAGE(MT_VERB_LVL+9,"%s=%.9lf is integer-valued",
00329 lp->colnames[i],x[i]);
00330 #else
00331 MESSAGE(MT_VERB_LVL+9,"X[%d]=%.9lf is integer-valued",i,x[i]);
00332 #endif
00333 }
00334 }
00335 *nint = n;
00336 return 0;
00337 }
00338
00339 int MTcompute_fractional_vars(const MTlp_t*const lp,
00340 const double*const x,
00341 int*const fracvars,
00342 int*const nfrac,
00343 const double min_gap)
00344 {
00345 const char*const ctype = lp->ctype;
00346 register int i = lp->ncols;
00347 int n=0;
00348 double dtmp=0;
00349 for( ; i-- ; )
00350 {
00351
00352 if(ctype[i] != CPX_BINARY && ctype[i] != CPX_INTEGER) continue;
00353 dtmp = fabs(x[i] - round(x[i]));
00354 if(dtmp > min_gap )
00355 {
00356 fracvars[n++] = i;
00357 #if MT_CCBK_USE_NAMES
00358 MESSAGE(MT_VERB_LVL+9,"%s=%.9lf is integer-fractional",
00359 lp->colnames[i],x[i]);
00360 #else
00361 MESSAGE(MT_VERB_LVL+9,"X[%d]=%.9lf is integer-fractional",i,x[i]);
00362 #endif
00363 }
00364 }
00365 *nfrac = n;
00366 return 0;
00367 }
00368
00369 void MTdisplay_lp(const MTlp_t*const lp,
00370 const MTsol_t*const sol,
00371 FILE*stream)
00372 {
00373 const double*const x = sol->x;
00374 const double*const slack = sol->slack;
00375 register int i = lp->ncols;
00376 for( ; i-- ; )
00377 {
00378 #if MT_CCBK_USE_NAMES
00379 fprintf(stream,"%s[%lf,%lf] = %.6lf %d %c\n", lp->colnames[i],
00380 lp->lb[i], lp->ub[i], x[i], lp->cstat[i],
00381 lp->ctype[i]);
00382 #else
00383 fprintf(stream,"x_%d[%lf,%lf] = %.6lf %d %c\n", i, lp->lb[i],
00384 lp->ub[i], x[i], lp->cstat[i],
00385 lp->ctype[i]);
00386 #endif
00387 }
00388 for( i = lp->nrows ; i-- ; )
00389 {
00390 #if MT_CCBK_USE_NAMES
00391 fprintf(stderr,"%s = %.6lf %d %c\n", lp->rownames[i],
00392 slack[i], lp->rstat[i], lp->rtype[i]);
00393 #else
00394 fprintf(stderr,"s_%d = %.6lf %d %c\n", i, slack[i],
00395 lp->rstat[i], lp->rtype[i]);
00396 #endif
00397 }
00398 }
00399
00400 char __mt_cplex_errbuf[4096];
00401
00402 void MTcompute_f(const MTlp_t*const lp,
00403 const double*const tableau,
00404 const double*const x,
00405 const double*const slack,
00406 double*const f)
00407 {
00408 const double*const stab = tableau + lp->ncols;
00409 double rhs = 0;
00410 register int i;
00411 for( i = lp->ncols ; i-- ; )
00412 {
00413 if(EGabs(tableau[i]) < MT_ZERO_TOL) continue;
00414 rhs += x[i]*tableau[i];
00415 }
00416 for( i = lp->nrows ; i-- ; )
00417 {
00418 if(EGabs(stab[i]) < MT_ZERO_TOL) continue;
00419 rhs += slack[i]*stab[i];
00420 }
00421 *f = rhs;
00422 }
00423
00424 int MTcplex_binv_to_tableau(const MTlp_t*const lp,
00425 const double*const binvrow,
00426 double*const tableau)
00427 {
00428 int rval=0;
00429 const int nrows = lp->nrows;
00430 const int ncols = lp->ncols;
00431 const int nvars = nrows+ncols;
00432 register int i,j;
00433 for( i = nvars ; i-- ; ) tableau[i]=0;
00434 for( i = nrows ; i-- ; )
00435 {
00436 if(EGabs(binvrow[i])>MT_ZERO_TOL)
00437 {
00438
00439 for( j = lp->matbeg[i]; j < lp->matbeg[i+1] ; j++)
00440 {
00441 tableau[lp->matind[j]] += lp->matval[j]*binvrow[i];
00442 }
00443
00444 switch(lp->sense[i])
00445 {
00446 case 'L':
00447 case 'l':
00448 case 'R':
00449 case 'r':
00450 tableau[ncols+i] += binvrow[i];
00451 break;
00452 case 'G':
00453 case 'g':
00454 tableau[ncols+i] -= binvrow[i];
00455 break;
00456 case 'E':
00457 case 'e':
00458 break;
00459 default:
00460 TESTG((rval=1),CLEANUP,"Imposible!");
00461 break;
00462 }
00463 }
00464 }
00465 CLEANUP:
00466 return rval;
00467 }
00468
00469 int MTlp_load_problem(CPXCENVptr env,
00470 MTlp_t*const lp,
00471 CPXLPptr CPXlp,
00472 void*cbdata,
00473 int wherefrom)
00474 {
00475 int rval = 0,i1,i2,isint;
00476 double dtmp;
00477 lp->ncols = CPXgetnumcols(env,CPXlp);
00478 lp->nrows = CPXgetnumrows(env,CPXlp);
00479 MTlp_rsz(lp,lp->nrows,lp->ncols,lp->nz);
00480 CPXgetrows( env, CPXlp, &rval, lp->matbeg, lp->matind, lp->matval,
00481 0, &(lp->nz), 0, lp->nrows-1);
00482 lp->nz = -lp->nz;
00483 MTlp_rsz(lp,lp->nrows,lp->ncols,lp->nz);
00484 lp->matbeg[lp->nrows]=lp->nz;
00485 MESSAGE(MT_VERB_LVL+5, "NZ: %d COLS: %d ROWS: %d matbeg %p, matind %p,"
00486 " matval %p", lp->nz, lp->ncols, lp->nrows, lp->matbeg,
00487 lp->matind, lp->matval);
00488
00489 rval = CPXgetrows(env, CPXlp, &i1, lp->matbeg, lp->matind,
00490 lp->matval, lp->nz, &i2, 0, lp->nrows-1);
00491 MTcplexCHECKRVALG(env,rval,CLEANUP);
00492
00493 rval = CPXgetsense(env, CPXlp, lp->sense, 0 , lp->nrows-1);
00494 MTcplexCHECKRVALG(env,rval,CLEANUP);
00495 for( i1 = lp->nrows ; i1-- ; )
00496 {
00497 TESTG((rval=(lp->sense[i1] == 'R')), CLEANUP,
00498 "We don't support problems with range constraints");
00499 }
00500 rval = CPXgetrhs(env, CPXlp, lp->rhs, 0, lp->nrows-1);
00501 MTcplexCHECKRVALG(env,rval,CLEANUP);
00502
00503 rval = CPXgetlb(env, CPXlp, lp->lb, 0, lp->ncols-1);
00504 MTcplexCHECKRVALG(env,rval,CLEANUP);
00505 rval = CPXgetub(env, CPXlp, lp->ub, 0, lp->ncols-1);
00506 MTcplexCHECKRVALG(env,rval,CLEANUP);
00507
00508 rval = CPXgetcallbackctype(env,cbdata,wherefrom,lp->ctype,0,lp->ncols-1);
00509 MTcplexCHECKRVALG(env,rval,CLEANUP);
00510
00511
00512 for( i1 = lp->nrows ; i1-- ; )
00513 {
00514 isint=1;
00515 for( i2 = lp->matbeg[i1] ; i2 < lp->matbeg[i1+1] ; i2++)
00516 {
00517 dtmp = lp->matval[i2];
00518 if(EGabs(dtmp)<MT_ZERO_TOL) continue;
00519 switch(lp->ctype[lp->matind[i2]])
00520 {
00521 case CPX_BINARY:
00522 case CPX_INTEGER:
00523 break;
00524 case CPX_CONTINUOUS:
00525 isint=0;
00526 goto BREAK;
00527 break;
00528 default:
00529 TESTG( (rval=1), CLEANUP, "Unexpected var type %c for var %d",
00530 lp->ctype[lp->matind[i2]], lp->matind[i2]);
00531 break;
00532 }
00533 dtmp -= floor(dtmp);
00534 if(dtmp>MT_ZERO_TOL)
00535 {
00536 isint=0;
00537 break;
00538 }
00539 }
00540 BREAK:
00541 lp->rtype[i1] = ((char)(isint ? CPX_INTEGER: CPX_CONTINUOUS));
00542 }
00543
00544 rval = CPXgetbase(env,CPXlp,lp->cstat,lp->rstat);
00545 MTcplexCHECKRVALG(env,rval,CLEANUP);
00546
00547 #if MT_CCBK_USE_NAMES
00548 CPXgetcolname(env, CPXlp, lp->colnames, lp->ccspace, 0, &(lp->ccsz),
00549 0, lp->ncols-1);
00550 EGfree(lp->ccspace);
00551 lp->ccsz = -lp->ccsz;
00552 lp->ccspace = EGsMalloc(char,lp->ccsz);
00553 rval = CPXgetcolname( env, CPXlp, lp->colnames, lp->ccspace, lp->ccsz,
00554 &i1, 0, lp->ncols-1);
00555 MTcplexCHECKRVALG(env,rval,CLEANUP);
00556 CPXgetrowname(env, CPXlp, lp->rownames, lp->rcspace, 0, &(lp->rcsz),
00557 0, lp->nrows-1);
00558 EGfree(lp->rcspace);
00559 lp->rcsz = -lp->rcsz;
00560 lp->rcspace = EGsMalloc(char,lp->rcsz);
00561 rval = CPXgetrowname( env, CPXlp, lp->rownames, lp->rcspace, lp->rcsz,
00562 &i1, 0, lp->nrows-1);
00563 MTcplexCHECKRVALG(env,rval,CLEANUP);
00564 #endif
00565 CLEANUP:
00566 return rval;
00567 }
00568
00569 int MTccbk_fail_tableau_ratio = 0;
00570 int MTccbk_fail_tableau_coeff = 0;
00571 int MTccbk_fail_tableau_frac = 0;
00572 int MTccbk_fail_tableau_btype = 0;
00573 int MTccbk_fail_tableau_nbasic = 0;
00574 int MTccbk_fail_violation = 0;
00575 int MTccbk_fail_ratio = 0;
00576 double MTccbk_discarded_violation = 0;
00577 double MTccbk_discarded_ratio = DBL_MAX;
00578
00579 int MTgomory_ccbk(CPXCENVptr env,
00580 void*cbdata,
00581 int wherefrom,
00582 void*cbhandle,
00583 int*useraction_p)
00584 {
00585 MTgomory_ccbk_t*const data=(MTgomory_ccbk_t*)cbhandle;
00586 register int i;
00587 int rval = 0, action = 0;
00588 CPXLPptr lp = 0;
00589 int ncols,nrows;
00590 double dtmp;
00591 double *base, *f;
00592 int cur_tabrow = 0;
00593
00594 MESSAGE(MT_VERB_LVL+100,"Entering");
00595 *useraction_p = CPX_CALLBACK_DEFAULT;
00596
00597 rval = MTccbk_info_process(&(data->info), env, cbdata, wherefrom, &action);
00598 CHECKRVALG(rval,CLEANUP);
00599 if(action) goto CLEANUP;
00600
00601 rval = CPXgetcallbacknodelp (env, cbdata, wherefrom, &lp);
00602 MTcplexCHECKRVALG(env,rval,CLEANUP);
00603
00604 if(MT_VERB_LVL +5 <= DEBUG)
00605 {
00606 rval = CPXwriteprob(env,lp,"node_lp.lp.gz","LP");
00607 MTcplexCHECKRVALG(env,rval,CLEANUP);
00608 }
00609
00610 rval = MTlp_load_problem(env, &(data->lp), lp, cbdata, wherefrom);
00611 CHECKRVALG(rval,CLEANUP);
00612
00613 ncols = CPXgetnumcols(env,lp);
00614 nrows = CPXgetnumrows(env,lp);
00615 MESSAGE(MT_VERB_LVL+3,"Problem has %d vars and %d constr",ncols,nrows);
00616
00617 rval = EGmax(nrows,ncols);
00618 MTgomory_ccbk_rsz(data,nrows,ncols+nrows,rval);
00619 f = data->f;
00620 base = data->base;
00621
00622 rval = MTget_sol(&(data->lp), env, lp, cbdata, wherefrom, &(data->sol));
00623 CHECKRVALG(rval,CLEANUP);
00624
00625 if(MT_VERB_LVL + 10 <= DEBUG)
00626 MTdisplay_lp(&(data->lp), &(data->sol), stderr);
00627
00628 rval = MTget_best_k_tableau_rows(&(data->lp), &(data->sol), data->info.max_rows,
00629 env, lp, &(data->tb), data->f);
00630 CHECKRVALG(rval,CLEANUP);
00631 if(!data->tb.nrows) goto CLEANUP;
00632
00633 for( i = data->tb.nrows ; i-- ; )
00634 {
00635 base[i] = 1.0;
00636 if(MT_VERB_LVL+5 <= DEBUG)
00637 {
00638 fprintf(stderr,"f[%d] = %7.4lf base[%d] = %7.4lf\n",i,f[i],i,base[i]);
00639 }
00640 }
00641
00642 cur_tabrow = data->tb.nrows;
00643 REDO:
00644 rval = MTgomoryCut(cur_tabrow, data->tb.ncols, data->tb.rowval,
00645 data->tb.rowind, data->tb.rowbeg, data->f, base,
00646 data->extcut, data->work);
00647 CHECKRVALG(rval,CLEANUP);
00648
00649 rval = MTraw_to_complemented_cut(&(data->lp), &(data->sol), data->extcut, &(data->cut));
00650 CHECKRVALG(rval,CLEANUP);
00651
00652
00653
00654 if(MT_DEBUG_LVL +10 <= DEBUG)
00655 {
00656 rval = MTcplex_test_cut(&(data->cut),&(data->lp));
00657 CHECKRVALG(rval,CLEANUP);
00658 }
00659
00660 dtmp = data->cut.max_abs/data->cut.min_abs;
00661 if(dtmp > MT_CCBK_MAX_RATIO)
00662 {
00663 MESSAGE(MT_VERB_LVL+1, "Discarded by ratio (%lf<= %lf)",
00664 dtmp, MT_CCBK_MAX_RATIO);
00665 MTccbk_fail_ratio++;
00666 if(MTccbk_discarded_ratio > dtmp)
00667 MTccbk_discarded_ratio = dtmp;
00668 goto CLEANUP;
00669 }
00670
00671 if(data->cut.violation < MT_CCBK_MIN_VIO)
00672 {
00673 if(MTccbk_discarded_violation < data->cut.violation)
00674 MTccbk_discarded_violation = data->cut.violation;
00675 MTccbk_fail_violation++;
00676 MESSAGE(MT_VERB_LVL+1, "Discarded by violation (%lf<= %lf)",
00677 data->cut.violation, MT_CCBK_MIN_VIO);
00678 goto CLEANUP;
00679 }
00680
00681 rval = CPXcutcallbackaddlocal( env, cbdata, wherefrom, data->cut.nz,
00682 data->cut.rhs, data->cut.sense ,
00683 data->cut.cutind, data->cut.cutval);
00684 MTcplexCHECKRVALG(env,rval,CLEANUP);
00685 data->info.added_cuts++;
00686 data->info.node_cuts++;
00687 MESSAGE(MT_VERB_LVL, "Node %zd LP:(%d,%d,%d) Constr: %d nz, %.2lf rhs,"
00688 " ratio %.2lf, violation (>0) %lf", data->info.node_cnt,
00689 data->lp.nrows, data->lp.ncols, data->lp.nz, data->cut.nz, data->cut.rhs,
00690 data->cut.max_abs/data->cut.min_abs, data->cut.violation);
00691 if(data->info.cut_style && cur_tabrow>2)
00692 {
00693 cur_tabrow--;
00694 goto REDO;
00695 }
00696 CLEANUP:
00697 MESSAGE(MT_VERB_LVL+100,"Done, status %d",rval);
00698 return rval;
00699 }
00700
00701 int MTread_cplex_options(CPXENVptr env, FILE * inputfile)
00702 {
00703 const char delim[3] = " :";
00704 const char coment[3] = "%#";
00705 char str[2048],
00706 *argv[1024];
00707 int argc,
00708 rval=0,
00709 todo = 1,
00710 itmp;
00711 double tmpd;
00712
00713 while(todo)
00714 {
00715 rval = EGioReadLine (str, (size_t) 2048, inputfile);
00716 CHECKRVALG(rval,CLEANUP);
00717 TESTG((rval=(feof(inputfile)||ferror(inputfile))), CLEANUP,
00718 "file ended prematurelly");
00719 EGioNParse (str, 1024, delim, coment, &argc, argv);
00720
00721 if (!argc) continue;
00722
00723 if (strncmp (argv[0], "NAME", (size_t) 33) == 0) continue;
00724
00725 else if (strncmp (argv[0], "COMMENT", (size_t) 33) == 0) continue;
00726
00727 else if (strncmp (argv[0], "TYPE", (size_t) 33) == 0)
00728 {
00729 TESTG((rval=(argc!=2)), CLEANUP, "TYPE has not 2 tokens");
00730 TESTG((rval=(strncmp (argv[1], "OPTIONFILE", (size_t) 33))), CLEANUP,
00731 "File TYPE is not OPTIONFILE, instead %s", argv[1]);
00732 }
00733 else if (strncmp (argv[0], "MIRCUTS", (size_t)33)==0)
00734 {
00735 TESTG((rval=(argc!=2)), CLEANUP, "MIRCUTS has not 2 tokens");
00736 rval = CPXsetintparam (env, CPX_PARAM_MIRCUTS, atoi(argv[1]));
00737 MTcplexCHECKRVALG(env,rval,CLEANUP);
00738 fprintf(stdout,"Setting: MIRCUTS %d\n",atoi(argv[1]));
00739 }
00740 else if (strncmp (argv[0], "GUBCOVERS", (size_t)33)==0)
00741 {
00742 TESTG((rval=(argc!=2)), CLEANUP, "GUBCOVERS has not 2 tokens");
00743 rval = CPXsetintparam (env, CPX_PARAM_GUBCOVERS, atoi(argv[1]));
00744 MTcplexCHECKRVALG(env,rval,CLEANUP);
00745 fprintf(stdout,"Setting: GUBCOVERS %d\n",atoi(argv[1]));
00746 }
00747 else if (strncmp (argv[0], "IMPLBD", (size_t)33)==0)
00748 {
00749 TESTG((rval=(argc!=2)), CLEANUP, "IMPLBD has not 2 tokens");
00750 rval = CPXsetintparam (env, CPX_PARAM_IMPLBD, atoi(argv[1]));
00751 MTcplexCHECKRVALG(env,rval,CLEANUP);
00752 fprintf(stdout,"Setting: IMPLBD %d\n",atoi(argv[1]));
00753 }
00754 else if (strncmp (argv[0], "COVERS", (size_t)33)==0)
00755 {
00756 TESTG((rval=(argc!=2)), CLEANUP, "COVERS has not 2 tokens");
00757 rval = CPXsetintparam (env, CPX_PARAM_COVERS, atoi(argv[1]));
00758 MTcplexCHECKRVALG(env,rval,CLEANUP);
00759 fprintf(stdout,"Setting: COVERS %d\n",atoi(argv[1]));
00760 }
00761 else if (strncmp (argv[0], "ZEROHALFCUTS", (size_t)33)==0)
00762 {
00763 TESTG((rval=(argc!=2)), CLEANUP, "ZEROHALFCUTS has not 2 tokens");
00764 if(CPX_VERSION < 1100)
00765 {
00766 fprintf(stdout,"WARNING NotSetting ZEROHALFCUTS CPLEX VERSION %.2lg < 11.00",((double)CPX_VERSION)/100.0);
00767 }
00768 else
00769 {
00770 #ifdef CPX_PARAM_ZEROHALFCUTS
00771 rval = CPXsetintparam (env, CPX_PARAM_ZEROHALFCUTS, atoi(argv[1]));
00772 MTcplexCHECKRVALG(env,rval,CLEANUP);
00773 fprintf(stdout,"Setting: ZEROHALFCUTS %d\n",atoi(argv[1]));
00774 #endif
00775 }
00776 }
00777 else if (strncmp (argv[0], "CLIQUES", (size_t)33)==0)
00778 {
00779 TESTG((rval=(argc!=2)), CLEANUP, "CLIQUES has not 2 tokens");
00780 rval = CPXsetintparam (env, CPX_PARAM_CLIQUES, atoi(argv[1]));
00781 MTcplexCHECKRVALG(env,rval,CLEANUP);
00782 fprintf(stdout,"Setting: CLIQUES %d\n",atoi(argv[1]));
00783 }
00784 else if (strncmp (argv[0], "DISJCUTS", (size_t)33)==0)
00785 {
00786 TESTG((rval=(argc!=2)), CLEANUP, "DISJCUTS has not 2 tokens");
00787 rval = CPXsetintparam (env, CPX_PARAM_DISJCUTS, atoi(argv[1]));
00788 MTcplexCHECKRVALG(env,rval,CLEANUP);
00789 fprintf(stdout,"Setting: DISJCUTS %d\n",atoi(argv[1]));
00790 }
00791 else if (strncmp (argv[0], "FLOWPATHS", (size_t)33)==0)
00792 {
00793 TESTG((rval=(argc!=2)), CLEANUP, "FLOWPATHS has not 2 tokens");
00794 rval = CPXsetintparam (env, CPX_PARAM_FLOWPATHS, atoi(argv[1]));
00795 MTcplexCHECKRVALG(env,rval,CLEANUP);
00796 fprintf(stdout,"Setting: FLOWPATHS %d\n",atoi(argv[1]));
00797 }
00798 else if (strncmp (argv[0], "FLOWCOVERS", (size_t)33)==0)
00799 {
00800 TESTG((rval=(argc!=2)), CLEANUP, "FLOWCOVERS has not 2 tokens");
00801 rval = CPXsetintparam (env, CPX_PARAM_FLOWCOVERS, atoi(argv[1]));
00802 MTcplexCHECKRVALG(env,rval,CLEANUP);
00803 fprintf(stdout,"Setting: FLOWCOVERS %d\n",atoi(argv[1]));
00804 }
00805 else if (strncmp (argv[0], "FRACCUTS", (size_t)33)==0)
00806 {
00807 TESTG((rval=(argc!=2)), CLEANUP, "FRACCUTS has not 2 tokens");
00808 rval = CPXsetintparam (env, CPX_PARAM_FRACCUTS, atoi(argv[1]));
00809 MTcplexCHECKRVALG(env,rval,CLEANUP);
00810 fprintf(stdout,"Setting: FRACCUTS %d\n",atoi(argv[1]));
00811 }
00812 else if (strncmp (argv[0], "INTTOL", (size_t)33)==0)
00813 {
00814 TESTG((rval=(argc!=2)), CLEANUP, "INTTOL has not 2 tokens");
00815 rval = CPXsetdblparam (env, CPX_PARAM_EPINT, strtod(argv[1],0));
00816 MTcplexCHECKRVALG(env,rval,CLEANUP);
00817 fprintf(stdout,"Setting: INTTOL %.6lg\n",strtod(argv[1],0));
00818 }
00819 else if (strncmp (argv[0], "PROBE", (size_t)33) == 0)
00820 {
00821 TESTG((rval=(argc!=2)), CLEANUP, "PROBE has not 2 tokens");
00822 rval = CPXsetintparam (env, CPX_PARAM_PROBE, atoi(argv[1]));
00823 MTcplexCHECKRVALG(env,rval,CLEANUP);
00824 fprintf(stdout,"Setting: PROBE %d\n",atoi(argv[1]));
00825 }
00826 else if (strncmp (argv[0], "VARSEL", (size_t)33) == 0)
00827 {
00828 TESTG((rval=(argc!=2)), CLEANUP, "VARSEL has not 2 tokens");
00829 rval = CPXsetintparam (env, CPX_PARAM_VARSEL, atoi(argv[1]));
00830 MTcplexCHECKRVALG(env,rval,CLEANUP);
00831 fprintf(stdout,"Setting: VARSEL %d\n",atoi(argv[1]));
00832 }
00833 else if (strncmp (argv[0], "MIPDISPLAY", (size_t)33)==0)
00834 {
00835 TESTG((rval=(argc!=2)), CLEANUP, "MIPDISPLAY has not 2 tokens");
00836 rval = CPXsetintparam (env, CPX_PARAM_MIPDISPLAY, atoi(argv[1]));
00837 MTcplexCHECKRVALG(env,rval,CLEANUP);
00838 fprintf(stdout,"Setting: MIPDISPLAY %d\n",atoi(argv[1]));
00839 }
00840 else if (strncmp (argv[0], "MIPINTERVAL", (size_t)33)==0)
00841 {
00842 TESTG((rval=(argc!=2)), CLEANUP, "MIPINTERVAL has not 2 tokens");
00843 rval = CPXsetintparam (env, CPX_PARAM_MIPINTERVAL, atoi(argv[1]));
00844 MTcplexCHECKRVALG(env,rval,CLEANUP);
00845 fprintf(stdout,"Setting: MIPINTERVAL %d\n",atoi(argv[1]));
00846 }
00847 else if (strncmp (argv[0], "RINSHEUR", (size_t)33) == 0)
00848 {
00849 TESTG((rval=(argc!=2)), CLEANUP, "RINSHEUR has not 2 tokens");
00850 rval = CPXsetintparam (env, CPX_PARAM_RINSHEUR, atoi(argv[1]));
00851 MTcplexCHECKRVALG(env,rval,CLEANUP);
00852 fprintf(stdout,"Setting: RINSHEUR %d\n",atoi(argv[1]));
00853 }
00854 else if (strncmp (argv[0], "HEURFREQ", (size_t)33) == 0)
00855 {
00856 TESTG((rval=(argc!=2)), CLEANUP, "HEURFREQ has not 2 tokens");
00857 rval = CPXsetintparam (env, CPX_PARAM_HEURFREQ, atoi(argv[1]));
00858 MTcplexCHECKRVALG(env,rval,CLEANUP);
00859 fprintf(stdout,"Setting: HEURFREQ %d\n",atoi(argv[1]));
00860 }
00861 else if (strncmp (argv[0], "NODELIM", (size_t)33) == 0)
00862 {
00863 TESTG((rval=(argc!=2)), CLEANUP, "NODELIM has not 2 tokens");
00864 rval = CPXsetintparam (env, CPX_PARAM_NODELIM, atoi(argv[1]));
00865 MTcplexCHECKRVALG(env,rval,CLEANUP);
00866 fprintf(stdout,"Setting: NODELIM %d\n",atoi(argv[1]));
00867 }
00868 else if (strncmp (argv[0], "LBHEUR", (size_t)33) == 0)
00869 {
00870 TESTG((rval=(argc!=2)), CLEANUP, "LBHEUR has not 2 tokens");
00871 if(strncmp(argv[1], "ON", (size_t)33)==0)
00872 {
00873 rval = CPXsetintparam (env, CPX_PARAM_LBHEUR, CPX_ON);
00874 MTcplexCHECKRVALG(env,rval,CLEANUP);
00875 }
00876 else if(strncmp(argv[1], "OFF", (size_t)33)==0)
00877 {
00878 rval = CPXsetintparam (env, CPX_PARAM_LBHEUR, CPX_OFF);
00879 MTcplexCHECKRVALG(env,rval,CLEANUP);
00880 }
00881 else
00882 {
00883 TESTG((rval=1),CLEANUP,"LBHEUR should be set to either ON or OFF");
00884 }
00885 fprintf(stdout,"Setting: LBHEUR %s\n",argv[1]);
00886 }
00887 else if (strncmp (argv[0], "SCREEN", (size_t)33) == 0)
00888 {
00889 TESTG((rval=(argc!=2)), CLEANUP, "SCREEN has not 2 tokens");
00890 if(strncmp(argv[1], "ON", (size_t)33)==0)
00891 {
00892 rval = CPXsetintparam (env, CPX_PARAM_SCRIND, CPX_ON);
00893 MTcplexCHECKRVALG(env,rval,CLEANUP);
00894 }
00895 else if(strncmp(argv[1], "OFF", (size_t)33)==0)
00896 {
00897 rval = CPXsetintparam (env, CPX_PARAM_SCRIND, CPX_OFF);
00898 MTcplexCHECKRVALG(env,rval,CLEANUP);
00899 }
00900 else
00901 {
00902 TESTG((rval=1),CLEANUP,"SCREEN should be set to either ON or OFF");
00903 }
00904 fprintf(stdout,"Setting: SCREEN %s\n",argv[1]);
00905 }
00906 else if (strncmp (argv[0], "THREADS", (size_t) 33) == 0)
00907 {
00908 TESTG((rval=(argc!=2)), CLEANUP, "THREADS has not 2 tokens");
00909 TESTG((rval=(atoi(argv[1])<1)), CLEANUP, "THREADS must be > 0");
00910 rval = CPXsetintparam(env,CPX_PARAM_THREADS,atoi(argv[1]));
00911 MTcplexCHECKRVALG(env,rval,CLEANUP);
00912 MTcplexCHECKRVALG(env,rval,CLEANUP);
00913 fprintf(stdout,"Setting: THREADS %d\n",atoi(argv[1]));
00914 }
00915 else if (strncmp (argv[0], "PRESOLVE", (size_t) 33) == 0)
00916 {
00917 TESTG((rval=(argc!=2)), CLEANUP, "PRESOLVE has not 2 tokens");
00918 if (strncmp (argv[1], "ON", (size_t) 33) == 0)
00919 {
00920 rval = CPXsetintparam(env,CPX_PARAM_PREIND,CPX_ON);
00921 MTcplexCHECKRVALG(env,rval,CLEANUP);
00922 fprintf(stdout,"Setting: PRESOLVE ON\n");
00923 }else if (strncmp (argv[1], "OFF", (size_t) 33) == 0)
00924 {
00925 rval = CPXsetintparam(env,CPX_PARAM_PREIND,CPX_OFF);
00926 MTcplexCHECKRVALG(env,rval,CLEANUP);
00927 fprintf(stdout,"Setting: PRESOLVE OFF\n");
00928 }
00929 else
00930 {
00931 rval = 1;
00932 fprintf(stdout, "PRESOLVE must be either ON or OFF\n");
00933 goto CLEANUP;
00934 }
00935 }
00936 else if (strncmp (argv[0], "MIPEMPHASIS", (size_t)33) == 0)
00937 {
00938 TESTG((rval=(argc!=2)), CLEANUP, "MIPEMPHASIS has not 2 tokens");
00939 itmp = atoi(argv[1]);
00940 TESTG((rval=(itmp<0)), CLEANUP, "MIPEMPHASIS must be >= 0");
00941 TESTG((rval=(itmp>4)), CLEANUP, "MIPEMPHASIS must be <= 4");
00942 rval=CPXsetintparam(env , CPX_PARAM_MIPEMPHASIS , itmp);
00943 MTcplexCHECKRVALG(env,rval,CLEANUP);
00944 fprintf(stdout,"Setting: MIPEMPHASIS to %d\n",itmp);
00945 }
00946 else if (strncmp (argv[0], "TIMELIMIT", (size_t) 33) == 0)
00947 {
00948 TESTG((rval=(argc!=2)), CLEANUP, "TIMELIMIT has not 2 tokens");
00949 TESTG((rval=(strtod(argv[1],0)<1)), CLEANUP, "TIMELIMIT must be > 0");
00950 rval=CPXsetintparam(env , CPX_PARAM_CLOCKTYPE , 1);
00951 MTcplexCHECKRVALG(env,rval,CLEANUP);
00952 rval=CPXsetdblparam(env , CPX_PARAM_TILIM , strtod(argv[1],0));
00953 MTcplexCHECKRVALG(env,rval,CLEANUP);
00954 fprintf(stdout,"Setting: TIMELIMIT %.2lf seconds (CPU time)\n",strtod(argv[1],0));
00955 }
00956 else if (strncmp (argv[0], "CUTSFACTOR", (size_t) 33) == 0)
00957 {
00958 TESTG((rval=(argc!=2)), CLEANUP, "CUTSFACTOR has not 2 tokens");
00959 tmpd = strtod (argv[1], 0);
00960 TESTG((rval=(tmpd<0.0)), CLEANUP, "CUTSFACTOR must be > 0,0");
00961 rval=CPXsetdblparam(env , CPX_PARAM_CUTSFACTOR , tmpd);
00962 MTcplexCHECKRVALG(env,rval,CLEANUP);
00963 fprintf(stdout,"Setting: CUTSFACTOR %f\n",tmpd);
00964 }
00965 else if (strncmp (argv[0], "GAP", (size_t) 33) == 0)
00966 {
00967 TESTG((rval=(argc!=2)), CLEANUP, "GAP has not 2 tokens");
00968 tmpd = strtod (argv[1], 0);
00969 TESTG((rval=(tmpd<0.0)), CLEANUP, "GAP must be > 0,0");
00970 rval=CPXsetdblparam(env , CPX_PARAM_EPGAP , tmpd);
00971 MTcplexCHECKRVALG(env,rval,CLEANUP);
00972 fprintf(stdout,"Setting: GAP %f\n",tmpd);
00973 }
00974 else if (strncmp (argv[0], "OBJ_UPLIM", (size_t) 33) == 0)
00975 {
00976 TESTG((rval=(argc!=2)), CLEANUP, "OBJ_UPLIM has not 2 tokens");
00977 tmpd = strtod (argv[1], 0);
00978 rval=CPXsetdblparam(env , CPX_PARAM_CUTUP , tmpd);
00979 MTcplexCHECKRVALG(env,rval,CLEANUP);
00980 fprintf(stdout,"Setting: OBJ_UPLIM %f\n",tmpd);
00981 }
00982 else if (strncmp (argv[0], "OBJ_LOLIM", (size_t) 33) == 0)
00983 {
00984 TESTG((rval=(argc!=2)), CLEANUP, "OBJ_LOLIM has not 2 tokens");
00985 tmpd = strtod (argv[1], 0);
00986 rval=CPXsetdblparam(env , CPX_PARAM_CUTLO , tmpd);
00987 MTcplexCHECKRVALG(env,rval,CLEANUP);
00988 fprintf(stdout,"Setting: OBJ_LOLIM %f\n",tmpd);
00989 }
00990 else if (strncmp (argv[0], "ROOT_ALG", (size_t) 33) == 0)
00991 {
00992 TESTG((rval=(argc!=2)), CLEANUP, "ROOT_ALG has not 2 tokens");
00993 if (strncmp (argv[1], "PRIMAL", (size_t) 33) == 0)
00994 {
00995 rval=CPXsetintparam(env,CPX_PARAM_STARTALG,CPX_ALG_PRIMAL);
00996 MTcplexCHECKRVALG(env,rval,CLEANUP);
00997 fprintf(stdout,"Setting: ROOT_ALG PRIMAL\n");
00998 }
00999 else if (strncmp (argv[1], "DUAL", (size_t) 33) == 0)
01000 {
01001 rval=CPXsetintparam(env,CPX_PARAM_STARTALG,CPX_ALG_DUAL);
01002 MTcplexCHECKRVALG(env,rval,CLEANUP);
01003 fprintf(stdout,"Setting: ROOT_ALG DUAL\n");
01004 }
01005 else if (strncmp (argv[1], "BARRIER", (size_t) 33) == 0)
01006 {
01007 rval=CPXsetintparam(env,CPX_PARAM_STARTALG,CPX_ALG_BARRIER);
01008 MTcplexCHECKRVALG(env,rval,CLEANUP);
01009 fprintf(stdout,"Setting: ROOT_ALG BARRIER\n");
01010 }
01011 else
01012 {
01013 rval = 1;
01014 fprintf(stdout, "ROOT_ALG must be PRIMAL, DUAL or BARRIER\n");
01015 goto CLEANUP;
01016 }
01017 }
01018 else if (strncmp (argv[0], "SUB_ALG", (size_t) 33) == 0)
01019 {
01020 TESTG((rval=(argc!=2)), CLEANUP, "SUB_ALG has not 2 tokens");
01021 if (strncmp (argv[1], "PRIMAL", (size_t) 33) == 0)
01022 {
01023 rval=CPXsetintparam(env,CPX_PARAM_SUBALG,CPX_ALG_PRIMAL);
01024 MTcplexCHECKRVALG(env,rval,CLEANUP);
01025 fprintf(stdout,"Setting: SUB_ALG PRIMAL\n");
01026 }
01027 else if (strncmp (argv[1], "DUAL", (size_t) 33) == 0)
01028 {
01029 rval=CPXsetintparam(env,CPX_PARAM_SUBALG,CPX_ALG_DUAL);
01030 MTcplexCHECKRVALG(env,rval,CLEANUP);
01031 fprintf(stdout,"Setting: SUB_ALG DUAL\n");
01032 }
01033 else if (strncmp (argv[1], "BARRIER", (size_t) 33) == 0)
01034 {
01035 rval=CPXsetintparam(env,CPX_PARAM_SUBALG,CPX_ALG_BARRIER);
01036 MTcplexCHECKRVALG(env,rval,CLEANUP);
01037 fprintf(stdout,"Setting: SUB_ALG BARRIER\n");
01038 }
01039 else
01040 {
01041 rval = 1;
01042 fprintf(stdout, "SUB_ALG must be PRIMAL, DUAL or BARRIER\n");
01043 goto CLEANUP;
01044 }
01045 }
01046 else if (strncmp (argv[0], "USE_TREE", (size_t) 33) == 0)
01047 {
01048
01049
01050
01051
01052
01053
01054
01055 ;
01056 }
01057 else if (strncmp (argv[0], "EOF", (size_t) 33) == 0)
01058 {
01059 todo = 0;
01060 }
01061
01062 else
01063 {
01064 rval = 1;
01065 printf ("Unknown token %s\n", argv[0]);
01066 goto CLEANUP;
01067 }
01068
01069 }
01070 CLEANUP:
01071 return rval;
01072 }
01073
01074 void MTsol_rsz( MTsol_t*const MTsol,
01075 const int cnz,
01076 const int rnz)
01077 {
01078 if(MTsol->cspace < cnz)
01079 {
01080 MTsol->cspace = cnz;
01081 MTsol->x = EGrealloc(MTsol->x,sizeof(double)*((size_t)cnz));
01082 MTsol->pseudocost = EGrealloc(MTsol->pseudocost,sizeof(double)*((size_t)cnz));
01083 }
01084 if(MTsol->rspace < rnz)
01085 {
01086 MTsol->rspace = rnz;
01087 MTsol->slack = EGrealloc(MTsol->slack,sizeof(double)*((size_t)rnz));
01088 }
01089 return;
01090 }
01091
01092 void MTrowmatrix_rsz(MTrowmatrix_t*const MTrm,
01093 const int rsz,
01094 const int tsz)
01095 {
01096 if(MTrm->rspace < rsz)
01097 {
01098 MTrm->rspace = rsz;
01099 MTrm->rowbeg = EGrealloc(MTrm->rowbeg, sizeof(int)*((size_t)(rsz+1)));
01100 }
01101 if(MTrm->nzspace < tsz)
01102 {
01103 MTrm->nzspace = tsz;
01104 MTrm->rowval = EGrealloc(MTrm->rowval,sizeof(double)*((size_t)tsz));
01105 MTrm->rowind = EGrealloc(MTrm->rowind,sizeof(int)*((size_t)tsz));
01106 }
01107 return;
01108 }
01109
01110 void MTccbk_info_display(const MTccbk_info_t*const info,FILE*out)
01111 {
01112 fprintf(out,"Root LP Value : %.6lf\n",info->root_val);
01113 fprintf(out,"Added cuts : %zd\n",info->added_cuts);
01114 }
01115
01116 int MTccbk_info_process(MTccbk_info_t*const info,
01117 CPXCENVptr env,
01118 void*cbdata,
01119 int wherefrom,
01120 int*const action)
01121 {
01122 int rval = 0;
01123 int node_cnt;
01124 *action = 0;
01125 rval = CPXgetcallbackinfo(env, cbdata, wherefrom,
01126 CPX_CALLBACK_INFO_NODE_COUNT, &node_cnt);
01127 MTcplexCHECKRVALG(env,rval,CLEANUP);
01128 if(((size_t)node_cnt) != info->node_cnt) info->node_cuts = 0;
01129 info->node_cnt = (size_t)node_cnt;
01130 if(node_cnt == 0)
01131 {
01132 rval = CPXgetcallbacknodeobjval(env, cbdata, wherefrom, &(info->root_val));
01133 MTcplexCHECKRVALG(env,rval,CLEANUP);
01134 }
01135 if(!info->use_cuts)
01136 {
01137 MESSAGE(MT_VERB_LVL,"Cuts disabled from beggining");
01138 *action = 1;
01139 goto CLEANUP;
01140 }
01141 if(info->root_only && node_cnt)
01142 {
01143 MESSAGE(MT_VERB_LVL,"node count limit reached");
01144 *action = 1;
01145 goto CLEANUP;
01146 }
01147 if(info->node_cuts >= info->max_cuts)
01148 {
01149 MESSAGE(MT_VERB_LVL,"Cut limit reached");
01150 *action = 1;
01151 goto CLEANUP;
01152 }
01153 CLEANUP:
01154 return rval;
01155 }
01156
01157 void MTsol_clear(MTsol_t*const MTsol)
01158 {
01159 EGfree(MTsol->x);
01160 EGfree(MTsol->slack);
01161 EGfree(MTsol->pseudocost);
01162 memset(MTsol,0,sizeof(MTsol_t));
01163 return;
01164 }
01165
01166 void MTrowmatrix_clear(MTrowmatrix_t*const MTrm)
01167 {
01168 EGfree(MTrm->rowbeg);
01169 EGfree(MTrm->rowind);
01170 EGfree(MTrm->rowval);
01171 memset(MTrm,0,sizeof(MTrowmatrix_t));
01172 return;
01173 }
01174
01175 void MTlp_clear(MTlp_t*const MTlp)
01176 {
01177 EGfree(MTlp->sense);
01178 EGfree(MTlp->rhs);
01179 EGfree(MTlp->matbeg);
01180 EGfree(MTlp->rtype);
01181 EGfree(MTlp->rstat);
01182 EGfree(MTlp->ctype);
01183 EGfree(MTlp->cstat);
01184 EGfree(MTlp->matind);
01185 EGfree(MTlp->matval);
01186 EGfree(MTlp->ub);
01187 EGfree(MTlp->lb);
01188 #if MT_CCBK_USE_NAMES
01189 EGfree(MTlp->colnames);
01190 EGfree(MTlp->rownames);
01191 EGfree(MTlp->ccspace);
01192 EGfree(MTlp->rcspace);
01193 MTlp->ccsz = MTlp->rcsz = 0;
01194 #endif
01195 MTlp->cspace = MTlp->rspace = MTlp->nzspace = 0;
01196 return;
01197 }
01198
01199 void MTcplex_display_tableau( FILE* file,
01200 const MTlp_t*const lp,
01201 const double*const tableau)
01202 {
01203 const double*const slacks = tableau + lp->ncols;
01204 register int i;
01205 for( i = 0 ; i < lp->ncols ; i++)
01206 {
01207 if(EGabs(tableau[i]) < MT_ZERO_TOL) continue;
01208 fprintf(file, "%s%.6lg ",tableau[i] > 0 ? "+":"-", EGabs(tableau[i]));
01209 fprintf(file,"[%c]", lp->cstat[i]+'A');
01210 #if MT_CCBK_USE_NAMES
01211 fprintf(file,"%s ", lp->colnames[i]);
01212 #else
01213 fprintf(file,"x_%d ", i);
01214 #endif
01215 }
01216 for( i = 0 ; i < lp->nrows ; i++)
01217 {
01218 if(EGabs(slacks[i]) < MT_ZERO_TOL) continue;
01219 fprintf(file, "%s%.6lg ", slacks[i] > 0 ? "+":"-", EGabs(slacks[i]));
01220 fprintf(file,"[%c]", lp->rstat[i]+'A');
01221 #if MT_CCBK_USE_NAMES
01222 fprintf(file,"%s ", lp->rownames[i]);
01223 #else
01224 fprintf(file,"s_%d ", i);
01225 #endif
01226 }
01227 return;
01228 }
01229
01230 void MTcplex_display_compress_tableau(FILE* file,
01231 const MTlp_t*const lp,
01232 const double*const matval,
01233 const int*const matind,
01234 const int nz)
01235 {
01236 register int i;
01237 int curind=0;
01238 for( i = 0 ; i < nz ; i++)
01239 {
01240 curind = matind[i];
01241 if(curind < lp->ncols)
01242 {
01243 fprintf(file, "%s%.5lf %s", matval[i]>0 ? "+":"-", EGabs(matval[i]),
01244 lp->cstat[curind] == CPX_AT_LOWER ? "": "~");
01245 #if MT_CCBK_USE_NAMES
01246 fprintf(file,"%s ",lp->colnames[curind]);
01247 #else
01248 fprintf(file,"x_%d ",curind);
01249 #endif
01250 }
01251 else
01252 {
01253 curind -= lp->ncols;
01254 fprintf(file, "%s%.5lf %s", matval[i]>0 ? "+":"-", EGabs(matval[i]),
01255 lp->rstat[curind] == CPX_AT_LOWER ? "": "~");
01256 #if MT_CCBK_USE_NAMES
01257 fprintf(file,"%s ",lp->rownames[curind]);
01258 #else
01259 fprintf(file,"s_%d ",curind);
01260 #endif
01261 }
01262 }
01263 }
01264
01265 int MTget_best_k_integer_tableau_rows(const MTlp_t*const lp,
01266 const MTsol_t*const sol,
01267 const int max_tableau,
01268 CPXCENVptr env,
01269 CPXLPptr CPXlp,
01270 MTrowmatrix_t*const tb,
01271 double*const f)
01272 {
01273 const double*const x = sol->x;
01274 const double*const slack = sol->slack;
01275 const double*const pseudocost = sol->pseudocost;
01276 const int nrows = lp->nrows;
01277 const int ncols = lp->ncols;
01278 const int*const cstat = lp->cstat;
01279 register int i = 0;
01280 double dtmp,*binvrow = EGsMalloc(double,nrows),*tableau = 0, minratio=DBL_MAX, ratio;
01281 int rval = 0, nfrac = 0, brow = 0, tnz = 0, nfrac2 = 0, col = 0, status;
01282 int* rowmap = EGsMalloc(int,nrows), *tabind = 0;
01283 MESSAGE(MT_VERB_LVL,"Entering");
01284 tb->nz = tb->nrows = 0;
01285 tb->nrows = 0;
01286 tb->ncols = ncols+nrows;
01287 MTrowmatrix_rsz(tb,nrows,0);
01288 tb->rowbeg[0] = 0;
01289
01290 rval = MTcompute_integer_vars(lp, x, rowmap, &nfrac2, MT_CCBK_MIN_FRAC);
01291 CHECKRVALG(rval,CLEANUP);
01292
01293 dbl_EGutilPermSort2(((size_t)nfrac2),rowmap, pseudocost);
01294
01295
01296 for( i = 0 ; i < nfrac2 && nfrac < max_tableau ; i++ )
01297 {
01298 col = rowmap[i];
01299
01300 if(cstat[col] != CPX_BASIC) continue;
01301
01302 rval = CPXgetijrow(env, CPXlp, -1, col, &brow);
01303 MTcplexCHECKRVALG(env,rval,CLEANUP);
01304 rval = CPXbinvrow(env, CPXlp, brow, binvrow);
01305 MTcplexCHECKRVALG(env,rval,CLEANUP);
01306 MTrowmatrix_rsz(tb,nrows,tb->nz+tb->ncols);
01307 tabind = tb->rowind+tb->nz;
01308 tableau = tb->rowval+tb->nz;
01309 rval = MTcplex_binv_to_tableau(lp, binvrow, tableau);
01310 CHECKRVALG(rval,CLEANUP);
01311 if(MT_VERB_LVL+10 < DEBUG)
01312 MTcplex_display_tableau(stderr, lp, tableau);
01313
01314 rval = MTcheckTabrow(lp,tableau,&status,&ratio,&tnz);
01315 CHECKRVALG(rval,CLEANUP);
01316
01317 if(status) continue;
01318 if(minratio > ratio) minratio = ratio;
01319
01320
01321 MTcompute_f(lp, tableau, x, slack, f+nfrac);
01322 tb->rowbeg[nfrac+1] = tb->nz+tnz;
01323
01324 rval = MTcompressTabRow(lp, sol, tableau, tabind, f+nfrac, &tnz);
01325 CHECKRVALG(rval,CLEANUP);
01326 MESSAGE(MT_VERB_LVL+5,"Tableau %d has %d non-zeros",nfrac,tnz);
01327 TESTG((rval=(tb->rowbeg[nfrac+1] !=tnz+tb->nz)), CLEANUP,"Wrong tnz count,"
01328 " found %d, should be %d", tnz + tb->nz, tb->rowbeg[nfrac+1]);
01329
01330
01331 f[nfrac] = -f[nfrac];
01332
01333 dtmp = EGabs(f[nfrac]);
01334 if(dtmp > MT_CCBK_MIN_FRAC)
01335 {
01336 MTccbk_fail_tableau_frac++;
01337 MESSAGE(MT_VERB_LVL, "Discarding tableau %d, because f[%d] = %.4lf",
01338 nfrac, nfrac, f[nfrac]);
01339 continue;
01340 }
01341
01342 nfrac++;
01343 tb->nrows++;
01344 tb->nz += tnz;
01345
01346 }
01347 CLEANUP:
01348 EGfree(rowmap);
01349 EGfree(binvrow);
01350 MESSAGE(MT_VERB_LVL,"Done, status %d, found %d integer tableau rows, minratio %.9lg",rval, nfrac,minratio);
01351 return rval;
01352 }
01353
01354 int MTget_best_k_tableau_rows(const MTlp_t*const lp,
01355 const MTsol_t*const sol,
01356 const int max_tableau,
01357 CPXCENVptr env,
01358 CPXLPptr CPXlp,
01359 MTrowmatrix_t*const tb,
01360 double*const f)
01361 {
01362 const double*const x = sol->x;
01363 const double*const slack = sol->slack;
01364 const double*const pseudocost = sol->pseudocost;
01365 const int nrows = lp->nrows;
01366 const int ncols = lp->ncols;
01367 const int*const cstat = lp->cstat;
01368 register int i = 0;
01369 double dtmp,*binvrow = EGsMalloc(double,nrows),*tableau = 0, minratio=DBL_MAX, ratio;
01370 int rval = 0, nfrac = 0, brow = 0, tnz = 0, nfrac2 = 0, col = 0, status;
01371 int* rowmap = EGsMalloc(int,nrows), *tabind = 0;
01372 MESSAGE(MT_VERB_LVL,"Entering");
01373 tb->nz = tb->nrows = 0;
01374 tb->ncols = ncols+nrows;
01375 MTrowmatrix_rsz(tb,nrows,0);
01376 tb->rowbeg[0] = 0;
01377
01378 rval = MTcompute_fractional_vars(lp, x, rowmap, &nfrac2, MT_CCBK_MIN_FRAC);
01379 CHECKRVALG(rval,CLEANUP);
01380
01381 dbl_EGutilPermSort2(((size_t)nfrac2),rowmap, pseudocost);
01382
01383
01384 for( i = 0 ; i < nfrac2 && nfrac < max_tableau ; i++ )
01385 {
01386 col = rowmap[i];
01387
01388 TESTG((rval=(cstat[col] != CPX_BASIC)),CLEANUP, "Variable[%d] = %lf, status"
01389 " %d is not basic (%d)", col, x[col], cstat[col], CPX_BASIC);
01390
01391 rval = CPXgetijrow(env, CPXlp, -1, col, &brow);
01392 MTcplexCHECKRVALG(env,rval,CLEANUP);
01393 rval = CPXbinvrow(env, CPXlp, brow, binvrow);
01394 MTcplexCHECKRVALG(env,rval,CLEANUP);
01395 MTrowmatrix_rsz(tb,nrows,tb->nz+tb->ncols);
01396 tableau = tb->rowval+tb->nz;
01397 tabind = tb->rowind+tb->nz;
01398 rval = MTcplex_binv_to_tableau(lp, binvrow, tableau);
01399 CHECKRVALG(rval,CLEANUP);
01400 if(MT_VERB_LVL+10 < DEBUG)
01401 MTcplex_display_tableau(stderr, lp, tableau);
01402
01403 rval = MTcheckTabrow(lp,tableau,&status,&ratio,&tnz);
01404 CHECKRVALG(rval,CLEANUP);
01405
01406 if(status) continue;
01407 if(minratio > ratio) minratio = ratio;
01408
01409
01410 MTcompute_f(lp, tableau, x, slack, f+nfrac);
01411 tb->rowbeg[nfrac+1] = tb->nz+tnz;
01412
01413 rval = MTcompressTabRow(lp, sol, tableau, tabind, f+nfrac, &tnz);
01414 CHECKRVALG(rval,CLEANUP);
01415 MESSAGE(MT_VERB_LVL+5,"Tableau %d has %d non-zeros",nfrac,tnz);
01416
01417
01418 f[nfrac] = -f[nfrac];
01419 f[nfrac] -= (floor(f[nfrac])+0x1p-1);
01420
01421 dtmp = EGabs(f[nfrac])-0x1p-1;
01422 dtmp = EGabs(dtmp);
01423 if(dtmp < MT_ZERO_TOL)
01424 {
01425 MTccbk_fail_tableau_frac++;
01426 MESSAGE(MT_VERB_LVL, "Discarding tableau %d, because f[%d] = %.4lf",
01427 nfrac, nfrac, f[nfrac]);
01428 continue;
01429 }
01430
01431 nfrac++;
01432 tb->nrows++;
01433 tb->nz += tnz;
01434
01435 }
01436 CLEANUP:
01437 EGfree(rowmap);
01438 EGfree(binvrow);
01439 MESSAGE(MT_VERB_LVL,"Done, status %d, found %d fractional tableau rows, minratio %.9lg",rval, nfrac,minratio);
01440 return rval;
01441 }
01442
01443 int MTraw_to_uncomplemented_cut(const MTlp_t*const lp,
01444 const double*const extended,
01445 const int nactive,
01446 const int*const active,
01447 MTcut_t*const cut,
01448 int*const status)
01449 {
01450 const int nvars = lp->ncols + lp->nrows;
01451 double*cutval = 0;
01452 int*cutind = 0;
01453 int nz = 0,pos;
01454 double min_abs = DBL_MAX, max_abs = 0.0, absval;
01455 register int i;
01456 MESSAGE(MT_VERB_LVL+3,"Entering");
01457
01458 MTcut_rsz(cut,nvars);
01459 cutind = cut->cutind;
01460 cutval = cut->cutval;
01461
01462 if(!active)
01463 {
01464 i = nvars;
01465 while(i--)
01466 {
01467 absval = EGabs(extended[i]);
01468 if(absval < MT_ZERO_TOL) continue;
01469 cutind[nz] = i;
01470 cutval[nz++] = extended[i];
01471 if(absval < min_abs) min_abs = absval;
01472 if(absval > max_abs) max_abs = absval;
01473 }
01474 }
01475 else
01476 {
01477 i = nactive;
01478 while(i--)
01479 {
01480 pos = active[i];
01481 absval = EGabs(extended[pos]);
01482 if(absval < MT_ZERO_TOL) continue;
01483 cutind[nz] = pos;
01484 cutval[nz++] = extended[pos];
01485 if(absval < min_abs) min_abs = absval;
01486 if(absval > max_abs) max_abs = absval;
01487 }
01488 }
01489 cut->score = 1.0/max_abs;
01490 cut->nz = nz;
01491 cut->rhs = 1.0;
01492 cut->sense = MT_CPLEX_SENSE;
01493 cut->violation = 1.0;
01494 cut->min_abs = min_abs;
01495 cut->max_abs = max_abs;
01496 cut->form = 1;
01497 *status = 0;
01498
01499 absval = max_abs / min_abs;
01500 if(absval > MT_CCBK_MAX_RATIO)
01501 {
01502 MESSAGE(MT_VERB_LVL+1, "Discarded by ratio (%lf<= %lf)",
01503 absval, MT_CCBK_MAX_RATIO);
01504 MTccbk_fail_ratio++;
01505 if(MTccbk_discarded_ratio > absval)
01506 MTccbk_discarded_ratio = absval;
01507 *status = 1;
01508 goto CLEANUP;
01509 }
01510
01511 if(cut->violation < MT_CCBK_MIN_VIO)
01512 {
01513 if(MTccbk_discarded_violation < cut->violation)
01514 MTccbk_discarded_violation = cut->violation;
01515 MTccbk_fail_violation++;
01516 MESSAGE(MT_VERB_LVL+1, "Discarded by violation (%lf<= %lf)",
01517 cut->violation, MT_CCBK_MIN_VIO);
01518 *status = 1;
01519 }
01520
01521 if(MT_VERB_LVL+9 <= DEBUG)
01522 {
01523 fprintf(stderr,"MTcut (extended): ");
01524 MTcplex_display_tableau(stderr,lp,extended);
01525 fprintf(stderr,">=1\n");
01526 }
01527 CLEANUP:
01528 MESSAGE(MT_VERB_LVL+3,"Done");
01529 return 0;
01530 }
01531
01532 int MTuncomplemented_to_complemented_cut( const MTlp_t*const lp,
01533 const MTsol_t*const sol,
01534 MTcut_t*const cut)
01535 {
01536 const int ncols = lp->ncols;
01537 const int nrows = lp->nrows;
01538 double*extended = EGsMalloc(double,ncols+nrows);
01539 int rval = 0;
01540 register int i;
01541
01542 memset(extended,0,sizeof(double)*((size_t)(ncols+nrows)));
01543 for( i = cut->nz ; i-- ; ) extended[cut->cutind[i]] = cut->cutval[i];
01544
01545 rval = MTraw_to_complemented_cut(lp,sol,extended,cut);
01546 CHECKRVALG(rval,CLEANUP);
01547 CLEANUP:
01548 EGfree(extended);
01549 MESSAGE(MT_VERB_LVL+3,"Done");
01550 return rval;
01551 }
01552
01553 int MTraw_to_complemented_cut( const MTlp_t*const lp,
01554 const MTsol_t*const sol,
01555 double*const extended,
01556 MTcut_t*const cut)
01557 {
01558 const int ncols = lp->ncols;
01559 const int nrows = lp->nrows;
01560 const int*const cstat = lp->cstat;
01561 const int*const rstat = lp->rstat;
01562 const char*const sense = lp->sense;
01563 const double*const rhs_arr = lp->rhs;
01564 const int*const matbeg = lp->matbeg;
01565 const int*const matind = lp->matind;
01566 const double*const matval = lp->matval;
01567 const double*const x = sol->x;
01568 const double*const slack = sol->slack;
01569 double*cutval = 0;
01570 int*cutind = 0;
01571 int rval = 0, nz = 0;
01572 double rhs = 1.0, dtmp, violation = 0.0, min_abs = DBL_MAX, max_abs = 0.0;
01573 register int i,j;
01574
01575 MTcut_rsz(cut,lp->ncols);
01576 cut->form = 0;
01577 cutind = cut->cutind;
01578 cutval = cut->cutval;
01579
01580 MESSAGE(MT_VERB_LVL+3,"Entering");
01581 if(MT_VERB_LVL+3 <= DEBUG)
01582 {
01583 fprintf(stderr,"MTcut (before compl): ");
01584 MTcplex_display_tableau(stderr,lp,extended);
01585 fprintf(stderr,">=1\n");
01586 }
01587
01588 for(dtmp = 0.0, i = ncols + nrows; i-- ; )
01589 {
01590 if(fabs(extended[i])>MT_ZERO_TOL)
01591 dtmp += extended[i]*extended[i];
01592 }
01593 cut->score = 1.0/dtmp;
01594
01595 if(MT_VERB_LVL + 5 <= DEBUG) fprintf(stderr,"rhs = %.4lf\n",rhs);
01596 for( i = ncols ; i-- ; )
01597 {
01598 if(EGabs(extended[i]) < MT_ZERO_TOL) continue;
01599 TESTG((rval=(cstat[i] == CPX_BASIC)),CLEANUP,"Imposible, basic variable with cutvalue %.9lf",extended[i]);
01600 if(cstat[i] == CPX_AT_UPPER) extended[i] *= -1.0;
01601 rhs += extended[i]*x[i];
01602 if(MT_VERB_LVL + 5 <= DEBUG)
01603 {
01604 fprintf(stderr,"rhs = %.3lf ",rhs);
01605 #if MT_CCBK_USE_NAMES
01606 fprintf(stderr,"%s\n",lp->colnames[i]);
01607 #else
01608 fprintf(stderr,"x_%d\n",i);
01609 #endif
01610 }
01611 }
01612
01613 for( i = nrows; i-- ; )
01614 {
01615 if(EGabs(extended[i+ncols]) < MT_ZERO_TOL) continue;
01616 TESTG((rval=(rstat[i]==CPX_BASIC)), CLEANUP, "Imposible");
01617 if(rstat[i] == CPX_AT_UPPER) extended[i+ncols] *= -1.0;
01618 rhs += extended[i+ncols]*slack[i];
01619 if(MT_VERB_LVL + 5 <= DEBUG)
01620 {
01621 fprintf(stderr,"rhs = %.3lf ",rhs);
01622 #if MT_CCBK_USE_NAMES
01623 fprintf(stderr,"%s\n",lp->rownames[i]);
01624 #else
01625 fprintf(stderr,"s_%d\n",i);
01626 #endif
01627 }
01628 }
01629
01630 for( i = nrows ; i-- ; )
01631 {
01632 if(EGabs(extended[i+ncols]) < MT_ZERO_TOL) continue;
01633 switch(sense[i])
01634 {
01635 case 'L':
01636 case 'R':
01637 case 'l':
01638 case 'r':
01639 dtmp = 1.0;
01640 break;
01641 case 'G':
01642 case 'g':
01643 dtmp = -1.0;
01644 break;
01645 default:
01646 FTESTG((rval = 1),CLEANUP,"Imposible!");
01647 break;
01648 }
01649 rhs -= dtmp*extended[i+ncols]*rhs_arr[i];
01650 for( j = matbeg[i] ; j < matbeg[i+1] ; j++)
01651 extended[matind[j]] -= dtmp*extended[i+ncols]*matval[j];
01652 extended[i+ncols] = 0;
01653 if(MT_VERB_LVL + 5 <= DEBUG)
01654 {
01655 fprintf(stderr,"rhs = %.3lf ",rhs);
01656 #if MT_CCBK_USE_NAMES
01657 fprintf(stderr,"complement %s\n",lp->rownames[i]);
01658 #else
01659 fprintf(stderr,"complement s_%d\n",i);
01660 #endif
01661 }
01662 }
01663
01664 violation = rhs;
01665 for( i = ncols ; i-- ; )
01666 {
01667 dtmp = EGabs(extended[i]);
01668 if(dtmp < MT_ZERO_TOL) continue;
01669 violation -= x[i]*extended[i];
01670 if(dtmp < min_abs) min_abs = dtmp;
01671 if(dtmp > max_abs) max_abs = dtmp;
01672 }
01673
01674 if(min_abs > 1.0)
01675 {
01676 rhs /= min_abs;
01677 violation /= min_abs;
01678 max_abs /= min_abs;
01679 for( i = ncols ; i-- ; ) extended[i] /= min_abs;
01680 min_abs = 1.0;
01681 }
01682
01683 if(MT_VERB_LVL <= DEBUG)
01684 {
01685 fprintf(stderr,"min_abs %.9lf max_abs %.9lf MTcut (complemented): ",
01686 min_abs, max_abs);
01687 MTcplex_display_tableau(stderr,lp,extended);
01688 fprintf(stderr," >= %.9lf\n", rhs);
01689 }
01690
01691 for( i = 0 ; i < ncols ; i++)
01692 {
01693 if(EGabs(extended[i]) < MT_ZERO_TOL) continue;
01694 cutval[nz] = extended[i];
01695 cutind[nz++] = i;
01696 }
01697 cut->nz = nz;
01698 cut->rhs = rhs;
01699 cut->sense = MT_CPLEX_SENSE;
01700 cut->violation = violation;
01701 cut->min_abs = min_abs;
01702 cut->max_abs = max_abs;
01703 if(MT_VERB_LVL+5 <= DEBUG)
01704 {
01705 fprintf(stderr,"MTcut (complemented+compresed): ");
01706 MTcplex_display_compress_tableau(stderr, lp, cutval, cutind, nz);
01707 fprintf(stderr," >= %.4lf\n", rhs);
01708 }
01709 CLEANUP:
01710 MESSAGE(MT_VERB_LVL+3,"Done");
01711 return rval;
01712 }
01713
01714 int MTget_sol(const MTlp_t*const lp,
01715 CPXCENVptr env,
01716 CPXLPptr CPXlp,
01717 void*cbdata,
01718 int wherefrom,
01719 MTsol_t*const sol)
01720 {
01721 const int ncols = lp->ncols;
01722 const int nrows = lp->nrows;
01723 register int i;
01724 int rval = EGmax(ncols,nrows);
01725 double dtmp;
01726 MTsol_rsz(sol,ncols,rval);
01727 sol->ncols = ncols;
01728 sol->nrows = nrows;
01729
01730 rval = CPXgetcallbacknodex(env,cbdata,wherefrom,sol->x,0,ncols-1);
01731 MTcplexCHECKRVALG(env,rval,CLEANUP);
01732
01733 rval = CPXgetcallbackpseudocosts(env, cbdata, wherefrom, sol->pseudocost, sol->slack, 0, ncols-1);
01734 MTcplexCHECKRVALG(env,rval,CLEANUP);
01735 for( i = ncols ; i-- ; )
01736 {
01737 dtmp = sol->x[i] - floor(sol->x[i]);
01738 sol->pseudocost[i] = sol->pseudocost[i]*(1-dtmp)+dtmp*sol->slack[i];
01739 WARNING(fabs(sol->pseudocost[i])<MT_ZERO_TOL, "pseudocost %d is zero",i);
01740 }
01741
01742 rval = CPXslackfromx(env,CPXlp,sol->x,sol->slack);
01743 MTcplexCHECKRVALG(env,rval,CLEANUP);
01744 CLEANUP:
01745 return rval;
01746 }
01747
01748 int MTcplex_test_cut( const MTcut_t*const cut,
01749 const MTlp_t*const lp)
01750 {
01751 const int ncols = lp->ncols;
01752 const int nrows = lp->nrows;
01753 const int*const cutind = cut->cutind;
01754 const double*const cutval = cut->cutval;
01755 int rval = 0;
01756 CPXENVptr env = 0;
01757 CPXLPptr curip = 0;
01758 double*obj = EGsMalloc(double,ncols);
01759 double curip_obj = 0.0;
01760 double curip_bound = 0.0,dtmp;
01761 int curip_stat = 0;
01762 register int i;
01763 MESSAGE(MT_VERB_LVL+3,"Entering");
01764 TESTG((rval = cut->form),CLEANUP,"Trying to test cut in complemented form!");
01765 for( i = ncols ; i-- ; ) obj[0] = 0;
01766 for( i = cut->nz ; i-- ; ) obj[cutind[i]] = cutval[i];
01767 env = CPXopenCPLEX(&rval);
01768 MTcplexCHECKRVALG(env,rval,CLEANUP);
01769 rval = CPXsetintparam(env,CPX_PARAM_PREIND,CPX_OFF);
01770 MTcplexCHECKRVALG(env,rval,CLEANUP);
01771 rval = CPXsetdblparam (env, CPX_PARAM_EPINT, MT_ZERO_TOL);
01772 MTcplexCHECKRVALG(env,rval,CLEANUP);
01773 rval = CPXsetdblparam(env , CPX_PARAM_EPAGAP , MT_ZERO_TOL);
01774 MTcplexCHECKRVALG(env,rval,CLEANUP);
01775 rval = CPXsetdblparam(env , CPX_PARAM_EPGAP , MT_ZERO_TOL);
01776 MTcplexCHECKRVALG(env,rval,CLEANUP);
01777 curip = CPXcreateprob (env, &rval, "node_ip");
01778 MTcplexCHECKRVALG(env,rval,CLEANUP);
01779 #if MT_CCBK_USE_NAMES
01780 rval = CPXnewcols(env, curip, lp->ncols, obj, lp->lb,
01781 lp->ub, lp->ctype, lp->colnames);
01782 #else
01783 rval = CPXnewcols(env, curip, lp->ncols, obj, lp->lb,
01784 lp->ub, lp->ctype, 0);
01785 #endif
01786 MTcplexCHECKRVALG(env,rval,CLEANUP);
01787 #if MT_CCBK_USE_NAMES
01788 rval = CPXaddrows(env, curip, 0, nrows,
01789 lp->matbeg[nrows], lp->rhs,
01790 lp->sense, lp->matbeg, lp->matind,
01791 lp->matval, 0, lp->rownames);
01792 #else
01793 rval = CPXaddrows(env, curip, 0, nrows,
01794 lp->matbeg[nrows], lp->rhs,
01795 lp->sense, lp->matbeg, lp->matind,
01796 lp->matval, 0, 0);
01797 #endif
01798 MTcplexCHECKRVALG(env,rval,CLEANUP);
01799 rval = CPXwriteprob(env,curip, "node_ip.lp.gz","lp");
01800 MTcplexCHECKRVALG(env,rval,CLEANUP);
01801
01802 rval = CPXmipopt (env, curip);
01803 MTcplexCHECKRVALG(env,rval,CLEANUP);
01804 curip_stat = CPXgetstat (env, curip);
01805 switch(curip_stat)
01806 {
01807 case CPXMIP_OPTIMAL:
01808 case CPXMIP_OPTIMAL_TOL:
01809 rval = CPXgetobjval (env, curip, &curip_obj);
01810 MTcplexCHECKRVALG(env,rval,CLEANUP);
01811 rval = CPXgetbestobjval (env, curip, &curip_bound);
01812 MTcplexCHECKRVALG(env,rval,CLEANUP);
01813
01814 rval = (curip_obj+MT_ZERO_TOL < cut->rhs);
01815 dtmp = fabs(cut->rhs);
01816 if(dtmp < 1.0) dtmp=1.0;
01817 FTESTG(rval, CLEANUP,
01818 "Found an infeasible cut! rhs = %.6lf, actual minimum "
01819 "%.6lf, difference %.6lg (%.3lf%%)", cut->rhs, curip_obj,
01820 cut->rhs - curip_obj, 100*(curip_bound-cut->rhs)/dtmp);
01821 fprintf(stderr,"\t\tdiff %.6lg (%.3lg%%)\n ",curip_bound-cut->rhs,
01822 100*(curip_bound-cut->rhs)/dtmp);
01823 break;
01824 case CPXMIP_INFEASIBLE:
01825 break;
01826 case CPXMIP_INForUNBD:
01827 break;
01828 case CPXMIP_UNBOUNDED:
01829 break;
01830 case CPXMIP_OPTIMAL_INFEAS:
01831 WARNING(1,"Optimal with unscaled infeasibilites");
01832 break;
01833 default:
01834 rval = 1;
01835 MESSAGE(0, "Unexpected status %d for node_ip", curip_stat);
01836 goto CLEANUP;
01837 }
01838
01839 rval = CPXcloseCPLEX(&env);
01840 MTcplexCHECKRVALG(env,rval,CLEANUP);
01841 CLEANUP:
01842 EGfree(obj);
01843 MESSAGE(MT_VERB_LVL+3,"Done, with status %d",rval);
01844 return rval;
01845 }
01846
01847 #define __MT_NS_LVL 0
01848 int MTnode_solve( CPXCENVptr env,
01849 void*cbdata,
01850 int wherefrom,
01851 void*cbhandle,
01852 int*useraction_p)
01853 {
01854 MTns_ccbk_t*const ns_data = (MTns_ccbk_t*)cbhandle;
01855 int nfixed=0, prevfixed=0, loop=0, ncols=0,nrows=0, rval=0, i=0, objsen=0,
01856 nextcol=INT_MAX, *rstat=0, *cstat=0, *cind=0, lp_stat=-1, stat0=-1, nz=0,
01857 surplus=0, matbeg=0, *matind=0;
01858 char*cfix=0, *rfix=0, *sense=0, ctmp='E';
01859 double*dj=0,*pi=0, *oobj=0, *lb=0, *ub=0, *x0=0, *x1=0, dtmp=0, *matval=0,
01860 llim=0, ulim=0;
01861 CPXLPptr lp = 0;
01862
01863 *useraction_p = CPX_CALLBACK_DEFAULT;
01864 ns_data->ncalls++;
01865
01866 rval = CPXgetcallbacknodelp(env,cbdata,wherefrom,&lp);
01867 MTcplexCHECKRVALG(env,rval,CLEANUP);
01868 ncols = CPXgetnumcols(env,lp);
01869 nrows = CPXgetnumrows(env,lp);
01870 objsen = CPXgetobjsen(env,lp);
01871 if(objsen == CPX_MAX) objsen = 1;
01872 else objsen = -1;
01873 MESSAGE(MT_VERB_LVL-__MT_NS_LVL,"Entering, ncols %d, nrows %d, sense %d",
01874 ncols, nrows, objsen);
01875 MTns_ccbk_rsz(ns_data,ncols,nrows);
01876 rval = CPXgetdblparam(env, CPX_PARAM_OBJLLIM, &llim);
01877 MTcplexCHECKRVALG(env,rval,CLEANUP);
01878 rval = CPXgetdblparam(env, CPX_PARAM_OBJULIM, &ulim);
01879 MTcplexCHECKRVALG(env,rval,CLEANUP);
01880 rval = CPXsetdblparam(env, CPX_PARAM_OBJLLIM, -DBL_MAX);
01881 MTcplexCHECKRVALG(env,rval,CLEANUP);
01882 rval = CPXsetdblparam(env, CPX_PARAM_OBJULIM, DBL_MAX);
01883 MTcplexCHECKRVALG(env,rval,CLEANUP);
01884 cfix = ns_data->cfix;
01885 rfix = ns_data->rfix;
01886 memset(cfix,'F',sizeof(char)*((size_t)ncols));
01887 memset(rfix,'F',sizeof(char)*((size_t)nrows));
01888 dj = ns_data->dj;
01889 pi = ns_data->pi;
01890 lb = ns_data->lb;
01891 ub = ns_data->ub;
01892 x0 = ns_data->x0;
01893 x1 = ns_data->x1;
01894 matind = ns_data->matind;
01895 matval = ns_data->matval;
01896 memset(x0,0,sizeof(double)*((size_t)ncols));
01897 memset(x1,0,sizeof(double)*((size_t)ncols));
01898 sense = ns_data->sense;
01899 oobj = ns_data->oobj;
01900 rstat = ns_data->rstat;
01901 cstat = ns_data->cstat;
01902 nfixed = EGmax(ncols,nrows);
01903 cind = EGsMalloc(int,nfixed);
01904 for( i = nfixed ; i-- ; ) cind[i] = i;
01905 rval = CPXgetobj(env, lp, oobj, 0, ncols-1);
01906 MTcplexCHECKRVALG(env,rval,CLEANUP);
01907 rval = CPXgetub(env, lp, ub, 0, ncols-1);
01908 MTcplexCHECKRVALG(env,rval,CLEANUP);
01909 rval = CPXgetlb(env, lp, lb, 0, ncols-1);
01910 MTcplexCHECKRVALG(env,rval,CLEANUP);
01911 rval = CPXgetsense(env, lp, sense, 0, nrows-1);
01912 MTcplexCHECKRVALG(env,rval,CLEANUP);
01913
01914 do
01915 {
01916
01917 rval = CPXdualopt(env,lp);
01918 MTcplexCHECKRVALG(env,rval,CLEANUP);
01919 lp_stat = CPXgetstat(env, lp);
01920 MESSAGE(MT_VERB_LVL-__MT_NS_LVL,"Optimizing... lp_stat %d",lp_stat);
01921 rval = CPXgetbase(env, lp, cstat, rstat);
01922 MTcplexCHECKRVALG(env,rval,CLEANUP);
01923
01924 if(loop==0)
01925 {
01926 stat0 = lp_stat;
01927 if(stat0 != CPX_STAT_OPTIMAL) break;
01928 rval = CPXgetx(env,lp,x0,0,ncols-1);
01929 MTcplexCHECKRVALG(env,rval,CLEANUP);
01930 }
01931
01932 TESTG((rval=(lp_stat!= CPX_STAT_OPTIMAL)), CLEANUP, "Must handle this case!");
01933
01934 rval = CPXgetdj(env,lp,dj,0,ncols-1);
01935 MTcplexCHECKRVALG(env,rval,CLEANUP);
01936 rval = CPXgetpi(env,lp,pi,0,nrows-1);
01937 MTcplexCHECKRVALG(env,rval,CLEANUP);
01938 rval = CPXgetx(env,lp,x1,0,ncols-1);
01939 MTcplexCHECKRVALG(env,rval,CLEANUP);
01940
01941 nfixed = 0;
01942 SOFT_REDO:
01943 loop++;
01944 nextcol = INT_MAX;
01945
01946 for( i = ncols ; i-- ; )
01947 {
01948 if(cfix[i] != 'F') continue;
01949 switch(cstat[i])
01950 {
01951 case CPX_AT_LOWER:
01952 if(dj[i]*objsen < -MT_ZERO_TOL)
01953 {
01954 nfixed++;
01955 cfix[i] = 'L';
01956 ctmp = 'U';
01957 rval = CPXchgbds(env, lp, 1, &i, &ctmp, lb+i);
01958 MTcplexCHECKRVALG(env,rval,CLEANUP);
01959 MESSAGE(MT_VERB_LVL-__MT_NS_LVL,"Fixing %d to %.4lf",i,lb[i]);
01960 }
01961 else
01962 {
01963 nextcol = EGmin(i, nextcol);
01964 MESSAGE(MT_VERB_LVL-__MT_NS_LVL,"Nextcol %d rd = %.7lg L",i,dj[i]);
01965 }
01966 break;
01967 case CPX_AT_UPPER:
01968 if(dj[i]*objsen > MT_ZERO_TOL)
01969 {
01970 nfixed++;
01971 cfix[i] = 'U';
01972 ctmp = 'L';
01973 rval = CPXchgbds(env, lp, 1, &i, &ctmp, ub+i);
01974 MTcplexCHECKRVALG(env,rval,CLEANUP);
01975 MESSAGE(MT_VERB_LVL-__MT_NS_LVL,"Fixing %d to %.4lf",i,ub[i]);
01976 }
01977 else
01978 {
01979 nextcol = EGmin(i, nextcol);
01980 MESSAGE(MT_VERB_LVL-__MT_NS_LVL,"Nextcol %d rd = %.7lg U",i,dj[i]);
01981 }
01982 break;
01983 case CPX_FREE_SUPER:
01984 nfixed++;
01985 cfix[i] = 'S';
01986 break;
01987 case CPX_BASIC:
01988 break;
01989 default:
01990 TESTG((rval=1),CLEANUP,"Imposible!");
01991 break;
01992 }
01993 }
01994
01995 for( i = nrows ; i-- ; )
01996 {
01997 if(rfix[i] != 'F') continue;
01998 switch(rstat[i])
01999 {
02000 case CPX_AT_LOWER:
02001 if(fabs(pi[i]) > MT_ZERO_TOL)
02002 {
02003 rfix[i] = 'L';
02004 nfixed++;
02005 ctmp = 'E';
02006 rval = CPXchgsense(env, lp, 1, &i, &ctmp);
02007 MESSAGE(MT_VERB_LVL-__MT_NS_LVL,"Fixing row %d to equality",i);
02008 MTcplexCHECKRVALG(env,rval,CLEANUP);
02009 }
02010 else
02011 {
02012 nextcol = EGmin(nextcol, i+ncols);
02013 MESSAGE(MT_VERB_LVL-__MT_NS_LVL,"Nextcol %d (row) pi %.7lg",i,pi[i]);
02014 }
02015 break;
02016 case CPX_BASIC:
02017 break;
02018 default:
02019 TESTG((rval=1),CLEANUP,"Imposible! slack variable with upper bound!");
02020 break;
02021 }
02022 }
02023
02024 if(prevfixed == 0)
02025 {
02026 if(ncols > nfixed)
02027 ns_data->nzrd += ((size_t)(ncols - nfixed));
02028 }
02029 prevfixed += nfixed;
02030 if(prevfixed == ncols)
02031 {
02032 MESSAGE(MT_VERB_LVL-__MT_NS_LVL, "Nothing to do!, nextcol %d, prevfixed"
02033 " %d, ncols %d", nextcol, prevfixed, ncols);
02034 break;
02035 }
02036 TESTG((rval=(nextcol >= ncols+nrows)), CLEANUP, "Imposible! ncols %d "
02037 "nrows %d prevfixed %d loop %d nextcol %d", ncols, nrows, prevfixed,
02038 loop, nextcol);
02039 MESSAGE(MT_VERB_LVL-__MT_NS_LVL, "Nextcol %d (%c), loop %d, to fix %d",
02040 nextcol, (nextcol < ncols) ? ((cstat[nextcol]== CPX_AT_LOWER) ?
02041 'L': 'U'): 'R', loop, ncols - prevfixed);
02042
02043
02044 if(nextcol < ncols)
02045 {
02046
02047 if(cstat[nextcol] == CPX_AT_UPPER)
02048 {
02049 ctmp = 'L';
02050 rval = CPXchgbds(env, lp, 1, &nextcol, &ctmp, ub+nextcol);
02051 MTcplexCHECKRVALG(env,rval,CLEANUP);
02052 cfix[nextcol] = 'U';
02053 nfixed=1;
02054 MESSAGE(MT_VERB_LVL-__MT_NS_LVL,"Soft redo");
02055 MESSAGE(MT_VERB_LVL-__MT_NS_LVL,"Fixing %d to %.4lf",nextcol,ub[nextcol]);
02056 goto SOFT_REDO;
02057 }
02058
02059
02060 else if( fabs(ub[nextcol] - lb[nextcol]) < MT_ZERO_TOL)
02061 {
02062 cfix[nextcol] = 'L';
02063 nfixed = 1;
02064 MESSAGE(MT_VERB_LVL-__MT_NS_LVL,"Soft redo");
02065 MESSAGE(MT_VERB_LVL-__MT_NS_LVL,"Fixing %d to %.4lf",nextcol,lb[nextcol]);
02066 goto SOFT_REDO;
02067 }
02068
02069 else
02070 {
02071 memset(dj,0,sizeof(double)*((size_t)ncols));
02072 dj[nextcol] = 1.0*objsen;
02073 rval = CPXchgobj(env, lp, ncols, cind, dj);
02074 MTcplexCHECKRVALG(env,rval,CLEANUP);
02075 MESSAGE(MT_VERB_LVL-__MT_NS_LVL,"Hard redo, prevfixed %d ncols %d",
02076 prevfixed, ncols);
02077 }
02078 }
02079
02080 else
02081 {
02082 nextcol -= ncols;
02083
02084 if(sense[nextcol] == 'E' || sense[nextcol] == 'e')
02085 {
02086 rfix[nextcol] = 'L';
02087 nfixed = 1;
02088 ctmp = 'E';
02089 rval = CPXchgsense(env, lp, 1, &nextcol, &ctmp);
02090 MTcplexCHECKRVALG(env,rval,CLEANUP);
02091 MESSAGE(MT_VERB_LVL-__MT_NS_LVL,"Soft redo");
02092 MESSAGE(MT_VERB_LVL-__MT_NS_LVL,"Fixing row %d to equality",nextcol);
02093 goto SOFT_REDO;
02094 }
02095
02096 rval = CPXgetrows(env, lp, &nz, &matbeg, matind, matval, ncols, &surplus,
02097 nextcol, nextcol);
02098 MTcplexCHECKRVALG(env,rval,CLEANUP);
02099 if(sense[nextcol] == 'L') surplus = 1;
02100 else surplus = -1;
02101 memset(dj,0,sizeof(double)*((size_t)ncols));
02102 for( i = nz ; i-- ; ) dj[matind[i]] = matval[i]*objsen*surplus;
02103 rval = CPXchgobj(env, lp, ncols, cind, dj);
02104 MTcplexCHECKRVALG(env,rval,CLEANUP);
02105 MESSAGE(MT_VERB_LVL-__MT_NS_LVL,"Hard redo");
02106 }
02107 } while(1);
02108
02109
02110 switch(lp_stat)
02111 {
02112 case CPX_STAT_OPTIMAL:
02113 dtmp = 0;
02114 for( i = ncols ; i-- ; ) dtmp += (x0[i]-x1[i])*(x0[i]-x1[i]);
02115 dtmp = sqrt(dtmp);
02116 ns_data->xdiff += dtmp;
02117 for( i = ncols ; i-- ; )
02118 {
02119 switch(cfix[i])
02120 {
02121 case 'F':
02122 cstat[i] = CPX_BASIC;
02123 break;
02124 case 'L':
02125 cstat[i] = CPX_AT_LOWER;
02126 break;
02127 case 'U':
02128 cstat[i] = CPX_AT_UPPER;
02129 break;
02130 case 'S':
02131 cstat[i] = CPX_FREE_SUPER;
02132 break;
02133 default:
02134 TESTG((rval=1), CLEANUP, "Imposible!");
02135 break;
02136 }
02137 }
02138 for( i = nrows ; i-- ; )
02139 {
02140 switch(rfix[i])
02141 {
02142 case 'L':
02143 rstat[i] = CPX_AT_LOWER;
02144 break;
02145 case 'F':
02146 rstat[i] = CPX_BASIC;
02147 break;
02148 default:
02149 TESTG((rval=1), CLEANUP, "Imposible!");
02150 break;
02151 }
02152 }
02153 rval = CPXcopybase(env, lp, cstat, rstat);
02154 MTcplexCHECKRVALG(env,rval,CLEANUP);
02155 case CPX_STAT_ABORT_OBJ_LIM:
02156 case CPX_STAT_UNBOUNDED:
02157 case CPX_STAT_INFEASIBLE:
02158 break;
02159 default:
02160 CPXgetstatstring(env, lp_stat, __mt_cplex_errbuf);
02161 TESTG((rval=1), CLEANUP, "Unknown LP status %d! LP0 stat %d, %s",
02162 lp_stat,stat0, __mt_cplex_errbuf);
02163 break;
02164 }
02165
02166 rval = CPXchgobj(env, lp, ncols, cind, oobj);
02167 MTcplexCHECKRVALG(env,rval,CLEANUP);
02168 memset(cfix,'B',((size_t)ncols)*sizeof(char));
02169 rval = CPXchgbds(env, lp, ncols, cind, cfix, lb);
02170 MTcplexCHECKRVALG(env,rval,CLEANUP);
02171 memset(cfix,'U',((size_t)ncols)*sizeof(char));
02172 rval = CPXchgbds(env, lp, ncols, cind, cfix, ub);
02173 MTcplexCHECKRVALG(env,rval,CLEANUP);
02174 rval = CPXchgsense(env, lp, nrows, cind, sense);
02175 MTcplexCHECKRVALG(env,rval,CLEANUP);
02176
02177 rval = CPXdualopt(env,lp);
02178 MTcplexCHECKRVALG(env,rval,CLEANUP);
02179 if(MT_DEBUG_LVL <= DEBUG && lp_stat == CPX_STAT_OPTIMAL)
02180 {
02181 rval = CPXgetx(env,lp,x0,0,ncols-1);
02182 MTcplexCHECKRVALG(env,rval,CLEANUP);
02183 for( i = 0 ; i<ncols ; i++ )
02184 {
02185 dtmp = fabs(x0[i]-x1[i]);
02186 TESTG((rval=(dtmp > MT_ZERO_TOL)), CLEANUP, "Imposible!, new solution is"
02187 " different! in column %d x_lex = %.5lf x_new = %.5lf, "
02188 "difference %.7le", i, x1[i], x0[i], dtmp);
02189 }
02190 }
02191
02192 rval = CPXsetdblparam(env, CPX_PARAM_OBJLLIM, llim);
02193 MTcplexCHECKRVALG(env,rval,CLEANUP);
02194 rval = CPXsetdblparam(env, CPX_PARAM_OBJULIM, ulim);
02195 MTcplexCHECKRVALG(env,rval,CLEANUP);
02196 CLEANUP:
02197 MESSAGE((rval ? 0 : MT_VERB_LVL-__MT_NS_LVL),"Done, code %d, loops %d, prevfixed %d, ncols %d"
02198 " LP0_stat %d", rval, loop, prevfixed, ncols, stat0 );
02199 ns_data->loops+=(size_t)loop;
02200 EGfree(cind);
02201 return rval;
02202 }
02203
02204
02205