00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "BonCouenneInterface.hpp"
00013 #include "CoinHelperFunctions.hpp"
00014 #include "CouenneProblem.hpp"
00015
00016 namespace Bonmin {
00017
00019 CouenneInterface::CouenneInterface():
00020 AmplInterface(),
00021 have_nlp_solution_ (false)
00022 {}
00023
00025 CouenneInterface::CouenneInterface(const CouenneInterface &other):
00026 AmplInterface(other),
00027 have_nlp_solution_ (false)
00028 {}
00029
00031 CouenneInterface * CouenneInterface::clone(bool CopyData){
00032 return new CouenneInterface(*this);
00033 }
00034
00036 CouenneInterface::~CouenneInterface(){
00037 }
00038
00039
00040 void
00041 CouenneInterface::readAmplNlFile(char **& argv, Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions,
00042 Ipopt::SmartPtr<Ipopt::OptionsList> options,
00043 Ipopt::SmartPtr<Ipopt::Journalist> journalist){
00044 AmplInterface::readAmplNlFile(argv, roptions, options, journalist);
00045 }
00046
00059 void
00060 CouenneInterface::extractLinearRelaxation
00061 (OsiSolverInterface &si, CouenneCutGenerator & couenneCg, bool getObj, bool solveNlp) {
00062
00063 CouenneProblem *p = couenneCg.Problem ();
00064
00065 if (solveNlp) {
00066
00067 int nvars = p -> nVars();
00068
00069 if (p -> doFBBT ()) {
00070
00071
00072
00073
00074 for (int i=0; i < p -> nCons (); i++) {
00075
00076
00077 CouenneConstraint *con = p -> Con (i);
00078
00079
00080 int index = con -> Body () -> Index ();
00081
00082 if ((index >= 0) && (con -> Body () -> Type () == AUX)) {
00083
00084
00085 CouNumber
00086 l = con -> Lb () -> Value (),
00087 u = con -> Ub () -> Value ();
00088
00089
00090 p -> Lb (index) = CoinMax (l, p -> Lb (index));
00091 p -> Ub (index) = CoinMin (u, p -> Ub (index));
00092 }
00093 }
00094
00095 t_chg_bounds *chg_bds = new t_chg_bounds [nvars];
00096
00097 for (int i=0; i<nvars; i++) {
00098 chg_bds [i].setLower(t_chg_bounds::CHANGED);
00099 chg_bds [i].setUpper(t_chg_bounds::CHANGED);
00100 }
00101
00102 if (!(p -> boundTightening (chg_bds, NULL)))
00103 printf ("warning, tightened NLP is infeasible\n");
00104
00105 delete [] chg_bds;
00106
00107 const double
00108 *nlb = getColLower (),
00109 *nub = getColUpper ();
00110
00111 for (int i=0; i < p -> nOrigVars (); i++)
00112 if (p -> Var (i) -> Multiplicity () > 0) {
00113 if (nlb [i] < p -> Lb (i) - COUENNE_EPS) setColLower (i, p -> Lb (i));
00114 if (nub [i] > p -> Ub (i) + COUENNE_EPS) setColUpper (i, p -> Ub (i));
00115 } else {
00116
00117 setColLower (i, 0.);
00118 setColUpper (i, 0.);
00119 }
00120 }
00121
00122 initialSolve ();
00123
00124 if (isProvenOptimal ()) {
00125
00126 CouNumber obj = getObjValue ();
00127 const CouNumber *solution = getColSolution ();
00128
00129 if (getNumIntegers () > 0) {
00130
00131 int
00132 norig = p -> nOrigVars (),
00133 nvars = p -> nVars ();
00134
00135 bool fractional = false;
00136
00137
00138
00139
00140 for (int i=0; i<norig; i++)
00141 if (p -> Var (i) -> isInteger () &&
00142 (p -> Var (i) -> Multiplicity () > 0) &&
00143 (!::isInteger (solution [i]))) {
00144 fractional = true;
00145 break;
00146 }
00147
00148 if (fractional) {
00149
00150 double
00151 *lbSave = new double [norig],
00152 *ubSave = new double [norig],
00153
00154 *lbCur = new double [nvars],
00155 *ubCur = new double [nvars],
00156
00157 *Y = new double [nvars];
00158
00159 CoinCopyN (getColLower (), norig, lbSave);
00160 CoinCopyN (getColUpper (), norig, ubSave);
00161
00162 CoinFillN (Y, nvars, 0.);
00163 CoinFillN (lbCur, nvars, -COUENNE_INFINITY);
00164 CoinFillN (ubCur, nvars, COUENNE_INFINITY);
00165
00166 CoinCopyN (getColLower (), norig, lbCur);
00167 CoinCopyN (getColUpper (), norig, ubCur);
00168
00169 if (p -> getIntegerCandidate (solution, Y, lbCur, ubCur) >= 0) {
00170
00171 for (int i=0; i<norig; i++)
00172 if ((p -> Var (i) -> Multiplicity () > 0) &&
00173 p -> Var (i) -> isInteger ()) {
00174 setColLower (i, lbCur [i]);
00175 setColUpper (i, ubCur [i]);
00176 }
00177
00178 setColSolution (Y);
00179
00180 resolve ();
00181
00182 obj = getObjValue ();
00183 solution = getColSolution ();
00184
00185 for (int i=0; i<norig; i++)
00186 if ((p -> Var (i) -> Multiplicity () > 0) &&
00187 p -> Var (i) -> isInteger ()) {
00188 setColLower (i, lbSave [i]);
00189 setColUpper (i, ubSave [i]);
00190 }
00191 }
00192
00193 delete [] Y;
00194 delete [] lbSave;
00195 delete [] ubSave;
00196 delete [] lbCur;
00197 delete [] ubCur;
00198 }
00199 }
00200
00201
00202 if (isProvenOptimal () &&
00203 (obj < p -> getCutOff ()) &&
00204 p -> checkNLP (solution, obj)) {
00205
00206
00207 have_nlp_solution_ = true;
00208
00209
00210 p -> setCutOff (obj);
00211
00212 OsiAuxInfo * auxInfo = si.getAuxiliaryInfo ();
00213 BabInfo * babInfo = dynamic_cast <BabInfo *> (auxInfo);
00214
00215 if (babInfo) {
00216 babInfo -> setNlpSolution (solution, getNumCols (), obj);
00217 babInfo -> setHasNlpSolution (true);
00218 }
00219 }
00220 }
00221 }
00222
00223 int
00224 numcols = getNumCols (),
00225 numcolsconv = p -> nVars ();
00226
00227 const double
00228 *lb = getColLower (),
00229 *ub = getColUpper ();
00230
00231
00232 for (int i=0; i<numcols; i++)
00233 if (p -> Var (i) -> Multiplicity () > 0) si.addCol (0, NULL,NULL, lb [i], ub [i], 0);
00234 else si.addCol (0, NULL,NULL, 0., 0., 0);
00235 for (int i=numcols; i<numcolsconv; i++) si.addCol (0, NULL,NULL, -COIN_DBL_MAX,COIN_DBL_MAX,0);
00236
00237
00238 OsiCuts cs;
00239 couenneCg.generateCuts (si, cs);
00240
00241
00242 CouNumber * colLower = new CouNumber [numcolsconv];
00243 CouNumber * colUpper = new CouNumber [numcolsconv];
00244
00245 CouNumber *ll = p -> Lb ();
00246 CouNumber *uu = p -> Ub ();
00247
00248
00249 for (int i = numcolsconv; i--;)
00250 if (p -> Var (i) -> Multiplicity () > 0) {
00251 colLower [i] = (ll [i] > - COUENNE_INFINITY) ? ll [i] : -COIN_DBL_MAX;
00252 colUpper [i] = (uu [i] < COUENNE_INFINITY) ? uu [i] : COIN_DBL_MAX;
00253 } else {
00254 colLower [i] = 0.;
00255 colUpper [i] = 0.;
00256 }
00257
00258 int numrowsconv = cs.sizeRowCuts ();
00259
00260
00261 CoinBigIndex * start = new CoinBigIndex [numrowsconv + 1];
00262
00263 int * length = new int [numrowsconv];
00264 double * rowLower = new double [numrowsconv];
00265 double * rowUpper = new double [numrowsconv];
00266
00267 start[0] = 0;
00268 int nnz = 0;
00269
00270 for(int i = 0 ; i < numrowsconv ; i++)
00271 {
00272 OsiRowCut * cut = cs.rowCutPtr (i);
00273
00274 const CoinPackedVector &v = cut->row();
00275 start[i+1] = start[i] + v.getNumElements();
00276 nnz += v.getNumElements();
00277 length[i] = v.getNumElements();
00278
00279 rowLower[i] = cut->lb();
00280 rowUpper[i] = cut->ub();
00281 }
00282
00283 assert (nnz == start [numrowsconv]);
00284
00285 int * ind = new int[start[numrowsconv]];
00286 double * elem = new double[start[numrowsconv]];
00287 for(int i = 0 ; i < numrowsconv ; i++) {
00288
00289 OsiRowCut * cut = cs.rowCutPtr (i);
00290
00291 const CoinPackedVector &v = cut->row();
00292
00293 if(v.getNumElements() != length[i])
00294 std::cout<<"Empty row"<<std::endl;
00295
00296 CoinCopyN (v.getIndices(), length[i], ind + start[i]);
00297 CoinCopyN (v.getElements(), length[i], elem + start[i]);
00298 }
00299
00300
00301 CoinPackedMatrix A;
00302 A.assignMatrix(false, numcolsconv, numrowsconv,
00303 start[numrowsconv], elem, ind,
00304 start, length);
00305 if(A.getNumCols() != numcolsconv || A.getNumRows() != numrowsconv){
00306 std::cout<<"Error in row number"<<std::endl;
00307 }
00308 assert(A.getNumElements() == nnz);
00309
00310 double * obj = new double[numcolsconv];
00311 CoinFillN(obj,numcolsconv,0.);
00312
00313
00314 if (p -> nObjs () > 0)
00315 p -> fillObjCoeff (obj);
00316
00317
00318 si.loadProblem (A, colLower, colUpper, obj, rowLower, rowUpper);
00319
00320 delete [] rowLower;
00321 delete [] rowUpper;
00322 delete [] colLower;
00323 delete [] colUpper;
00324 delete [] obj;
00325
00326 for (int i=0; i<numcolsconv; i++)
00327 if ((p -> Var (i) -> Multiplicity () > 0) &&
00328 (p -> Var (i) -> isDefinedInteger ()))
00329 si.setInteger (i);
00330
00331
00332
00333 app_ -> enableWarmStart();
00334
00335
00336 setColSolution (problem () -> x_sol ());
00337 setRowPrice (problem () -> duals_sol ());
00338
00339 }
00340
00341
00343 void CouenneInterface::setAppDefaultOptions(Ipopt::SmartPtr<Ipopt::OptionsList> Options){
00344 Options->SetStringValue("bonmin.algorithm", "B-Couenne", true, true);
00345 Options->SetIntegerValue("bonmin.filmint_ecp_cuts", 1, true, true);
00346 }
00347 }