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

Go to the documentation of this file.
00001 /* $Id: createCuts.cpp 748 2011-07-28 16:13:32Z pbelotti $
00002  *
00003  * Name:    createCuts.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: a standard cut creator for use with convexification
00006  *
00007  * (C) Carnegie-Mellon University, 2006-08. 
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 #include "OsiRowCut.hpp"
00012 
00013 #include "CouenneTypes.hpp"
00014 #include "CouennePrecisions.hpp"
00015 #include "CouenneCutGenerator.hpp"
00016 #include "CouenneProblem.hpp"
00017 
00018 using namespace Ipopt;
00019 using namespace Couenne;
00020 
00022 bool badCoeff (CouNumber coe) {
00023 
00024   coe = fabs (coe);
00025   return ((coe > COU_MAX_COEFF) || ((coe < COU_MIN_COEFF) && (coe > 0.)));
00026 }
00027 
00028 
00031 
00032 int CouenneCutGenerator::createCut (OsiCuts &cs,
00033                                     CouNumber lb, CouNumber ub, 
00034                                     int i1, CouNumber c1,
00035                                     int i2, CouNumber c2,
00036                                     int i3, CouNumber c3,
00037                                     bool is_global) const {
00038   bool numerics = false;
00039 
00040   // a maximum of three terms allowed here. If index -1 (default) the
00041   // term is not considered
00042 
00043   int nterms = 0;
00044 
00045   // CAUTION: this can make the problem infeasible...
00046   if (fabs (c3) <= 1.e-21) {                                    i3 = -1;} // shift coeff/index to
00047   if (fabs (c2) <= 1.e-21) {                  c2 = c3; i2 = i3; i3 = -1;} // keep consistency
00048   if (fabs (c1) <= 1.e-21) {c1 = c2; i1 = i2; c2 = c3; i2 = i3; i3 = -1;}
00049   // why 1.e-21? Look at CoinPackedMatrix.cpp:2273
00050 
00051 #if 0
00052   if (i1 >= 0) {if (fabs (c1) > COU_MAX_COEFF) numerics = true; nterms++;} else c1 = 0;
00053   if (i2 >= 0) {if (fabs (c2) > COU_MAX_COEFF) numerics = true; nterms++;} else c2 = 0;
00054   if (i3 >= 0) {if (fabs (c3) > COU_MAX_COEFF) numerics = true; nterms++;} else c3 = 0;
00055 #else
00056   if (i1 >= 0) {if (badCoeff (c1)) numerics = true; nterms++;} else c1 = 0;
00057   if (i2 >= 0) {if (badCoeff (c2)) numerics = true; nterms++;} else c2 = 0;
00058   if (i3 >= 0) {if (badCoeff (c3)) numerics = true; nterms++;} else c3 = 0;
00059 #endif
00060 
00061   if (!nterms) // nonsense cut
00062     return 0;
00063 
00064   // cut has large coefficients/rhs, bail out
00065   if (numerics
00066       //|| ((fabs (lb) < COU_MIN_COEFF) || 
00067       //(fabs (ub) < COU_MIN_COEFF))
00068       || ((fabs (lb) > COU_MAX_COEFF) &&
00069           (fabs (ub) > COU_MAX_COEFF))) {
00070 
00071     jnlst_->Printf(J_STRONGWARNING, J_CONVEXIFYING,
00072                    "### Discarding cut, large coeff/rhs: %g (%d), %g (%d), %g (%d); [%g,%g]\n", 
00073                    c1, i1, c2, i2, c3, i3, lb, ub);
00074     return 0;
00075   }
00076 
00077   if (!firstcall_ && addviolated_) { // need to check violation 
00078 
00079     const CouNumber *x = problem_ -> X ();
00080 
00081     // compute violation
00082     CouNumber violation = 0.;
00083 
00084     if (i1 >= 0) violation += c1 * x [i1];
00085     if (i2 >= 0) violation += c2 * x [i2];
00086     if (i3 >= 0) violation += c3 * x [i3];
00087 
00088     // quit if not violated
00089 
00090     if ((violation < ub + 0 * COUENNE_EPS) &&
00091         (violation > lb - 0 * COUENNE_EPS))
00092       return 0;
00093   }
00094 
00095   // check if cut violates optimal solution (irrespective of the
00096   // branching rules applied, so handle with care)
00097 
00098   CouNumber *best = problem_ -> bestSol ();
00099 
00100   if (best &&
00101       ((i1 < 0) || ((best [i1] >= problem_ -> Lb (i1)) && (best [i1] <= problem_ -> Ub (i1)))) &&
00102       ((i2 < 0) || ((best [i2] >= problem_ -> Lb (i2)) && (best [i2] <= problem_ -> Ub (i2)))) &&
00103       ((i3 < 0) || ((best [i3] >= problem_ -> Lb (i3)) && (best [i3] <= problem_ -> Ub (i3))))) {
00104 
00105     CouNumber lhs = 0.;
00106 
00107     if (i1 >= 0) lhs += c1 * best [i1];
00108     if (i2 >= 0) lhs += c2 * best [i2];
00109     if (i3 >= 0) lhs += c3 * best [i3];
00110 
00111     if (lhs > ub + COUENNE_EPS)
00112       jnlst_->Printf(J_STRONGWARNING, J_CONVEXIFYING,
00113                      "### cut (%d,%d,%d) (%g,%g,%g) cuts optimum: %g >= %g [%g]\n", 
00114                      i1,i2,i3, c1,c2,c3, lhs, ub, lhs - ub); 
00115 
00116     if (lhs < lb - COUENNE_EPS)
00117       jnlst_->Printf(J_STRONGWARNING, J_CONVEXIFYING,
00118                      "### cut (%d,%d,%d) (%g,%g,%g) cuts optimum: %g <= %g [%g]\n", 
00119                      i1,i2,i3, c1,c2,c3, lhs, lb, lb - lhs);
00120   }
00121 
00122   // You are here if:
00123   //
00124   // 1) this is the first call to CouenneCutGenerator::generateCuts(), or
00125   // 2) you also want unviolated cuts, or
00126   // 3) the cut is violated
00127 
00128   // two cases: cut is of the form w1 [<|>]= alpha, hence a column
00129   // cut, or it is of the form (a w1 + b w2 + c w3 [<|>]= alpha), a
00130   // row cut
00131 
00132   if ((i2 < 0) && (i3 < 0)) { // column cut /////////////////////////////////////////
00133 
00134     if (   (fabs (c1) < COUENNE_EPS)
00135         && (fabs (lb) > COU_MAX_COEFF * COUENNE_EPS)
00136         && (fabs (ub) > COU_MAX_COEFF * COUENNE_EPS)) {
00137 
00138       jnlst_->Printf(J_STRONGWARNING, J_CONVEXIFYING,
00139                      "#### nonsense column cut: %e <= %e w_%d <= %e\n", 
00140                      lb, c1, i1, ub);
00141       return 0;
00142     }
00143 
00144     OsiColCut *cut = new OsiColCut;
00145 
00146     CouNumber 
00147       ll = lb / c1, 
00148       uu = ub / c1;
00149 
00150     if (c1 < 0) {
00151       CouNumber tmp = ll;
00152       ll = uu;
00153       uu = tmp;
00154     }
00155 
00156     CouNumber &curL = problem_ -> Lb (i1),
00157               &curU = problem_ -> Ub (i1);
00158 
00159     if ((uu < COUENNE_INFINITY) &&
00160         (uu < curU - COUENNE_EPS)) {
00161 
00162       cut -> setUbs (1, &i1, &uu); 
00163       curU = uu; // TODO: chg_bds
00164     }
00165 
00166     if ((ll > -COUENNE_INFINITY) && 
00167         (ll > curL + COUENNE_EPS)) {
00168       cut -> setLbs (1, &i1, &ll); 
00169       curL = ll; // idem
00170     }
00171 
00172     cut -> setGloballyValid (is_global); // global?
00173 
00174     cs.insert (cut);
00175     delete cut;
00176 
00177   } else {
00178 
00179     // row cut //////////////////////////////////////////////////////////////////////
00180 
00181     CouNumber *coeff = new CouNumber [nterms]; 
00182     int       *index = new int       [nterms];
00183     OsiRowCut *cut   = new OsiRowCut;
00184 
00185     int nt = 0;
00186 
00187     if (i1 >= 0) {coeff [nt] = c1; index [nt++] = i1;}
00188     if (i2 >= 0) {coeff [nt] = c2; index [nt++] = i2;}
00189     if (i3 >= 0) {coeff [nt] = c3; index [nt++] = i3;}
00190 
00191     if (lb > -COUENNE_INFINITY) cut -> setLb (lb);
00192     if (ub <  COUENNE_INFINITY) cut -> setUb (ub);
00193 
00194     cut -> setRow (nterms, index, coeff);
00195 
00196     delete [] coeff;
00197     delete [] index;
00198 
00199     cut -> setGloballyValid (is_global); // global?
00200 
00201     cs.insert (cut);
00202     delete cut;
00203   }
00204 
00205   return 1;
00206 }
00207 
00208 
00211 
00212 int CouenneCutGenerator::createCut (OsiCuts &cs,
00213                                     CouNumber rhs, int sign, 
00214                                     int i1, CouNumber c1,
00215                                     int i2, CouNumber c2,
00216                                     int i3, CouNumber c3,
00217                                     bool is_global)       const {
00218 
00219   return createCut (cs, (sign >= 0) ? rhs : - COIN_DBL_MAX,
00220                         (sign <= 0) ? rhs :   COIN_DBL_MAX,
00221                     i1, c1, i2, c2, i3, c3, is_global);
00222 }

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