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 bool tightened = false;
00266
00267 for (int i=0; i<ncols; i++, newLo++, newUp++) {
00268
00269 if (*newLo > *oldLo++ + COUENNE_EPS) {tighterLower.insert (i, *newLo); tightened = true;}
00270 if (*newUp < *oldUp++ - COUENNE_EPS) {tighterUpper.insert (i, *newUp); tightened = true;}
00271 }
00272
00273 if (tightened) {
00274 OsiColCut tighter;
00275 tighter.setLbs (tighterLower);
00276 tighter.setUbs (tighterUpper);
00277 if (jnlst_ -> ProduceOutput (J_DETAILED, J_DISJCUTS)) {
00278 printf ("tightened bounds in disjunctive cuts:");
00279 tighter.print ();
00280 }
00281 cs.insert (tighter);
00282 }
00283
00284 int deltaNcuts =
00285 cs.sizeRowCuts () - initRowCuts +
00286 cs.sizeColCuts () - initColCuts;
00287
00288 if (info.level <= 0 && !(info.inTree))
00289 nrootcuts_ += deltaNcuts;
00290 ntotalcuts_ += deltaNcuts;
00291
00292 if (jnlst_ -> ProduceOutput (J_DETAILED, J_DISJCUTS)) {
00293
00294 if (cs.sizeRowCuts()>initRowCuts) printf ("added %d row cuts\n", cs.sizeRowCuts () - initRowCuts);
00295 if (cs.sizeColCuts()>initColCuts) printf ("added %d col cuts\n", cs.sizeColCuts () - initColCuts);
00296 }
00297
00298 if ((info.level <= 0) && !(info.inTree))
00299 jnlst_ -> Printf (J_ERROR, J_COUENNE,
00300 "%d cuts\n", CoinMax (0, nrootcuts_ - nInitCuts));
00301 else if (deltaNcuts)
00302 jnlst_ -> Printf (J_WARNING, J_COUENNE,
00303 "In-BB disjunctive cuts: %d row cuts, %d col cuts\n",
00304 cs.sizeRowCuts () - initRowCuts,
00305 cs.sizeColCuts () - initColCuts);
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 delete csi;
00319
00320 septime_ += (CoinCpuTime () - time);
00321 }