source: trunk/Couenne/src/problem/CouenneSolverInterface.cpp @ 576

Last change on this file since 576 was 576, checked in by fmargot, 9 years ago

Fix bug in CouenneProblem::checkAux(), cosmetic changes otherwise

  • Property svn:keywords set to Author Date Id Revision
File size: 9.4 KB
Line 
1/* $Id: CouenneSolverInterface.cpp 576 2011-05-11 10:01:21Z fmargot $
2 *
3 * Name:    CouenneSolverInterface.cpp
4 * Authors: Pietro Belotti, Carnegie Mellon University
5 *          Andreas Waechter, IBM Corp.
6 * Purpose: Implementation of the OsiSolverInterface::resolve () method
7 *
8 * (C) Carnegie-Mellon University, 2006-09.
9 * This file is licensed under the Eclipse Public License (EPL)
10 */
11
12#include "OsiSolverInterface.hpp"
13
14#include "CouenneProblem.hpp"
15#include "CouenneProblemElem.hpp"
16#include "CouenneCutGenerator.hpp"
17
18#include "CouenneRecordBestSol.hpp"                         
19
20//#define FM_CHECK
21
22namespace Couenne {
23
24/// constructor
25template <class T> 
26CouenneSolverInterface<T>::CouenneSolverInterface
27(CouenneCutGenerator *cg /*= NULL*/):
28
29  T (),
30  cutgen_ (cg),
31  knowInfeasible_(false),
32  knowOptimal_(false),
33  knowDualInfeasible_(false) {}
34//  doingResolve_ (true) {}
35
36
37/// copy constructor
38template <class T> 
39CouenneSolverInterface<T>::CouenneSolverInterface
40(const CouenneSolverInterface &src):
41
42  OsiSolverInterface    (src),
43  T                     (src),
44  cutgen_               (src.cutgen_),
45  knowInfeasible_       (src.knowInfeasible_),
46  knowOptimal_          (src.knowOptimal_),
47  knowDualInfeasible_   (src.knowDualInfeasible_) {}
48//doingResolve_         (src.doingResolve_) {}
49
50/// Destructor
51template <class T> 
52CouenneSolverInterface<T>::~CouenneSolverInterface () {
53  //  if (cutgen_)
54  //    delete cutgen_;
55}
56
57
58/// Solve initial LP relaxation
59template <class T> 
60void CouenneSolverInterface<T>::initialSolve () {
61
62  knowInfeasible_     = 
63  knowOptimal_        = 
64  knowDualInfeasible_ = false;
65
66  T::initialSolve ();
67
68  // printf ("init solution: (");
69  // for (int i=0; i< T::getNumCols (); i++)
70  //   printf ("%g [%g,%g] ",
71  //        T::getColSolution () [i],
72  //        T::getColLower    () [i],
73  //        T::getColUpper    () [i]);
74  // printf (")\n");
75
76  if (T::getObjValue () <= - Couenne_large_bound)
77    knowDualInfeasible_ = true;
78
79  // some originals may be unused due to their zero multiplicity (that
80  // happens when they are duplicates), restore their value
81  if (cutgen_ -> Problem () -> nUnusedOriginals () > 0) {
82    CouNumber *x = new CouNumber [T::getNumCols ()];
83    CoinCopyN (T::getColSolution (), T::getNumCols (), x);
84    cutgen_ -> Problem () -> restoreUnusedOriginals (x);
85    T::setColSolution (x);
86    delete [] x;
87  }
88}
89
90template <class T>
91bool CouenneSolverInterface<T>::isProvenPrimalInfeasible() const {
92  return knowInfeasible_ || T::isProvenPrimalInfeasible();
93}
94
95template <class T> 
96bool CouenneSolverInterface<T>::isProvenOptimal() const {
97  return knowOptimal_ || T::isProvenOptimal();
98}
99
100template <class T> 
101bool CouenneSolverInterface<T>::isProvenDualInfeasible() const {
102  return knowDualInfeasible_ || T::isProvenDualInfeasible();
103}
104
105/// Defined in Couenne/src/convex/generateCuts.cpp
106void sparse2dense (int, t_chg_bounds *, int *&, int &);
107
108
109/// Resolve an LP relaxation after problem modification
110template <class T> 
111void CouenneSolverInterface<T>::resolve () {
112
113  static int count = -1;
114  char filename [30];
115
116  // save problem to be loaded later
117  if (cutgen_ && (cutgen_ -> check_lp ())) {
118    count++;
119    sprintf (filename, "resolve_%d", count);
120    T::writeMps (filename);
121  }
122
123  knowInfeasible_     = 
124  knowOptimal_        = 
125  knowDualInfeasible_ = false;
126
127  const CoinWarmStart *ws = NULL;
128
129  if (cutgen_ && (cutgen_ -> check_lp ()))
130    ws = T::getWarmStart ();
131
132  //deleteScaleFactors ();
133
134  // re-solve problem
135  T::resolve ();
136
137  // printf ("solution: (");
138  // for (int i=0; i< T::getNumCols (); i++)
139  //   printf ("%g ", T::getColSolution () [i]);
140  // printf (")\n");
141
142  if (T::getObjValue () <= - Couenne_large_bound)
143    knowDualInfeasible_ = true;
144
145  CouNumber
146    //objval     = T::getObjValue (),
147    curCutoff  = cutgen_ -> Problem () -> getCutOff (),
148    objvalGlob = T::getColSolution () [cutgen_ -> Problem () -> Obj (0) -> Body () -> Index ()]; 
149
150  // check if resolve found new integer solution
151  bool isChecked = false; 
152#ifdef FM_CHECKNLP2
153  double curBestVal = 1e50;                                                   
154  if(cutgen_->Problem()->getRecordBestSol()->getHasSol()) { 
155    curBestVal =  cutgen_->Problem()->getRecordBestSol()->getVal(); 
156  }
157  curBestVal = (curBestVal < curCutoff ? curBestVal : curCutoff);
158  if(isProvenOptimal()) {
159    isChecked = cutgen_->Problem()->checkNLP2(T::getColSolution(), 
160                                              curBestVal, false,
161                                              true, // stopAtFirstViol
162                                              true, // checkALL
163                                              cutgen_->Problem()->getFeasTol());
164    if(isChecked) {
165      objvalGlob = cutgen_->Problem()->getRecordBestSol()->getModSolVal();
166      if(!(objvalGlob < curBestVal - COUENNE_EPS)) {
167        isChecked = false; 
168      }
169    }
170  }
171
172#ifdef FM_CHECK
173  bool ckIsChecked = false;
174  double ckObj = objvalGlob;
175  if(isProvenOptimal () &&
176     (objvalGlob < curCutoff - COUENNE_EPS)) {
177    ckIsChecked = cutgen_->Problem()->checkNLP(T::getColSolution (),
178                                               ckObj, true);
179  }
180  if(!isChecked && ckIsChecked) {
181    printf("CouenneSolverInterface::resolve(): ### ERROR: isChecked: false  ckIsChecked: true\n");
182    exit(1);
183  }
184  else {
185    printf("CouenneSolverInterface::resolve(): isChecked == ckIsChecked\n");
186  }
187#endif
188
189#else /* not FM_CHECKNLP2 */
190  if(isProvenOptimal () &&
191     (objvalGlob < curCutoff - COUENNE_EPS)) {
192    isChecked = cutgen_->Problem()->checkNLP(T::getColSolution (),
193                                             objvalGlob, true);
194  }
195#endif /* not FM_CHECKNLP2 */
196
197  if (//doingResolve () &&    // this is not called from strong branching
198      isChecked &&
199      (objvalGlob > -COUENNE_INFINITY/2)) {    // check if it makes sense
200
201    // also save the solution so that cbcModel::setBestSolution saves it too
202
203    //printf ("new cutoff from CSI: %g\n", objval);
204    cutgen_ -> Problem () -> setCutOff (objvalGlob);
205
206#ifdef FM_TRACE_OPTSOL
207#ifdef FM_CHECKNLP2
208    cutgen_->Problem()->getRecordBestSol()->update();
209#else /* not FM_CHECKNLP2 */
210
211  // some originals may be unused due to their zero multiplicity (that
212  // happens when they are duplicates), restore their value
213  if (cutgen_ -> Problem () -> nUnusedOriginals () > 0) {
214    CouNumber *x = new CouNumber [T::getNumCols ()];
215    CoinCopyN (T::getColSolution (), T::getNumCols (), x);
216    cutgen_ -> Problem () -> restoreUnusedOriginals (x);
217    T::setColSolution (x);
218    delete [] x;
219  }
220
221  cutgen_->Problem()->getRecordBestSol()->update(T::getColSolution(), 
222                                                 cutgen_->Problem()->nVars(),
223                                                 objvalGlob,
224                                                 cutgen_->Problem()->getFeasTol());
225#endif  /* not FM_CHECKNLP2 */
226#endif /* FM_TRACE_OPTSOL */
227
228  }
229
230  // check LP independently
231  if (cutgen_ && (cutgen_ -> check_lp ())) {
232
233    OsiSolverInterface
234      *nsi = new T,
235      *csi = clone ();
236
237    sprintf (filename, "resolve_%d.mps", count);
238    nsi -> readMps (filename);
239
240    nsi -> messageHandler () -> setLogLevel (0);
241    nsi -> setWarmStart (ws);
242
243    nsi -> initialSolve ();
244
245    if ((nsi -> isProvenOptimal () && isProvenOptimal ()) ||
246        (!(nsi -> isProvenOptimal ()) && !isProvenOptimal ())) {
247
248      if (nsi -> isProvenOptimal () &&
249          (fabs (nsi -> getObjValue () - T::getObjValue ()) / 
250           (1. + fabs (nsi -> getObjValue ()) + fabs (T::getObjValue ())) > 1e-2))
251
252        printf ("Warning: discrepancy between saved %g and current %g [%g], file %s\n", 
253                nsi -> getObjValue (),  T::getObjValue (),
254                nsi -> getObjValue () - T::getObjValue (),
255                filename);
256    }
257
258    csi -> messageHandler () -> setLogLevel (0);
259    csi -> setWarmStart (ws);
260
261    csi -> initialSolve ();
262
263    if ((csi -> isProvenOptimal () && isProvenOptimal ()) ||
264        (!(csi -> isProvenOptimal ()) && !isProvenOptimal ())) {
265
266      if (csi -> isProvenOptimal () &&
267          (fabs (csi -> getObjValue () - T::getObjValue ()) / 
268           (1. + fabs (csi -> getObjValue ()) + fabs (T::getObjValue ())) > 1e-2))
269
270        printf ("Warning: discrepancy between cloned %g and current %g [%g]\n", 
271                csi -> getObjValue (),  T::getObjValue (),
272                csi -> getObjValue () - T::getObjValue ());
273    }
274
275    delete nsi;
276    delete csi;
277   
278    delete ws;
279
280    //else printf ("Warning: discrepancy between statuses %s -- %s feasible\n",
281    //filename, isProvenOptimal () ? "current" : "saved");
282  }
283}
284
285
286/// Create a hot start snapshot of the optimization process.
287template <class T> 
288void CouenneSolverInterface<T>::markHotStart () 
289{OsiSolverInterface::markHotStart ();} // OsiClpSolverInterface::markHotStart() seems not to work
290
291
292/// Delete the hot start snapshot.
293template <class T> 
294void CouenneSolverInterface<T>::unmarkHotStart () 
295{OsiSolverInterface::unmarkHotStart();}
296
297
298/// Optimize starting from the hot start snapshot.
299template <class T> 
300void CouenneSolverInterface<T>::solveFromHotStart () {
301
302  knowInfeasible_     = 
303  knowOptimal_        = 
304  knowDualInfeasible_ = false;
305
306  resolve();
307
308  if (T::getObjValue () <= - Couenne_large_bound)
309    knowDualInfeasible_ = true;
310
311  // some originals may be unused due to their zero multiplicity (that
312  // happens when they are duplicates), restore their value
313  if (cutgen_ -> Problem () -> nUnusedOriginals () > 0) {
314    CouNumber *x = new CouNumber [T::getNumCols ()];
315    CoinCopyN (T::getColSolution (), T::getNumCols (), x);
316    cutgen_ -> Problem () -> restoreUnusedOriginals (x);
317    T::setColSolution (x);
318    delete [] x;
319  }
320
321  if (isProvenPrimalInfeasible ()) knowInfeasible_     = true;
322  if (isProvenOptimal          ()) knowOptimal_        = true;
323  if (isProvenDualInfeasible   ()) knowDualInfeasible_ = true;
324}
325
326//class CouenneSolverInterface <OsiClpSolverInterface>;
327
328}
Note: See TracBrowser for help on using the repository browser.