/home/coin/SVN-release/OS-2.1.1/Couenne/src/convex/addEnvelope.cpp

Go to the documentation of this file.
00001 /* $Id: addEnvelope.cpp 141 2009-06-03 04:19:19Z pbelotti $ */
00002 /*
00003  * File: addEnvelope.cpp
00004  * Author: Pietro Belotti, Carnegie Mellon University
00005  * Purpose: add generic envelope to convex function based on function and its derivative
00006  *
00007  * (C) Carnegie-Mellon University, 2006. 
00008  * This file is licensed under the Common Public License (CPL)
00009  */
00010 
00011 
00012 #include "OsiRowCut.hpp"
00013 #include "CouennePrecisions.hpp"
00014 #include "CouenneTypes.hpp"
00015 #include "CouenneCutGenerator.hpp"
00016 #include "funtriplets.hpp"
00017 
00018 
00019 void CouenneCutGenerator::addEnvelope (OsiCuts &cs, int sign,
00020                                        unary_function f,      // function to be linearized
00021                                        unary_function fprime, // derivative of f
00022                                        int w_ind, int x_ind, 
00023                                        CouNumber x, CouNumber l, CouNumber u,
00024                                        t_chg_bounds *chg,
00025                                        bool is_global) const {
00026 
00027   simpletriplet st (f, fprime, fprime); // don't really care about third parameter...
00028   addEnvelope (cs, sign, &st, w_ind, x_ind, x, l, u, chg, is_global);
00029 }
00030 
00031 
00032 void CouenneCutGenerator::addEnvelope (OsiCuts &cs, int sign,
00033                                        funtriplet *ft,
00034                                        int w_ind, int x_ind, 
00035                                        CouNumber x, CouNumber l, CouNumber u,
00036                                        t_chg_bounds *chg,
00037                                        bool is_global) const {
00038   CouNumber opp_slope = - ft -> Fp (x);
00039 
00040   // TODO: remove check of !firstcall_ if point is available already
00041 
00042   // if bounds are very close, convexify with a single line
00043 
00044   bool cLeft  = !chg || (chg [x_ind].lower() != t_chg_bounds::UNCHANGED) || firstcall_;
00045   bool cRight = !chg || (chg [x_ind].upper() != t_chg_bounds::UNCHANGED) || firstcall_;
00046 
00047   if (fabs (u - l) < COUENNE_EPS) {
00048 
00049     CouNumber x0 = 0.5 * (u+l), fp0 = ft -> Fp (x0);
00050     if (cLeft || cRight) 
00051       createCut (cs, ft -> F(x0) - fp0 * x0, 0, w_ind, 1., x_ind, - fp0);
00052     return;
00053   }
00054 
00055   // Add tangent in any case
00056 
00057   if (((!firstcall_) || ((x >= l) && (x <= u)))
00058       && (fabs (opp_slope) < COUENNE_INFINITY))
00059     createCut (cs, ft -> F (x) + opp_slope * x, sign, w_ind, 1., 
00060                x_ind, opp_slope, -1, 0., is_global);
00061 
00062     //      addTangent (cs, w_ind, x_ind, x, f (x), fprime (x), sign);
00063 
00064   if ((convtype_ == UNIFORM_GRID) || firstcall_) {
00065 
00066     if (cLeft || cRight) {
00067       // now add tangent at each sampling point
00068 
00069       CouNumber sample = l, 
00070         step   = (u-l) / nSamples_;
00071 
00072       //    printf ("[%.4f %.4f], step = %.4f, %d samples\n", 
00073       //            l, u, step, nSamples_);
00074 
00075       for (int i = 0; i <= nSamples_; i++) {
00076 
00077         opp_slope = - ft -> Fp (sample);
00078 
00079         if ((fabs (opp_slope) < COUENNE_INFINITY) && 
00080             (fabs (sample-x) > COUENNE_EPS)) // do not add twice cut at current point
00081           createCut (cs, ft -> F (sample) + opp_slope * sample, sign, 
00082                      w_ind, 1.,
00083                      x_ind, opp_slope, 
00084                      -1, 0., is_global);
00085 
00086         //      printf ("  Uniform %d: ", i); cut -> print ();
00087 
00088         sample += step;
00089       }
00090     }
00091   }
00092   else if (convtype_ != CURRENT_ONLY) {
00093 
00094     CouNumber sample = x;
00095 
00096     if (fabs (opp_slope) < COUENNE_INFINITY)
00097       createCut (cs, ft -> F (x) + opp_slope * x, sign, 
00098                  w_ind, 1.,
00099                  x_ind, opp_slope, 
00100                  -1, 0.,
00101                  is_global);
00102       //      printf ("  Current tangent: "); cut -> print ();
00103 
00104     for (int i = 0; i <= nSamples_/2; i++) {
00105 
00106       sample += (x-l) / nSamples_;
00107       opp_slope = - ft -> Fp (sample);
00108 
00109       if (fabs (opp_slope) < COUENNE_INFINITY)
00110         createCut (cs, ft -> F (sample) + opp_slope * sample, sign, 
00111                    w_ind, 1.,
00112                    x_ind, opp_slope, 
00113                    -1, 0.,
00114                    is_global);
00115         //      printf ("  neighbour -%d: ", i); cut -> print ();
00116     }
00117 
00118     sample = x;
00119 
00120     for (int i = 0; i <= nSamples_/2; i++) {
00121 
00122       sample += (u-x) / nSamples_;
00123       opp_slope = - ft -> Fp (sample);
00124 
00125       createCut (cs, ft -> F(sample) + opp_slope * sample, sign, 
00126                  w_ind, 1.,
00127                  x_ind, opp_slope, 
00128                  -1, 0.,
00129                  is_global);
00130         //      printf ("  neighbour  %d: ", i); cut -> print ();
00131     }
00132   }
00133 }

Generated on Mon May 3 03:05:19 2010 by  doxygen 1.4.7