/home/coin/SVN-release/OS-2.2.0/Couenne/src/convex/operators/conv-exprAbs.cpp

Go to the documentation of this file.
00001 /* $Id: conv-exprAbs.cpp 217 2009-07-08 17:02:07Z pbelotti $
00002  *
00003  * Name:    conv-exprAbs.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: convexification methods for |f(x)|
00006  *
00007  * (C) Carnegie-Mellon University, 2006-09.
00008  * This file is licensed under the Common Public License (CPL)
00009  */
00010 
00011 #include "OsiSolverInterface.hpp"
00012 #include "CouenneTypes.hpp"
00013 #include "CouenneCutGenerator.hpp"
00014 #include "exprAbs.hpp"
00015 #include "exprAux.hpp"
00016 
00017 
00018 // generate convexification cut for constraint w = |x|
00019 
00020 void exprAbs::generateCuts (expression *w, //const OsiSolverInterface &si, 
00021                             OsiCuts &cs, const CouenneCutGenerator *cg, 
00022                             t_chg_bounds *chg, int wind, 
00023                             CouNumber lbw, CouNumber ubw) {
00024 
00025   int w_ind = w         -> Index (),
00026       x_ind = argument_ -> Index ();
00027 
00028   CouNumber l, u;
00029   argument_ -> getBounds (l, u);
00030 
00031   bool
00032     cbase  = !chg || cg -> isFirst (),
00033     cLeft  = cbase || (chg [x_ind].lower() != t_chg_bounds::UNCHANGED),
00034     cRight = cbase || (chg [x_ind].upper() != t_chg_bounds::UNCHANGED);
00035 
00036   // if l, u have the same sign, then w = x (l > 0) or w = -x (u < 0)
00037 
00038   if      (l >= -0) {if (cLeft)  cg -> createCut (cs, 0., 0, w_ind, 1., x_ind, -1.);}
00039   else if (u <=  0) {if (cRight) cg -> createCut (cs, 0., 0, w_ind, 1., x_ind, +1.);}
00040   else {
00041 
00042     // add two global cuts: w >= x and w >= -x
00043     if (cg -> isFirst ()) {
00044       cg -> createCut (cs, 0., +1, w_ind, 1., x_ind, -1.);
00045       cg -> createCut (cs, 0., +1, w_ind, 1., x_ind,  1.);
00046     }
00047 
00048     // otherwise check if at most one of the bounds is infinite: even
00049     // so, we can still add a plane, whose slope is 1 (x unbounded
00050     // from above) or -1 (from below)
00051 
00052     if (l > - COUENNE_INFINITY) {
00053       if (u < COUENNE_INFINITY) { // the upper approximation has slope other than -1, 1
00054 
00055         CouNumber slope = (u+l) / (u-l); // should be stable, l < 0 < u
00056 
00057         // add an upper segment, which depends on the lower/upper bounds
00058         if (cLeft || cRight) 
00059           cg -> createCut (cs, -l*(slope+1.), -1, w_ind, 1., x_ind, -slope);
00060       }
00061       else // slope = 1
00062         if (cLeft) cg -> createCut (cs, -2*l, -1, w_ind, 1., x_ind, -1.);
00063     }
00064     else if (u < COUENNE_INFINITY) // slope = -1
00065       if (cRight) cg -> createCut (cs, 2*u, -1, w_ind, 1., x_ind, 1.);
00066   }
00067 }

Generated on Thu Aug 5 03:02:56 2010 by  doxygen 1.4.7