/home/coin/SVN-release/OS-2.4.1/Couenne/src/interfaces/BonCouenneInterface.cpp

Go to the documentation of this file.
00001 /* $Id: BonCouenneInterface.cpp 752 2011-08-08 03:45:07Z pbelotti $ */
00002 // (C) Copyright International Business Machines Corporation (IBM) 2006, 2007
00003 // All Rights Reserved.
00004 // This code is published under the Eclipse Public License (EPL).
00005 //
00006 // Authors :
00007 // Pietro Belotti, Carnegie Mellon University
00008 // Pierre Bonami, International Business Machines Corporation
00009 //
00010 // Date : 12/19/2006
00011 
00012 
00013 #include "BonCouenneInterface.hpp"
00014 #include "CoinHelperFunctions.hpp"
00015 
00016 #include "CouenneProblem.hpp"
00017 #include "CouenneProblemElem.hpp"
00018 #include "CouenneExprVar.hpp"
00019 #include "CouenneRecordBestSol.hpp"
00020 
00021 using namespace Couenne;
00022 
00024 CouenneInterface::CouenneInterface():
00025   AmplInterface(),
00026   have_nlp_solution_ (false)
00027 {}
00028 
00030 CouenneInterface::CouenneInterface(const CouenneInterface &other):
00031   AmplInterface(other),
00032   have_nlp_solution_ (false)
00033 {}
00034 
00036 CouenneInterface * CouenneInterface::clone(bool CopyData){
00037   return new CouenneInterface(*this);
00038 }
00039 
00041 CouenneInterface::~CouenneInterface(){
00042 }
00043 
00044 #ifdef COUENNEINTERFACE_FROM_ASL
00045 void 
00046 CouenneInterface::readAmplNlFile(char **& argv, Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions,
00047                                  Ipopt::SmartPtr<Ipopt::OptionsList> options,
00048                                  Ipopt::SmartPtr<Ipopt::Journalist> journalist){
00049   //  if (!IsValid (app_))
00050   //createApplication (roptions, options, journalist, "couenne.");
00051   AmplInterface::readAmplNlFile(argv, roptions, options, journalist);
00052 }
00053 #endif
00054 
00067 void
00068 CouenneInterface::extractLinearRelaxation 
00069 (OsiSolverInterface &si, CouenneCutGenerator & couenneCg, bool getObj, bool solveNlp) {
00070 
00071   {
00072     int nlpLogLevel;
00073     options () -> GetIntegerValue ("nlp_log_level", nlpLogLevel, "couenne.");
00074     messageHandler () -> setLogLevel (nlpLogLevel);
00075   }
00076 
00077   CouenneProblem *p = couenneCg.Problem ();
00078   bool is_feasible = true;
00079 
00080   if (solveNlp) {
00081 
00082     int nvars = p -> nVars();
00083 
00084     if (p -> doFBBT ()) {
00085 
00086       // include the rhs of auxiliary-based constraints into the FBBT
00087       // (should be useful with Vielma's problems, for example)
00088 
00089       for (int i=0; i < p -> nCons (); i++) {
00090 
00091         // for each constraint
00092         CouenneConstraint *con = p -> Con (i);
00093 
00094         // (which has an aux as its body)
00095         int index = con -> Body () -> Index ();
00096 
00097         if ((index >= 0) && (con -> Body () -> Type () == AUX)) {
00098 
00099           // if there exists violation, add constraint
00100           CouNumber 
00101             l = con -> Lb () -> Value (),       
00102             u = con -> Ub () -> Value ();
00103 
00104           // tighten bounds in Couenne's problem representation
00105           p -> Lb (index) = CoinMax (l, p -> Lb (index));
00106           p -> Ub (index) = CoinMin (u, p -> Ub (index));
00107         }
00108       }
00109 
00110       t_chg_bounds *chg_bds = new t_chg_bounds [nvars];
00111 
00112       for (int i=0; i<nvars; i++) {
00113         chg_bds [i].setLower(t_chg_bounds::CHANGED);
00114         chg_bds [i].setUpper(t_chg_bounds::CHANGED);
00115       }
00116 
00117       if (!(p -> boundTightening (chg_bds, NULL))) {
00118         is_feasible = false;
00119         *messageHandler() << "Couenne: Warning, tightened NLP is infeasible" << CoinMessageEol;
00120       }
00121 
00122       delete [] chg_bds;
00123 
00124       const double 
00125         *nlb = getColLower (),
00126         *nub = getColUpper ();
00127 
00128       for (int i=0; i < p -> nOrigVars () - p -> nDefVars (); i++) 
00129         if (p -> Var (i) -> Multiplicity () > 0) {
00130           /*printf ("---- %4d [%g,%g] [%g,%g]\n", i,
00131                   nlb [i], nub [i],
00132                   p -> Lb (i), p -> Ub (i));*/
00133           if (nlb [i] < p -> Lb (i) - COUENNE_EPS) setColLower (i, p -> Lb (i));
00134           if (nub [i] > p -> Ub (i) + COUENNE_EPS) setColUpper (i, p -> Ub (i));
00135         } else { 
00136           // if not enabled, fix them in the NLP solver
00137           setColLower (i, -COIN_DBL_MAX);
00138           setColUpper (i,  COIN_DBL_MAX);
00139         }
00140     } // ends FBBT part
00141 
00142     if (is_feasible) {
00143       try {
00144         options () -> SetNumericValue ("max_cpu_time", CoinMax (0., (p -> getMaxCpuTime () - CoinCpuTime ()) / 2));
00145         initialSolve ();
00146       }
00147       catch (Bonmin::TNLPSolver::UnsolvedError *E) {
00148         // wrong, if NLP has problems this is not necessarily true...
00149         //is_feasible = false;
00150       }
00151     }
00152 
00153     if (!is_feasible) {
00154       OsiAuxInfo * auxInfo = si.getAuxiliaryInfo ();
00155       Bonmin::BabInfo * babInfo = dynamic_cast <Bonmin::BabInfo *> (auxInfo);
00156 
00157       if (babInfo) 
00158         babInfo -> setInfeasibleNode ();
00159     }
00160     
00161     if (is_feasible && isProvenOptimal ()) {
00162 
00163       CouNumber obj             = getObjValue    ();
00164       const CouNumber *solution = getColSolution ();
00165 
00166       if (getNumIntegers () > 0) {
00167 
00168         int
00169           norig = p -> nOrigVars () - p -> nDefVars (),
00170           nvars = p -> nVars ();
00171 
00172         bool fractional = false;
00173 
00174         // if problem is integer, check if any integral variable is
00175         // fractional. If so, round them and re-optimize
00176 
00177         for (int i=0; i<norig; i++)
00178           if ((p -> Var (i) -> Multiplicity () > 0) &&
00179               p  -> Var (i) -> isDefinedInteger () &&
00180               (!::isInteger (solution [i]))) {
00181             fractional = true;
00182             break;
00183           }
00184 
00185         if (fractional) { // try again if solution found by Ipopt is fractional
00186 
00187           double 
00188             *lbSave = new double [norig],
00189             *ubSave = new double [norig],
00190 
00191             *lbCur  = new double [nvars],
00192             *ubCur  = new double [nvars],
00193 
00194             *Y      = new double [nvars];
00195 
00196           CoinCopyN (getColLower (), norig, lbSave);
00197           CoinCopyN (getColUpper (), norig, ubSave);
00198 
00199           CoinFillN (Y,     nvars, 0.);
00200           CoinFillN (lbCur, nvars, -COUENNE_INFINITY);
00201           CoinFillN (ubCur, nvars,  COUENNE_INFINITY);
00202 
00203           CoinCopyN (getColLower (), norig, lbCur);
00204           CoinCopyN (getColUpper (), norig, ubCur);
00205 
00206           if (p -> getIntegerCandidate (solution, Y, lbCur, ubCur) >= 0) {
00207 
00208             for (int i = getNumCols (); i--;) {
00209 
00210               if (lbCur [i] > ubCur [i]) {
00211                 double swap = lbCur [i];
00212                 lbCur [i] = ubCur [i];
00213                 ubCur [i] = swap;
00214               }
00215 
00216               if      (Y [i] < lbCur [i]) Y [i] = lbCur [i];
00217               else if (Y [i] > ubCur [i]) Y [i] = ubCur [i];
00218             }
00219 
00220             for (int i=0; i<norig; i++)
00221               if ((p -> Var (i) -> Multiplicity () > 0) &&
00222                   p  -> Var (i) -> isDefinedInteger ()) {
00223                 setColLower (i, lbCur [i]);
00224                 setColUpper (i, ubCur [i]);
00225               }
00226 
00227             setColSolution (Y); // use initial solution given 
00228 
00229             try {
00230               options () -> SetNumericValue ("max_cpu_time", CoinMax (0., p -> getMaxCpuTime () - CoinCpuTime ()));
00231               resolve (); // solve with integer variables fixed
00232             }
00233             catch (Bonmin::TNLPSolver::UnsolvedError *E) {
00234             }
00235 
00236             //resolve (); 
00237 
00238             obj      = getObjValue ();
00239             solution = getColSolution ();
00240 
00241             // restore previous bounds on integer variables
00242             for (int i=0; i<norig; i++)
00243               if ((p -> Var (i) -> Multiplicity () > 0) &&
00244                   p  -> Var (i) -> isDefinedInteger ()) {
00245                 setColLower (i, lbSave [i]);
00246                 setColUpper (i, ubSave [i]);
00247               }
00248           }
00249 
00250           delete [] Y;
00251           delete [] lbSave;
00252           delete [] ubSave;
00253           delete [] lbCur;
00254           delete [] ubCur;
00255         } 
00256       }
00257 
00258       // re-check optimality in case resolve () was called
00259       if (isProvenOptimal () && 
00260           (obj < p -> getCutOff ())           && // check #1 (before re-computing)
00261 
00262 #ifdef FM_CHECKNLP2
00263           (p->checkNLP2(solution, 0, false, true, false, p->getFeasTol())) &&
00264           (p->getRecordBestSol()->getModSolVal() < p->getCutOff())
00265 #else
00266           p -> checkNLP (solution, obj, true) && // true for recomputing obj
00267           (obj < p -> getCutOff ())
00268 #endif
00269           ) {           // check #2 (real object might be different)
00270 
00271         // tell caller there is an initial solution to be fed to the initHeuristic
00272         have_nlp_solution_ = true;
00273 
00274         // set cutoff to take advantage of bound tightening
00275 
00276 #ifdef FM_CHECKNLP2
00277         obj = p->getRecordBestSol()->getModSolVal();
00278 #endif
00279 
00280         p -> setCutOff (obj, solution);
00281 
00282         OsiAuxInfo * auxInfo = si.getAuxiliaryInfo ();
00283         Bonmin::BabInfo * babInfo = dynamic_cast <Bonmin::BabInfo *> (auxInfo);
00284 
00285         if (babInfo) {
00286 
00287 #ifdef FM_CHECKNLP2
00288           babInfo -> setNlpSolution (p->getRecordBestSol()->modSol, 
00289                                      getNumCols(), obj);
00290 #else
00291           babInfo -> setNlpSolution (solution, getNumCols (), obj);
00292 #endif
00293           babInfo -> setHasNlpSolution (true);
00294         }
00295 
00296 #ifdef FM_TRACE_OPTSOL
00297 #ifdef FM_CHECKNLP2
00298         p->getRecordBestSol()->update();
00299 #else
00300         p->getRecordBestSol()->update(solution, getNumCols(), 
00301                                       obj, p->getFeasTol());
00302 #endif
00303 #endif
00304 
00305       }
00306     }
00307   }
00308 
00309   if (!is_feasible) // nothing else to do, problem infeasible
00310     return;
00311 
00312   int 
00313     numcols     = p -> nOrigVars (), // # original               variables
00314     numcolsconv = p -> nVars     (); // # original + # auxiliary variables
00315 
00316   const double
00317     *lb = p -> Lb (), //getColLower (),
00318     *ub = p -> Ub (); //getColUpper ();
00319 
00320    // add original and auxiliary variables to the new problem
00321    for (int i=0; i<numcols; i++) 
00322      if (p -> Var (i) -> Multiplicity () > 0) si.addCol (0, NULL,NULL, lb [i],       ub [i],      0);
00323      else                                     si.addCol (0, NULL,NULL, -COIN_DBL_MAX,COIN_DBL_MAX,0);
00324    for (int i=numcols; i<numcolsconv; i++)    si.addCol (0, NULL,NULL, -COIN_DBL_MAX,COIN_DBL_MAX,0);
00325 
00326    // get initial relaxation
00327    OsiCuts cs;
00328    couenneCg.generateCuts (si, cs);
00329 
00330    // store all (original + auxiliary) bounds in the relaxation
00331    CouNumber * colLower = new CouNumber [numcolsconv];
00332    CouNumber * colUpper = new CouNumber [numcolsconv];
00333 
00334    CouNumber *ll = p -> Lb ();
00335    CouNumber *uu = p -> Ub ();
00336 
00337    // overwrite original bounds, could have improved within generateCuts
00338    for (int i = numcolsconv; i--;) 
00339      if (p -> Var (i) -> Multiplicity () > 0) {
00340        colLower [i] = (ll [i] > - COUENNE_INFINITY) ? ll [i] : -COIN_DBL_MAX;
00341        colUpper [i] = (uu [i] <   COUENNE_INFINITY) ? uu [i] :  COIN_DBL_MAX;
00342      } else {
00343        colLower [i] = -COIN_DBL_MAX;
00344        colUpper [i] =  COIN_DBL_MAX;
00345      }
00346 
00347    int numrowsconv = cs.sizeRowCuts ();
00348 
00349    // create matrix and other stuff
00350    CoinBigIndex * start = new CoinBigIndex [numrowsconv + 1];
00351 
00352    int    * length   = new int    [numrowsconv];
00353    double * rowLower = new double [numrowsconv];
00354    double * rowUpper = new double [numrowsconv];
00355 
00356    start[0] = 0;
00357    int nnz = 0;
00358    /* fill the four arrays. */
00359    for(int i = 0 ; i < numrowsconv ; i++)
00360    {
00361      OsiRowCut * cut = cs.rowCutPtr (i);
00362 
00363      const CoinPackedVector &v = cut->row();
00364      start[i+1] = start[i] + v.getNumElements();
00365      nnz += v.getNumElements();
00366      length[i] = v.getNumElements();
00367 
00368      rowLower[i] = cut->lb();
00369      rowUpper[i] = cut->ub();
00370    }
00371 
00372    assert (nnz == start [numrowsconv]);
00373    /* Now fill the elements arrays. */
00374    int * ind = new int[start[numrowsconv]];
00375    double * elem = new double[start[numrowsconv]];
00376    for(int i = 0 ; i < numrowsconv ; i++) {
00377 
00378      OsiRowCut * cut = cs.rowCutPtr (i);
00379 
00380      const CoinPackedVector &v = cut->row();
00381 
00382      if(v.getNumElements() != length[i])
00383        std::cout<<"Empty row"<<std::endl;
00384      //     cut->print();
00385      CoinCopyN (v.getIndices(),  length[i], ind  + start[i]);
00386      CoinCopyN (v.getElements(), length[i], elem + start[i]);
00387    }
00388 
00389    // Ok everything done now create interface
00390    CoinPackedMatrix A;
00391    A.assignMatrix(false, numcolsconv, numrowsconv,
00392                   start[numrowsconv], elem, ind,
00393                   start, length);
00394    if(A.getNumCols() != numcolsconv || A.getNumRows() != numrowsconv){
00395      std::cout<<"Error in row number"<<std::endl;
00396    }
00397    assert(A.getNumElements() == nnz);
00398    // Objective function
00399    double * obj = new double[numcolsconv];
00400    CoinFillN(obj,numcolsconv,0.);
00401 
00402    // some instances have no (or null) objective function, check it here
00403    if (p -> nObjs () > 0)
00404      p -> fillObjCoeff (obj);
00405 
00406    // Finally, load interface si with the initial LP relaxation
00407    si.loadProblem (A, colLower, colUpper, obj, rowLower, rowUpper);
00408 
00409    delete [] rowLower; 
00410    delete [] rowUpper;
00411    delete [] colLower;
00412    delete [] colUpper;
00413    delete [] obj;
00414 
00415    for (int i=0; i<numcolsconv; i++)
00416      if ((p -> Var (i) -> Multiplicity () > 0) &&
00417          (p -> Var (i) -> isDefinedInteger ()))
00418        si.setInteger (i);
00419  
00420    //si.writeMpsNative("toto",NULL,NULL,1);
00421    //si.writeLp ("toto");
00422    app_ -> enableWarmStart();
00423 
00424    // restored check. With "TOO FEW DEGREES OF FREEDOM" exception, x_sol() is null
00425    if (problem () -> x_sol ()) {
00426      setColSolution (problem () -> x_sol     ());
00427      setRowPrice    (problem () -> duals_sol ());
00428    }
00429 }
00430 
00431 
00433 void CouenneInterface::setAppDefaultOptions(Ipopt::SmartPtr<Ipopt::OptionsList> Options){
00434   Options->SetStringValue("bonmin.algorithm", "B-Couenne", true, true);
00435   Options->SetIntegerValue("bonmin.filmint_ecp_cuts", 1, true, true);
00436 }
00437 

Generated on Thu Nov 10 03:05:45 2011 by  doxygen 1.4.7