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

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

Fix bugs related to CouenneRecordBestSol?, add flags FM_UP_BND and FM_PRINT_INFO

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