/home/coin/SVN-release/OS-2.2.0/Couenne/src/problem/getIntegerCandidate.cpp

Go to the documentation of this file.
00001 /* $Id: getIntegerCandidate.cpp 230 2009-07-18 11:42:59Z pbelotti $ */
00002 /*
00003  * Name:    getIntegerCandidate.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: generate integer NLP point Y starting from fractional 
00006  *          solution using bound tightening
00007  *
00008  * (C) Carnegie-Mellon University, 2007-08.
00009  * This file is licensed under the Common Public License (CPL)
00010  */
00011 
00012 #include "CoinTime.hpp"
00013 #include "CouenneProblem.hpp"
00014 
00015 // lose patience after this many iterations of non-improving valid
00016 // tightening (step 1)
00017 #define VALID_ONLY_THRESHOLD 5 
00018 
00025 
00026 int CouenneProblem::getIntegerCandidate (const double *xFrac, double *xInt, 
00027                                          double *lb, double *ub) const {
00028   fillIntegerRank ();
00029 
00030   if (numberInRank_.size () == 0) // there is no original integer to fix
00031     return 0;
00032 
00033   CouNumber *store_optimum = optimum_; // temporary place for debug
00034                                        // optimal solution --- we
00035                                        // don't want to debug while
00036                                        // faking bounds, or we'd cut
00037                                        // the optimum all the time
00038   optimum_ = NULL;
00039 
00040   int
00041     ncols  = nVars (), 
00042     retval = 0;
00043 
00044   double
00045     *olb   = new double [ncols],       *oub   = new double [ncols],      // outer bounds
00046     *dualL = new double [nOrigVars_],  *dualR = new double [nOrigVars_]; // lb[objind] per fix index/direction
00047 
00048   // copy in current bounds
00049   CoinCopyN (Lb (), ncols, olb);
00050   CoinCopyN (Ub (), ncols, oub);
00051 
00052   // for now save fractional point into integer point
00053   CoinCopyN (xFrac, nOrigVars_, xInt);
00054 
00055   domain_.push (nVars (), xInt, lb, ub);
00056 
00057   //CoinCopyN (lb, nVars (), Lb ()); // useless?
00058   //CoinCopyN (ub, nVars (), Ub ()); // useless?
00059 
00060   enum fixType *fixed = new enum fixType [nOrigVars_]; // integer variables that were fixed
00061 
00062   for (int i=0; i<nOrigVars_; i++) 
00063     fixed [i] = (Var (i) -> isInteger () &&        // work on integer variables only
00064                  Var (i) -> Multiplicity () > 0) ? // don't care if unused variable
00065       UNFIXED : CONTINUOUS;
00066 
00067   // A more sophisticated rounding procedure
00068   //
00069   // Call aggressive tightening for all integer variables, setting
00070   // each first at floor(x_i) and then at ceil(x_i).
00071   //
00072   //
00073   // for each value r of the rank: 1 .. maxrank {
00074   //
00075   //   restrict search of unfixed original variables with rank r to
00076   //   [floor,ceil] box around LP value
00077   //
00078   //   do {
00079   //
00080   //     threshold = nVarWithThisRank / k
00081   //     niter = 0;
00082   //     for each such (unfixed) variable {
00083   //
00084   //       try left
00085   //       try right
00086   //
00087   //       if      both infeasible, abort
00088   //       else if one infeasible, fix
00089   //       else if both feasible
00090   //         if niter < threshold skip
00091   //         else                 fix based on lb(left<>right)
00092   //     }
00093   //
00094   //     if no variables fixed, fix first unfixed
00095   //     ++niter
00096   //
00097   //   } while there are unfixed variables at this rank
00098   // }   
00099   //
00100   // check value of objective -> set cutoff and run bound tightening
00101   //
00102 
00103   const int infeasible = 1;
00104 
00105   try {
00106 
00107     // for all values of the integer rank
00108 
00109     jnlst_ -> Printf (Ipopt::J_ERROR, J_NLPHEURISTIC,
00110                       "Heuristic: looking for an initial point\n");
00111 
00112     if (jnlst_ -> ProduceOutput (Ipopt::J_MOREVECTOR, J_NLPHEURISTIC)) {
00113       printf ("=       ===========================================\n");
00114       printf ("= BEGIN ===========================================\n");
00115       printf ("=       ===========================================\n");
00116       for (int i=0; i<nOrigVars_; i++)
00117         if (variables_ [i] -> Multiplicity () > 0)
00118           printf ("#### %4d: %d %c %2d frac %20g  [%20g,%20g]\n", 
00119                   i, fixed [i], 
00120                   variables_ [i] -> isInteger () ? 'I' : ' ',
00121                   integerRank_ ? integerRank_ [i] : -1,
00122                   xFrac [i], Lb (i), Ub (i));
00123       printf ("---\n");
00124       for (int i=nOrigVars_; i<nVars (); i++)
00125         if (variables_ [i] -> Multiplicity () > 0)
00126           printf ("#### %4d:   %c    frac %20g   [%20g,%20g]\n", 
00127                   i, variables_ [i] -> isInteger () ? 'I' : ' ',
00128                   //(integerRank_ && integerRank_ [i]) ? 'F' : ' ',
00129                   X (i), Lb (i), Ub (i));
00130       printf ("===================================================\n");
00131       printf ("===================================================\n");
00132       printf ("===================================================\n");
00133     }
00134 
00135 
00136     const int 
00137       N_VARS_HUGE   = 10000,
00138       N_VARS_LARGE  = 1000,
00139       N_VARS_MEDIUM = 100,
00140       N_VARS_SMALL  = 10,
00141       N_VARS_TINY   = 5;
00142 
00143     int 
00144       ntrials   = 0, 
00145       nvars     = nVars (),
00146       maxtrials =
00147       (nvars >= N_VARS_HUGE)   ? 0 :
00148       (nvars >= N_VARS_LARGE)  ? 1 :
00149       (nvars >= N_VARS_MEDIUM) ? 2 :
00150       (nvars >= N_VARS_SMALL)  ? 4 :
00151       (nvars >= N_VARS_TINY)   ? 8 : 16;
00152 
00153     int rank = 1;
00154 
00155     for (std::vector <int>::iterator rNum = numberInRank_.begin(); 
00156          ++rNum != numberInRank_.end(); rank++) 
00157 
00158       if (*rNum > 0) {
00159 
00160         jnlst_ -> Printf (Ipopt::J_STRONGWARNING, J_NLPHEURISTIC,
00161                           "Analyzing %d variables with rank %d\n", *rNum, rank);
00162 
00163         if (CoinCpuTime () > maxCpuTime_)
00164           break;
00165 
00166         // *rNum is the number of variable with integer rank equal to rank
00167 
00168         // start restricting around current integer box
00169         for (int i=0; i<nOrigVars_; i++) 
00170           if ((Var (i) -> Multiplicity () > 0) && // alive variable
00171               (Var (i) -> isInteger    ())     && // integer, may fix if independent of other integers
00172               (integerRank_ [i] == rank)) {
00173 
00174             Lb (i) = CoinMax (Lb (i), floor (xFrac [i])); 
00175             Ub (i) = CoinMin (Ub (i), ceil  (xFrac [i]));
00176           }
00177 
00178         // translate current NLP point+bounds into higher-dimensional space
00179         initAuxs ();
00180 
00181         if (jnlst_ -> ProduceOutput (Ipopt::J_MOREVECTOR, J_NLPHEURISTIC)) {
00182           printf ("= RANK LEVEL = %d [%d] ==================================\n", rank, *rNum);
00183           for (int i=0; i<nOrigVars_; i++)
00184             if (Var (i) -> Multiplicity () > 0) // alive variable
00185               printf ("#### %4d: %d %c %2d frac %20g -> int %20g [%20g,%20g]\n", 
00186                       i, fixed [i], 
00187                       variables_ [i] -> isInteger () ? 'I' : ' ',
00188                       integerRank_ ? integerRank_ [i] : -1,
00189                       xFrac [i], xInt [i], Lb (i), Ub (i));
00190           printf ("--------------------\n");
00191           for (int i=nOrigVars_; i<nVars (); i++)
00192             if (Var (i) -> Multiplicity () > 0) // alive variable
00193               printf ("#### %4d:   %c    frac %20g   [%20g,%20g]\n", 
00194                       i, variables_ [i] -> isInteger () ? 'I' : ' ',
00195                       //(integerRank_ && integerRank_ [i]) ? 'F' : ' ',
00196                       X (i), Lb (i), Ub (i));
00197           printf ("=================================================\n");
00198         }
00199 
00200         //CoinCopyN (xFrac, nOrigVars_, xInt);// TODO: re-copy first nOrigVars_ variables into xInt?
00201 
00202         int remaining = *rNum;
00203 
00204         do {
00205 
00206           bool one_fixed = false;
00207 
00208           for (int i=0; i<nOrigVars_; i++) 
00209 
00210             if ((Var (i) -> Multiplicity () > 0) && // alive 
00211                 (integerRank_ [i] == rank)       && // at this rank
00212                 (fixed [i] == UNFIXED)           && // still to be fixed
00213                 Var (i) -> isInteger ()) {          // and integer
00214 
00215               if (CoinCpuTime () > maxCpuTime_)
00216                 break;
00217 
00218               // check if initAuxs() closed any bound; if so, fix variable
00219               //if (Lb (i) == Ub (i)) { // doesn't work
00220               if (ceil (Lb (i) - COUENNE_EPS) + COUENNE_EPS >= floor (Ub (i) + COUENNE_EPS)) {
00221 
00222                 X (i) = Lb (i) = Ub (i) = xInt [i] = ceil (Lb (i) - COUENNE_EPS);
00223                 fixed [i] = FIXED;
00224                 one_fixed = true;
00225                 --remaining;
00226                 continue;
00227               }
00228 
00229               // if variable already integer values, fix it (TODO: do
00230               // this only if impatient, e.g. if #variables huge)
00231               if (ceil (xInt [i] - COUENNE_EPS) - COUENNE_EPS <= xInt [i]) {
00232 
00233                 X (i) = Lb (i) = Ub (i) = xInt [i] = ceil (xInt [i] - COUENNE_EPS);
00234                 fixed [i] = FIXED;
00235                 one_fixed = true;
00236                 --remaining;
00237                 continue;
00238               }
00239 
00240               // otherwise, test rounding up and down
00241               int result = testIntFix (i, xFrac [i], fixed, xInt,
00242                                        dualL, dualR, olb, oub, ntrials < maxtrials);
00243 
00244               jnlst_ -> Printf (J_STRONGWARNING, J_NLPHEURISTIC, 
00245                                 "testing %d [%g -> %g], res = %d\n", i, xFrac [i], xInt [i], result);
00246 
00247               if (result > 0) {
00248                 one_fixed = true;
00249                 --remaining;
00250               } else if (result < 0) 
00251                 throw infeasible;
00252             }
00253 
00254           // if none fixed, fix first unfixed variable with this rank
00255 
00256           if (!one_fixed) {
00257 
00258             int index = 0;
00259 
00260             // find first unfixed integer at this rank
00261             while ((index < nOrigVars_) && 
00262                    (!(Var (index) -> isInteger ()) ||
00263                     (integerRank_ [index] != rank) ||
00264                     (fixed [index] != UNFIXED)))
00265               index++;
00266 
00267             assert (index < nOrigVars_);
00268 
00269             jnlst_ -> Printf (J_MOREVECTOR, J_NLPHEURISTIC, 
00270                               "none fixed, fix %d from %g [%g,%g] [L=%g, R=%g]", 
00271                               index, xFrac [index], Lb (index), Ub (index), 
00272                               dualL [index], dualR [index]);
00273 
00274             Lb (index) = Ub (index) = X (index) = xInt [index] = 
00275               ((dualL [index] < dualR [index] - COUENNE_EPS) ? floor (xFrac [index]) :
00276                (dualL [index] > dualR [index] + COUENNE_EPS) ? ceil  (xFrac [index]) :
00277                ((CoinDrand48 () > xFrac [index] - floor (xFrac [index])) ? 
00278                 floor (xFrac [index]) : ceil (xFrac [index])));
00279 
00280             jnlst_ -> Printf (J_MOREVECTOR, J_NLPHEURISTIC, " to %g\n", xInt [index]);
00281 
00282             fixed [index] = FIXED;
00283 
00284             --remaining;
00285           }
00286 
00287           ntrials++;
00288 
00289           if (jnlst_ -> ProduceOutput (Ipopt::J_MOREVECTOR, J_NLPHEURISTIC)) {
00290             printf ("--- remaining = %d --------------------------- \n", remaining);
00291             for (int i=0; i<nOrigVars_; i++)
00292               if (variables_ [i] -> Multiplicity () > 0)
00293                 printf ("#### %4d: %d %c %2d frac %20g -> int %20g  [%20g,%20g]\n", 
00294                         i, fixed [i], 
00295                         variables_ [i] -> isInteger () ? 'I' : ' ',
00296                         integerRank_ ? integerRank_ [i] : -1,
00297                         xFrac [i], xInt [i], Lb (i), Ub (i));
00298             printf ("---------------------------\n");
00299 
00300           }
00301 
00302           if (CoinCpuTime () > maxCpuTime_)
00303             break;
00304 
00305         } while (remaining > 0);
00306       } // for
00307 
00308     // save tightened bounds in NLP space. Sanity check
00309     for (int i = nOrigVars_; i--;)
00310       if (Var (i) -> Multiplicity () > 0) {
00311 
00312         if (fixed [i] == FIXED)       // integer point, fixed
00313           lb [i] = ub [i] = X (i) = xInt [i];
00314 
00315         else if (Lb (i) > Ub (i)) {    // non-sense bounds, fix them
00316           xInt [i] = X (i) = lb [i] = ub [i] = 
00317             (fixed [i] == CONTINUOUS) ?
00318                           (0.5 * (Lb (i) + Ub (i))) :
00319             COUENNE_round (0.5 * (Lb (i) + Ub (i)));
00320 
00321           if (fixed [i] != CONTINUOUS)
00322             fixed [i] = FIXED;
00323 
00324         } else {                        // normal case
00325           lb [i] = Lb (i);
00326           ub [i] = Ub (i);
00327           if      (xInt [i] < lb [i]) X (i) = xInt [i] = lb [i];
00328           else if (xInt [i] > ub [i]) X (i) = xInt [i] = ub [i];
00329         }
00330       }
00331 
00332     restoreUnusedOriginals (xInt);
00333 
00334     // if initial point is feasible, compute corresponding objective
00335     // and update if upper bound improves
00336     initAuxs ();
00337     int objind = Obj (0) -> Body () -> Index ();
00338 
00339     if (X (objind) < getCutOff ()) {
00340 
00341       const CouNumber *x = X ();
00342       CouNumber xp = x [objind];
00343 
00344       if (checkNLP (x, xp, true)) { // true for recomputing xp
00345         setCutOff (xp);
00346         jnlst_ -> Printf (J_DETAILED, J_NLPHEURISTIC, 
00347                           "new cutoff from getIntCand: %g\n", xp);
00348       }
00349     }
00350   } // try
00351 
00352   catch (int i) {
00353 
00354     if (i == infeasible)
00355       retval = -1;
00356   }
00357 
00359 
00360   if (jnlst_->ProduceOutput(Ipopt::J_MOREVECTOR, J_NLPHEURISTIC)) {
00361     if (retval >= 0) {
00362       printf ("- Done: retval %d ----------------------------------------------------------------\n", 
00363               retval);
00364       for (int i=0; i<nOrigVars_; i++)
00365         if (variables_ [i] -> Multiplicity () > 0)
00366           printf ("#### %4d: %d %c frac %20g -> int %20g [%20g,%20g]\n", 
00367                   i, fixed [i], variables_ [i] -> isInteger () ? 'I' : ' ',
00368                   xFrac [i], xInt [i], lb [i], ub [i]);
00369     } else printf ("no good point was found\n");
00370   }
00371 
00372   jnlst_ -> Printf (Ipopt::J_ERROR, J_NLPHEURISTIC, "Heuristic done\n");
00373 
00374 
00375   delete [] fixed;
00376 
00377   delete [] olb;   delete [] oub;
00378   delete [] dualL; delete [] dualR;
00379 
00380   domain_.pop ();
00381 
00382   jnlst_ -> Printf (J_MOREVECTOR, J_NLPHEURISTIC, "Done with GetIntegerCandidate\n");
00383 
00384   optimum_ = store_optimum; // restore 
00385 
00386   return retval;
00387 }

Generated on Thu Aug 5 03:02:57 2010 by  doxygen 1.4.7