/home/coin/SVN-release/OS-2.4.0/Couenne/src/problem/CouenneSolverInterface.cpp

Go to the documentation of this file.
00001 /* $Id: CouenneSolverInterface.cpp 660 2011-06-15 13:58:24Z pbelotti $
00002  *
00003  * Name:    CouenneSolverInterface.cpp
00004  * Authors: Pietro Belotti, Carnegie Mellon University
00005  *          Andreas Waechter, IBM Corp.
00006  * Purpose: Implementation of the OsiSolverInterface::resolve () method 
00007  *
00008  * (C) Carnegie-Mellon University, 2006-09.
00009  * This file is licensed under the Eclipse Public License (EPL)
00010  */
00011 
00012 #include "OsiSolverInterface.hpp"
00013 
00014 #include "CouenneProblem.hpp"
00015 #include "CouenneProblemElem.hpp"
00016 #include "CouenneCutGenerator.hpp"
00017 
00018 #include "CouenneRecordBestSol.hpp"                         
00019 
00020 //#define FM_CHECK
00021 
00022 namespace Couenne {
00023 
00025 template <class T> 
00026 CouenneSolverInterface<T>::CouenneSolverInterface 
00027 (CouenneCutGenerator *cg /*= NULL*/):
00028 
00029   T (),
00030   cutgen_ (cg),
00031   knowInfeasible_(false),
00032   knowOptimal_(false),
00033   knowDualInfeasible_(false) {}
00034 //  doingResolve_ (true) {}
00035 
00036 
00038 template <class T> 
00039 CouenneSolverInterface<T>::CouenneSolverInterface 
00040 (const CouenneSolverInterface &src):
00041 
00042   OsiSolverInterface    (src),
00043   T                     (src),
00044   cutgen_               (src.cutgen_),
00045   knowInfeasible_       (src.knowInfeasible_),
00046   knowOptimal_          (src.knowOptimal_),
00047   knowDualInfeasible_   (src.knowDualInfeasible_) {}
00048 //doingResolve_         (src.doingResolve_) {}
00049 
00051 template <class T> 
00052 CouenneSolverInterface<T>::~CouenneSolverInterface () {
00053   //  if (cutgen_)
00054   //    delete cutgen_;
00055 }
00056 
00057 
00059 template <class T> 
00060 void CouenneSolverInterface<T>::initialSolve () {
00061 
00062   knowInfeasible_     = 
00063   knowOptimal_        = 
00064   knowDualInfeasible_ = false;
00065 
00066   T::initialSolve ();
00067 
00068   // printf ("init solution: (");
00069   // for (int i=0; i< T::getNumCols (); i++)
00070   //   printf ("%g [%g,%g] ", 
00071   //        T::getColSolution () [i],
00072   //        T::getColLower    () [i],
00073   //        T::getColUpper    () [i]);
00074   // printf (")\n");
00075 
00076   if (T::getObjValue () <= - Couenne_large_bound)
00077     knowDualInfeasible_ = true;
00078 
00079   // some originals may be unused due to their zero multiplicity (that
00080   // happens when they are duplicates), restore their value
00081   if (cutgen_ -> Problem () -> nUnusedOriginals () > 0) {
00082     CouNumber *x = new CouNumber [T::getNumCols ()];
00083     CoinCopyN (T::getColSolution (), T::getNumCols (), x);
00084     cutgen_ -> Problem () -> restoreUnusedOriginals (x);
00085     T::setColSolution (x);
00086     delete [] x;
00087   }
00088 }
00089 
00090 template <class T>
00091 bool CouenneSolverInterface<T>::isProvenPrimalInfeasible() const {
00092   return knowInfeasible_ || T::isProvenPrimalInfeasible();
00093 }
00094 
00095 template <class T> 
00096 bool CouenneSolverInterface<T>::isProvenOptimal() const {
00097   return knowOptimal_ || T::isProvenOptimal();
00098 }
00099 
00100 template <class T> 
00101 bool CouenneSolverInterface<T>::isProvenDualInfeasible() const {
00102   return knowDualInfeasible_ || T::isProvenDualInfeasible();
00103 }
00104 
00106 void sparse2dense (int, t_chg_bounds *, int *&, int &);
00107 
00108 
00110 template <class T> 
00111 void CouenneSolverInterface<T>::resolve () {
00112 
00113   static int count = -1;
00114   char filename [30];
00115 
00116   // save problem to be loaded later
00117   if (cutgen_ && (cutgen_ -> check_lp ())) {
00118     count++;
00119     sprintf (filename, "resolve_%d", count);
00120     T::writeMps (filename);
00121   }
00122 
00123   knowInfeasible_     = 
00124   knowOptimal_        = 
00125   knowDualInfeasible_ = false;
00126 
00127   const CoinWarmStart *ws = NULL;
00128 
00129   if (cutgen_ && (cutgen_ -> check_lp ()))
00130     ws = T::getWarmStart ();
00131 
00132   //deleteScaleFactors ();
00133 
00134   // re-solve problem
00135   T::resolve ();
00136 
00137   // printf ("solution: (");
00138   // for (int i=0; i< T::getNumCols (); i++)
00139   //   printf ("%g ", T::getColSolution () [i]);
00140   // printf (")\n");
00141 
00142   if (T::getObjValue () <= - Couenne_large_bound)
00143     knowDualInfeasible_ = true;
00144 
00145   CouNumber 
00146     //objval     = T::getObjValue (),
00147     curCutoff  = cutgen_ -> Problem () -> getCutOff (),
00148     objvalGlob = T::getColSolution () [cutgen_ -> Problem () -> Obj (0) -> Body () -> Index ()];  
00149 
00150   // check if resolve found new integer solution
00151   bool isChecked = false;  
00152 #ifdef FM_CHECKNLP2
00153   double curBestVal = 1e50;                                                    
00154   if(cutgen_->Problem()->getRecordBestSol()->getHasSol()) { 
00155     curBestVal =  cutgen_->Problem()->getRecordBestSol()->getVal(); 
00156   }
00157   curBestVal = (curBestVal < curCutoff ? curBestVal : curCutoff);
00158   if(isProvenOptimal()) {
00159     isChecked = cutgen_->Problem()->checkNLP2(T::getColSolution(), 
00160                                               curBestVal, false,
00161                                               true, // stopAtFirstViol
00162                                               true, // checkALL
00163                                               cutgen_->Problem()->getFeasTol());
00164     if(isChecked) {
00165       objvalGlob = cutgen_->Problem()->getRecordBestSol()->getModSolVal();
00166       if(!(objvalGlob < curBestVal - COUENNE_EPS)) {
00167         isChecked = false; 
00168       }
00169     }
00170   }
00171 
00172 #ifdef FM_CHECK
00173   bool ckIsChecked = false;
00174   double ckObj = objvalGlob;
00175   if(isProvenOptimal () &&
00176      (objvalGlob < curCutoff - COUENNE_EPS)) {
00177     ckIsChecked = cutgen_->Problem()->checkNLP(T::getColSolution (),
00178                                                ckObj, true);
00179   }
00180   if(!isChecked && ckIsChecked) {
00181     printf("CouenneSolverInterface::resolve(): ### ERROR: isChecked: false  ckIsChecked: true\n");
00182     exit(1);
00183   }
00184   else {
00185     printf("CouenneSolverInterface::resolve(): isChecked == ckIsChecked\n");
00186   }
00187 #endif
00188 
00189 #else /* not FM_CHECKNLP2 */
00190   if(isProvenOptimal () &&
00191      (objvalGlob < curCutoff - COUENNE_EPS)) {
00192     isChecked = cutgen_->Problem()->checkNLP(T::getColSolution (),
00193                                              objvalGlob, true);
00194   }
00195 #endif /* not FM_CHECKNLP2 */
00196 
00197   if (//doingResolve () &&    // this is not called from strong branching
00198       isChecked &&
00199       (objvalGlob > -COUENNE_INFINITY/2)) {    // check if it makes sense
00200 
00201     // also save the solution so that cbcModel::setBestSolution saves it too
00202 
00203     //printf ("new cutoff from CSI: %g\n", objval);
00204     cutgen_ -> Problem () -> setCutOff (objvalGlob);
00205 
00206 #ifdef FM_TRACE_OPTSOL
00207 #ifdef FM_CHECKNLP2
00208     cutgen_->Problem()->getRecordBestSol()->update();
00209 #else /* not FM_CHECKNLP2 */
00210 
00211   // some originals may be unused due to their zero multiplicity (that
00212   // happens when they are duplicates), restore their value
00213   if (cutgen_ -> Problem () -> nUnusedOriginals () > 0) {
00214     CouNumber *x = new CouNumber [T::getNumCols ()];
00215     CoinCopyN (T::getColSolution (), T::getNumCols (), x);
00216     cutgen_ -> Problem () -> restoreUnusedOriginals (x);
00217     T::setColSolution (x);
00218     delete [] x;
00219   }
00220 
00221   cutgen_->Problem()->getRecordBestSol()->update(T::getColSolution(), 
00222                                                  cutgen_->Problem()->nVars(),
00223                                                  objvalGlob,
00224                                                  cutgen_->Problem()->getFeasTol());
00225 #endif  /* not FM_CHECKNLP2 */
00226 #endif /* FM_TRACE_OPTSOL */
00227 
00228   }
00229 
00230   // check LP independently
00231   if (cutgen_ && (cutgen_ -> check_lp ())) {
00232 
00233     OsiSolverInterface
00234       *nsi = new T,
00235       *csi = clone ();
00236 
00237     sprintf (filename, "resolve_%d.mps", count);
00238     nsi -> readMps (filename);
00239 
00240     nsi -> messageHandler () -> setLogLevel (0);
00241     nsi -> setWarmStart (ws);
00242 
00243     nsi -> initialSolve ();
00244 
00245     if ((nsi -> isProvenOptimal () && isProvenOptimal ()) ||
00246         (!(nsi -> isProvenOptimal ()) && !isProvenOptimal ())) {
00247 
00248       if (nsi -> isProvenOptimal () &&
00249           (fabs (nsi -> getObjValue () - T::getObjValue ()) / 
00250            (1. + fabs (nsi -> getObjValue ()) + fabs (T::getObjValue ())) > 1e-2))
00251 
00252         printf ("Warning: discrepancy between saved %g and current %g [%g], file %s\n", 
00253                 nsi -> getObjValue (),  T::getObjValue (),
00254                 nsi -> getObjValue () - T::getObjValue (),
00255                 filename);
00256     }
00257 
00258     csi -> messageHandler () -> setLogLevel (0);
00259     csi -> setWarmStart (ws);
00260 
00261     csi -> initialSolve ();
00262 
00263     if ((csi -> isProvenOptimal () && isProvenOptimal ()) ||
00264         (!(csi -> isProvenOptimal ()) && !isProvenOptimal ())) {
00265 
00266       if (csi -> isProvenOptimal () &&
00267           (fabs (csi -> getObjValue () - T::getObjValue ()) / 
00268            (1. + fabs (csi -> getObjValue ()) + fabs (T::getObjValue ())) > 1e-2))
00269 
00270         printf ("Warning: discrepancy between cloned %g and current %g [%g]\n", 
00271                 csi -> getObjValue (),  T::getObjValue (),
00272                 csi -> getObjValue () - T::getObjValue ());
00273     }
00274 
00275     delete nsi;
00276     delete csi;
00277     
00278     delete ws;
00279 
00280     //else printf ("Warning: discrepancy between statuses %s -- %s feasible\n", 
00281     //filename, isProvenOptimal () ? "current" : "saved");
00282   }
00283 }
00284 
00285 
00287 template <class T> 
00288 void CouenneSolverInterface<T>::markHotStart () 
00289 {OsiSolverInterface::markHotStart ();} // OsiClpSolverInterface::markHotStart() seems not to work
00290 
00291 
00293 template <class T> 
00294 void CouenneSolverInterface<T>::unmarkHotStart () 
00295 {OsiSolverInterface::unmarkHotStart();}
00296 
00297 
00299 template <class T> 
00300 void CouenneSolverInterface<T>::solveFromHotStart () {
00301 
00302   knowInfeasible_     = 
00303   knowOptimal_        = 
00304   knowDualInfeasible_ = false;
00305 
00306   resolve();
00307 
00308   if (T::getObjValue () <= - Couenne_large_bound)
00309     knowDualInfeasible_ = true;
00310 
00311   // some originals may be unused due to their zero multiplicity (that
00312   // happens when they are duplicates), restore their value
00313   if (cutgen_ -> Problem () -> nUnusedOriginals () > 0) {
00314     CouNumber *x = new CouNumber [T::getNumCols ()];
00315     CoinCopyN (T::getColSolution (), T::getNumCols (), x);
00316     cutgen_ -> Problem () -> restoreUnusedOriginals (x);
00317     T::setColSolution (x);
00318     delete [] x;
00319   }
00320 
00321   if (isProvenPrimalInfeasible ()) knowInfeasible_     = true;
00322   if (isProvenOptimal          ()) knowOptimal_        = true;
00323   if (isProvenDualInfeasible   ()) knowDualInfeasible_ = true;
00324 }
00325 
00326 }

Generated on Thu Sep 22 03:05:59 2011 by  doxygen 1.4.7