00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <vector>
00012 #include "CoinTime.hpp"
00013
00014 #include "CouenneCutGenerator.hpp"
00015 #include "CouenneDisjCuts.hpp"
00016 #include "CouenneProblem.hpp"
00017 #include "CouenneInfeasCut.hpp"
00018
00019 using namespace Ipopt;
00020 using namespace Couenne;
00021
00023 void CouenneDisjCuts::generateCuts (const OsiSolverInterface &si,
00024 OsiCuts &cs,
00025 const CglTreeInfo info)
00026 #if CGL_VERSION_MAJOR == 0 && CGL_VERSION_MINOR <= 57
00027 const
00028 #endif
00029 {
00030
00031
00032
00033
00034
00035
00036 if (isWiped (cs))
00037 return;
00038
00039 if (jnlst_ -> ProduceOutput (J_DETAILED, J_DISJCUTS))
00040 printf ("--- generateDisjCuts: level = %d, pass = %d, intree = %d [%d]\n",
00041 info.level, info.pass, info.inTree, depthStopSeparate_);
00042
00043 if ((depthStopSeparate_ >= 0) &&
00044 (info.level > depthStopSeparate_))
00045 return;
00046
00047 int nInitCuts = nrootcuts_;
00048
00049 if ((info.level <= 0) && !(info.inTree)) {
00050
00051 jnlst_ -> Printf (J_ERROR, J_COUENNE,
00052 "Disjunctive cuts (root node): ");
00053 fflush (stdout);
00054 }
00055
00056 double time = CoinCpuTime ();
00057
00058
00059 OsiSolverInterface *csi = si.clone ();
00060
00061 int
00062 initRowCuts = cs.sizeRowCuts (),
00063 initColCuts = cs.sizeColCuts ();
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 int maxDisj = (initDisjNumber_ >= 0) ?
00116 CoinMin ((int) (csi -> numberObjects () * initDisjPercentage_), initDisjNumber_) :
00117 (int) (csi -> numberObjects () * initDisjPercentage_);
00118
00119
00120 numDisjunctions_ = (depthLevelling_ < 0 || info.level < depthLevelling_) ?
00121 (int) (maxDisj) :
00122 (int) (maxDisj / (2 + info.level - depthLevelling_));
00123
00124 if (numDisjunctions_ < 1) numDisjunctions_ = 1;
00125
00126 const int
00127 exc_infeasible = 1,
00128 exc_normal = 2,
00129 max_iterations = 1;
00130
00131 couenneCG_ -> Problem () -> domain () -> push (&si, &cs, false);
00132
00133 std::vector <std::pair <OsiCuts *, OsiCuts *> > disjunctions;
00134
00135 bool infeasNode = false;
00136
00137 try {
00138
00139
00140
00141 bool start_over;
00142 int iterations = 0;
00143
00144 do {
00145
00146
00147 ++iterations;
00148
00149 start_over = false;
00150
00151
00152 int result = getDisjunctions (disjunctions, *csi, cs, info);
00153
00154 if (result == COUENNE_INFEASIBLE) throw exc_infeasible;
00155 else if (result == COUENNE_TIGHTENED &&
00156 iterations < max_iterations) start_over = true;
00157
00158 if (disjunctions.empty ())
00159 throw exc_normal;
00160
00161
00162 for (std::vector <std::pair <OsiCuts *, OsiCuts *> >::iterator disjI = disjunctions.begin ();
00163 disjI != disjunctions.end (); ++disjI) {
00164
00165 if (CoinCpuTime () > couenneCG_ -> Problem () -> getMaxCpuTime ()) {
00166 start_over = false;
00167 break;
00168 }
00169
00170
00171
00172
00173 result = separateWithDisjunction (disjI -> first, *csi, cs, info);
00174 if (result == COUENNE_INFEASIBLE) throw exc_infeasible;
00175 else if (result == COUENNE_TIGHTENED && iterations < max_iterations) {
00176 start_over = true;
00177 break;
00178 }
00179
00180
00181 result = separateWithDisjunction (disjI -> second, *csi, cs, info);
00182 if (result == COUENNE_INFEASIBLE) throw exc_infeasible;
00183 else if (result == COUENNE_TIGHTENED && iterations < max_iterations) {
00184 start_over = true;
00185 break;
00186 }
00187 }
00188
00189 if (start_over) {
00190
00191 for (std::vector <std::pair <OsiCuts *, OsiCuts *> >::iterator disjI = disjunctions.begin ();
00192 disjI != disjunctions.end (); ++disjI) {
00193 delete disjI -> first;
00194 delete disjI -> second;
00195 }
00196
00197 disjunctions.erase (disjunctions.begin (), disjunctions.end ());
00198 }
00199
00200 if (!start_over && jnlst_ -> ProduceOutput (J_VECTOR, J_DISJCUTS))
00201
00202
00203 for (std::vector <std::pair <OsiCuts *, OsiCuts *> >::iterator disjI = disjunctions.begin ();
00204 disjI != disjunctions.end (); ++disjI) {
00205
00206 printf ("=========================== CUTS for the LEFT part\n");
00207 for (int i=0; i<disjI->first->sizeColCuts (); i++) disjI->first->colCutPtr(i)->print();
00208 for (int i=0; i<disjI->first->sizeRowCuts (); i++) disjI->first->rowCutPtr(i)->print();
00209 printf ("=========================== CUTS for the RIGHT part\n");
00210 for (int i=0; i<disjI->second->sizeColCuts (); i++) disjI->second->colCutPtr(i)->print();
00211 for (int i=0; i<disjI->second->sizeRowCuts (); i++) disjI->second->rowCutPtr(i)->print();
00212 printf ("===========================\n");
00213 }
00214
00215 } while (start_over && (iterations < max_iterations));
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 if (generateDisjCuts (disjunctions, *csi, cs, info) == COUENNE_INFEASIBLE)
00228 throw exc_infeasible;
00229 }
00230
00231 catch (int exception) {
00232
00233 if (exception == exc_infeasible) {
00234
00235 jnlst_ -> Printf (J_DETAILED, J_DISJCUTS, "--- Disjunctive Cut separator: infeasible node\n");
00236 WipeMakeInfeas (cs);
00237 infeasNode = true;
00238 }
00239 }
00240
00241
00242 for (std::vector <std::pair <OsiCuts *, OsiCuts *> >::iterator disjI = disjunctions.begin ();
00243 disjI != disjunctions.end (); ++disjI) {
00244
00245 delete disjI -> first;
00246 delete disjI -> second;
00247 }
00248
00249 couenneCG_ -> Problem () -> domain () -> pop ();
00250
00251 if (!infeasNode) {
00252
00253
00254
00255 CoinPackedVector
00256 tighterLower,
00257 tighterUpper;
00258
00259 const double
00260 *oldLo = si. getColLower (), *newLo = csi -> getColLower (),
00261 *oldUp = si. getColUpper (), *newUp = csi -> getColUpper ();
00262
00263 int ncols = si.getNumCols ();
00264
00265 for (int i=0; i<ncols; i++, newLo++, newUp++) {
00266
00267 if (*newLo > *oldLo++ + COUENNE_EPS) tighterLower.insert (i, *newLo);
00268 if (*newUp < *oldUp++ - COUENNE_EPS) tighterUpper.insert (i, *newUp);
00269 }
00270
00271 if ((tighterLower.getNumElements () > 0) ||
00272 (tighterUpper.getNumElements () > 0)) {
00273 OsiColCut tighter;
00274 tighter.setLbs (tighterLower);
00275 tighter.setUbs (tighterUpper);
00276 if (jnlst_ -> ProduceOutput (J_DETAILED, J_DISJCUTS)) {
00277 printf ("tightened bounds in disjunctive cuts:");
00278 tighter.print ();
00279 }
00280 cs.insert (tighter);
00281 }
00282
00283 int deltaNcuts =
00284 cs.sizeRowCuts () - initRowCuts +
00285 cs.sizeColCuts () - initColCuts;
00286
00287 if (info.level <= 0 && !(info.inTree))
00288 nrootcuts_ += deltaNcuts;
00289 ntotalcuts_ += deltaNcuts;
00290
00291 if (jnlst_ -> ProduceOutput (J_DETAILED, J_DISJCUTS)) {
00292
00293 if (cs.sizeRowCuts()>initRowCuts) printf ("added %d row cuts\n", cs.sizeRowCuts () - initRowCuts);
00294 if (cs.sizeColCuts()>initColCuts) printf ("added %d col cuts\n", cs.sizeColCuts () - initColCuts);
00295 }
00296
00297 if ((info.level <= 0) && !(info.inTree))
00298 jnlst_ -> Printf (J_ERROR, J_COUENNE,
00299 "%d cuts\n", CoinMax (0, nrootcuts_ - nInitCuts));
00300 else if (deltaNcuts)
00301 jnlst_ -> Printf (J_WARNING, J_COUENNE,
00302 "In-BB disjunctive cuts: %d row cuts, %d col cuts\n",
00303 cs.sizeRowCuts () - initRowCuts,
00304 cs.sizeColCuts () - initColCuts);
00305 }
00306
00307 if (jnlst_ -> ProduceOutput (J_DETAILED, J_DISJCUTS)) {
00308
00309 printf ("Disjunctive cuts (%d row + %d col):\n", cs.sizeRowCuts () - initRowCuts, cs.sizeColCuts () - initColCuts);
00310 for (int i=initRowCuts; i<cs.sizeRowCuts (); ++i) cs.rowCutPtr (i) -> print ();
00311 for (int i=initColCuts; i<cs.sizeColCuts (); ++i) cs.colCutPtr (i) -> print ();
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 delete csi;
00325
00326 septime_ += (CoinCpuTime () - time);
00327 }