/home/coin/SVN-release/OS-2.4.0/Couenne/src/heuristics/CouenneIterativeRounding.cpp

Go to the documentation of this file.
00001 // (C) Copyright International Business Machines Corporation 2010
00002 // and others.
00003 // All Rights Reserved.
00004 // This code is published under the Eclipse Public License (EPL).
00005 //
00006 // Authors :
00007 // Giacomo Nannicini, Tepper School of Business, Carnegie Mellon University
00008 //
00009 // Date : 07/25/2010
00010 
00011 #include "CouenneIterativeRounding.hpp"
00012 #include "BonTMINLP2Quad.hpp"
00013 #include "BonTMINLPLinObj.hpp"
00014 #ifdef COIN_HAS_CPX
00015 #include "OsiCpxSolverInterface.hpp"
00016 #include "cplex.h"
00017 #endif
00018 
00019 #include "CouenneRecordBestSol.hpp"
00020 
00021 #define MILPTIME 5
00022 #define CBCMILPTIME 20
00023 
00024 namespace Couenne{
00025 
00026   CouenneIterativeRounding::CouenneIterativeRounding():
00027     CbcHeuristic(),
00028     nlp_(NULL), cinlp_(NULL), milp_(NULL),
00029     maxRoundingIter_(10),
00030     maxFirPoints_(5), maxTime_(60), maxTimeFirstCall_(60), numInitialRows_(0),
00031     numSol_(-1), colLower_(NULL), colUpper_(NULL), 
00032     colLowerNlp_(NULL), colUpperNlp_(NULL),
00033     omega_(0.2), baseLbRhs_(15),
00034     couenne_(NULL)
00035   {
00036     setHeuristicName("CouenneIterativeRounding");
00037   }
00038  
00039   CouenneIterativeRounding::CouenneIterativeRounding(Bonmin::OsiTMINLPInterface* nlp, 
00040                                                      OsiSolverInterface* cinlp,
00041                                                      CouenneProblem* couenne,
00042                                                      Ipopt::SmartPtr<Ipopt::OptionsList> options):
00043     CbcHeuristic(), nlp_(NULL),
00044     cinlp_(NULL), milp_(NULL),
00045     numSol_(-1), colLower_(NULL), colUpper_(NULL), 
00046     colLowerNlp_(NULL), colUpperNlp_(NULL),
00047     couenne_(couenne)
00048   {
00049     // Initialize Dynamic NLP
00050     setNlp(nlp, cinlp);
00051 
00052     // Read options
00053     int irAggressiveness;
00054     options->GetIntegerValue("iterative_rounding_aggressiveness",
00055                              irAggressiveness, "couenne.");
00056     setAggressiveness(irAggressiveness);
00057     double maxTime, maxTimeInit;
00058     options->GetNumericValue("iterative_rounding_time", maxTime,
00059                              "couenne.");
00060     options->GetNumericValue("iterative_rounding_time_firstcall",
00061                              maxTimeInit, "couenne.");
00062     if (maxTime >= 0){
00063       setMaxTime(maxTime);
00064     }
00065     if (maxTimeInit >= 0){
00066       setMaxTimeFirstCall(maxTimeInit);
00067     }
00068     int irLbrhs;
00069     options->GetIntegerValue("iterative_rounding_base_lbrhs",
00070                              irLbrhs, "couenne.");
00071     setBaseLbRhs(irLbrhs);
00072     int numFirPoints;
00073     options->GetIntegerValue("iterative_rounding_num_fir_points",
00074                              numFirPoints, "couenne.");
00075     setMaxFirPoints(numFirPoints);
00076     double omega;
00077     options->GetNumericValue("iterative_rounding_omega",
00078                              omega, "couenne.");
00079     setOmega(omega);
00080   }
00081   
00082   CouenneIterativeRounding::CouenneIterativeRounding(const CouenneIterativeRounding & other):
00083     CbcHeuristic(other), nlp_(other.nlp_), 
00084     cinlp_(other.cinlp_), milp_(other.milp_), 
00085     maxRoundingIter_(other.maxRoundingIter_),
00086     maxFirPoints_(other.maxFirPoints_),
00087     maxTime_(other.maxTime_),
00088     maxTimeFirstCall_(other.maxTimeFirstCall_),
00089     numInitialRows_(other.numInitialRows_),
00090     numSol_(other.numSol_),
00091     omega_(other.omega_), baseLbRhs_(other.baseLbRhs_),
00092     couenne_(other.couenne_)
00093   {
00094     if(nlp_ != NULL){
00095       nlp_ = dynamic_cast<Bonmin::OsiTMINLPInterface*>(other.nlp_->clone());
00096     }
00097     if(milp_ != NULL)
00098 #ifdef COIN_HAS_CPX
00099       milp_ =  dynamic_cast<OsiCpxSolverInterface*>(other.milp_->clone());
00100 #else
00101       milp_ =  dynamic_cast<OsiClpSolverInterface*>(other.milp_->clone());
00102 #endif
00103     if (other.colLower_ != NULL){
00104       if (colLower_ != NULL)
00105         delete colLower_;
00106       colLower_ = new double[milp_->getNumCols()];
00107       CoinCopyN (other.colLower_, milp_->getNumCols(), colLower_);
00108     }
00109     if (other.colUpper_ != NULL){
00110       if (colUpper_ != NULL)
00111         delete colUpper_;
00112       colUpper_ = new double[milp_->getNumCols()];
00113       CoinCopyN (other.colUpper_, milp_->getNumCols(), colUpper_);
00114     }
00115     if (other.colLowerNlp_ != NULL){
00116       if (colLowerNlp_ != NULL)
00117         delete colLowerNlp_;
00118       colLowerNlp_ = new double[nlp_->getNumCols()];
00119       CoinCopyN (other.colLowerNlp_, nlp_->getNumCols(), colLowerNlp_);
00120     }
00121     if (other.colUpperNlp_ != NULL){
00122       if (colUpperNlp_ != NULL)
00123         delete colUpperNlp_;
00124       colUpperNlp_ = new double[nlp_->getNumCols()];
00125       CoinCopyN (other.colUpperNlp_, nlp_->getNumCols(), colLowerNlp_);
00126     }
00127   }
00128   
00129   CbcHeuristic * 
00130   CouenneIterativeRounding::clone() const{
00131     return new CouenneIterativeRounding(*this);
00132   }
00133   
00134   CouenneIterativeRounding &
00135   CouenneIterativeRounding::operator=(const CouenneIterativeRounding & rhs){
00136     if(this != &rhs){
00137       CbcHeuristic::operator=(rhs);
00138       if(nlp_)
00139         delete nlp_;
00140       
00141       if(rhs.nlp_ != NULL){
00142         nlp_ = dynamic_cast<Bonmin::OsiTMINLPInterface*>(rhs.nlp_->clone());
00143       }
00144       cinlp_ = rhs.cinlp_;
00145       maxRoundingIter_ = rhs.maxRoundingIter_;
00146       maxFirPoints_ = rhs.maxFirPoints_;
00147       maxTime_ = rhs.maxTime_;
00148       maxTimeFirstCall_ = rhs.maxTimeFirstCall_;
00149       numSol_ = rhs.numSol_;
00150       numInitialRows_ = rhs.numInitialRows_;
00151       omega_ = rhs.omega_;
00152       baseLbRhs_ = rhs.baseLbRhs_;
00153       couenne_ = rhs.couenne_;
00154       if (rhs.colLower_ != NULL){
00155         if (colLower_ != NULL)
00156           delete colLower_;
00157         colLower_ = new double[milp_->getNumCols()];
00158         CoinCopyN (rhs.colLower_, milp_->getNumCols(), colLower_);
00159       }
00160       if (rhs.colUpper_ != NULL){
00161         if (colUpper_ != NULL)
00162           delete colUpper_;
00163         colUpper_ = new double[milp_->getNumCols()];
00164         CoinCopyN (rhs.colUpper_, milp_->getNumCols(), colLower_);
00165       }
00166       if (rhs.colLowerNlp_ != NULL){
00167         if (colLowerNlp_ != NULL)
00168           delete colLowerNlp_;
00169         colLowerNlp_ = new double[nlp_->getNumCols()];
00170         CoinCopyN (rhs.colLowerNlp_, nlp_->getNumCols(), colLowerNlp_);
00171       }
00172       if (rhs.colUpperNlp_ != NULL){
00173         if (colUpperNlp_ != NULL)
00174           delete colUpperNlp_;
00175         colUpperNlp_ = new double[nlp_->getNumCols()];
00176         CoinCopyN (rhs.colUpperNlp_, nlp_->getNumCols(), colLowerNlp_);
00177       }
00178     }
00179     return *this;
00180   }
00181   
00182   CouenneIterativeRounding::~CouenneIterativeRounding(){
00183     delete nlp_;
00184     nlp_ = NULL;
00185     if (colLower_)
00186       delete[] colLower_;
00187     if (colUpper_)
00188       delete[] colUpper_;
00189     if (colLowerNlp_)
00190       delete[] colLowerNlp_;
00191     if (colUpperNlp_)
00192       delete[] colUpperNlp_;
00193     if (milp_)
00194       delete milp_;
00195     milp_ = NULL;
00196   }
00197   
00198   void
00199   CouenneIterativeRounding::setNlp(Bonmin::OsiTMINLPInterface* nlp, 
00200                                    OsiSolverInterface * cinlp){
00201     // Create a dynamic NLP (i.e. one that can be used to add/remove
00202     // linear inequalities) from the initial one
00203     if(nlp_ != NULL)
00204       delete nlp_;
00205     nlp_ = new Bonmin::OsiTMINLPInterface;
00206     Ipopt::SmartPtr<Bonmin::TMINLP> tminlp = nlp->model();
00207     if (tminlp->hasLinearObjective()){
00208       Ipopt::SmartPtr<Bonmin::TMINLPLinObj> linObj =
00209         new Bonmin::TMINLPLinObj;
00210       linObj->setTminlp(GetRawPtr(tminlp));
00211       tminlp = GetRawPtr(linObj);
00212     }
00213     nlp_->initialize(nlp->regOptions(), nlp->options(), nlp->solver()->journalist(), "bonmin.", tminlp);
00214     nlp_->use(new Bonmin::TMINLP2TNLPQuadCuts(tminlp));
00215     cinlp_ = cinlp;
00216   }
00217 
00218   void
00219   CouenneIterativeRounding::setMilp(){
00220     if(milp_ != NULL)
00221       delete milp_;
00222 
00223     // Save the LP relaxation of the root node
00224 
00225     OsiSolverInterface * milp = model_->solver();
00226     int n = milp->getNumCols();
00227 
00228 #ifdef COIN_HAS_CPX
00229     milp_ = new OsiCpxSolverInterface();
00230     milp_->loadProblem(*(milp->getMatrixByRow()), milp->getColLower(), 
00231                        milp->getColUpper(), milp->getObjCoefficients(),
00232                        milp->getRowLower(), milp->getRowUpper());
00233     for (int i = 0; i < n; ++i){
00234       if (milp->isInteger(i))
00235         milp_->setInteger(i); 
00236     }
00237 #else
00238     milp_ =  dynamic_cast<OsiClpSolverInterface*>(milp->clone());
00239 #endif
00240 
00241     colLower_ = new double[n];
00242     colUpper_ = new double[n];
00243     memcpy(colLower_, milp->getColLower(), n*sizeof(double));
00244     memcpy(colUpper_, milp->getColUpper(), n*sizeof(double));
00245 
00246     int nNlp = cinlp_->getNumCols();
00247 
00248     colLowerNlp_ = new double[nNlp];
00249     colUpperNlp_ = new double[nNlp];
00250     memcpy(colLowerNlp_, cinlp_->getColLower(), nNlp*sizeof(double));
00251     memcpy(colUpperNlp_, cinlp_->getColUpper(), nNlp*sizeof(double));
00252 
00253     numIntegers_ = 0;
00254     for (int i = 0; i < nNlp; ++i){
00255       if (cinlp_->isInteger(i)){
00256         numIntegers_++;
00257       }
00258     }
00259 
00260     // workaround for inconsistent bounds:
00261     // sometimes using getColLower and getColUpper we get *slightly*
00262     // inconsistent bounds, which make everything crash afterwards
00263     double swap;
00264     for (int i = 0; i < n; ++i){
00265       if (colUpper_[i] < colLower_[i]){
00266         swap = colUpper_[i];
00267         colUpper_[i] = colLower_[i];
00268         colLower_[i] = swap;
00269       }
00270     }
00271 
00272     numInitialRows_ = milp_->getNumRows();
00273     
00274     // this array contains zeroes; we use it to set empty elements
00275     double * tmpArray = new double[n];
00276     CoinFillN(tmpArray, n, 0.0);
00277     milp_->setObjective(tmpArray);
00278     milp_->setObjSense(1);
00279 
00280     // now there is no objective function
00281     // create new variables with objective coefficient 1
00282     for (int i = 0; i < n; ++i){
00283       milp_->addCol(0, NULL, NULL, 0.0, COIN_DBL_MAX, 1.0);
00284     }
00285 
00286     milp_->setHintParam(OsiDoDualInResolve,true,OsiHintDo);
00287     milp_->setHintParam(OsiDoPresolveInResolve,true,OsiHintDo);
00288     milp_->setHintParam(OsiDoReducePrint,true,OsiHintDo);
00289     milp_->setDblParam(OsiPrimalTolerance, COUENNE_EPS_INT);
00290     milp_->messageHandler()->setLogLevel(0);
00291     milp_->setDblParam(OsiDualTolerance, COUENNE_EPS_INT);
00292 
00293 #ifdef COIN_HAS_CPX
00294     // Set options if we have Cplex
00295     CPXsetintparam(milp_->getEnvironmentPtr(), CPX_PARAM_MIPEMPHASIS, CPX_MIPEMPHASIS_HIDDENFEAS);
00296     CPXsetintparam(milp_->getEnvironmentPtr(), CPX_PARAM_FPHEUR, 2);
00297     CPXsetintparam(milp_->getEnvironmentPtr(), CPX_PARAM_NODESEL, 0);
00298     CPXsetintparam(milp_->getEnvironmentPtr(), CPX_PARAM_LBHEUR, 1);
00299     CPXsetintparam(milp_->getEnvironmentPtr(), CPX_PARAM_RINSHEUR, 99);
00300     CPXsetintparam(milp_->getEnvironmentPtr(), CPX_PARAM_NODELIM, 50);
00301     CPXsetdblparam(milp_->getEnvironmentPtr(), CPX_PARAM_CUTSFACTOR, 1.0);
00302     CPXsetdblparam(milp_->getEnvironmentPtr(), CPX_PARAM_TILIM, MILPTIME);
00303 #else
00304     // Set up heuristics if we use Cbc (not recommended)
00305     heuristics_ = new CbcHeuristic*[1];
00306     numHeuristics_ = 1;
00307     CbcHeuristicFPump * feaspump = new CbcHeuristicFPump();
00308     feaspump->setMaximumRetries(2);
00309     feaspump->setMaximumPasses(100);
00310     feaspump->setAccumulate(3);
00311     heuristics_[0] = feaspump;
00312 #endif
00313 
00314     delete[] tmpArray;
00315 
00316 
00317   }
00318   
00319   void CouenneIterativeRounding::setAggressiveness(int value){
00320     switch (value){
00321     case 0:
00322       setMaxRoundingIter(5);
00323       setMaxTimeFirstCall(300);
00324       setMaxFirPoints(5);
00325       setMaxTime(60);
00326       break;
00327     case 1:
00328       setMaxRoundingIter(10);
00329       setMaxTimeFirstCall(300);
00330       setMaxFirPoints(5);
00331       setMaxTime(120);
00332       break;
00333     case 2:
00334       setMaxRoundingIter(20);
00335       setMaxTimeFirstCall(1000);
00336       setMaxFirPoints(5);
00337       setMaxTime(300);
00338       break;
00339     default:
00340       std::cerr << "CouenneIterativeRounding::setAggressiveness() : unknown value!\n" << std::endl;
00341     }
00342   }
00343 
00344   int
00345   CouenneIterativeRounding::solution(double & objectiveValue, double* newSolution){
00346     if (milp_ == NULL){
00347       // On the very first call, we set the MILP
00348       setMilp();
00349       return 0;
00350     }
00351 
00352     if ((model_->numberIntegers() == 0) || 
00353         (numSol_ == model_->getSolutionCount())){
00354       // There are no integers, or we already tried to improve current
00355       // solution. Exit immediately.
00356       return 0;
00357     }
00358 
00359     numSol_ = model_->getSolutionCount();
00360 
00361     std::cout << "Launching IterativeRounding with parameters:" << std::endl;
00362     std::cout << "Max rounding iter: " << maxRoundingIter_ << std::endl;
00363     std::cout << "Max feas point: " << maxFirPoints_ << std::endl;
00364     std::cout << "Base lbrhs: " << baseLbRhs_ << std::endl;
00365     std::cout << "Omega: " << omega_ << std::endl;
00366     std::cout << "Max time firstcall: " << maxTimeFirstCall_ << std::endl;
00367 
00368     // write down starting time and apply heuristics
00369     startTime_ = CoinCpuTime();
00370     endTime_ = ((numSol_ == 0) ? maxTimeFirstCall_ : maxTime_);
00371 
00372     const double* bestKnownSolution = model_->bestSolution();
00373     bool found = false;
00374     bool hasSolution = true;
00375     bool improved = true;
00376     if (numSol_ == 0){
00377       // No solution available; start with our feasibility heuristic
00378       hasSolution = feasibilityIR(objectiveValue, newSolution);
00379       if (hasSolution){
00380         bestKnownSolution = newSolution;
00381         found = hasSolution;
00382       }
00383     }
00384     if (!hasSolution){
00385       // Still do not have a starting solution, we cannot run improvementIR
00386       return found;
00387     }
00388     while (improved && (CoinCpuTime()-startTime_) < (endTime_ - MILPTIME)){
00389       // Keep improving current solution as long as it works
00390       improved = false;
00391       improved = improvementIR(objectiveValue, newSolution, bestKnownSolution);
00392       if (improved){
00393         bestKnownSolution = newSolution;
00394       }
00395       found = (found || improved);
00396     }
00397     if (found){
00398       // make sure we do not run improvementIR again on the same solution
00399       numSol_++;
00400     }
00401 
00402     return found;
00403   }
00404 
00405   int
00406   CouenneIterativeRounding::feasibilityIR(double& objectiveValue, 
00407                                             double* newSolution){
00408 
00409     std::cout << "starting feasibility IR" << std::endl;
00410 
00411     OsiSolverInterface * solver = model_->solver();
00412 
00413     OsiAuxInfo * auxInfo = solver->getAuxiliaryInfo();
00414     Bonmin::BabInfo * babInfo = dynamic_cast<Bonmin::BabInfo *> (auxInfo);
00415 
00416     if(babInfo){
00417       babInfo->setHasNlpSolution(false);
00418       if(babInfo->infeasibleNode()){
00419         return 0;
00420       }
00421     }
00422    
00423     int n = couenne_->nVars();
00424     int nNlp = cinlp_->getNumCols();
00425 
00426     // get best solution and count the number of binary variables
00427     int numIntAtBound = 0;
00428 
00429     OsiRowCut cut;
00430     OsiRowCut lbcut1;
00431     OsiRowCut lbcut2;
00432     OsiCuts lbcuts;
00433     double obj;
00434 
00435     bool boundsChanged = false;
00436     std::vector<int> previousBranches;
00437 
00438     // Try to find a feasible solution
00439 
00440     // apply NLP solver to obtain point xprime
00441     nlp_->resolve();
00442     if (nlp_->isProvenPrimalInfeasible() || nlp_->isProvenDualInfeasible() ||
00443         nlp_->isAbandoned()){
00444       nlp_->resolveForRobustness(3);
00445     }
00446     
00447     if (nlp_->isProvenPrimalInfeasible() || nlp_->isProvenDualInfeasible() ||
00448         nlp_->isAbandoned()){
00449       obj = COIN_DBL_MAX;
00450     }
00451     else{
00452       obj = nlp_->getObjValue();
00453     }
00454     
00455     if (obj == COIN_DBL_MAX){std::cout << " IR: no feasible solution found " << std::endl;
00456       std::cout << " IR: elapsed time " << CoinCpuTime()-startTime_ << std::endl;
00457       return 0;
00458     }
00459 
00460     double* xprime = new double [n];
00461     CoinCopyN (nlp_->getColSolution(), nlp_->getNumCols(), xprime);
00462     couenne_ -> getAuxs (xprime);
00463 
00464     // now prepare the MILP that we will solve
00465 
00466     // the objective is : minimize sum_{j = 1}^n w_j
00467     int constrInd[2];
00468     double constrElem[2];
00469 
00470     // main loop: solve a sequence of MILPs and NLPs
00471     bool foundSolution = false;
00472     double* tmpSolution = new double[n];
00473     OsiCuts revlb_all;
00474     OsiSolverInterface* curr_milp = milp_;
00475 
00476     int outerLoop = maxFirPoints_;
00477     for (int h = 0; h < outerLoop && 
00478            ((CoinCpuTime()-startTime_) < (endTime_ - MILPTIME)); ++h){
00479 
00480       OsiCuts cs;
00481       cs.insert(lbcut1);
00482       cs.insert(lbcut2);
00483       // write constraints:
00484       // xbar[j] - x[j] <= w_j
00485       // x[j] - xbar[j] <= w_j
00486       for (int i = 0; i < n; i++){
00487         constrInd[0] = i;
00488         constrInd[1] = i+n;
00489         constrElem[0] = -1;
00490         constrElem[1] = -1;
00491         cut.mutableRow().setVector(2, constrInd, constrElem);
00492         cut.setLb(-COIN_DBL_MAX);
00493         cut.setUb(-xprime[i]);
00494         cs.insert(cut);
00495         constrElem[0] = +1;
00496         constrElem[1] = -1;
00497         cut.mutableRow().setVector(2, constrInd, constrElem);
00498         cut.setLb(-COIN_DBL_MAX);
00499         cut.setUb(xprime[i]);
00500         cs.insert(cut);
00501       }
00502       curr_milp->applyCuts(cs);
00503 
00504       for (int k = 0; k < maxRoundingIter_ &&
00505              ((CoinCpuTime()-startTime_) < (endTime_ - MILPTIME)); ++k){
00506         // Solve MILP to obtain an integral feasible point near xprime
00507         curr_milp->restoreBaseModel(numInitialRows_+cs.sizeRowCuts());
00508         curr_milp->applyCuts(revlb_all);
00509         bool solFound = solveMilp(curr_milp, 
00510                                   endTime_-(CoinCpuTime()-startTime_)-2);
00511         if (!solFound && !boundsChanged){
00512           std::cout << " MILP cannot be solved, terminating LB " << std::endl;
00513           // we cannot solve the MILP and bounds were not changed; exit
00514           curr_milp->restoreBaseModel(numInitialRows_);
00515           delete[] xprime;
00516           delete[] tmpSolution;
00517           if (boundsChanged){
00518             curr_milp->setColLower(colLower_);
00519             curr_milp->setColUpper(colUpper_);
00520           }
00521           std::cout << " IR: elapsed time " << CoinCpuTime()-startTime_ << std::endl;
00522           return foundSolution;
00523         }
00524         else if (!solFound && boundsChanged){
00525           // the MILP is infeasible but bounds were changed;
00526           // restore original bounds and branch on a random variable
00527           // of the solution at the previous iteration (so we do not cycle)
00528           curr_milp->setColLower(colLower_);
00529           curr_milp->setColUpper(colUpper_);
00530           branchToCut(tmpSolution, curr_milp, previousBranches);
00531           continue;
00532         }
00533 
00534         const double * xtilde = curr_milp->getColSolution();
00535 
00536         // now fix integer variables and solve NLP
00537         // xtilde has more columns than the NLP, so this should be ok
00538         CoinCopyN (xtilde, n, tmpSolution);
00539         for (int i = 0; i < nNlp; ++i){
00540           if (model_->isInteger(i)){
00541             tmpSolution[i] = floor(tmpSolution[i]+0.5);
00542             cinlp_->setColLower(i, tmpSolution[i]);
00543             cinlp_->setColUpper(i, tmpSolution[i]);
00544           }
00545         }
00546         cinlp_->setColSolution(tmpSolution);
00547 
00548         cinlp_->messageHandler()->setLogLevel(1);
00549         cinlp_->resolve();
00550         obj = ((cinlp_->isProvenOptimal()) ? 
00551                cinlp_->getObjValue():COIN_DBL_MAX);
00552         memcpy(tmpSolution, cinlp_->getColSolution(), 
00553                nNlp*sizeof(double));
00554         // check solution of the NLP;
00555         // if we have a new incumbent we are done, otherwise we iterate
00556 
00557         bool isChecked = false;
00558 #ifdef FM_CHECKNLP2
00559         isChecked = couenne_->checkNLP2(tmpSolution, 0, false, // do not care about obj
00560                                         true, // stopAtFirstViol
00561                                         false, // checkALL
00562                                         couenne_->getFeasTol());
00563         if(isChecked) {
00564           obj = couenne_->getRecordBestSol()->getModSolVal();
00565         }
00566 #else /* not FM_CHECKNLP2 */
00567         isChecked = couenne_->checkNLP(tmpSolution, obj, true);
00568 #endif  /* not FM_CHECKNLP2 */
00569         
00570         if (cinlp_->isProvenOptimal () &&
00571             isChecked &&
00572             (obj < couenne_->getCutOff())) {
00573           
00574 #ifdef FM_CHECKNLP2
00575 #ifdef FM_TRACE_OPTSOL
00576           couenne_->getRecordBestSol()->update();
00577           CoinCopyN (couenne_->getRecordBestSol()->getSol(), n, tmpSolution);
00578           obj = couenne_->getRecordBestSol()->getVal();
00579 #else /* not FM_TRACE_OPTSOL */
00580           CoinCopyN (couenne_->getRecordBestSol()->getModSol(n), n, tmpSolution);
00581 #endif /* not FM_TRACE_OPTSOL */
00582 #else /* not FM_CHECKNLP2 */
00583           
00584           //Get correct values for all auxiliary variables
00585           couenne_ -> getAuxs (tmpSolution);
00586           
00587 #ifdef FM_TRACE_OPTSOL
00588           couenne_->getRecordBestSol()->update(tmpSolution, n,
00589                                                obj, couenne_->getFeasTol());
00590           CoinCopyN (couenne_->getRecordBestSol()->getSol(), n, tmpSolution);
00591           obj = couenne_->getRecordBestSol()->getVal();
00592 #endif /* FM_TRACE_OPTSOL */
00593 #endif /* not FM_CHECKNLP2 */
00594           
00595           if (babInfo){
00596             babInfo->setNlpSolution (tmpSolution, n, obj);
00597             babInfo->setHasNlpSolution (true);
00598           }
00599           
00600           std::cout << "Final Nlp solution with objective " << obj << " :" << std::endl;
00601           
00602           if (obj < objectiveValue - COUENNE_EPS) { // found better solution?
00603             std::cout << "New incumbent found" << std::endl;
00604             const CouNumber 
00605               *lb = solver -> getColLower (),
00606               *ub = solver -> getColUpper ();
00607             
00608             // check bounds once more after getAux. This avoids false
00609             // asserts in CbcModel.cpp:8305 on integerTolerance violated
00610             for (int i=0; i < n; ++i, ++lb, ++ub) {
00611               CouNumber &t = tmpSolution [i];
00612               if      (t < *lb) t = *lb;
00613               else if (t > *ub) t = *ub;
00614             }
00615 
00616             couenne_ -> setCutOff (obj);
00617             foundSolution = true;
00618             objectiveValue = obj;
00619             CoinCopyN (tmpSolution, n, newSolution);
00620             cinlp_->setColLower(colLowerNlp_);
00621             cinlp_->setColUpper(colUpperNlp_);
00622           
00623             curr_milp->restoreBaseModel(numInitialRows_);
00624             delete[] xprime;
00625             delete[] tmpSolution;
00626             if (boundsChanged){
00627               curr_milp->setColLower(colLower_);
00628               curr_milp->setColUpper(colUpper_);
00629             }
00630             //delete curr_milp;
00631             double elapsed = CoinCpuTime()-startTime_;
00632             std::cout << "IR: Heuristic: " << objectiveValue << std::endl;
00633             std::cout << "IR: Heuristic time: " << elapsed << std::endl;
00634             return foundSolution;
00635           }
00636         }
00637         cinlp_->setColLower(colLowerNlp_);
00638         cinlp_->setColUpper(colUpperNlp_);
00639         double avgBound;
00640         numIntAtBound = computeIntAtBound(xtilde, avgBound);
00641         
00642         if (numIntAtBound >= 50 || 
00643             numIntAtBound >= ((numIntegers_*0.1 > 5) ? numIntegers_*0.1 : 5)){
00644           // write reverse local branching constraint
00645           // this avoids finding the same xtilde again
00646           avgBound = floor(avgBound + 0.5);
00647           std::cout << "Using reverse LB with rhs " << avgBound << std::endl;
00648           writeLB(cut, xtilde, 'G', avgBound);
00649           revlb_all.insert(cut);
00650         }
00651         else{
00652           // Branch on a random variable to obtain a different integer point
00653           branchToCut(xtilde, curr_milp, previousBranches);
00654           boundsChanged = true;
00655         }
00656       }
00657       if (h <= outerLoop -2){
00658         // Compute a NLP-feasible point by solving a log-barrier problem
00659         // with a given minimum value for the log-barrier parameter mu
00660         Bonmin::OsiTMINLPInterface * nlp = dynamic_cast<Bonmin::OsiTMINLPInterface *> (nlp_);
00661         Ipopt::SmartPtr< Ipopt::OptionsList > opt = nlp->solver()->options();
00662         nlp->messageHandler()->setLogLevel(10);
00663         double mu_target;
00664         double kappa_d;
00665         opt->GetNumericValue("mu_target", mu_target, "ipopt.");
00666         opt->SetNumericValue("mu_target", omega_*(h+1), "ipopt.");
00667         opt->GetNumericValue("kappa_d", kappa_d, "ipopt.");
00668         opt->SetNumericValue("kappa_d", 0.0, "ipopt.");
00669         nlp_->resolve();
00670         if (nlp_->isProvenPrimalInfeasible() || 
00671             nlp_->isProvenDualInfeasible() ||
00672             nlp_->isAbandoned()){
00673           nlp_->resolveForRobustness(3);
00674         }
00675         opt->SetNumericValue("mu_target", mu_target, "ipopt.");
00676         opt->SetNumericValue("kappa_d", kappa_d, "ipopt.");
00677 
00678         if (!nlp->isProvenPrimalInfeasible() &&
00679             !nlp->isProvenDualInfeasible() && 
00680             !nlp->isAbandoned()){
00681           CoinCopyN (nlp_->getColSolution(), nlp_->getNumCols(), xprime);
00682           couenne_ -> getAuxs (xprime);
00683           curr_milp->restoreBaseModel(numInitialRows_);
00684           if (boundsChanged){
00685             curr_milp->setColLower(colLower_);
00686             curr_milp->setColUpper(colUpper_);
00687           }
00688         }
00689       }
00690     }
00691     
00692     curr_milp->restoreBaseModel(numInitialRows_);
00693     delete[] xprime;
00694     delete[] tmpSolution;
00695     if (boundsChanged){
00696       curr_milp->setColLower(colLower_);
00697       curr_milp->setColUpper(colUpper_);
00698     }
00699     double elapsed = CoinCpuTime()-startTime_;
00700     std::cout << "IR: Heuristic: " << COUENNE_INFINITY << std::endl;
00701     std::cout << "IR: Heuristic time: " << elapsed << std::endl;
00702     return foundSolution;
00703   }
00704 
00705   int
00706   CouenneIterativeRounding::improvementIR(double& objectiveValue,
00707                                             double* newSolution,
00708                                             const double* solution){
00709     std::cout << "starting Improvement IR" << std::endl;
00710 
00711     OsiSolverInterface * solver = model_->solver();
00712 
00713     OsiAuxInfo * auxInfo = solver->getAuxiliaryInfo();
00714     Bonmin::BabInfo * babInfo = dynamic_cast<Bonmin::BabInfo *> (auxInfo);
00715 
00716     if(babInfo){
00717       babInfo->setHasNlpSolution(false);
00718       if(babInfo->infeasibleNode()){
00719         return 0;
00720       }
00721     }
00722 
00723 
00724     int n = couenne_->nVars();
00725     int nNlp = cinlp_->getNumCols();
00726 
00727     // count the number of binary variables
00728     int numIntAtBound = 0;
00729 
00730     double lbrhs = CoinMin(baseLbRhs_, CoinMax(1,numIntegers_/2) );
00731     OsiRowCut cut;
00732     OsiRowCut lbcut1;
00733     OsiRowCut lbcut2;
00734     OsiCuts lbcuts;
00735     int currentIndex = 0;
00736     double obj;
00737 
00738     bool boundsChanged = false;
00739     std::vector<int> previousBranches;
00740 
00741     double avgBound = 0.0;
00742     numIntAtBound = computeIntAtBound(solution, avgBound);
00743 
00744     if (numIntAtBound >= 50 ||
00745         numIntAtBound >= ((numIntegers_*0.1 > 5) ? numIntegers_*0.1 : 5)){
00746       // write local branching constraint
00747       writeLB(lbcut1, solution, 'L', lbrhs + floor(avgBound - 0.5));
00748       lbcuts.insert(lbcut1);
00749       writeLB(lbcut2, solution, 'G', 1);
00750       lbcuts.insert(lbcut2);
00751 
00752       // We cannot add a row because OsiTMINLP will not let us do that!
00753       // Therefore we add a cut -- does the same thing.
00754       // We must delete the cut afterwards!
00755       nlp_->applyCuts(lbcuts);
00756     }
00757     else{
00758       // we cannot use a local branching constraint, so we simply
00759       // reduce the size of the box bounds, to have a smaller NLP and
00760       // stay somehow "close" to the current point
00761       for (int i = 0; i < nlp_->getNumCols(); ++i){
00762         if (nlp_->isInteger(i)){
00763           nlp_->setColLower(i, colLowerNlp_[i]+(solution[i]-colLower_[i])*0.5);
00764           nlp_->setColUpper(i, colUpperNlp_[i]+(solution[i]-colUpper_[i])*0.5);
00765         }
00766       }
00767     }
00768     // apply NLP solver to obtain point xprime
00769     nlp_->setColSolution(solution);
00770     nlp_->resolve();
00771     if (nlp_->isProvenPrimalInfeasible() || nlp_->isProvenDualInfeasible() ||
00772         nlp_->isAbandoned()){
00773       nlp_->resolveForRobustness(3);
00774     }
00775 
00776     if (nlp_->isProvenPrimalInfeasible() || nlp_->isProvenDualInfeasible() ||
00777         nlp_->isAbandoned()){
00778       obj = COIN_DBL_MAX;
00779     }
00780     else{
00781       obj = nlp_->getObjValue();
00782     }
00783 
00784     // Restore NLP
00785     if (numIntAtBound > 0){
00786       currentIndex = nlp_->getNumRows()-1;
00787       nlp_->deleteRows(1, &currentIndex);
00788       currentIndex = nlp_->getNumRows()-1;
00789       nlp_->deleteRows(1, &currentIndex);
00790     }
00791     else{
00792       nlp_->setColLower(colLowerNlp_);
00793       nlp_->setColUpper(colUpperNlp_);
00794     }
00795       
00796     if (obj == COIN_DBL_MAX || obj >= objectiveValue - COUENNE_EPS){
00797       std::cout << " IR: no improvement possible " << std::endl;
00798       std::cout << " IR: elapsed time " << CoinCpuTime()-startTime_ << std::endl;
00799       return 0;
00800     }
00801 
00802     double* xprime = new double [n];
00803     CoinCopyN (nlp_->getColSolution(), nlp_->getNumCols(), xprime);
00804     couenne_ -> getAuxs (xprime);
00805 
00806     // now prepare the MILP that we will solve
00807 
00808     // the objective is : minimize sum_{j = 1}^n w_j
00809     int constrInd[2];
00810     double constrElem[2];
00811 
00812     // main loop: solve a sequence of MILPs and NLPs
00813     bool foundSolution = false;
00814     double* tmpSolution = new double[n];
00815     OsiCuts revlb_all;
00816     OsiSolverInterface* curr_milp = milp_;
00817     
00818     OsiCuts cs;
00819     cs.insert(lbcut1);
00820     cs.insert(lbcut2);
00821     // write constraints:
00822     // xbar[j] - x[j] <= w_j
00823     // x[j] - xbar[j] <= w_j
00824     for (int i = 0; i < n; i++){
00825       constrInd[0] = i;
00826       constrInd[1] = i+n;
00827       constrElem[0] = -1;
00828       constrElem[1] = -1;
00829       cut.mutableRow().setVector(2, constrInd, constrElem);
00830       cut.setLb(-COIN_DBL_MAX);
00831       cut.setUb(-xprime[i]);
00832       cs.insert(cut);
00833       constrElem[0] = +1;
00834       constrElem[1] = -1;
00835       cut.mutableRow().setVector(2, constrInd, constrElem);
00836       cut.setLb(-COIN_DBL_MAX);
00837       cut.setUb(xprime[i]);
00838       cs.insert(cut);
00839     }
00840     curr_milp->applyCuts(cs);
00841 
00842     for (int k = 0; k < maxRoundingIter_ &&
00843            ((CoinCpuTime()-startTime_) < (endTime_ - MILPTIME)); ++k){
00844       // Solve MILP to obtain an integral feasible point near xprime
00845       curr_milp->restoreBaseModel(numInitialRows_+cs.sizeRowCuts());
00846       curr_milp->applyCuts(revlb_all);
00847       bool solFound = solveMilp(curr_milp, 
00848                                 endTime_-(CoinCpuTime()-startTime_)-2);
00849       if (!solFound && !boundsChanged){
00850         std::cout << " MILP cannot be solved, terminating LB " << std::endl;
00851         // we cannot solve the MILP and bounds were not changed; exit
00852         curr_milp->restoreBaseModel(numInitialRows_);
00853         delete[] xprime;
00854         delete[] tmpSolution;
00855         if (boundsChanged){
00856           curr_milp->setColLower(colLower_);
00857           curr_milp->setColUpper(colUpper_);
00858         }
00859         std::cout << " IR: elapsed time " << CoinCpuTime()-startTime_ << std::endl;
00860         return foundSolution;
00861       }
00862       else if (!solFound && boundsChanged){
00863         // the MILP is infeasible but bounds were changed;
00864         // restore original bounds and branch on a random variable
00865         // of the solution at the previous iteration (so we do not cycle)
00866         curr_milp->setColLower(colLower_);
00867         curr_milp->setColUpper(colUpper_);
00868         branchToCut(tmpSolution, curr_milp, previousBranches);
00869         continue;
00870       }
00871       const double * xtilde = curr_milp->getColSolution();
00872 
00873       // now fix integer variables and solve NLP
00874       // xtilde has more columns than the NLP, so this should be ok
00875       CoinCopyN (xtilde, n, tmpSolution);
00876       for (int i = 0; i < nNlp; ++i){
00877         if (model_->isInteger(i)){
00878           tmpSolution[i] = floor(tmpSolution[i]+0.5);
00879           cinlp_->setColLower(i, tmpSolution[i]);
00880           cinlp_->setColUpper(i, tmpSolution[i]);
00881         }
00882       }
00883       cinlp_->setColSolution(tmpSolution);
00884 
00885       cinlp_->messageHandler()->setLogLevel(1);
00886       cinlp_->resolve();
00887       obj = ((cinlp_->isProvenOptimal()) ? cinlp_->getObjValue():COIN_DBL_MAX);
00888       memcpy(tmpSolution, cinlp_->getColSolution(), 
00889              nNlp*sizeof(double));
00890       // check solution of the NLP;
00891       // if we have a new incumbent we are done, otherwise we iterate
00892 
00893       bool isChecked = false;
00894 #ifdef FM_CHECKNLP2
00895       isChecked = couenne_->checkNLP2(tmpSolution, 0, false, // do not care about obj
00896                                       true, // stopAtFirstViol
00897                                       false, // checkALL
00898                                       couenne_->getFeasTol());
00899       if(isChecked) {
00900         obj = couenne_->getRecordBestSol()->getModSolVal();
00901       }
00902 #else /* not FM_CHECKNLP2 */
00903       isChecked = couenne_->checkNLP(tmpSolution, obj, true);
00904 #endif  /* not FM_CHECKNLP2 */
00905       
00906       if (cinlp_->isProvenOptimal () &&
00907           isChecked &&
00908           (obj < couenne_->getCutOff())) {
00909         
00910 #ifdef FM_CHECKNLP2
00911 #ifdef FM_TRACE_OPTSOL
00912         couenne_->getRecordBestSol()->update();
00913         CoinCopyN (couenne_->getRecordBestSol()->getSol(), n, tmpSolution);
00914         obj = couenne_->getRecordBestSol()->getVal();
00915 #else /* not FM_TRACE_OPTSOL */
00916         CoinCopyN (couenne_->getRecordBestSol()->getModSol(n), n, tmpSolution);
00917 #endif /* not FM_TRACE_OPTSOL */
00918 #else /* not FM_CHECKNLP2 */
00919         
00920         //Get correct values for all auxiliary variables
00921         couenne_ -> getAuxs (tmpSolution);
00922         
00923 #ifdef FM_TRACE_OPTSOL
00924         couenne_->getRecordBestSol()->update(tmpSolution, n,
00925                                              obj, couenne_->getFeasTol());
00926         CoinCopyN (couenne_->getRecordBestSol()->getSol(), n, tmpSolution);
00927         obj = couenne_->getRecordBestSol()->getVal();
00928 #endif /* FM_TRACE_OPTSOL */
00929 #endif /* not FM_CHECKNLP2 */
00930         
00931         if (babInfo){
00932           babInfo->setNlpSolution (tmpSolution, n, obj);
00933           babInfo->setHasNlpSolution (true);
00934         }
00935 
00936         std::cout << "Final Nlp solution with objective " << obj << " :" << std::endl;
00937 
00938         if (obj < objectiveValue - COUENNE_EPS) { // found better solution?
00939           std::cout << "New incumbent found" << std::endl;
00940           const CouNumber 
00941             *lb = solver -> getColLower (),
00942             *ub = solver -> getColUpper ();
00943 
00944           // check bounds once more after getAux. This avoids false
00945           // asserts in CbcModel.cpp:8305 on integerTolerance violated
00946           for (int i=0; i < n; ++i, ++lb, ++ub) {
00947             CouNumber &t = tmpSolution [i];
00948             if      (t < *lb) t = *lb;
00949             else if (t > *ub) t = *ub;
00950           }
00951 
00952           couenne_ -> setCutOff (obj);
00953           foundSolution = true;
00954           objectiveValue = obj;
00955           CoinCopyN (tmpSolution, n, newSolution);
00956           cinlp_->setColLower(colLowerNlp_);
00957           cinlp_->setColUpper(colUpperNlp_);
00958           
00959           curr_milp->restoreBaseModel(numInitialRows_);
00960           delete[] xprime;
00961           delete[] tmpSolution;
00962           if (boundsChanged){
00963             curr_milp->setColLower(colLower_);
00964             curr_milp->setColUpper(colUpper_);
00965           }
00966           //delete curr_milp;
00967           double elapsed = CoinCpuTime()-startTime_;
00968           std::cout << "IR: Heuristic: " << objectiveValue << std::endl;
00969           std::cout << "IR: Heuristic time: " << elapsed << std::endl;
00970           return foundSolution;
00971         }
00972       }
00973       cinlp_->setColLower(colLowerNlp_);
00974       cinlp_->setColUpper(colUpperNlp_);
00975       numIntAtBound = computeIntAtBound(xtilde, avgBound);
00976         
00977       if (numIntAtBound >= 50 || 
00978           numIntAtBound >= ((numIntegers_*0.1 > 5) ? numIntegers_*0.1 : 5)){
00979         // write reverse local branching constraint
00980         // this avoids finding the same xtilde again
00981         avgBound = floor(avgBound + 0.5);
00982         std::cout << "Using reverse LB with rhs " << avgBound << std::endl;
00983         writeLB(cut, xtilde, 'G', avgBound);
00984         revlb_all.insert(cut);
00985       }
00986       else{
00987         // Branch (randomly) so that we can obtain a new integer point
00988         branchToCut(xtilde, curr_milp, previousBranches);
00989         boundsChanged = true;
00990       }
00991     }
00992     
00993     curr_milp->restoreBaseModel(numInitialRows_);
00994     delete[] xprime;
00995     delete[] tmpSolution;
00996     if (boundsChanged){
00997       curr_milp->setColLower(colLower_);
00998       curr_milp->setColUpper(colUpper_);
00999     }
01000     double elapsed = CoinCpuTime()-startTime_;
01001     std::cout << "IR: Heuristic: " << COUENNE_INFINITY << std::endl;
01002     std::cout << "IR: Heuristic time: " << elapsed << std::endl;
01003     return foundSolution;
01004   }
01005 
01006   int 
01007   CouenneIterativeRounding::computeIntAtBound(const double* x){
01008     int numIntAtBound = 0;
01009     for (int i = 0; i < nlp_->getNumCols(); ++i){
01010       if (nlp_->isInteger(i) && (areEqual(x[i], colLower_[i]) || 
01011                                  areEqual(x[i], colUpper_[i]))){
01012         numIntAtBound++;
01013       }
01014     }
01015     return numIntAtBound;
01016   }
01017 
01018   int 
01019   CouenneIterativeRounding::computeIntAtBound(const double* x, 
01020                                                 double& avgBoundSize){
01021     int numIntAtBound = 0;
01022     avgBoundSize = 0;
01023     for (int i = 0; i < nlp_->getNumCols(); ++i){
01024       if (nlp_->isInteger(i) && (areEqual(x[i], colLower_[i]) || 
01025                                  areEqual(x[i], colUpper_[i]))){
01026         numIntAtBound++;
01027         avgBoundSize += colUpper_[i] - colLower_[i];
01028       }
01029     }
01030     avgBoundSize /= numIntAtBound;
01031     return numIntAtBound;
01032   }
01033 
01034   void
01035   CouenneIterativeRounding::writeLB(OsiRowCut& cut, const double* x, 
01036                                     char sense, double rhs){
01037     cut.mutableRow().clear();
01038     for (int i = 0; i < nlp_->getNumCols(); ++i){
01039       if (nlp_->isInteger(i)){
01040         if (areEqual(x[i], colUpper_[i])){
01041           cut.mutableRow().insert(i, -1);
01042           rhs -= x[i];
01043         }
01044         else if (areEqual(x[i], colLower_[i])){
01045           cut.mutableRow().insert(i, 1);
01046           rhs += x[i];
01047         }
01048       }
01049     }
01050     if (sense == 'L'){
01051       cut.setLb(-COIN_DBL_MAX);
01052       cut.setUb(rhs);
01053     }
01054     else if (sense == 'G'){
01055       cut.setLb(rhs);
01056       cut.setUb(COIN_DBL_MAX);
01057     }
01058     else{
01059       std::cerr << "### ERROR: wrong sense of LB constraint" << std::endl;
01060       exit(1);
01061     }
01062   }
01063 
01064   bool
01065   CouenneIterativeRounding::solveMilp(OsiSolverInterface* milp,
01066                                       double maxTime){
01067     double start = CoinCpuTime();
01068 #ifdef COIN_HAS_CPX
01069     OsiCpxSolverInterface * solver = dynamic_cast<OsiCpxSolverInterface*>(milp);
01070     CPXENVptr env = solver->getEnvironmentPtr();
01071     CPXLPptr cpxlp = solver->getLpPtr(OsiCpxSolverInterface::KEEPCACHED_ALL);
01072     int status = 0;
01073     bool solFound = false;
01074     bool infeasible = false;
01075     while (!solFound && !infeasible && ((CoinCpuTime() - start) < maxTime)){
01076       solver->branchAndBound();
01077       status = CPXgetstat(env, cpxlp);
01078       solFound = ((status == CPXMIP_NODE_LIM_FEAS) ||
01079                   (status == CPXMIP_TIME_LIM_FEAS) ||
01080                   (status == CPXMIP_MEM_LIM_FEAS) ||
01081                   (status == CPXMIP_ABORT_FEAS) ||
01082                   (status == CPXMIP_OPTIMAL) ||
01083                   (status == CPXMIP_OPTIMAL_TOL) ||                  
01084                   (status == CPXMIP_ABORT_FEAS) ||
01085                   (status == CPXMIP_FAIL_FEAS) ||
01086                   (status == CPXMIP_FAIL_FEAS_NO_TREE) ||
01087                   (status == CPXMIP_FEASIBLE));
01088       infeasible = ((status == CPXMIP_INForUNBD) ||
01089                     (status == CPXMIP_OPTIMAL_INFEAS) ||
01090                     (status == CPXMIP_INFEASIBLE));
01091     }
01092     if (solFound){
01093       return true;
01094     }
01095     return false;
01096 #else
01097     CbcModel cbcModel(*milp);
01098     for (int i = 0; i < numHeuristics_; ++i){
01099       cbcModel.addHeuristic(heuristics_[i]);
01100     }
01101     cbcModel.setMaximumSeconds(CBCMILPTIME);
01102     //CglPreProcess * prep = cbcModel.preProcess(0,2,5);
01103     while ((cbcModel.getSolutionCount() == 0) && 
01104            (!cbcModel.isProvenInfeasible()) &&
01105            (!cbcModel.isProvenDualInfeasible()) &&
01106            (!cbcModel.isAbandoned()) &&
01107            ((CoinCpuTime() - start) < maxTime)){
01108       cbcModel.branchAndBound();
01109     }
01110     //cbcModel.postProcess(prep);
01111     milp = cbcModel.solver();
01112     if (cbcModel.getSolutionCount() > 0){
01113       return true;
01114     }
01115     return false;
01116 #endif
01117   }
01118 
01119   int
01120   CouenneIterativeRounding::branchToCut(const double* x, 
01121                                         OsiSolverInterface* solver,
01122                                         std::vector<int>& previousBranches){
01123     int branch;
01124     bool found = false;
01125     while (!found){
01126       branch = rand()%numIntegers_;
01127       found = true;
01128       for (unsigned int i = 0; i < previousBranches.size(); ++i){
01129         if (branch == previousBranches[i]){
01130           found = false;
01131           break;
01132         }
01133       }
01134       if (found){
01135         previousBranches.push_back(branch);
01136       }
01137       else{
01138         continue;
01139       }
01140       for (int i = 0; i < nlp_->getNumCols(); ++i){
01141         if (model_->isInteger(i)){
01142           if (branch == 0){
01143             branch = i;
01144             break;
01145           }
01146           else{
01147             branch--;
01148           }
01149         }
01150       }
01151     }
01152     double sample = rand();
01153     if (sample <= ((x[branch]-colLower_[branch])/(colUpper_[branch]-colLower_[branch]))){
01154       solver->setColUpper(branch, x[branch]-1);
01155     }
01156     else{
01157       solver->setColLower(branch, x[branch]+1);
01158     }
01159     return branch;
01160   }
01161 
01162   void 
01163   CouenneIterativeRounding::registerOptions (Ipopt::SmartPtr <Bonmin::RegisteredOptions> roptions){
01164     roptions -> AddStringOption2
01165       ("iterative_rounding_heuristic",
01166        "Do we use the Iterative Rounding heuristic",
01167        "no",
01168        "no","",
01169        "yes","",
01170        "If enabled, a heuristic based on Iterative Rounding is used "
01171        "to find feasible solutions for the problem. "
01172        "The heuristic may take some time, but usually finds good solutions. "
01173        "Recommended if you want good upper bounds and have Cplex."
01174        "Not recommended if you do not have Cplex");
01175 
01176     roptions -> AddNumberOption
01177       ("iterative_rounding_time",
01178        "Specify the maximum time allowed for the Iterative Rounding heuristic",
01179        -1, "Maximum CPU time employed by the Iterative Rounding heuristic; "
01180        "if no solution found in this time, failure is reported."
01181        "This overrides the CPU time set by Aggressiveness if positive.");
01182 
01183     roptions -> AddNumberOption
01184       ("iterative_rounding_time_firstcall",
01185        "Specify the maximum time allowed for the Iterative Rounding heuristic "
01186        "when no feasible solution is known",
01187        -1, "Maximum CPU time employed by the Iterative Rounding heuristic "
01188        "when no solution is known; if no solution found in this time, "
01189        "failure is reported."
01190        "This overrides the CPU time set by Aggressiveness if  posive.");
01191     
01192     roptions -> AddBoundedIntegerOption 
01193       ("iterative_rounding_aggressiveness",
01194        "Aggressiveness of the Iterative Rounding heuristic",
01195        0, 2, 1,
01196        "Set the aggressiveness of the heuristic; i.e., how many iterations "
01197        "should be run, and with which parameters. The maximum time can be"
01198        "overridden by setting the _time and _time_firstcall options."
01199        "0 = non aggressive, 1 = standard (default), 2 = aggressive.");
01200 
01201     roptions -> AddLowerBoundedIntegerOption 
01202       ("iterative_rounding_num_fir_points",
01203        "Max number of points rounded at the beginning of Iterative Rounding",
01204        1, 5,
01205        "Number of different points (obtained solving a log-barrier problem)"
01206        "that the heuristic will try to round at most, during its execution"
01207        "at the root node (i.e. the F-IR heuristic). Default 5.");
01208 
01209     roptions -> AddBoundedNumberOption 
01210       ("iterative_rounding_omega",
01211        "Omega parameter of the Iterative Rounding heuristic",
01212        0, true, 1, true, 0.2,
01213        "Set the omega parameter of the heuristic, which represents a"
01214        "multiplicative factor for the minimum log-barrier parameter"
01215        "of the NLP which is solved to obtain feasible points. This"
01216        "corresponds to \\omega' in the paper. Default 0.2.");
01217 
01218     roptions -> AddLowerBoundedIntegerOption 
01219       ("iterative_rounding_base_lbrhs",
01220        "Base rhs of the local branching constraint for Iterative Rounding",
01221        0, 15,
01222        "Base rhs for the local branching constraint that defines a"
01223        "neighbourhood of the local incumbent. The base rhs is modified by"
01224        "the algorithm according to variable bounds. This corresponds to"
01225        "k' in the paper. Default 15.");
01226 
01227   }
01228 
01229 }

Generated on Thu Sep 22 03:05:58 2011 by  doxygen 1.4.7