/home/coin/SVN-release/OS-2.4.2/Couenne/src/convex/CouenneCutGenerator.cpp

Go to the documentation of this file.
00001 /* $Id: CouenneCutGenerator.cpp 748 2011-07-28 16:13:32Z pbelotti $
00002  *
00003  * Name:    CouenneCutGenerator.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: define a class of convexification procedures 
00006  *
00007  * (C) Carnegie-Mellon University, 2006-09.
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 #include "CglCutGenerator.hpp"
00012 
00013 #include "CouenneCutGenerator.hpp"
00014 
00015 #include "CouenneProblem.hpp"
00016 #include "CouenneChooseStrong.hpp"
00017 #include "CouenneChooseVariable.hpp"
00018 
00019 #include "CbcTree.hpp"
00020 #include "BonCbc.hpp"
00021 #include "CouenneRecordBestSol.hpp"
00022 
00023 using namespace Ipopt;
00024 using namespace Couenne;
00025 
00027 CouenneCutGenerator::CouenneCutGenerator (Bonmin::OsiTMINLPInterface *nlp,
00028                                           Bonmin::BabSetupBase *base,
00029                                           CouenneProblem *problem,
00030                                           struct ASL *asl):
00031 
00032   CglCutGenerator (),
00033   
00034   firstcall_      (true),
00035   problem_        (problem),
00036   nrootcuts_      (0),
00037   ntotalcuts_     (0),
00038   septime_        (0),
00039   objValue_       (- DBL_MAX),
00040   nlp_            (nlp),
00041   BabPtr_         (NULL),
00042   infeasNode_     (false),
00043   jnlst_          (base ? base -> journalist () : NULL),
00044   rootTime_       (-1.) {
00045 
00046   if (base) {
00047 
00048     base -> options () -> GetIntegerValue ("convexification_points", nSamples_, "couenne.");
00049 
00050     std::string s;
00051 
00052     base -> options () -> GetStringValue ("convexification_type", s, "couenne.");
00053     if      (s == "current-point-only") convtype_ = CURRENT_ONLY;
00054     else if (s == "uniform-grid")       convtype_ = UNIFORM_GRID;
00055     else                                convtype_ = AROUND_CURPOINT;
00056 
00057     base -> options () -> GetStringValue ("violated_cuts_only", s, "couenne."); 
00058     addviolated_ = (s == "yes");
00059 
00060     base -> options () -> GetStringValue ("check_lp", s, "couenne."); 
00061     check_lp_ = (s == "yes");
00062 
00063     base -> options () -> GetStringValue ("enable_lp_implied_bounds", s, "couenne.");
00064     enable_lp_implied_bounds_ = (s == "yes");
00065 
00066   } else {
00067 
00068     nSamples_                 = 4;
00069     convtype_                 = CURRENT_ONLY;
00070     addviolated_              = true;
00071     check_lp_                 = false;
00072     enable_lp_implied_bounds_ = false;
00073   }
00074 
00075   lastPrintLine = -1;
00076 
00077   //if (asl) // deal with problems not originating from AMPL
00078   //problem_ = new CouenneProblem (asl, base, jnlst_);
00079 }
00080 
00081 
00083 CouenneCutGenerator::~CouenneCutGenerator ()
00084 {}//if (problem_) delete problem_;}
00085 
00086 
00088 CouenneCutGenerator::CouenneCutGenerator (const CouenneCutGenerator &src):
00089 
00090   CglCutGenerator (src),
00091 
00092   firstcall_   (src. firstcall_),
00093   addviolated_ (src. addviolated_), 
00094   convtype_    (src. convtype_), 
00095   nSamples_    (src. nSamples_),
00096   problem_     (src. problem_),// -> clone ()),
00097   nrootcuts_   (src. nrootcuts_),
00098   ntotalcuts_  (src. ntotalcuts_),
00099   septime_     (src. septime_),
00100   objValue_    (src. objValue_),
00101   nlp_         (src. nlp_),
00102   BabPtr_      (src. BabPtr_),
00103   infeasNode_  (src. infeasNode_),
00104   jnlst_       (src. jnlst_),
00105   rootTime_    (src. rootTime_),
00106   check_lp_    (src. check_lp_),
00107   enable_lp_implied_bounds_ (src.enable_lp_implied_bounds_),
00108   lastPrintLine(src.lastPrintLine)
00109 {}
00110 
00111 
00112 #define MAX_SLOPE 1e3
00113 
00115 int CouenneCutGenerator::addSegment (OsiCuts &cs, int wi, int xi, 
00116                                      CouNumber x1, CouNumber y1, 
00117                                      CouNumber x2, CouNumber y2, int sign) const { 
00118 
00119   if (fabs (x2-x1) < COUENNE_EPS) {
00120     if (fabs (y2-y1) > MAX_SLOPE * COUENNE_EPS)
00121       jnlst_->Printf(J_WARNING, J_CONVEXIFYING,
00122                      "warning, discontinuity of %e over an interval of %e\n", y2-y1, x2-x1);
00123     //else return createCut (cs, y2, (int) 0, wi, 1.);
00124   }
00125 
00126   CouNumber dx = x2-x1, dy = y2-y1;
00127 
00128   //  return createCut (cs, y1 + oppslope * x1, sign, wi, 1., xi, oppslope);
00129   return createCut (cs, y1*dx - dy*x1, (dx>0) ? sign : -sign, wi, dx, xi, -dy);
00130 }
00131 
00132 
00134 int CouenneCutGenerator::addTangent (OsiCuts &cs, int wi, int xi, 
00135                                      CouNumber x, CouNumber w, 
00136                                      CouNumber slope, int sign) const
00137   {return createCut (cs, w - slope * x, sign, wi, 1., xi, - slope);}
00138 
00139 
00141 int CouenneCutGenerator::getnvars () const
00142   {return problem_ -> nVars ();} 
00143 
00144 
00146 void CouenneCutGenerator::registerOptions (Ipopt::SmartPtr <Bonmin::RegisteredOptions> roptions) {
00147 
00148   roptions -> SetRegisteringCategory ("Couenne options", Bonmin::RegisteredOptions::CouenneCategory);
00149 
00150   roptions -> AddLowerBoundedIntegerOption
00151     ("convexification_cuts",
00152      "Specify the frequency (in terms of nodes) at which couenne ecp cuts are generated.",
00153      -99,1,
00154      "A frequency of 0 amounts to never solve the NLP relaxation.");
00155 
00156   roptions -> AddStringOption2
00157     ("check_lp",
00158      "Check all LPs through an independent call to OsiClpSolverInterface::initialSolve()",
00159      "no",
00160      "no","",
00161      "yes","");
00162 
00163   roptions -> AddStringOption3
00164     ("convexification_type",
00165      "Determines in which point the linear over/under-estimator are generated",
00166      "current-point-only",
00167      "current-point-only","Only at current optimum of relaxation",
00168      "uniform-grid","Points chosen in a uniform grid between the bounds of the problem",
00169      "around-current-point","At points around current optimum of relaxation",
00170      "For the lower envelopes of convex functions, this is the number of points where a supporting hyperplane is generated. "
00171      "This only holds for the initial linearization, as all other linearizations only add at most one cut per expression."
00172     );
00173     
00174   roptions -> AddLowerBoundedIntegerOption
00175     ("convexification_points",
00176      "Specify the number of points at which to convexify when convexification type "
00177      "is uniform-grid or around-current-point.",
00178      0,4,
00179      "");
00180 
00181   roptions -> AddStringOption2 
00182     ("violated_cuts_only",
00183      "Yes if only violated convexification cuts should be added",
00184      "yes",
00185      "no","",
00186      "yes","");
00187 
00188   roptions -> AddStringOption2 
00189     ("enable_lp_implied_bounds",
00190      "Enable OsiSolverInterface::tightenBounds () -- warning: it has caused "
00191      "some trouble to Couenne",
00192      "no",
00193      "no","",
00194      "yes","");
00195 
00196   roptions -> AddStringOption3
00197     ("multilinear_separation",
00198      "Separation for multilinear terms",
00199      "tight",
00200      "none",   "No separation -- just use the four McCormick inequalities",
00201      "simple", "Use one considering lower curve only",
00202      "tight",  "Use one considering both curves pi(x) = l_{k+1} and pi(x) = u_{k+1}",
00203      "Type of separation for multilinear terms where the dependent variable is also bounded"
00204     );
00205 }
00206 
00207 /*********************************************************************/
00208 void CouenneCutGenerator::printLineInfo() const {
00209 
00210   double cbcLb = BabPtr_->model().getBestPossibleObjValue();
00211   double lpVal = BabPtr_->model().solver()->getObjValue();
00212   int nbNodes = BabPtr_->model().getNodeCount();
00213   int nbNodesRem = BabPtr_->model().tree()->size();
00214   int depth = BabPtr_->model().currentDepth();
00215   CouenneRecordBestSol *rs = problem_->getRecordBestSol();
00216 
00217   if(rs->getHasSol()) {
00218     double bestSolVal = rs->getVal(); 
00219     printf("%10d  %8d  %6d  %10.6f  %10.6f  %10.6f\n", 
00220            nbNodes, nbNodesRem, depth, cbcLb, lpVal, bestSolVal);
00221   }
00222   else {
00223     printf("%10d  %8d  %6d  %10.6f  %10.6f   ----------\n", 
00224            nbNodes, nbNodesRem, depth, cbcLb, lpVal);
00225   }
00226   problem_->doPrint_ = true;
00227   if((depth < problem_->minDepthPrint_) ||
00228      (nbNodes < problem_->minNodePrint_)) {
00229     problem_->doPrint_ = false;
00230   }
00231   /***
00232   if(depth > 200) {
00233     printf("CouenneCutGenerator::printLineInfo(): exit on depth\n");
00234     exit(1);
00235   }
00236   ***/
00237 } /* printLineInfo */

Generated on Wed Nov 30 03:03:58 2011 by  doxygen 1.4.7