/home/coin/SVN-release/OS-2.0.0/Couenne/src/branch/doStrongBranching.cpp

Go to the documentation of this file.
00001 /* $Id$
00002  *
00003  * Name:    doStrongBranching.cpp
00004  * Authors: Andreas Waechter, IBM Corp.
00005  *          Pietro Belotti, CMU
00006  * Purpose: actual strong branching method
00007  *
00008  * (C) Carnegie-Mellon University, 2008-09.
00009  * This file is licensed under the Common Public License (CPL)
00010  */
00011 
00012 #include "CoinTime.hpp"
00013 #include "CouenneChooseStrong.hpp"
00014 #include "CouenneProblem.hpp"
00015 #include "CouenneBranchingObject.hpp"
00016 #include "CouenneSolverInterface.hpp"
00017 
00020 double distance (const double *p1, const double *p2, int size, double k=2.) {
00021 
00022   double 
00023     result = 0.,
00024     element;
00025 
00026   if (k == 2.) // a bit faster, probably
00027 
00028     while (size--) {
00029       element = *p1++ - *p2++;
00030       result += element * element;
00031     }
00032 
00033   else
00034 
00035     while (size--) {
00036       element = *p1++ - *p2++;
00037       result += pow (element, k);
00038     }
00039 
00040   return pow (result, 1. / k);
00041 }
00042 
00043 
00044 //namespace Bonmin {
00045 
00058   int CouenneChooseStrong::doStrongBranching (CouenneSolverInterface * solver, 
00059                                               OsiBranchingInformation *info,
00060                                               int numberToDo, int returnCriterion) {
00061 
00062     jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING, 
00063                       "\n-\n------- CCS: trying %d objects:\n", numberToDo);
00064 
00065     solver -> doingResolve () = false; // turns off setCutoff and restoreUnused
00066 
00067     int numberColumns = solver -> getNumCols ();
00068 
00069     solver -> markHotStart (); // save current LP point
00070 
00071     const double
00072       *lower = info -> lower_,
00073       *upper = info -> upper_;
00074 
00075     double 
00076       *saveLower = CoinCopyOfArray (info -> lower_, numberColumns),
00077       *saveUpper = CoinCopyOfArray (info -> upper_, numberColumns),
00078       *Lower0    = CoinCopyOfArray (info -> lower_, numberColumns), // delete afterwards
00079       *Upper0    = CoinCopyOfArray (info -> upper_, numberColumns),
00080       *oldLower  = new double [numberColumns],
00081       *oldUpper  = new double [numberColumns],
00082       *lpSol     = NULL, 
00083        timeStart = CoinCpuTime ();
00084 
00085     // LP solution for distance
00086     if (pseudoUpdateLP_) 
00087       lpSol = CoinCopyOfArray (info -> solution_, numberColumns);
00088 
00089     // provide Couenne problem with point/bounds contained in info
00090     problem_ -> domain () -> push
00091       (problem_ -> nVars (),
00092        info -> solution_,
00093        info -> lower_,
00094        info -> upper_);
00095 
00096     int returnCode = 0, iDo = 0;
00097 
00098     for (;iDo < numberToDo; iDo++) {
00099 
00100       Bonmin::HotInfo * result = results_ () + iDo; // retrieve i-th object to test
00101 
00102       OsiObject     *Object = solver_ -> objects () [result -> whichObject ()];
00103       CouenneObject *CouObj = dynamic_cast <CouenneObject *> (Object);
00104 
00105       // For now just 2 way
00106       OsiBranchingObject * branch = result -> branchingObject ();
00107       assert (branch->numberBranches()==2);
00108 
00109       CouenneBranchingObject *cb = dynamic_cast <CouenneBranchingObject *> (branch);
00110       if (cb) cb -> setSimulate (true);
00111 
00112       /* Try the first direction.  Each subsequent call to branch()
00113          performs the specified branch and advances the branch object
00114          state to the next branch alternative. */
00115 
00116       int 
00117         status0 = -1, 
00118         status1 = -1;
00119 
00120       OsiSolverInterface * thisSolver = solver; 
00121 
00122       // DOWN DIRECTION ///////////////////////////////////////////////////////
00123 
00124       if (branch -> boundBranch ()) { // a (variable) bound branch
00125 
00126         if (branch -> branch (solver) > COUENNE_INFINITY) // branch is infeasible
00127           result -> setDownStatus (status0 = 1);
00128 
00129         else { // branch is feasible, solve and compare
00130 
00131           bool infeasible = false;
00132 
00133           // Bound tightening if not a CouenneObject -- explicit bound tightening
00134           if (!CouObj) {
00135 
00136             int 
00137               indVar = Object   -> columnNumber (),
00138               nvars  = problem_ -> nVars ();
00139 
00140             t_chg_bounds *chg_bds = new t_chg_bounds [nvars];
00141 
00142             chg_bds [indVar].setUpper (t_chg_bounds::CHANGED);
00143 
00144             if (problem_ -> doFBBT ()) {         // problem allowed to do FBBT
00145 
00146               problem_ -> installCutOff ();
00147 
00148               if (!problem_ -> btCore (chg_bds)) // done FBBT and this branch is infeasible
00149                 infeasible = true;        // ==> report it
00150 
00151               else {
00152                 const double
00153                   *lb = solver -> getColLower (),
00154                   *ub = solver -> getColUpper ();
00155 
00156                 for (int i=0; i<nvars; i++) {
00157                   if (problem_ -> Lb (i) > lb [i]) solver -> setColLower (i, problem_ -> Lb (i));
00158                   if (problem_ -> Ub (i) < ub [i]) solver -> setColUpper (i, problem_ -> Ub (i));
00159                 }
00160               }
00161             }
00162 
00163             delete [] chg_bds;
00164           }
00165 
00166           if (infeasible) result -> setDownStatus (status0 = 1);
00167           else {
00168             solver -> solveFromHotStart ();
00169             //solver -> solveFromHotStart ();
00170 
00171             if (pseudoUpdateLP_ && CouObj && solver -> isProvenOptimal ()) {
00172               CouNumber dist = distance (lpSol, solver -> getColSolution (), numberColumns);
00173               if (dist > COUENNE_EPS)
00174                 CouObj -> setEstimate (dist, 0);
00175             }
00176           }
00177         }
00178 
00179       } else {                       // some more complex branch, have to clone solver
00180 
00181         // adding cuts or something 
00182         thisSolver = solver -> clone ();
00183 
00184         if (branch -> branch (thisSolver) > COUENNE_INFINITY)
00185           result -> setDownStatus (status0 = 1);
00186 
00187         else { // set hot start iterations
00188           int limit;
00189           thisSolver -> getIntParam (OsiMaxNumIterationHotStart, limit);
00190           thisSolver -> setIntParam (OsiMaxNumIteration,         limit); 
00191 
00192           thisSolver -> resolve ();
00193           if (pseudoUpdateLP_ && CouObj && thisSolver -> isProvenOptimal ()) {
00194             CouNumber dist = distance (lpSol, thisSolver -> getColSolution (), numberColumns);
00195             if (dist > COUENNE_EPS)
00196               CouObj -> setEstimate (dist, 0);
00197           }
00198         }
00199       }
00200 
00201       // can check if we got solution
00202       // status is 0 finished, 1 infeasible and 2 unfinished and 3 is solution
00203 
00204       /*if (CouObj)
00205         jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING, "dnEst %g upEst %g\n",
00206                           CouObj->downEstimate(),
00207                           CouObj->upEstimate());*/
00208 
00209       // only update information if this branch is feasible
00210       if (status0 < 0)
00211         status0 = result -> updateInformation (thisSolver, info, this);
00212 
00213       numberStrongIterations_ += thisSolver -> getIterationCount();
00214 
00215       if ((status0 == 3) && (trustStrongForSolution_)) {
00216         // new solution already saved
00217         info -> cutoff_ = goodObjectiveValue_;
00218         problem_ -> setCutOff (goodObjectiveValue_);
00219         status0 = 0;
00220       }
00221 
00222       if (solver != thisSolver)
00223         delete thisSolver;
00224 
00225       // save current bounds as tightened by the down branch; will be
00226       // used below to update global bounding box in solver
00227       CoinCopyN (problem_ -> Lb (), numberColumns, oldLower);
00228       CoinCopyN (problem_ -> Ub (), numberColumns, oldUpper);
00229 
00230       // Restore pre-left-branch bounds in solver
00231       for (int j=0; j<numberColumns; j++) {
00232 
00233         if (saveLower [j] != lower [j]) solver -> setColLower (j, saveLower [j]);
00234         if (saveUpper [j] != upper [j]) solver -> setColUpper (j, saveUpper [j]);
00235       }
00236 
00237       // UP DIRECTION ///////////////////////////////////////////////////////
00238 
00239       thisSolver = solver; 
00240 
00241       if (branch -> boundBranch ()) { // (variable) bound branch 
00242 
00243         if (branch -> branch (solver) > COUENNE_INFINITY)
00244           result -> setUpStatus (status1 = 1);
00245 
00246         else {
00247 
00248           bool infeasible = false;
00249 
00250           // Bound tightening if not a CouenneObject -- explicit bound tightening
00251           if (!CouObj) {
00252 
00253             int 
00254               indVar = Object   -> columnNumber (),
00255               nvars  = problem_ -> nVars ();
00256 
00257             t_chg_bounds *chg_bds = new t_chg_bounds [nvars];
00258 
00259             chg_bds [indVar].setLower (t_chg_bounds::CHANGED);
00260 
00261             if (problem_ -> doFBBT ()) {         // problem allowed to do FBBT
00262 
00263               problem_ -> installCutOff ();
00264 
00265               if (!problem_ -> btCore (chg_bds)) // done FBBT and this branch is infeasible
00266                 infeasible = true;        // ==> report it
00267 
00268               else {
00269                 const double
00270                   *lb = solver -> getColLower (),
00271                   *ub = solver -> getColUpper ();
00272 
00273                 for (int i=0; i<nvars; i++) {
00274                   if (problem_ -> Lb (i) > lb [i]) solver -> setColLower (i, problem_ -> Lb (i));
00275                   if (problem_ -> Ub (i) < ub [i]) solver -> setColUpper (i, problem_ -> Ub (i));
00276                 }
00277               }
00278             }
00279 
00280             delete [] chg_bds;
00281           }
00282 
00283           if (infeasible) result -> setUpStatus (status0 = 1);
00284           else {
00285 
00286             solver -> solveFromHotStart ();
00287 
00288             if (pseudoUpdateLP_ && CouObj && solver -> isProvenOptimal ()) {
00289               CouNumber dist = distance (lpSol, solver -> getColSolution (), numberColumns);
00290               if (dist > COUENNE_EPS)
00291                 CouObj -> setEstimate (dist, 1);
00292             }
00293           }
00294         }
00295       } else {                     // some more complex branch, have to clone solver
00296         // adding cuts or something 
00297         thisSolver = solver -> clone ();
00298 
00299         if (branch -> branch (thisSolver) > COUENNE_INFINITY)
00300           result -> setUpStatus (status1 = 1);
00301 
00302         else {
00303           // set hot start iterations
00304           int limit;
00305           thisSolver -> getIntParam (OsiMaxNumIterationHotStart, limit);
00306           thisSolver -> setIntParam (OsiMaxNumIteration,         limit); 
00307 
00308           thisSolver -> resolve();
00309           if (pseudoUpdateLP_ && CouObj && thisSolver -> isProvenOptimal ()) {
00310             CouNumber dist = distance (lpSol, thisSolver -> getColSolution (), numberColumns);
00311             if (dist > COUENNE_EPS)
00312               CouObj -> setEstimate (dist, 1);
00313           }
00314         }
00315       }
00316 
00317       // can check if we got solution
00318       // status is 0 finished, 1 infeasible and 2 unfinished and 3 is solution
00319 
00320       /*if (CouObj)
00321         jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING, "dnEst %g upEst %g\n",
00322                           CouObj->downEstimate(),
00323                           CouObj->upEstimate());*/
00324 
00325       // only update information if this branch is feasible
00326       if (status1 < 0)
00327         status1 = result -> updateInformation (thisSolver, info, this);
00328 
00329       numberStrongDone_++;
00330       numberStrongIterations_ += thisSolver->getIterationCount();
00331 
00332       if ((status1 == 3) && (trustStrongForSolution_)) {
00333         // new solution already saved
00334         info -> cutoff_ = goodObjectiveValue_;
00335         problem_ -> setCutOff (goodObjectiveValue_);
00336         status1 = 0;
00337       }
00338 
00339       jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING, "-------\n");
00340 
00341       if (cb) cb -> setSimulate (false);
00342 
00344 
00345       if (solver != thisSolver)
00346         delete thisSolver;
00347 
00348       bool tightened = false;
00349 
00350       t_chg_bounds *chg_bds = new t_chg_bounds [numberColumns];
00351 
00352       // extend problem_'s bounding box to include downbranch's tightened
00353       for (int j=0; j<numberColumns; j++) {
00354 
00355         if (oldLower [j] < problem_ -> Lb (j)) problem_ -> Lb (j) = oldLower [j];
00356         if (oldUpper [j] > problem_ -> Ub (j)) problem_ -> Ub (j) = oldUpper [j];
00357 
00358         if (problem_ -> Lb (j) > lower [j] + COUENNE_EPS) {
00359           chg_bds [j].setLower (t_chg_bounds::CHANGED);
00360           tightened = true;
00361         }
00362 
00363         if (problem_ -> Ub (j) < upper [j] - COUENNE_EPS) {
00364           chg_bds [j].setUpper (t_chg_bounds::CHANGED);
00365           tightened = true;
00366         }
00367       }
00368 
00369       if (tightened &&                     // have tighter bounds
00370           (problem_ -> doFBBT ()) &&       // selected FBBT
00371           !(problem_ -> btCore (chg_bds))) // tighten again on root
00372 
00373         status0 = status1 = 1;             // if returns false, problem is infeasible
00374 
00375       delete [] chg_bds;
00376 
00377       // create union of bounding box from both branching directions
00378       for (int j=0; j<numberColumns; j++) {
00379 
00380         if (oldLower [j] < problem_ -> Lb (j)) problem_ -> Lb (j) = oldLower [j];
00381         if (oldUpper [j] > problem_ -> Ub (j)) problem_ -> Ub (j) = oldUpper [j];
00382       }
00383 
00384       // set new bounding box as the possibly tightened one (a subset
00385       // of the initial)
00386       for (int j=0; j<numberColumns; j++) {
00387 
00388         solver -> setColLower (j, saveLower [j] = problem_ -> Lb (j));
00389         solver -> setColUpper (j, saveUpper [j] = problem_ -> Ub (j));
00390       }
00391 
00392       /*
00393         End of evaluation for this candidate object. Possibilities are:
00394 
00395         * Both sides below cutoff; this variable is a candidate for
00396           branching.
00397 
00398         * Both sides infeasible or above the objective cutoff: no
00399           further action here. Break from the evaluation loop and
00400           assume the node will be purged by the caller.
00401 
00402         * One side feasible and below cutoff: Install the branch
00403           (i.e., fix the variable). Possibly break from the evaluation
00404           loop and assume the node will be reoptimised by the caller.
00405       */
00406 
00407       if (status0 == 1 && 
00408           status1 == 1) { // infeasible
00409         returnCode=-1;
00410         break; // exit loop
00411       } else if (status0==1 || status1==1) {
00412         numberStrongFixed_++;
00413         if (!returnCriterion) {
00414           returnCode=1;
00415         } else {
00416           returnCode=2;
00417           break;
00418         }
00419       }
00420 
00421       bool hitMaxTime = ( CoinCpuTime()-timeStart > info->timeRemaining_);
00422       if (hitMaxTime) {
00423         returnCode=3;
00424         break;
00425       }
00426     } // end loop /***********************************/
00427   
00428 
00429     if (jnlst_ -> ProduceOutput (J_DETAILED, J_BRANCHING)) {
00430       printf ("tightened bounds: ");
00431       // create union of bounding box from both branching directions
00432       for (int j=0; j<numberColumns; j++) {
00433       
00434         if (problem_ -> Lb (j) > Lower0 [j]) printf ("l%d (%g-->%g) ", j,Lower0[j], problem_->Lb (j));
00435         if (problem_ -> Ub (j) < Upper0 [j]) printf ("u%d (%g-->%g) ", j,Upper0[j], problem_->Ub (j));
00436       }
00437     }
00438 
00439     delete [] Lower0;
00440     delete [] Upper0;
00441 
00442     problem_ -> domain () -> pop (); // discard current point/bounds from problem
00443 
00444     delete [] lpSol;
00445 
00446     jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING, "----------------------done\n\n\n");
00447 
00448     if (iDo < numberToDo) iDo++; // exited due to infeasibility
00449     assert (iDo <= (int) results_.size());
00450     results_.resize (iDo);
00451 
00452     delete [] oldLower;
00453     delete [] oldUpper;
00454 
00455     delete [] saveLower;
00456     delete [] saveUpper;
00457 
00458     solver -> unmarkHotStart ();     // Delete the snapshot
00459 
00460     solver -> doingResolve () = true;
00461 
00462     return returnCode;
00463   }
00464 //}

Generated on Mon Aug 3 03:02:19 2009 by  doxygen 1.4.7