00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "BonAuxInfos.hpp"
00012 #include "CglCutGenerator.hpp"
00013
00014 #include "CouenneCutGenerator.hpp"
00015 #include "CouenneProblem.hpp"
00016
00017 #define Couenne_large_bound2 9.99e12
00018
00019
00020 bool isOptimumCut (const CouNumber *opt, OsiCuts &cs, CouenneProblem *p);
00021
00022
00023
00024 void fictitiousBound (OsiCuts &cs,
00025 CouenneProblem *p,
00026 bool action) {
00027
00028
00029 const CouNumber large_tol = (Couenne_large_bound2 / 1e6);
00030
00031
00032
00033 int ind_obj = p -> Obj (0) -> Body () -> Index ();
00034
00035 if (ind_obj < 0) return;
00036
00037
00038
00039
00040
00041 if (action)
00042
00043 {if (p -> Lb (ind_obj) < - Couenne_large_bound2) p -> Lb (ind_obj) = - Couenne_large_bound2;}
00044
00045 else
00046
00047
00048 {if (fabs (p->Lb(ind_obj)+Couenne_large_bound2)<large_tol) p->Lb(ind_obj) =-COUENNE_INFINITY;}
00049 }
00050
00051
00052
00053 void sparse2dense (int ncols, t_chg_bounds *chg_bds, int *&changed, int &nchanged) {
00054
00055
00056
00057 changed = (int *) realloc (changed, ncols * sizeof (int));
00058 nchanged = 0;
00059
00060 for (register int i=ncols, j=0; i--; j++, chg_bds++)
00061 if (chg_bds -> lower() != t_chg_bounds::UNCHANGED ||
00062 chg_bds -> upper() != t_chg_bounds::UNCHANGED ) {
00063 *changed++ = j;
00064 nchanged++;
00065 }
00066
00067 changed -= nchanged;
00068
00069 }
00070
00071
00073 void updateBranchInfo (const OsiSolverInterface &si, CouenneProblem *p,
00074 t_chg_bounds *chg, const CglTreeInfo &info);
00075
00077
00078 void CouenneCutGenerator::generateCuts (const OsiSolverInterface &si,
00079 OsiCuts &cs,
00080 const CglTreeInfo info) const {
00081 const int infeasible = 1;
00082
00083 int nInitCuts = cs.sizeRowCuts ();
00084
00085 CouNumber
00086 *&realOpt = problem_ -> bestSol (),
00087 *saveOptimum = realOpt;
00088
00089 if (!firstcall_ && realOpt) {
00090
00091
00092
00093
00094 CouNumber *opt = realOpt;
00095
00096 const CouNumber
00097 *sol = si.getColSolution (),
00098 *lb = si.getColLower (),
00099 *ub = si.getColUpper ();
00100
00101 int objind = problem_ -> Obj (0) -> Body () -> Index ();
00102
00103 for (int j=0, i=problem_ -> nVars (); i--; j++, opt++, lb++, ub++)
00104 if ((j != objind) &&
00105 ((*opt < *lb - COUENNE_EPS * (1 + CoinMin (fabs (*opt), fabs (*lb)))) ||
00106 (*opt > *ub + COUENNE_EPS * (1 + CoinMin (fabs (*opt), fabs (*ub)))))) {
00107
00108 jnlst_ -> Printf (J_VECTOR, J_CONVEXIFYING,
00109 "out of bounds, ignore x%d = %g [%g,%g] opt = %g\n",
00110 problem_ -> nVars () - i - 1, *sol, *lb, *ub, *opt);
00111
00112
00113
00114 realOpt = NULL;
00115 break;
00116 }
00117 }
00118
00119
00120
00121
00122
00123
00124
00125 jnlst_ -> Printf (J_DETAILED, J_CONVEXIFYING,
00126 "generateCuts: level = %d, pass = %d, intree = %d\n",
00127 info.level, info.pass, info.inTree);
00128
00129 Bonmin::BabInfo * babInfo = dynamic_cast <Bonmin::BabInfo *> (si.getAuxiliaryInfo ());
00130
00131 if (babInfo)
00132 babInfo -> setFeasibleNode ();
00133
00134 double now = CoinCpuTime ();
00135 int ncols = problem_ -> nVars ();
00136
00137
00138
00139
00140
00141 t_chg_bounds *chg_bds = new t_chg_bounds [ncols];
00142
00143
00144
00145
00146
00147
00148
00149 problem_ -> installCutOff ();
00150
00151 if (firstcall_) {
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 for (int i=0; i < ncols; i++)
00162 if (problem_ -> Var (i) -> Multiplicity () > 0) {
00163 chg_bds [i].setLower (t_chg_bounds::CHANGED);
00164 chg_bds [i].setUpper (t_chg_bounds::CHANGED);
00165 }
00166
00167
00168
00169 if (problem_ -> doFBBT () &&
00170 (! (problem_ -> boundTightening (chg_bds, babInfo))))
00171 jnlst_ -> Printf (J_STRONGWARNING, J_CONVEXIFYING,
00172 "Couenne: WARNING, first convexification is infeasible\n");
00173
00174
00175
00176
00177
00178 int nnlc = problem_ -> nCons ();
00179
00180 for (int i=0; i<nnlc; i++) {
00181
00182
00183 CouenneConstraint *con = problem_ -> Con (i);
00184
00185
00186 int index = con -> Body () -> Index ();
00187
00188 if ((index >= 0) &&
00189 ((con -> Body () -> Type () == AUX) ||
00190 (con -> Body () -> Type () == VAR))) {
00191
00192
00193 exprVar *conaux = problem_ -> Var (index);
00194
00195 if (conaux &&
00196 (conaux -> Type () == AUX) &&
00197 (conaux -> Image ()) &&
00198 (conaux -> Image () -> Linearity () <= LINEAR)) {
00199
00200
00201
00202
00203 double
00204 lb = (*(con -> Lb ())) (),
00205 ub = (*(con -> Ub ())) ();
00206
00207 OsiColCut newBound;
00208 if (lb > -COUENNE_INFINITY) newBound.setLbs (1, &index, &lb);
00209 if (ub < COUENNE_INFINITY) newBound.setUbs (1, &index, &ub);
00210
00211 cs.insert (newBound);
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 } else {
00245
00246
00247 assert (false);
00248 }
00249 }
00250
00251 if (jnlst_ -> ProduceOutput (J_ITERSUMMARY, J_CONVEXIFYING)) {
00252 if (cs.sizeRowCuts ()) {
00253 jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,"Couenne: %d constraint row cuts\n",
00254 cs.sizeRowCuts ());
00255 for (int i=0; i<cs.sizeRowCuts (); i++)
00256 cs.rowCutPtr (i) -> print ();
00257 }
00258 if (cs.sizeColCuts ()) {
00259 jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,"Couenne: %d constraint col cuts\n",
00260 cs.sizeColCuts ());
00261 for (int i=0; i<cs.sizeColCuts (); i++)
00262 cs.colCutPtr (i) -> print ();
00263 }
00264 }
00265 } else {
00266
00267
00268 int indobj = problem_ -> Obj (0) -> Body () -> Index ();
00269
00270 assert (indobj >= 0);
00271
00272
00273 problem_ -> domain () -> push
00274 (problem_ -> nVars (),
00275 si. getColSolution (),
00276 si. getColLower (),
00277 si. getColUpper ());
00278
00279 if (indobj >= 0) {
00280
00281
00282
00283 double lp_bound = problem_ -> domain () -> x (indobj);
00284
00285
00286 {if (lp_bound > problem_ -> Lb (indobj)) problem_ -> Lb (indobj) = lp_bound;}
00287
00288 }
00289
00290 updateBranchInfo (si, problem_, chg_bds, info);
00291 }
00292
00293
00294 for (int i = problem_ -> nCons (); i--;) {
00295
00296
00297 CouenneConstraint *con = problem_ -> Con (i);
00298
00299
00300 int index = con -> Body () -> Index ();
00301
00302 if ((index >= 0) &&
00303 ((con -> Body () -> Type () == AUX) ||
00304 (con -> Body () -> Type () == VAR))) {
00305
00306
00307 CouNumber l = con -> Lb () -> Value (),
00308 u = con -> Ub () -> Value ();
00309
00310
00311 problem_ -> Lb (index) = CoinMax (l, problem_ -> Lb (index));
00312 problem_ -> Ub (index) = CoinMin (u, problem_ -> Ub (index));
00313 }
00314 }
00315
00316 problem_ -> installCutOff ();
00317
00318 fictitiousBound (cs, problem_, false);
00319
00320 int *changed = NULL, nchanged;
00321
00322
00323
00324
00325
00326
00327
00328 try {
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340 if (!firstcall_ &&
00341 problem_ -> doRCBT () &&
00342 problem_ -> redCostBT (&si, chg_bds) &&
00343 !(problem_ -> btCore (chg_bds)))
00344 throw infeasible;
00345
00346
00347 if (problem_ -> doFBBT () &&
00348
00349 (! (problem_ -> boundTightening (chg_bds, babInfo))))
00350 throw infeasible;
00351
00352
00353 if (!firstcall_ &&
00354 problem_ -> obbt (this, si, cs, info, babInfo, chg_bds) < 0)
00355 throw infeasible;
00356
00357
00358
00359 if ((problem_ -> doFBBT () ||
00360 problem_ -> doOBBT () ||
00361 problem_ -> doABT ()) &&
00362 (jnlst_ -> ProduceOutput (J_VECTOR, J_CONVEXIFYING))) {
00363
00364 jnlst_ -> Printf(J_VECTOR, J_CONVEXIFYING,"== after bt =============\n");
00365 for (int i = 0; i < problem_ -> nVars (); i++)
00366 if (problem_ -> Var (i) -> Multiplicity () > 0)
00367 jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
00368 problem_ -> X (i), problem_ -> Lb (i), problem_ -> Ub (i));
00369 jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"=============================\n");
00370 }
00371
00372
00373
00374 sparse2dense (ncols, chg_bds, changed, nchanged);
00375
00376 double *nlpSol;
00377
00378
00379
00380 if (babInfo && ((nlpSol = const_cast <double *> (babInfo -> nlpSolution ())))) {
00381
00382
00383
00384 int logAbtLev = problem_ -> logAbtLev ();
00385
00386 if (problem_ -> doABT () &&
00387 ((logAbtLev != 0) ||
00388 (info.level == 0)) &&
00389 (info.pass == 0) &&
00390 ((logAbtLev < 0) ||
00391 (info.level <= logAbtLev) ||
00392 (CoinDrand48 () <
00393 pow (2., (double) logAbtLev - (info.level + 1))))) {
00394
00395 jnlst_ -> Printf(J_ITERSUMMARY, J_CONVEXIFYING," performing ABT\n");
00396 if (! (problem_ -> aggressiveBT (nlp_, chg_bds, babInfo)))
00397 throw infeasible;
00398
00399 sparse2dense (ncols, chg_bds, changed, nchanged);
00400 }
00401
00402
00403
00404
00405
00406
00407
00408
00409 bool save_av = addviolated_;
00410 addviolated_ = false;
00411
00412
00413 problem_ -> domain () -> push
00414 (problem_ -> nVars (),
00415 problem_ -> domain () -> x (),
00416 problem_ -> domain () -> lb (),
00417 problem_ -> domain () -> ub (), false);
00418
00419
00420 CoinCopyN (nlpSol, problem_ -> nOrigVars (), problem_ -> domain () -> x ());
00421
00422
00423 problem_ -> getAuxs (problem_ -> domain () -> x ());
00424
00425 if (jnlst_ -> ProduceOutput (J_VECTOR, J_CONVEXIFYING)) {
00426 jnlst_ -> Printf(J_VECTOR, J_CONVEXIFYING,"== genrowcuts on NLP =============\n");
00427 for (int i = 0; i < problem_ -> nVars (); i++)
00428 if (problem_ -> Var (i) -> Multiplicity () > 0)
00429 jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
00430 problem_ -> X (i),
00431 problem_ -> Lb (i),
00432 problem_ -> Ub (i));
00433 jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"=============================\n");
00434 }
00435
00436 problem_ -> domain () -> current () -> isNlp () = true;
00437 genRowCuts (si, cs, nchanged, changed, chg_bds);
00438
00439 problem_ -> domain () -> pop ();
00440
00441 addviolated_ = save_av;
00442
00443
00444 babInfo -> setHasNlpSolution (false);
00445 } else {
00446
00447 if (jnlst_ -> ProduceOutput (J_VECTOR, J_CONVEXIFYING)) {
00448 jnlst_ -> Printf(J_VECTOR, J_CONVEXIFYING,"== genrowcuts on LP =============\n");
00449 for (int i = 0; i < problem_ -> nVars (); i++)
00450 if (problem_ -> Var (i) -> Multiplicity () > 0)
00451 jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
00452 problem_ -> X (i),
00453 problem_ -> Lb (i),
00454 problem_ -> Ub (i));
00455 jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"=============================\n");
00456 }
00457
00458 genRowCuts (si, cs, nchanged, changed, chg_bds);
00459 }
00460
00461
00462 if (nchanged)
00463 genColCuts (si, cs, nchanged, changed);
00464
00465 if (firstcall_ && (cs.sizeRowCuts () >= 1))
00466 jnlst_->Printf(J_ITERSUMMARY, J_CONVEXIFYING,
00467 "Couenne: %d initial row cuts\n", cs.sizeRowCuts ());
00468
00469 if (realOpt &&
00470 isOptimumCut (realOpt, cs, problem_))
00471 jnlst_->Printf(J_ITERSUMMARY, J_CONVEXIFYING,
00472 "\n\n CUT OPTIMUM\n\n");
00473 }
00474
00475 catch (int exception) {
00476
00477 if ((exception == infeasible) && (!firstcall_)) {
00478
00479 jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,
00480 "Couenne: Infeasible node\n");
00481
00482 OsiColCut *infeascut = new OsiColCut;
00483
00484 if (infeascut) {
00485 int i=0;
00486 double upper = -1., lower = +1.;
00487 infeascut -> setLbs (1, &i, &lower);
00488 infeascut -> setUbs (1, &i, &upper);
00489 cs.insert (infeascut);
00490 delete infeascut;
00491 }
00492 }
00493
00494 if (babInfo)
00495 babInfo -> setInfeasibleNode ();
00496 }
00497
00498 delete [] chg_bds;
00499
00500 if (changed)
00501 free (changed);
00502
00503 if (firstcall_) {
00504
00505 jnlst_ -> Printf (J_SUMMARY, J_CONVEXIFYING,
00506 "Couenne: %d cuts (%d row, %d col) for linearization\n",
00507 cs.sizeRowCuts () + cs.sizeColCuts (),
00508 cs.sizeRowCuts (), cs.sizeColCuts ());
00509
00510 fictitiousBound (cs, problem_, true);
00511 firstcall_ = false;
00512 ntotalcuts_ = nrootcuts_ = cs.sizeRowCuts ();
00513 } else {
00514 problem_ -> domain () -> pop ();
00515
00516 ntotalcuts_ += (cs.sizeRowCuts () - nInitCuts);
00517
00518 if (saveOptimum)
00519 realOpt = saveOptimum;
00520 }
00521
00522 septime_ += CoinCpuTime () - now;
00523
00524 if (jnlst_ -> ProduceOutput (J_ITERSUMMARY, J_CONVEXIFYING)) {
00525
00526 if (cs.sizeColCuts ()) {
00527 jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,"Couenne col cuts:\n");
00528 for (int i=0; i<cs.sizeColCuts (); i++)
00529 cs.colCutPtr (i) -> print ();
00530 }
00531 }
00532
00533 if (!(info.inTree))
00534 rootTime_ = CoinCpuTime ();
00535 }