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 {}
00037
00038
00040 template <class T>
00041 CouenneSolverInterface<T>::CouenneSolverInterface
00042 (const CouenneSolverInterface &src):
00043
00044 OsiSolverInterface (src),
00045 T (src),
00046 cutgen_ (src.cutgen_),
00047 knowInfeasible_ (src.knowInfeasible_),
00048 knowOptimal_ (src.knowOptimal_),
00049 knowDualInfeasible_ (src.knowDualInfeasible_)
00050
00051
00052 {}
00053
00054
00056 template <class T>
00057 CouenneSolverInterface<T>::~CouenneSolverInterface () {
00058
00059
00060 }
00061
00062
00064 template <class T>
00065 void CouenneSolverInterface<T>::initialSolve () {
00066
00067 knowInfeasible_ =
00068 knowOptimal_ =
00069 knowDualInfeasible_ = false;
00070
00071 T::initialSolve ();
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 if (getObjValue () <= - Couenne_large_bound)
00088 knowDualInfeasible_ = true;
00089
00090
00091
00092 if (cutgen_ -> Problem () -> nUnusedOriginals () > 0) {
00093 CouNumber *x = new CouNumber [T::getNumCols ()];
00094 CoinCopyN (T::getColSolution (), T::getNumCols (), x);
00095 cutgen_ -> Problem () -> restoreUnusedOriginals (x);
00096 T::setColSolution (x);
00097 delete [] x;
00098 }
00099 }
00100
00101 template <class T>
00102 bool CouenneSolverInterface<T>::isProvenPrimalInfeasible() const {
00103 return knowInfeasible_ || T::isProvenPrimalInfeasible();
00104 }
00105
00106 template <class T>
00107 bool CouenneSolverInterface<T>::isProvenOptimal() const {
00108 return knowOptimal_ || T::isProvenOptimal();
00109 }
00110
00111 template <class T>
00112 bool CouenneSolverInterface<T>::isProvenDualInfeasible() const {
00113 return knowDualInfeasible_ || T::isProvenDualInfeasible();
00114 }
00115
00117 void sparse2dense (int, t_chg_bounds *, int *&, int &);
00118
00119
00121 template <class T>
00122 void CouenneSolverInterface<T>::resolve () {
00123
00124 static int count = -1;
00125 char filename [30];
00126
00127
00128 if (cutgen_ && (cutgen_ -> check_lp ())) {
00129 count++;
00130 sprintf (filename, "resolve_%d", count);
00131 T::writeMps (filename);
00132 }
00133
00134 knowInfeasible_ =
00135 knowOptimal_ =
00136 knowDualInfeasible_ = false;
00137
00138 const CoinWarmStart *ws = NULL;
00139
00140 if (cutgen_ && (cutgen_ -> check_lp ()))
00141 ws = T::getWarmStart ();
00142
00143
00144
00145
00146 T::resolve ();
00147
00148
00149
00150
00151
00152
00153 if (getObjValue () <= - Couenne_large_bound)
00154 knowDualInfeasible_ = true;
00155
00156 int objind = cutgen_ -> Problem () -> Obj (0) -> Body () -> Index ();
00157
00158 CouNumber
00159
00160 curCutoff = cutgen_ -> Problem () -> getCutOff (),
00161 objvalGlob = objind >= 0 ? T::getColSolution () [objind] : cutgen_ -> Problem () -> Obj (0) -> Body () -> Value ();
00162
00163
00164 bool isChecked = false;
00165 #ifdef FM_CHECKNLP2
00166 double curBestVal = 1.e50;
00167 if(cutgen_->Problem()->getRecordBestSol()->getHasSol()) {
00168 curBestVal = cutgen_->Problem()->getRecordBestSol()->getVal();
00169 }
00170 curBestVal = (curBestVal < curCutoff ? curBestVal : curCutoff);
00171 if(isProvenOptimal()) {
00172 isChecked = cutgen_->Problem()->checkNLP2(T::getColSolution(),
00173 curBestVal, false,
00174 true,
00175 true,
00176 cutgen_->Problem()->getFeasTol());
00177 if(isChecked) {
00178 objvalGlob = cutgen_->Problem()->getRecordBestSol()->getModSolVal();
00179 if(!(objvalGlob < curBestVal - COUENNE_EPS)) {
00180 isChecked = false;
00181 }
00182 }
00183 }
00184
00185 #ifdef FM_CHECK
00186 bool ckIsChecked = false;
00187 double ckObj = objvalGlob;
00188 if(isProvenOptimal () &&
00189 (objvalGlob < curCutoff - COUENNE_EPS)) {
00190 ckIsChecked = cutgen_->Problem()->checkNLP(T::getColSolution (),
00191 ckObj, true);
00192 }
00193 if(!isChecked && ckIsChecked) {
00194 printf("CouenneSolverInterface::resolve(): ### ERROR: isChecked: false ckIsChecked: true\n");
00195 exit(1);
00196 }
00197 else {
00198 printf("CouenneSolverInterface::resolve(): isChecked == ckIsChecked\n");
00199 }
00200 #endif
00201
00202 #else
00203 if(isProvenOptimal () &&
00204 (objvalGlob < curCutoff - COUENNE_EPS)) {
00205 isChecked = cutgen_->Problem()->checkNLP(T::getColSolution (),
00206 objvalGlob, true);
00207 }
00208 #endif
00209
00210 if (
00211 isChecked &&
00212 (objvalGlob > -COUENNE_INFINITY/2)) {
00213
00214
00215
00216
00217 cutgen_ -> Problem () -> setCutOff (objvalGlob);
00218
00219 #ifdef FM_TRACE_OPTSOL
00220 #ifdef FM_CHECKNLP2
00221 cutgen_->Problem()->getRecordBestSol()->update();
00222 #else
00223
00224
00225
00226 if (cutgen_ -> Problem () -> nUnusedOriginals () > 0) {
00227 CouNumber *x = new CouNumber [T::getNumCols ()];
00228 CoinCopyN (T::getColSolution (), T::getNumCols (), x);
00229 cutgen_ -> Problem () -> restoreUnusedOriginals (x);
00230 T::setColSolution (x);
00231 delete [] x;
00232 }
00233
00234 cutgen_->Problem()->getRecordBestSol()->update(T::getColSolution(),
00235 cutgen_->Problem()->nVars(),
00236 objvalGlob,
00237 cutgen_->Problem()->getFeasTol());
00238 #endif
00239 #endif
00240
00241 }
00242
00243
00244 if (cutgen_ && (cutgen_ -> check_lp ())) {
00245
00246 OsiSolverInterface
00247 *nsi = new T,
00248 *csi = clone ();
00249
00250 sprintf (filename, "resolve_%d.mps", count);
00251 nsi -> readMps (filename);
00252
00253 nsi -> messageHandler () -> setLogLevel (0);
00254 nsi -> setWarmStart (ws);
00255
00256 nsi -> initialSolve ();
00257
00258 if ((nsi -> isProvenOptimal () && isProvenOptimal ()) ||
00259 (!(nsi -> isProvenOptimal ()) && !isProvenOptimal ())) {
00260
00261 if (nsi -> isProvenOptimal () &&
00262 (fabs (nsi -> getObjValue () - T::getObjValue ()) /
00263 (1. + fabs (nsi -> getObjValue ()) + fabs (T::getObjValue ())) > 1e-2))
00264
00265 printf ("Warning: discrepancy between saved %g and current %g [%g], file %s\n",
00266 nsi -> getObjValue (), T::getObjValue (),
00267 nsi -> getObjValue () - T::getObjValue (),
00268 filename);
00269 }
00270
00271 csi -> messageHandler () -> setLogLevel (0);
00272 csi -> setWarmStart (ws);
00273
00274 csi -> initialSolve ();
00275
00276 if ((csi -> isProvenOptimal () && isProvenOptimal ()) ||
00277 (!(csi -> isProvenOptimal ()) && !isProvenOptimal ())) {
00278
00279 if (csi -> isProvenOptimal () &&
00280 (fabs (csi -> getObjValue () - getObjValue ()) /
00281 (1. + fabs (csi -> getObjValue ()) + fabs (getObjValue ())) > 1e-2))
00282
00283 printf ("Warning: discrepancy between cloned %g and current %g [%g]\n",
00284 csi -> getObjValue (), getObjValue (),
00285 csi -> getObjValue () - getObjValue ());
00286 }
00287
00288 delete nsi;
00289 delete csi;
00290
00291 delete ws;
00292
00293
00294
00295 }
00296 }
00297
00298
00300 template <class T>
00301 void CouenneSolverInterface<T>::markHotStart ()
00302 {OsiSolverInterface::markHotStart ();}
00303
00304
00306 template <class T>
00307 void CouenneSolverInterface<T>::unmarkHotStart ()
00308 {OsiSolverInterface::unmarkHotStart();}
00309
00310
00312 template <class T>
00313 void CouenneSolverInterface<T>::solveFromHotStart () {
00314
00315 knowInfeasible_ =
00316 knowOptimal_ =
00317 knowDualInfeasible_ = false;
00318
00319 resolve();
00320
00321 if (getObjValue () <= - Couenne_large_bound)
00322 knowDualInfeasible_ = true;
00323
00324
00325
00326 if (cutgen_ -> Problem () -> nUnusedOriginals () > 0) {
00327 CouNumber *x = new CouNumber [T::getNumCols ()];
00328 CoinCopyN (T::getColSolution (), T::getNumCols (), x);
00329 cutgen_ -> Problem () -> restoreUnusedOriginals (x);
00330 T::setColSolution (x);
00331 delete [] x;
00332 }
00333
00334 if (isProvenPrimalInfeasible ()) knowInfeasible_ = true;
00335 if (isProvenOptimal ()) knowOptimal_ = true;
00336 if (isProvenDualInfeasible ()) knowDualInfeasible_ = true;
00337 }
00338
00341 template <class T>
00342 inline double CouenneSolverInterface<T>::getObjValue() const {
00343 return cutgen_ -> Problem () -> constObjVal () + T::getObjValue();
00344 }
00345
00346 }