/home/coin/SVN-release/OS-1.1.1/Bonmin/experimental/NotConvex/BonCouenneInterface.cpp

Go to the documentation of this file.
00001 // (C) Copyright International Business Machines Corporation (IBM) 2006, 2007
00002 // All Rights Reserved.
00003 // This code is published under the Common Public License.
00004 //
00005 // Authors :
00006 // Pietro Belotti, Carnegie Mellon University
00007 // Pierre Bonami, International Business Machines Corporation
00008 //
00009 // Date : 12/19/2006
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       // include the rhs of auxiliary-based constraints into the FBBT
00072       // (should be useful with Vielma's problems, for example)
00073 
00074       for (int i=0; i < p -> nCons (); i++) {
00075 
00076         // for each constraint
00077         CouenneConstraint *con = p -> Con (i);
00078 
00079         // (which has an aux as its body)
00080         int index = con -> Body () -> Index ();
00081 
00082         if ((index >= 0) && (con -> Body () -> Type () == AUX)) {
00083 
00084           // if there exists violation, add constraint
00085           CouNumber 
00086             l = con -> Lb () -> Value (),       
00087             u = con -> Ub () -> Value ();
00088 
00089           // tighten bounds in Couenne's problem representation
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           // if not enabled, fix them in the NLP solver
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         // if problem is integer, check if any integral variable is
00138         // fractional. If so, round them and re-optimize
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); // use initial solution given 
00179 
00180             resolve (); // solve with integer variables fixed
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       // re-check optimality in case resolve () was called
00202       if (isProvenOptimal () && 
00203           (obj < p -> getCutOff ()) &&
00204           p -> checkNLP (solution, obj)) {
00205 
00206         // tell caller there is an initial solution to be fed to the initHeuristic
00207         have_nlp_solution_ = true;
00208 
00209         // set cutoff to take advantage of bound tightening
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 (), // # original               variables
00225     numcolsconv = p -> nVars (); // # original + # auxiliary variables
00226 
00227   const double
00228     *lb = getColLower (),
00229     *ub = getColUpper ();
00230 
00231    // add original and auxiliary variables to the new problem
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    // get initial relaxation
00238    OsiCuts cs;
00239    couenneCg.generateCuts (si, cs);
00240 
00241    // store all (original + auxiliary) bounds in the relaxation
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    // overwrite original bounds, could have improved within generateCuts
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    // create matrix and other stuff
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    /* fill the four arrays. */
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    /* Now fill the elements arrays. */
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      //     cut->print();
00296      CoinCopyN (v.getIndices(),  length[i], ind  + start[i]);
00297      CoinCopyN (v.getElements(), length[i], elem + start[i]);
00298    }
00299 
00300    // Ok everything done now create interface
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    // Objective function
00310    double * obj = new double[numcolsconv];
00311    CoinFillN(obj,numcolsconv,0.);
00312 
00313    // some instances have no (or null) objective function, check it here
00314    if (p -> nObjs () > 0)
00315      p -> fillObjCoeff (obj);
00316 
00317    // Finally, load interface si with the initial LP relaxation
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    //si.writeMpsNative("toto",NULL,NULL,1);
00332    //si.writeLp ("toto");
00333    app_ -> enableWarmStart();
00334 
00335    //   if (problem () -> x_sol ()) {
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 } 

Generated on Tue Sep 30 03:01:22 2008 by  doxygen 1.4.7