1 /* $Id$
2  *
3  * Name:    CouenneLPtightenBounds.cpp
4  * Authors: Pietro Belotti, Carnegie Mellon University
5  * Purpose: tighten LP bounds on all variables (including continuous)
6  *
7  * (C) Carnegie-Mellon University, 2008-09.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "CouenneProblem.hpp"
12 #include "CouenneCutGenerator.hpp"
13 
14 namespace Couenne {
15 
16 // Tighten bounds - lightweight. Returns -1 if infeasible, otherwise
17 // number of variables tightened.
18 template <class T>
tightenBounds(int lightweight)19 int CouenneSolverInterface<T>::tightenBounds (int lightweight) {
20 
21   if (!(cutgen_ -> enableLpImpliedBounds ()))
22     return 0;
23 
24   int
25     ncols = T::getNumCols (),
26     nTightened;
27 
28   double
29     *oldLower = new double [ncols],
30     *oldUpper = new double [ncols];
31 
32   CoinCopyN (T::getColLower (), ncols, oldLower);
33   CoinCopyN (T::getColUpper (), ncols, oldUpper);
34 
35 //   printf ("-------- BOUNDS BEFORE ------------\n  ");
36 //   int j=0;
37 //   for (int i=0; i < ncols; i++) {
38 //     printf("x_%03d [%+15.8g %+15.8g] ", i, oldLower [i], oldUpper [i]);
39 //     if (!(++j % 6)) printf ("\n  ");
40 //   }
41 //   if (j % 6) printf ("\n");
42 
43   nTightened = tightenBoundsCLP (lightweight);
44 
45   if (nTightened < 0)
46     return nTightened;
47 
48 //   printf ("-------- BOUNDS DURING ------------\n  ");
49 //   j=0;
50 //   for (int i=0; i < ncols; i++) {
51 //     printf("x_%03d [%+15.8g %+15.8g] ", i, getColLower () [i], getColUpper () [i]);
52 //     if (!(++j % 6)) printf ("\n  ");
53 //   }
54 //   if (j % 6) printf ("\n");
55 
56   if (nTightened > 0) {
57 
58     // something was tightened. Run an extra btCore "por si las
59     // moscas" (just in case)
60 
61     const double
62       *newLower = T::getColLower (),
63       *newUpper = T::getColUpper ();
64 
65     t_chg_bounds *chgd = new t_chg_bounds [ncols];
66 
67     for (int i=0; i<ncols; i++) {
68       if (newLower [i] > oldLower [i] + COUENNE_EPS) chgd [i].setLower (t_chg_bounds::CHANGED);
69       if (newUpper [i] < oldUpper [i] - COUENNE_EPS) chgd [i].setUpper (t_chg_bounds::CHANGED);
70     }
71 
72     cutgen_ -> Problem () -> domain () -> push (ncols, NULL, newLower, newUpper);
73 
74     if (!(cutgen_ -> Problem () -> btCore (chgd))) // infeasible
75       nTightened = -1;
76 
77     else {
78 
79       const double
80 	*newerLower = cutgen_ -> Problem () -> Lb (),
81 	*newerUpper = cutgen_ -> Problem () -> Ub ();
82 
83       for (int i=0; i<ncols; i++) {
84 
85 	if (newerLower [i] > newLower [i] + COUENNE_EPS) {
86 	  T::setColLower (i, newerLower [i]);
87 	  if (newLower [i] < oldLower [i] + COUENNE_EPS) nTightened++; // extra tightening
88 	}
89 
90       	if (newerUpper [i] < newUpper [i] - COUENNE_EPS) {
91 	  T::setColUpper (i, newerUpper [i]);
92 	  if (newUpper [i] > oldUpper [i] - COUENNE_EPS) nTightened++; // extra tightening
93 	}
94       }
95     }
96 
97 //     const double
98 //       *newerLower = cutgen_ -> Problem () -> Lb (),
99 //       *newerUpper = cutgen_ -> Problem () -> Ub ();
100 
101 //     printf ("-------- BOUNDS AFTER ------------\n  ");
102 //     for (int i=0; i < ncols; i++) {
103 //       printf("x_%03d [%+15.8g %+15.8g] ", i, newerLower [i], newerUpper [i]);
104 //       if (!(++j % 6)) printf ("\n  ");
105 //     }
106 //     if (j % 6) printf ("\n");
107 
108     cutgen_ -> Problem () -> domain () -> pop ();
109 
110     delete [] chgd;
111   }
112 
113   delete [] oldLower;
114   delete [] oldUpper;
115 
116   return nTightened;
117 }
118 
119 }
120