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

Go to the documentation of this file.
00001 /* $Id: doStrongBranching.cpp 260 2009-10-04 14:22:01Z pbelotti $
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 "BonChooseVariable.hpp"
00014 #include "CouenneChooseStrong.hpp"
00015 #include "CouenneProblem.hpp"
00016 #include "CouenneBranchingObject.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 (OsiSolverInterface *solver, 
00059                                               OsiBranchingInformation *info,
00060                                               int numberToDo, int returnCriterion) {
00061 
00062     //CouenneSolverInterface *solver = dynamic_cast <CouenneSolverInterface *> (OsiSolver);
00063     
00064     jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING, 
00065                       "\n-\n------- CCS: trying %d objects:\n", numberToDo);
00066 
00067     //solver -> doingResolve () = false; // turns off setCutoff and restoreUnused
00068 
00069     int numberColumns = solver -> getNumCols ();
00070 
00071     solver -> markHotStart (); // save current LP point
00072 
00073     const double
00074       *lower = info -> lower_,
00075       *upper = info -> upper_;
00076 
00077     double 
00078       *saveLower = CoinCopyOfArray (info -> lower_, numberColumns),
00079       *saveUpper = CoinCopyOfArray (info -> upper_, numberColumns),
00080 
00081       *Lower0 = NULL,
00082       *Upper0 = NULL,
00083 
00084       *oldLower  = new double [numberColumns],
00085       *oldUpper  = new double [numberColumns],
00086 
00087       *lpSol     = NULL, 
00088        timeStart = CoinCpuTime ();
00089 
00090     if (jnlst_ -> ProduceOutput (J_DETAILED, J_BRANCHING)) {
00091       Lower0 = CoinCopyOfArray (info -> lower_, numberColumns); // delete afterwards
00092       Upper0 = CoinCopyOfArray (info -> upper_, numberColumns);
00093     }
00094 
00095     // LP solution for distance
00096     if (pseudoUpdateLP_) 
00097       lpSol = CoinCopyOfArray (info -> solution_, numberColumns);
00098 
00099     // provide Couenne problem with point/bounds contained in info
00100     problem_ -> domain () -> push
00101       (problem_ -> nVars (),
00102        info -> solution_,
00103        info -> lower_,
00104        info -> upper_);
00105 
00106     int returnCode = 0, iDo = 0;
00107 
00108     for (;iDo < numberToDo; iDo++) {
00109 
00110       Bonmin::HotInfo * result = results_ () + iDo; // retrieve i-th object to test
00111 
00112       OsiObject *Object = solver_ -> objects () [result -> whichObject ()];
00113 
00114       //  _______    ____    _____      ____          
00115       // |__   __|  / __ \  |  __ \    / __ \         
00116       //    | |    | |  | | | |  | |  | |  | |        
00117       //    | |    | |  | | | |  | |  | |  | |   : apply isCuttable()     
00118       //    | |    | |__| | | |__| |  | |__| |        
00119       //    |_|     \____/  |_____/    \____/         
00120 
00121       // todo: set a cutoff for dual bound in dual simplex
00122       //       do the same for primal based on SB's alpha
00123 
00124       // For now just 2 way
00125       OsiBranchingObject * branch = result -> branchingObject ();
00126       assert (branch->numberBranches()==2);
00127 
00128       CouenneBranchingObject *cb = dynamic_cast <CouenneBranchingObject *> (branch);
00129       if (cb) cb -> setSimulate (true);
00130 
00131       int 
00132         status0 = -1, 
00133         status1 = -1;
00134 
00136 
00137       /* Try the first direction.  Each subsequent call to branch()
00138          performs the specified branch and advances the branch object
00139          state to the next branch alternative. */
00140 
00141       status0 = simulateBranch (Object, info, branch, solver, result, -1);
00142 
00143       // save current bounds as tightened by the down branch; will be
00144       // used below to update global bounding box in solver
00145       CoinCopyN (problem_ -> Lb (), numberColumns, oldLower);
00146       CoinCopyN (problem_ -> Ub (), numberColumns, oldUpper);
00147 
00148       // Restore pre-left-branch bounds in solver
00149       for (int j=0; j<numberColumns; j++) {
00150 
00151         if (saveLower [j] != lower [j]) solver -> setColLower (j, saveLower [j]);
00152         if (saveUpper [j] != upper [j]) solver -> setColUpper (j, saveUpper [j]);
00153       }
00154 
00155       status1 = simulateBranch (Object, info, branch, solver, result, +1);
00156 
00158 
00159       jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING, "-------\n");
00160 
00161       if (cb) cb -> setSimulate (false);
00162 
00164 
00165       bool tightened = false;
00166 
00167       t_chg_bounds *chg_bds = new t_chg_bounds [numberColumns];
00168 
00169       // extend problem_'s bounding box to include downbranch's tightened
00170       for (int j=0; j<numberColumns; j++) {
00171 
00172         if (oldLower [j] < problem_ -> Lb (j)) problem_ -> Lb (j) = oldLower [j];
00173         if (oldUpper [j] > problem_ -> Ub (j)) problem_ -> Ub (j) = oldUpper [j];
00174 
00175         if (problem_ -> Lb (j) > lower [j] + COUENNE_EPS) {
00176           chg_bds [j].setLower (t_chg_bounds::CHANGED);
00177           tightened = true;
00178         }
00179 
00180         if (problem_ -> Ub (j) < upper [j] - COUENNE_EPS) {
00181           chg_bds [j].setUpper (t_chg_bounds::CHANGED);
00182           tightened = true;
00183         }
00184       }
00185 
00186       if (tightened &&                     // have tighter bounds
00187           (problem_ -> doFBBT ()) &&       // selected FBBT
00188           !(problem_ -> btCore (chg_bds))) // tighten again on root
00189 
00190         status0 = status1 = 1;             // if returns false, problem is infeasible
00191 
00192       delete [] chg_bds;
00193 
00194       // create union of bounding box from both branching directions
00195       for (int j=0; j<numberColumns; j++) {
00196 
00197         if (oldLower [j] < problem_ -> Lb (j)) problem_ -> Lb (j) = oldLower [j];
00198         if (oldUpper [j] > problem_ -> Ub (j)) problem_ -> Ub (j) = oldUpper [j];
00199       }
00200 
00201       // set new bounding box as the possibly tightened one (a subset
00202       // of the initial)
00203       for (int j=0; j<numberColumns; j++) {
00204 
00205         solver -> setColLower (j, saveLower [j] = problem_ -> Lb (j));
00206         solver -> setColUpper (j, saveUpper [j] = problem_ -> Ub (j));
00207       }
00208 
00209       /*
00210         End of evaluation for this candidate object. Possibilities are:
00211 
00212         * Both sides below cutoff; this variable is a candidate for
00213           branching.
00214 
00215         * Both sides infeasible or above the objective cutoff: no
00216           further action here. Break from the evaluation loop and
00217           assume the node will be purged by the caller.
00218 
00219         * One side feasible and below cutoff: Install the branch
00220           (i.e., fix the variable). Possibly break from the evaluation
00221           loop and assume the node will be reoptimised by the caller.
00222       */
00223 
00224       if (status0 == 1 && 
00225           status1 == 1) { // infeasible
00226         returnCode=-1;
00227         break; // exit loop
00228       } else if (status0==1 || status1==1) {
00229         numberStrongFixed_++;
00230         if (!returnCriterion) {
00231           returnCode=1;
00232         } else {
00233           returnCode=2;
00234           break;
00235         }
00236       }
00237 
00238       bool hitMaxTime = ( CoinCpuTime()-timeStart > info->timeRemaining_);
00239       if (hitMaxTime) {
00240         returnCode=3;
00241         break;
00242       }
00243     } // end loop /***********************************/
00244   
00245 
00246     if (jnlst_ -> ProduceOutput (J_DETAILED, J_BRANCHING)) {
00247       printf ("tightened bounds: ");
00248       // create union of bounding box from both branching directions
00249       for (int j=0; j<numberColumns; j++) {
00250       
00251         if (problem_ -> Lb (j) > Lower0 [j]) printf ("l%d (%g-->%g) ", j,Lower0[j], problem_->Lb (j));
00252         if (problem_ -> Ub (j) < Upper0 [j]) printf ("u%d (%g-->%g) ", j,Upper0[j], problem_->Ub (j));
00253       }
00254 
00255       delete [] Lower0;
00256       delete [] Upper0;
00257     }
00258 
00259     problem_ -> domain () -> pop (); // discard current point/bounds from problem
00260 
00261     delete [] lpSol;
00262 
00263     jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING, "----------------------done\n\n\n");
00264 
00265     if (iDo < numberToDo) iDo++; // exited due to infeasibility
00266     assert (iDo <= (int) results_.size());
00267     results_.resize (iDo);
00268 
00269     delete [] oldLower;
00270     delete [] oldUpper;
00271 
00272     delete [] saveLower;
00273     delete [] saveUpper;
00274 
00275     solver -> unmarkHotStart ();     // Delete the snapshot
00276 
00277     //solver -> doingResolve () = true;
00278     branchtime_ += CoinCpuTime () - timeStart;
00279 
00280     return returnCode;
00281   }
00282 
00283 
00284 // Do one side of strong branching
00285 int CouenneChooseStrong::simulateBranch (OsiObject *Object,
00286                                          OsiBranchingInformation *info,
00287                                          OsiBranchingObject *branch,
00288                                          OsiSolverInterface *solver,
00289                                          Bonmin::HotInfo * result,
00290                                          int direction) {
00291 
00292   bool boundBranch = branch -> boundBranch ();
00293 
00294   int status = -1;
00295 
00296   OsiSolverInterface *thisSolver = 
00297     boundBranch ? solver : solver -> clone ();
00298 
00299   CouenneObject *CouObj = dynamic_cast <CouenneObject *> (Object);
00300 
00301   if ((branch -> branch (thisSolver) > COUENNE_INFINITY) || // branch is infeasible
00302       // Bound tightening if not a CouenneObject -- explicit 
00303       (!CouObj && !BranchingFBBT (problem_, Object, thisSolver))) {
00304 
00305     status = 1;
00306 
00307     if (direction < 0) result -> setDownStatus (1);
00308     else               result -> setUpStatus   (1);
00309 
00310   } else {
00311 
00312     if (boundBranch) thisSolver -> solveFromHotStart ();
00313     else {
00314 
00315       int limit;
00316       thisSolver -> getIntParam (OsiMaxNumIterationHotStart, limit);
00317       thisSolver -> setIntParam (OsiMaxNumIteration,         limit); 
00318 
00319       thisSolver -> resolve ();
00320     }
00321 
00322     if (pseudoUpdateLP_ && CouObj && thisSolver -> isProvenOptimal ()) {
00323       CouNumber dist = distance (info -> solution_, thisSolver -> getColSolution (), 
00324                                  problem_ -> nVars ());
00325       if (dist > COUENNE_EPS)
00326         CouObj -> setEstimate (dist, direction < 0 ? 0 : 1);
00327     }
00328   }
00329 
00330   // Can check if we got solution
00331   // status is 0 finished, 1 infeasible and 2 unfinished and 3 is solution
00332 
00333   // only update information if this branch is feasible
00334   if (status < 0)
00335     status = result -> updateInformation (thisSolver, info, this);
00336 
00337   numberStrongIterations_ += thisSolver -> getIterationCount ();
00338 
00339   if ((status == 3) && (trustStrongForSolution_)) {
00340     // new solution already saved
00341     info -> cutoff_ = goodObjectiveValue_;
00342     problem_ -> setCutOff (goodObjectiveValue_);
00343     status = 0;
00344   }
00345 
00346   if (solver != thisSolver)
00347     delete thisSolver;
00348 
00349   return status;
00350 }

Generated on Mon May 3 03:05:18 2010 by  doxygen 1.4.7