00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "CoinTime.hpp"
00013 #include "BonChooseVariable.hpp"
00014 #include "CouenneChooseStrong.hpp"
00015 #include "CouenneProblem.hpp"
00016 #include "CouenneObject.hpp"
00017 #include "CouenneBranchingObject.hpp"
00018
00019
00020
00021
00022 using namespace Ipopt;
00023 using namespace Couenne;
00024
00027 bool BranchingFBBT (CouenneProblem *problem,
00028 OsiObject *Object,
00029 OsiSolverInterface *solver);
00030
00033 double distance (const double *p1, const double *p2, int size, double k=2.) {
00034
00035 double
00036 result = 0.,
00037 element;
00038
00039 if (k == 2.)
00040
00041 while (size--) {
00042 element = *p1++ - *p2++;
00043 result += element * element;
00044 }
00045
00046 else
00047
00048 while (size--) {
00049 element = *p1++ - *p2++;
00050 result += pow (element, k);
00051 }
00052
00053 return pow (result, 1. / k);
00054 }
00055
00056
00069 int CouenneChooseStrong::doStrongBranching (OsiSolverInterface *solver,
00070 OsiBranchingInformation *info,
00071 int numberToDo, int returnCriterion) {
00072
00073 #ifdef TRACE_STRONG2
00074 int pv = -1;
00075 if(problem_->doPrint_) {
00076 if(pv > -1) {
00077 printf("doSB: beg: x[%d]: %10.4f lb: %10.4f ub: %10.4f\n",
00078 pv, solver->getColSolution()[pv], solver->getColLower()[pv], solver->getColUpper()[pv]);
00079 printf("doSB: info: x[%d]: %10.4f lb: %10.4f ub: %10.4f\n",
00080 pv, info->solution_[pv], info->lower_[pv], info->upper_[pv]);
00081 printf("doSB: problem: lb: %10.4f ub: %10.4f\n",
00082 problem_->Lb(pv), problem_->Ub(pv));
00083 }
00084 }
00085 #endif
00086
00087 jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING,
00088 "\n-\n------- CCS: trying %d objects:\n", numberToDo);
00089
00090
00091
00092 int numberColumns = solver -> getNumCols ();
00093
00094 solver -> markHotStart ();
00095
00096
00097 const double
00098 *initLower = info -> lower_,
00099 *initUpper = info -> upper_;
00100
00101
00102 double
00103 *saveLower = CoinCopyOfArray (info -> lower_, numberColumns),
00104 *saveUpper = CoinCopyOfArray (info -> upper_, numberColumns),
00105
00106 *Lower0 = NULL,
00107 *Upper0 = NULL,
00108
00109
00110
00111 *unionLower = new double [numberColumns],
00112 *unionUpper = new double [numberColumns],
00113
00114 *lpSol = NULL,
00115 timeStart = CoinCpuTime ();
00116
00117 if (jnlst_ -> ProduceOutput (J_DETAILED, J_BRANCHING)) {
00118 Lower0 = CoinCopyOfArray (info -> lower_, numberColumns);
00119 Upper0 = CoinCopyOfArray (info -> upper_, numberColumns);
00120 }
00121
00122
00123 if (pseudoUpdateLP_)
00124 lpSol = CoinCopyOfArray (info -> solution_, numberColumns);
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 int returnCode = 0, iDo = 0;
00136
00137 for (iDo = 0; iDo < numberToDo; iDo++) {
00138
00139 Bonmin::HotInfo * result = results_ () + iDo;
00140
00141 OsiObject *Object = solver_ -> objects () [result -> whichObject ()];
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 OsiBranchingObject * branch = result -> branchingObject ();
00154 assert (branch->numberBranches()==2);
00155
00156 CouenneBranchingObject *cb = dynamic_cast <CouenneBranchingObject *> (branch);
00157
00158 if (cb) cb -> setSimulate (true);
00159
00160 int
00161 status0 = -1,
00162 status1 = -1;
00163
00165
00166
00167
00168
00169
00170 bool isInf0 = false;
00171 bool isInf1 = false;
00172
00173 double indUb = 0, indLb = 0;
00174 CouenneObject *CouObj = dynamic_cast <CouenneObject *> (Object);
00175 OsiSimpleInteger *simpl = dynamic_cast <OsiSimpleInteger *>(solver_->objects()[result->whichObject ()]);
00176
00177
00178
00179
00180 int objVarIndex = -1;
00181 if(CouObj) {
00182 objVarIndex = CouObj->Reference()->Index();
00183 }
00184 else {
00185 objVarIndex = Object->columnNumber();
00186 }
00187 if(simpl) {
00188 if(objVarIndex >= 0) {
00189 indUb = solver->getColUpper()[objVarIndex];
00190 indLb = solver->getColLower()[objVarIndex];
00191 if(info->solution_[objVarIndex] < indLb) {
00192 isInf0 = true;
00193 }
00194 if(info->solution_[objVarIndex] > indUb) {
00195 isInf1 = true;
00196 }
00197 }
00198 }
00199
00200
00201 status0 = simulateBranch (Object, info, branch, solver, result, -1);
00202
00203 if(isInf0) {
00204 status0 = 1;
00205 result->setDownStatus(1);
00206 }
00207
00208
00209
00210
00211 CoinCopyN (solver->getColLower(), numberColumns, unionLower);
00212 CoinCopyN (solver->getColUpper(), numberColumns, unionUpper);
00213
00214
00215 for (int j=0; j<numberColumns; j++) {
00216 if(problem_->Lb(j) > unionLower[j]) {
00217 unionLower[j] = problem_->Lb(j);
00218 }
00219 if(problem_->Ub(j) < unionLower[j]) {
00220 unionLower[j] = problem_->Ub(j);
00221 }
00222
00223 solver->setColLower(j, saveLower [j]);
00224 solver->setColUpper (j, saveUpper [j]);
00225 problem_ -> Lb (j) = saveLower [j];
00226 problem_ -> Ub (j) = saveUpper [j];
00227 }
00228
00229
00230
00231 status1 = simulateBranch (Object, info, branch, solver, result, +1);
00232
00233 if(isInf1) {
00234 status1 = 1;
00235 result->setUpStatus(1);
00236 }
00237
00238 #ifdef TRACE_STRONG
00239 if(problem_->doPrint_) {
00240 printf("Strong on object %d: status0: %d status1: %d\n",
00241 result->whichObject(), status0, status1);
00242 }
00243 #endif
00244
00246
00247 jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING, "-------\n");
00248
00249 if (cb)
00250 cb -> setSimulate (false);
00251
00253
00254 bool tightened = false;
00255
00256 t_chg_bounds *chg_bds = new t_chg_bounds [numberColumns];
00257
00258 const double *sLb = solver->getColLower();
00259 const double *sUb = solver->getColUpper();
00260
00261 if(status1 != 1) {
00262 if(status0 != 1) {
00263 for (int j=0; j<numberColumns; j++) {
00264 double maxLb = (problem_->Lb(j) < sLb[j] ? sLb[j] : problem_->Lb(j));
00265 double minUb = (problem_->Ub(j) < sUb[j] ? problem_->Ub(j) : sUb[j]);
00266 problem_->Lb(j) = (unionLower[j] > maxLb ? maxLb : unionLower [j]);
00267 problem_->Ub(j) = (unionUpper[j] < minUb ? minUb : unionUpper [j]);
00268 }
00269 }
00270 else {
00271 for (int j=0; j<numberColumns; j++) {
00272 problem_->Lb(j) = (problem_->Lb(j) < sLb[j] ? sLb[j] : problem_->Lb(j));
00273 problem_->Ub(j) = (problem_->Ub(j) < sUb[j] ? problem_->Ub(j) : sUb[j]);
00274 }
00275 }
00276 }
00277 else {
00278 if(status0 != 1) {
00279
00280 for (int j=0; j<numberColumns; j++) {
00281 problem_->Lb (j) = unionLower [j];
00282 problem_->Ub (j) = unionUpper [j];
00283 }
00284 }
00285 }
00286
00287 if((status0 == 1) && (status1 == 1)) {
00288 tightened = false;
00289
00290
00291
00292 double lbVar0 = solver->getColLower()[0];
00293 if(lbVar0 < 1) {
00294 solver->setColLower(0, 1);
00295 solver->setColUpper(0, 0);
00296 }
00297 else {
00298 solver->setColUpper(0, lbVar0-1);
00299 }
00300 }
00301 else {
00302 for (int j=0; j<numberColumns; j++) {
00303 if (problem_ -> Lb (j) > initLower [j] + COUENNE_EPS) {
00304 chg_bds [j].setLower (t_chg_bounds::CHANGED);
00305 tightened = true;
00306 }
00307
00308 if (problem_ -> Ub (j) < initUpper [j] - COUENNE_EPS) {
00309 chg_bds [j].setUpper (t_chg_bounds::CHANGED);
00310 tightened = true;
00311 }
00312 }
00313 }
00314 if (tightened &&
00315 (problem_ -> doFBBT ()) &&
00316 !(problem_ -> btCore (chg_bds)))
00317
00318 status0 = status1 = 1;
00319
00320 delete [] chg_bds;
00321
00322 if ((status0 != 1) || (status1 != 1)) {
00323
00324
00325
00326 for (int j=0; j<numberColumns; j++) {
00327 solver -> setColLower (j, saveLower [j] = problem_ -> Lb (j));
00328 solver -> setColUpper (j, saveUpper [j] = problem_ -> Ub (j));
00329 }
00330 }
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 if (status0 == 1 &&
00348 status1 == 1) {
00349 returnCode=-1;
00350 break;
00351 } else if (status0==1 || status1==1) {
00352
00353 #ifdef COIN_HAS_NTY
00354 if (problem_ -> orbitalBranching () &&
00355 (Object -> columnNumber () >= 0) &&
00356 (problem_ -> Find_Orbit (Object -> columnNumber ()) -> size () > 1)) {
00357
00358 problem_ -> ChangeBounds (solver -> getColLower (),
00359 solver -> getColUpper (),
00360 problem_ -> nVars ());
00361
00362 problem_ -> Compute_Symmetry ();
00363 }
00364 #endif
00365
00366 numberStrongFixed_++;
00367 if (!returnCriterion) {
00368 returnCode=1;
00369 } else {
00370 returnCode=2;
00371 break;
00372 }
00373 }
00374
00375 bool hitMaxTime = ( CoinCpuTime()-timeStart > info->timeRemaining_);
00376 if (hitMaxTime) {
00377 returnCode=3;
00378 break;
00379 }
00380 }
00381
00382 if (jnlst_ -> ProduceOutput (J_DETAILED, J_BRANCHING)) {
00383 printf ("strong branching: tightened bounds. ");
00384
00385 for (int j=0; j<numberColumns; j++) {
00386
00387 if (problem_ -> Lb (j) > Lower0 [j]) printf ("l%d (%g-->%g) ", j,Lower0[j], problem_->Lb (j));
00388 if (problem_ -> Ub (j) < Upper0 [j]) printf ("u%d (%g-->%g) ", j,Upper0[j], problem_->Ub (j));
00389 }
00390
00391 delete [] Lower0;
00392 delete [] Upper0;
00393 }
00394
00395
00396
00397 delete [] lpSol;
00398
00399 jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING, "----------------------done\n\n\n");
00400
00401 #ifdef TRACE_STRONG2
00402 if(problem_->doPrint_) {
00403 if(pv > -1) {
00404 printf("doSB: beg: x[%d]: %10.4f lb: %10.4f ub: %10.4f\n",
00405 pv, solver->getColSolution()[pv], solver->getColLower()[pv], solver->getColUpper()[pv]);
00406 printf("doSB: info: x[%d]: %10.4f lb: %10.4f ub: %10.4f\n",
00407 pv, info->solution_[pv], info->lower_[pv], info->upper_[pv]);
00408 printf("doSB: problem: lb: %10.4f ub: %10.4f\n",
00409 problem_->Lb(pv), problem_->Ub(pv));
00410 }
00411 }
00412 #endif
00413
00414 if (iDo < numberToDo) iDo++;
00415 assert (iDo <= (int) results_.size());
00416 results_.resize (iDo);
00417
00418 delete [] unionLower;
00419 delete [] unionUpper;
00420
00421 delete [] saveLower;
00422 delete [] saveUpper;
00423
00424 solver -> unmarkHotStart ();
00425
00426
00427 branchtime_ += CoinCpuTime () - timeStart;
00428
00429 jnlst_ -> Printf (J_DETAILED, J_BRANCHING, "Done doStrongBranching\n");
00430
00431 return returnCode;
00432 }
00433
00434
00435
00436 int CouenneChooseStrong::simulateBranch (OsiObject *Object,
00437 OsiBranchingInformation *info,
00438 OsiBranchingObject *branch,
00439 OsiSolverInterface *solver,
00440 Bonmin::HotInfo * result,
00441 int direction) {
00442
00443 bool boundBranch = branch -> boundBranch ();
00444
00445 int status = -1;
00446
00447
00448
00449 OsiSolverInterface *thisSolver =
00450 boundBranch ? solver : solver -> clone ();
00451
00452 CouenneObject *CouObj = dynamic_cast <CouenneObject *> (Object);
00453
00454 if ((branch -> branch (thisSolver) > COUENNE_INFINITY) ||
00455
00456
00457 (!CouObj && !BranchingFBBT (problem_, Object, thisSolver))) {
00458
00459 status = 1;
00460
00461 if (direction < 0) result -> setDownStatus (1);
00462 else result -> setUpStatus (1);
00463
00464 } else {
00465
00466 if (boundBranch)
00467
00468 thisSolver -> solveFromHotStart ();
00469
00470 else {
00471
00472 int limit;
00473 thisSolver -> getIntParam (OsiMaxNumIterationHotStart, limit);
00474 thisSolver -> setIntParam (OsiMaxNumIteration, limit);
00475
00476 thisSolver -> resolve ();
00477
00478 CouObj -> setEstimate (COUENNE_EPS, direction < 0 ? 0 : 1);
00479 }
00480
00481 if (pseudoUpdateLP_ && CouObj && thisSolver -> isProvenOptimal ()) {
00482 CouNumber dist = distance (info -> solution_, thisSolver -> getColSolution (),
00483 problem_ -> nVars ());
00484
00485 if (dist > COUENNE_EPS)
00486 CouObj -> setEstimate (dist, direction < 0 ? 0 : 1);
00487 }
00488 }
00489
00490
00491
00492
00493
00494 if (status < 0)
00495 status = result -> updateInformation (thisSolver, info, this);
00496
00497 numberStrongIterations_ += thisSolver -> getIterationCount ();
00498
00499 if ((status == 3) && (trustStrongForSolution_)) {
00500
00501 info -> cutoff_ = goodObjectiveValue_;
00502
00503 status = 0;
00504 }
00505
00506 if (solver != thisSolver)
00507 delete thisSolver;
00508
00509 return status;
00510 }
00511
00514 bool BranchingFBBT (CouenneProblem *problem,
00515 OsiObject *Object,
00516 OsiSolverInterface *solver) {
00517
00518 bool feasible = true;
00519
00520 if (problem -> doFBBT ()) {
00521
00522 problem -> domain () -> push (solver);
00523
00524 int
00525 indVar = Object -> columnNumber (),
00526 nvars = problem -> nVars ();
00527
00528
00529
00530 if (indVar >= 0) {
00531
00532
00533
00534 t_chg_bounds *chg_bds = new t_chg_bounds [nvars];
00535 chg_bds [indVar].setUpper (t_chg_bounds::CHANGED);
00536 chg_bds [indVar].setLower (t_chg_bounds::CHANGED);
00537
00538 problem -> installCutOff ();
00539
00540 if ((feasible = problem -> btCore (chg_bds))) {
00541
00542 const double
00543 *lb = solver -> getColLower (),
00544 *ub = solver -> getColUpper (),
00545 *nLB = problem -> Lb (),
00546 *nUB = problem -> Ub ();
00547
00548 for (int i=0; i<nvars; i++) {
00549 if (nLB [i] > lb [i]) solver -> setColLower (i, nLB [i]);
00550 if (nUB [i] < ub [i]) solver -> setColUpper (i, nUB [i]);
00551 }
00552 }
00553
00554 delete [] chg_bds;
00555 }
00556
00557 problem -> domain () -> pop ();
00558 }
00559
00560 return feasible;
00561 }