00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "CglCutGenerator.hpp"
00013
00014 #include "CouenneProblem.hpp"
00015 #include "CouenneCutGenerator.hpp"
00016 #include "CouenneChooseStrong.hpp"
00017 #include "CouenneChooseVariable.hpp"
00018
00019
00021 CouenneCutGenerator::CouenneCutGenerator (Bonmin::OsiTMINLPInterface *nlp,
00022 Bonmin::BabSetupBase *base,
00023 struct ASL *asl):
00024
00025 CglCutGenerator (),
00026
00027 firstcall_ (true),
00028 problem_ (NULL),
00029 nrootcuts_ (0),
00030 ntotalcuts_ (0),
00031 septime_ (0),
00032 objValue_ (- DBL_MAX),
00033 nlp_ (nlp),
00034 BabPtr_ (NULL),
00035 infeasNode_ (false),
00036 jnlst_ (base ? base -> journalist () : NULL),
00037 rootTime_ (-1.) {
00038
00039 if (base) {
00040
00041 base -> options () -> GetIntegerValue ("convexification_points", nSamples_, "couenne.");
00042
00043 std::string s;
00044
00045 base -> options () -> GetStringValue ("convexification_type", s, "couenne.");
00046 if (s == "current-point-only") convtype_ = CURRENT_ONLY;
00047 else if (s == "uniform-grid") convtype_ = UNIFORM_GRID;
00048 else convtype_ = AROUND_CURPOINT;
00049
00050 base -> options () -> GetStringValue ("violated_cuts_only", s, "couenne.");
00051 addviolated_ = (s == "yes");
00052
00053 base -> options () -> GetStringValue ("check_lp", s, "couenne.");
00054 check_lp_ = (s == "yes");
00055
00056 base -> options () -> GetStringValue ("enable_lp_implied_bounds", s, "couenne.");
00057 enable_lp_implied_bounds_ = (s == "yes");
00058
00059 } else {
00060
00061 nSamples_ = 4;
00062 convtype_ = CURRENT_ONLY;
00063 addviolated_ = true;
00064 check_lp_ = false;
00065 enable_lp_implied_bounds_ = false;
00066 }
00067
00068 if (asl)
00069 problem_ = new CouenneProblem (asl, base, jnlst_);
00070 }
00071
00072
00074 CouenneCutGenerator::~CouenneCutGenerator ()
00075 {if (problem_) delete problem_;}
00076
00077
00079 CouenneCutGenerator::CouenneCutGenerator (const CouenneCutGenerator &src):
00080
00081 CglCutGenerator (src),
00082
00083 firstcall_ (src. firstcall_),
00084 addviolated_ (src. addviolated_),
00085 convtype_ (src. convtype_),
00086 nSamples_ (src. nSamples_),
00087 problem_ (src. problem_ -> clone ()),
00088 nrootcuts_ (src. nrootcuts_),
00089 ntotalcuts_ (src. ntotalcuts_),
00090 septime_ (src. septime_),
00091 objValue_ (src. objValue_),
00092 nlp_ (src. nlp_),
00093 BabPtr_ (src. BabPtr_),
00094 infeasNode_ (src. infeasNode_),
00095 jnlst_ (src. jnlst_),
00096 rootTime_ (src. rootTime_),
00097 check_lp_ (src. check_lp_),
00098 enable_lp_implied_bounds_ (src.enable_lp_implied_bounds_)
00099 {}
00100
00101
00102 #define MAX_SLOPE 1e3
00103
00105 int CouenneCutGenerator::addSegment (OsiCuts &cs, int wi, int xi,
00106 CouNumber x1, CouNumber y1,
00107 CouNumber x2, CouNumber y2, int sign) const {
00108
00109 if (fabs (x2-x1) < COUENNE_EPS) {
00110 if (fabs (y2-y1) > MAX_SLOPE * COUENNE_EPS)
00111 jnlst_->Printf(J_WARNING, J_CONVEXIFYING,
00112 "warning, discontinuity of %e over an interval of %e\n", y2-y1, x2-x1);
00113 else return createCut (cs, y2, (int) 0, wi, 1.);
00114 }
00115
00116 CouNumber dx = x2-x1, dy = y2-y1;
00117
00118
00119 return createCut (cs, y1*dx - dy*x1, (dx>0) ? sign : -sign, wi, dx, xi, -dy);
00120 }
00121
00122
00124 int CouenneCutGenerator::addTangent (OsiCuts &cs, int wi, int xi,
00125 CouNumber x, CouNumber w,
00126 CouNumber slope, int sign) const
00127 {return createCut (cs, w - slope * x, sign, wi, 1., xi, - slope);}
00128
00129
00131 int CouenneCutGenerator::getnvars () const
00132 {return problem_ -> nVars ();}
00133
00134
00136 void CouenneCutGenerator::registerOptions (Ipopt::SmartPtr <Bonmin::RegisteredOptions> roptions) {
00137
00138 roptions -> SetRegisteringCategory ("Couenne options", Bonmin::RegisteredOptions::CouenneCategory);
00139
00140 roptions -> AddLowerBoundedIntegerOption
00141 ("convexification_cuts",
00142 "Specify the frequency (in terms of nodes) at which couenne ecp cuts are generated.",
00143 -99,1,
00144 "A frequency of 0 amounts to never solve the NLP relaxation.");
00145
00146 roptions -> AddStringOption2
00147 ("check_lp",
00148 "Check all LPs through an independent call to OsiClpSolverInterface::initialSolve()",
00149 "no",
00150 "no","",
00151 "yes","");
00152
00153 roptions -> AddStringOption2
00154 ("local_optimization_heuristic",
00155 "Do we search for local solutions of NLP's",
00156 "yes",
00157 "no","",
00158 "yes","");
00159
00160 roptions -> AddLowerBoundedIntegerOption
00161 ("log_num_local_optimization_per_level",
00162 "Specify the logarithm of the number of local optimizations to perform"
00163 " on average for each level of given depth of the tree.",
00164 -1,
00165 2, "Solve as many nlp's at the nodes for each level of the tree. "
00166 "Nodes are randomly selected. If for a "
00167 "given level there are less nodes than this number nlp are solved for every nodes. "
00168 "For example if parameter is 8, nlp's are solved for all node until level 8, "
00169 "then for half the node at level 9, 1/4 at level 10.... "
00170 "Value -1 specify to perform at all nodes.");
00171
00172 roptions -> AddStringOption3
00173 ("convexification_type",
00174 "Deterimnes in which point the linear over/under-estimator are generated",
00175 "current-point-only",
00176 "current-point-only","Only at current optimum of relaxation",
00177 "uniform-grid","Points chosen in a unform grid between the bounds of the problem",
00178 "around-current-point","At points around current optimum of relaxation");
00179
00180 roptions -> AddLowerBoundedIntegerOption
00181 ("convexification_points",
00182 "Specify the number of points at which to convexify when convexification type"
00183 "is uniform-grid or arround-current-point.",
00184 0,4,
00185 "");
00186
00187 roptions -> AddStringOption2
00188 ("violated_cuts_only",
00189 "Yes if only violated convexification cuts should be added",
00190 "yes",
00191 "no","",
00192 "yes","");
00193
00194 roptions -> AddStringOption2
00195 ("enable_lp_implied_bounds",
00196 "Enable OsiSolverInterface::tightenBounds () -- warning: it has caused "
00197 "some trouble to Couenne",
00198 "no",
00199 "no","",
00200 "yes","");
00201
00202 CouenneProblem :: registerOptions (roptions);
00203 CouenneChooseStrong :: registerOptions (roptions);
00204 CouenneChooseVariable :: registerOptions (roptions);
00205 }