00001
00002
00003
00004
00005
00006
00007
00008
00009
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
00021
00022 namespace Couenne {
00023
00025 template <class T>
00026 CouenneSolverInterface<T>::CouenneSolverInterface
00027 (CouenneCutGenerator *cg ):
00028
00029 T (),
00030 cutgen_ (cg),
00031 knowInfeasible_(false),
00032 knowOptimal_(false),
00033 knowDualInfeasible_(false) {}
00034
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
00049
00051 template <class T>
00052 CouenneSolverInterface<T>::~CouenneSolverInterface () {
00053
00054
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
00069
00070
00071
00072
00073
00074
00075
00076 if (getObjValue () <= - Couenne_large_bound)
00077 knowDualInfeasible_ = true;
00078
00079
00080
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
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
00133
00134
00135 T::resolve ();
00136
00137
00138
00139
00140
00141
00142 if (getObjValue () <= - Couenne_large_bound)
00143 knowDualInfeasible_ = true;
00144
00145 int objind = cutgen_ -> Problem () -> Obj (0) -> Body () -> Index ();
00146
00147 CouNumber
00148
00149 curCutoff = cutgen_ -> Problem () -> getCutOff (),
00150 objvalGlob = objind >= 0 ? T::getColSolution () [objind] : cutgen_ -> Problem () -> Obj (0) -> Body () -> Value ();
00151
00152
00153 bool isChecked = false;
00154 #ifdef FM_CHECKNLP2
00155 double curBestVal = 1.e50;
00156 if(cutgen_->Problem()->getRecordBestSol()->getHasSol()) {
00157 curBestVal = cutgen_->Problem()->getRecordBestSol()->getVal();
00158 }
00159 curBestVal = (curBestVal < curCutoff ? curBestVal : curCutoff);
00160 if(isProvenOptimal()) {
00161 isChecked = cutgen_->Problem()->checkNLP2(T::getColSolution(),
00162 curBestVal, false,
00163 true,
00164 true,
00165 cutgen_->Problem()->getFeasTol());
00166 if(isChecked) {
00167 objvalGlob = cutgen_->Problem()->getRecordBestSol()->getModSolVal();
00168 if(!(objvalGlob < curBestVal - COUENNE_EPS)) {
00169 isChecked = false;
00170 }
00171 }
00172 }
00173
00174 #ifdef FM_CHECK
00175 bool ckIsChecked = false;
00176 double ckObj = objvalGlob;
00177 if(isProvenOptimal () &&
00178 (objvalGlob < curCutoff - COUENNE_EPS)) {
00179 ckIsChecked = cutgen_->Problem()->checkNLP(T::getColSolution (),
00180 ckObj, true);
00181 }
00182 if(!isChecked && ckIsChecked) {
00183 printf("CouenneSolverInterface::resolve(): ### ERROR: isChecked: false ckIsChecked: true\n");
00184 exit(1);
00185 }
00186 else {
00187 printf("CouenneSolverInterface::resolve(): isChecked == ckIsChecked\n");
00188 }
00189 #endif
00190
00191 #else
00192 if(isProvenOptimal () &&
00193 (objvalGlob < curCutoff - COUENNE_EPS)) {
00194 isChecked = cutgen_->Problem()->checkNLP(T::getColSolution (),
00195 objvalGlob, true);
00196 }
00197 #endif
00198
00199 if (
00200 isChecked &&
00201 (objvalGlob > -COUENNE_INFINITY/2)) {
00202
00203
00204
00205
00206 cutgen_ -> Problem () -> setCutOff (objvalGlob);
00207
00208 #ifdef FM_TRACE_OPTSOL
00209 #ifdef FM_CHECKNLP2
00210 cutgen_->Problem()->getRecordBestSol()->update();
00211 #else
00212
00213
00214
00215 if (cutgen_ -> Problem () -> nUnusedOriginals () > 0) {
00216 CouNumber *x = new CouNumber [T::getNumCols ()];
00217 CoinCopyN (T::getColSolution (), T::getNumCols (), x);
00218 cutgen_ -> Problem () -> restoreUnusedOriginals (x);
00219 T::setColSolution (x);
00220 delete [] x;
00221 }
00222
00223 cutgen_->Problem()->getRecordBestSol()->update(T::getColSolution(),
00224 cutgen_->Problem()->nVars(),
00225 objvalGlob,
00226 cutgen_->Problem()->getFeasTol());
00227 #endif
00228 #endif
00229
00230 }
00231
00232
00233 if (cutgen_ && (cutgen_ -> check_lp ())) {
00234
00235 OsiSolverInterface
00236 *nsi = new T,
00237 *csi = clone ();
00238
00239 sprintf (filename, "resolve_%d.mps", count);
00240 nsi -> readMps (filename);
00241
00242 nsi -> messageHandler () -> setLogLevel (0);
00243 nsi -> setWarmStart (ws);
00244
00245 nsi -> initialSolve ();
00246
00247 if ((nsi -> isProvenOptimal () && isProvenOptimal ()) ||
00248 (!(nsi -> isProvenOptimal ()) && !isProvenOptimal ())) {
00249
00250 if (nsi -> isProvenOptimal () &&
00251 (fabs (nsi -> getObjValue () - T::getObjValue ()) /
00252 (1. + fabs (nsi -> getObjValue ()) + fabs (T::getObjValue ())) > 1e-2))
00253
00254 printf ("Warning: discrepancy between saved %g and current %g [%g], file %s\n",
00255 nsi -> getObjValue (), T::getObjValue (),
00256 nsi -> getObjValue () - T::getObjValue (),
00257 filename);
00258 }
00259
00260 csi -> messageHandler () -> setLogLevel (0);
00261 csi -> setWarmStart (ws);
00262
00263 csi -> initialSolve ();
00264
00265 if ((csi -> isProvenOptimal () && isProvenOptimal ()) ||
00266 (!(csi -> isProvenOptimal ()) && !isProvenOptimal ())) {
00267
00268 if (csi -> isProvenOptimal () &&
00269 (fabs (csi -> getObjValue () - getObjValue ()) /
00270 (1. + fabs (csi -> getObjValue ()) + fabs (getObjValue ())) > 1e-2))
00271
00272 printf ("Warning: discrepancy between cloned %g and current %g [%g]\n",
00273 csi -> getObjValue (), getObjValue (),
00274 csi -> getObjValue () - getObjValue ());
00275 }
00276
00277 delete nsi;
00278 delete csi;
00279
00280 delete ws;
00281
00282
00283
00284 }
00285 }
00286
00287
00289 template <class T>
00290 void CouenneSolverInterface<T>::markHotStart ()
00291 {OsiSolverInterface::markHotStart ();}
00292
00293
00295 template <class T>
00296 void CouenneSolverInterface<T>::unmarkHotStart ()
00297 {OsiSolverInterface::unmarkHotStart();}
00298
00299
00301 template <class T>
00302 void CouenneSolverInterface<T>::solveFromHotStart () {
00303
00304 knowInfeasible_ =
00305 knowOptimal_ =
00306 knowDualInfeasible_ = false;
00307
00308 resolve();
00309
00310 if (getObjValue () <= - Couenne_large_bound)
00311 knowDualInfeasible_ = true;
00312
00313
00314
00315 if (cutgen_ -> Problem () -> nUnusedOriginals () > 0) {
00316 CouNumber *x = new CouNumber [T::getNumCols ()];
00317 CoinCopyN (T::getColSolution (), T::getNumCols (), x);
00318 cutgen_ -> Problem () -> restoreUnusedOriginals (x);
00319 T::setColSolution (x);
00320 delete [] x;
00321 }
00322
00323 if (isProvenPrimalInfeasible ()) knowInfeasible_ = true;
00324 if (isProvenOptimal ()) knowOptimal_ = true;
00325 if (isProvenDualInfeasible ()) knowDualInfeasible_ = true;
00326 }
00327
00330 template <class T>
00331 inline double CouenneSolverInterface<T>::getObjValue() const {
00332 return cutgen_ -> Problem () -> constObjVal () + T::getObjValue();
00333 }
00334
00335
00336 }