/home/coin/SVN-release/OS-2.0.1/Couenne/src/bound_tightening/aggressiveBT.cpp

Go to the documentation of this file.
00001 /* $Id: aggressiveBT.cpp 141 2009-06-03 04:19:19Z pbelotti $ */
00002 /*
00003  * Name:    aggressiveBT.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: aggressive bound tightening -- fake bounds in variables to
00006  *          exclude parts of the solution space through fathoming on
00007  *          bounds/infeasibility
00008  *
00009  * (C) Carnegie-Mellon University, 2007-09.
00010  * This file is licensed under the Common Public License (CPL)
00011  */
00012 
00013 #include "BonTNLPSolver.hpp"
00014 #include "BonNlpHeuristic.hpp"
00015 #include "CoinHelperFunctions.hpp"
00016 #include "BonCouenneInfo.hpp"
00017 
00018 #include "CouenneCutGenerator.hpp"
00019 #include "CouenneProblem.hpp"
00020 
00021 #define MAX_ABT_ITER           1  // max # aggressive BT iterations
00022 #define THRES_ABT_IMPROVED     0  // only continue ABT if at least these bounds have improved
00023 #define THRES_ABT_ORIG      1000  // only do ABT on originals if they are more than this 
00024 
00025 static double distanceToBound(int n, const double* xOrig,
00026                               const double* lower, const double* upper)
00027 {
00028   double Xdist = 0.;
00029   for (int i=0; i<n; i++) {
00030     if (lower[i] > xOrig[i]) {
00031       Xdist += lower[i] - xOrig[i];
00032     }
00033     if (upper[i] < xOrig[i]) {
00034       Xdist += xOrig[i] - upper[i];
00035     }
00036   }
00037   return Xdist;
00038 }
00039 
00040 // Aggressive Bound Tightening: for each variable, fake new bounds
00041 // [l,b] or [b,u] and apply bound tightening. If the interval is
00042 // fathomed on bounds or on infeasibility, the complementary bound
00043 // interval is a valid tightening.
00044 
00045 bool CouenneProblem::aggressiveBT (Bonmin::OsiTMINLPInterface *nlp,
00046                                    t_chg_bounds *chg_bds, 
00047                                    Bonmin::BabInfo * babInfo) const {
00048 
00049   Jnlst()->Printf (J_ITERSUMMARY, J_BOUNDTIGHTENING, "Aggressive FBBT\n");
00050 
00051   Bonmin::CouenneInfo* couInfo =
00052     dynamic_cast<Bonmin::CouenneInfo*>(babInfo);
00053 
00054   int  ncols  = nVars ();
00055   bool retval = true;
00056 
00057   CouNumber
00058     *olb = new CouNumber [ncols],
00059     *oub = new CouNumber [ncols];
00060 
00061   // save current bounds
00062   CoinCopyN (Lb (), ncols, olb);
00063   CoinCopyN (Ub (), ncols, oub);
00064 
00065   // Find the solution that is closest to the current bounds
00066   // TODO: Also check obj value
00067   SmartPtr<const Bonmin::CouenneInfo::NlpSolution> closestSol;
00068   double dist = 1e50;
00069 
00070   const std::list<SmartPtr<const Bonmin::CouenneInfo::NlpSolution> >& solList =
00071     couInfo->NlpSolutions();
00072 
00073   for (std::list<SmartPtr<const Bonmin::CouenneInfo::NlpSolution> >::const_iterator 
00074          i = solList.begin();
00075        i != solList.end(); i++) {
00076     assert(nOrigVars_ == (*i)->nVars());
00077     const double thisDist = distanceToBound(nOrigVars_, (*i)->solution(), olb, oub);
00078     if (thisDist < dist) {
00079       closestSol = *i;
00080       dist = thisDist;
00081     }
00082   }
00083 
00084   jnlst_ -> Printf(J_VECTOR, J_BOUNDTIGHTENING, "best dist = %e\n", dist);
00085 
00086   // If this solution is not sufficiently inside the bounds, we solve the NLP now
00087   if (dist > 0.1) { // TODO: Find tolerance
00088 
00089     // find integer initial point /////////////////////////
00090 
00091     int nvars = nVars ();
00092 
00093     double *lower = new double [nvars];
00094     double *upper = new double [nvars];
00095 
00096     CoinFillN (lower, nvars, -COUENNE_INFINITY);
00097     CoinFillN (upper, nvars,  COUENNE_INFINITY);
00098 
00099     CoinCopyN (nlp -> getColLower (), nOrigVars_, lower);
00100     CoinCopyN (nlp -> getColUpper (), nOrigVars_, upper);
00101 
00102     double *Y = new double [nvars];
00103     CoinFillN (Y, nvars, 0.);
00104     CoinCopyN (X (), nOrigVars_, Y);
00105 
00106     if (getIntegerCandidate (nlp -> getColSolution (), Y, lower, upper) < 0) {
00107       jnlst_ -> Printf(J_ITERSUMMARY, J_BOUNDTIGHTENING, "TODO: find NLP point in ABT failed\n");
00108       delete [] Y;
00109       delete [] lower;
00110       delete [] upper;
00111       return true;
00112     }
00113 
00115 
00116     nlp -> setColLower    (lower);
00117     nlp -> setColUpper    (upper);
00118     nlp -> setColSolution (Y);
00119 
00120     try {
00121       nlp -> initialSolve ();
00122     }
00123     catch (Bonmin::TNLPSolver::UnsolvedError *E) {
00124     }
00125     
00126     delete [] Y;
00127     delete [] lower;
00128     delete [] upper;
00129 
00130     if (nlp->isProvenOptimal()) {
00131       closestSol = new Bonmin::CouenneInfo::NlpSolution 
00132         (nOrigVars_, nlp->getColSolution(), nlp->getObjValue());
00133       couInfo->addSolution(closestSol);
00134       dist = 0.;
00135     }
00136     else {
00137       jnlst_ -> Printf(J_ITERSUMMARY, J_BOUNDTIGHTENING, "TODO: NLP solve in ABT failed\n");
00138       return true;
00139     }
00140   }
00141 
00142   if (dist>1e10) {
00143     jnlst_ -> Printf(J_ITERSUMMARY, J_BOUNDTIGHTENING, "TODO: Don't have point for ABT\n");
00144     return true;
00145   }
00146 
00147   // X is now the NLP solution, but in a low-dimensional space. We
00148   // have to get the corresponding point in higher dimensional space
00149   // through getAuxs()
00150 
00151   double *X = new double [ncols];
00152   CoinCopyN (closestSol->solution(), nOrigVars_, X);
00153   getAuxs (X);
00154 
00155   // create a new, fictitious, bound bookkeeping structure
00156   t_chg_bounds *f_chg = new t_chg_bounds [ncols];
00157 
00158   if (Jnlst()->ProduceOutput(J_ITERSUMMARY, J_BOUNDTIGHTENING)) {
00159     //    CouNumber cutoff = getCutOff ();
00160     int       objind = Obj (0) -> Body  () -> Index ();
00161     for (int i=0; i<nOrigVars_; i++)
00162       Jnlst()->Printf(J_MOREVECTOR, J_BOUNDTIGHTENING,
00163                       "   %2d %+20g [%+20g %+20g]\n",
00164                       i, X [i], Lb (i), Ub (i));
00165     Jnlst()->Printf(J_ITERSUMMARY, J_BOUNDTIGHTENING,
00166                     "-------------\nAggressive BT. Current bound = %g, cutoff = %g, %d vars\n", 
00167                     Lb (objind), getCutOff (), ncols);
00168   }
00169 
00170   int improved, second, iter = 0;
00171 
00172   // Repeatedly fake tightening bounds on both sides of every variable
00173   // to concentrate around current NLP point.
00174   //
00175   // MAX_ABT_ITER is the maximum # of outer cycles. Each call to
00176   // fake_tighten in turn has an iterative algorithm for a
00177   // derivative-free, uni-dimensional optimization problem on a
00178   // monotone function.
00179 
00180   do {
00181 
00182     improved = 0;
00183 
00184     // scan all variables
00185     for (int i=0; i<ncols; i++) {
00186 
00187       if (CoinCpuTime () > maxCpuTime_)
00188         break;
00189 
00190       int index = evalOrder (i);
00191 
00192       if (Var (index) -> Multiplicity () <= 0) 
00193         continue;
00194 
00195       // AW: We only want to do the loop that temporarily changes
00196       // bounds around the NLP solution only for those points from the
00197       // NLP solution (no auxiliary vars)?
00198 
00199       // PBe: if we do want that, index should be initialized as i, as
00200       // evalOrder gives a variable index out of an array index.
00201 
00202       // PBe: That makes a lot of sense when problems are really
00203       // big. Instances arki000[24].nl spend a lot of time here
00204 
00205       if ((nOrigVars_ < THRES_ABT_ORIG) || (index < nOrigVars_)) {
00206 
00207         // if (index == objind) continue; // don't do it on objective function
00208 
00209         Jnlst()->Printf(J_DETAILED, J_BOUNDTIGHTENING,
00210                         "------------- tighten left x%d\n", index);
00211 
00212         // tighten on left
00213         if ((X [index] >= Lb (index) + COUENNE_EPS)
00214             && ((improved = fake_tighten (0, index, X, olb, oub, chg_bds, f_chg)) < 0)) {
00215           retval = false;
00216           break;
00217         }
00218 
00219         second = 0;
00220 
00221         Jnlst()->Printf(J_DETAILED, J_BOUNDTIGHTENING,
00222                         "------------- tighten right x%d\n", index);
00223 
00224         // tighten on right
00225         if ((X [index] <= Ub (index) - COUENNE_EPS)
00226             && ((second = fake_tighten (1, index, X, olb, oub, chg_bds, f_chg) < 0))) {
00227           retval = false;
00228           break;
00229         }
00230 
00231         improved += second;
00232       }
00233     }
00234   } while (retval && (improved > THRES_ABT_IMPROVED) && (iter++ < MAX_ABT_ITER));
00235 
00236   // store new valid bounds, or restore old ones if none changed
00237   CoinCopyN (olb, ncols, Lb ());
00238   CoinCopyN (oub, ncols, Ub ());
00239 
00240   if (Jnlst()->ProduceOutput(J_ITERSUMMARY, J_BOUNDTIGHTENING)) {
00241     Jnlst()->Printf(J_ITERSUMMARY, J_BOUNDTIGHTENING,"------------------\n");
00242 
00243     if (!retval) Jnlst()->Printf(J_ITERSUMMARY, J_BOUNDTIGHTENING,
00244                                  "Couenne infeasible node from aggressive BT\n");
00245 
00246     int objind = Obj (0) -> Body  () -> Index ();
00247 
00248     Jnlst()->Printf(J_ITERSUMMARY, J_BOUNDTIGHTENING,
00249                     "-------------\ndone Aggressive BT. Current bound = %g, cutoff = %g, %d vars\n", 
00250                     Lb (objind), getCutOff (), ncols);
00251 
00252     if (Jnlst()->ProduceOutput(J_DETAILED, J_BOUNDTIGHTENING))
00253       for (int i=0; i<nOrigVars_; i++)
00254         printf("   x%02d [%+20g %+20g]  | %+20g\n",
00255                i, Lb (i), Ub (i), X [i]);
00256 
00257     if (Jnlst()->ProduceOutput(J_MOREDETAILED, J_BOUNDTIGHTENING))
00258       for (int i=nOrigVars_; i<ncols; i++)
00259         printf ("   w%02d [%+20g %+20g]  | %+20g\n", i, Lb (i), Ub (i), X [i]);
00260   }
00261 
00262   delete [] X;
00263   delete [] f_chg;
00264   delete [] olb;
00265   delete [] oub;
00266 
00267   return retval;// && btCore (psi, cs, chg_bds, babInfo, true); // !!!
00268   //return retval && btCore (psi, cs, chg_bds, babInfo, true);
00269 }

Generated on Thu Oct 8 03:02:55 2009 by  doxygen 1.4.7