source: branches/Couenne/Couenne/src/convex/operators/conv-exprAbs.cpp @ 534

Last change on this file since 534 was 534, checked in by pbelotti, 13 years ago

moved include files to make them doxygenable. Introduced three-way branching, with fixed intervals for now. Added check for small bound interval within all generateCuts()

File size: 1.8 KB
Line 
1/*
2 * Name:    conv-exprAbs.cpp
3 * Author:  Pietro Belotti
4 * Purpose: convexification methods for |f(x)|
5 *
6 * This file is licensed under the Common Public License (CPL)
7 */
8
9#include <OsiSolverInterface.hpp>
10#include <CouenneTypes.h>
11#include <CouenneCutGenerator.h>
12#include <exprAbs.h>
13#include <exprAux.h>
14
15
16// generate convexification cut for constraint w = |x|
17
18void exprAbs::generateCuts (exprAux *w, const OsiSolverInterface &si, 
19                            OsiCuts &cs, const CouenneCutGenerator *cg) {
20
21  int w_ind = w         -> Index (),
22      x_ind = argument_ -> Index ();
23
24  expression *lbe, *ube;
25  argument_ -> getBounds (lbe, ube);
26
27  CouNumber l = (*lbe) (),
28            u = (*ube) ();
29
30  delete lbe;
31  delete ube;
32
33  // if l, u have the same sign, then w = x (l > 0) or w = -x (u < 0)
34
35  if      (l >= 0) cg -> createCut (cs, 0., 0, w_ind, 1., x_ind, -1.);
36  else if (u <= 0) cg -> createCut (cs, 0., 0, w_ind, 1., x_ind, +1.);
37  else {
38
39    // add two global cuts: w >= x and w >= -x
40    if (cg -> isFirst ()) {
41      cg -> createCut (cs, 0., +1, w_ind, 1., x_ind, -1.);
42      cg -> createCut (cs, 0., +1, w_ind, 1., x_ind,  1.);
43    }
44
45    // otherwise check if at most one of the bounds is infinite: even
46    // so, we can still add a plane, whose slope will be 1 (if x is
47    // unbounded from above) or -1 (from below)
48
49    if (l > - COUENNE_INFINITY) {
50
51      if (u < COUENNE_INFINITY) { // the upper approximation has slope other than -1, 1
52
53          CouNumber slope = (u+l) / (u-l);
54          // add an upper segment, which depends on the lower/upper bounds
55          cg -> createCut (cs, -l*(slope+1.), -1, w_ind, 1., x_ind, -slope);
56        }
57        else // slope = 1
58          cg -> createCut (cs, -2*l, -1, w_ind, 1., x_ind, -1.);
59      }
60      else if (u < COUENNE_INFINITY) // slope = -1
61        cg -> createCut (cs, 2*u, -1, w_ind, 1., x_ind, 1.);
62    }
63}
Note: See TracBrowser for help on using the repository browser.