Example #1
0
//#############################################################################
bool
MibSHeuristic::checkLowerFeasibility(OsiSolverInterface * si, 
				     double * solution)
{

  MibSModel * model = MibSModel_;
  OsiSolverInterface * lSolver = model->bS_->setUpModel(si, true, solution);

  if(0){
     dynamic_cast<OsiCbcSolverInterface *> 
	(lSolver)->getModelPtr()->messageHandler()->setLogLevel(0);
  }    
  else{
     dynamic_cast<OsiSymSolverInterface *> 
	(lSolver)->setSymParam("prep_level", -1);
     
     dynamic_cast<OsiSymSolverInterface *> 
	(lSolver)->setSymParam("verbosity", -2);
     
     dynamic_cast<OsiSymSolverInterface *> 
	(lSolver)->setSymParam("max_active_nodes", 1);
  }

  lSolver->branchAndBound();

  if(lSolver->isProvenOptimal())
    return true;
  else
    return false;
}
Example #2
0
//#############################################################################
bfSol*
MibSHeuristic::getBilevelSolution(const double * sol, double origLower)
{

  /* 
     Find a bilevel feasible solution by solving the LL problem
     for a fixed UL solution, given by the UL portion of sol
  */

  MibSModel * model = MibSModel_;
  OsiSolverInterface * oSolver = model->getSolver();
  OsiSolverInterface * lSolver = model->bS_->setUpModel(oSolver, true, sol);
  
  //double uObjSense(model->getSolver()->getObjSense());
  int lCols(model->getLowerDim());
  int uCols(model->getUpperDim());
  int * lColIndices = model->getLowerColInd();
  int * uColIndices = model->getUpperColInd();
  double etol(etol_);

  int tCols(uCols + lCols); 
  int i(0);

  if(0){
     lSolver->writeLp("bilevelsolver");
     std::cout 
       << "Original Lower-level Solution Value: " << origLower << std::endl;
     for(i = 0; i < lCols; i++){
       std::cout << "lowsol[" << i << "]: " << sol[lColIndices[i]] << std::endl;
     }
  }
  
  if(0){
     dynamic_cast<OsiCbcSolverInterface *> 
	(lSolver)->getModelPtr()->messageHandler()->setLogLevel(0);
  }    
  else{
     dynamic_cast<OsiSymSolverInterface *> 
	(lSolver)->setSymParam("prep_level", -1);
     
     dynamic_cast<OsiSymSolverInterface *> 
	(lSolver)->setSymParam("verbosity", -2);
     
     dynamic_cast<OsiSymSolverInterface *> 
	(lSolver)->setSymParam("max_active_nodes", 1);
  }

  lSolver->branchAndBound();

  if(lSolver->isProvenOptimal()){

    double objVal(0.0);
    double lowerObj(lSolver->getObjValue());
    double * colsol = new double[tCols];

    for(i = 0; i < uCols; i++){
      colsol[uColIndices[i]] = sol[uColIndices[i]];
    }

    if(0){
      std::cout << "candidate lower solution value: " << origLower << std::endl;
      std::cout << "actual lower solution value: " << lowerObj << std::endl;
    }

    if(fabs(origLower - lowerObj) < etol){
      //original solution was bilevel feasible
      if(0)
	std::cout << "Original solution was bilevel feasible:" << std::endl;
      for(i = 0; i < lCols; i++){
	if(0){
	  std::cout << "lowerportion[" 
		    << i << "]: " << sol[lColIndices[i]] << std::endl; 
	}	
	colsol[lColIndices[i]] = sol[lColIndices[i]];
      }
    }
    else{
      if(0){
	std::cout << "Not bilevel feasible." << std::endl;
      }
      for(i = 0; i < lCols; i++){
	if(0){
	  std::cout << "newportion[" 
		    << i << "]: " << lSolver->getColSolution()[i] << std::endl; 
	}
	colsol[lColIndices[i]] = lSolver->getColSolution()[i];
      }
    }


    for(i = 0; i < tCols; i++)
      objVal += colsol[i] * oSolver->getObjCoefficients()[i];

    bfSol * bfsol = 
      new bfSol(objVal, colsol);
    delete lSolver;
    return bfsol;
  }
  else{
    delete lSolver;
    return NULL;
  }

}
Example #3
0
//#############################################################################
void 
MibSHeuristic::lowerObjHeuristic()
{

  /* 
     optimize wrt to lower-level objective 
     over current feasible lp feasible region 
  */

  MibSModel * model = MibSModel_;

  OsiSolverInterface * oSolver = model->getSolver();
  //OsiSolverInterface * hSolver = new OsiCbcSolverInterface();
  OsiSolverInterface* hSolver = new OsiSymSolverInterface();

  double objSense(model->getLowerObjSense());  
  int lCols(model->getLowerDim());
  int uCols(model->getUpperDim());
  int * lColIndices = model->getLowerColInd();
  int * uColIndices = model->getUpperColInd();
  double * lObjCoeffs = model->getLowerObjCoeffs();
  
  //int tCols(lCols + uCols);
  int tCols(oSolver->getNumCols());
  //assert(tCols == oSolver->getNumCols());

  hSolver->loadProblem(*oSolver->getMatrixByCol(),
		       oSolver->getColLower(), oSolver->getColUpper(),
		       oSolver->getObjCoefficients(),
		       oSolver->getRowLower(), oSolver->getRowUpper());

  int j(0);
  for(j = 0; j < tCols; j++){
    if(oSolver->isInteger(j))
      hSolver->setInteger(j);
  }

  double * nObjCoeffs = new double[tCols];
  int i(0), index(0);
  
  CoinZeroN(nObjCoeffs, tCols);

  for(i = 0; i < lCols; i++){
    index = lColIndices[i];
    nObjCoeffs[index] = lObjCoeffs[i];
  }

  //MibS objective sense is the opposite of OSI's!
  hSolver->setObjSense(objSense);

  hSolver->setObjective(nObjCoeffs);
 
  //double cutoff(model->getCutoff());
  double cutoff(model->getKnowledgeBroker()->getIncumbentValue());

  if(model->getNumSolutions()){
  
    CoinPackedVector objCon;
    //double rhs(cutoff * objSense);
    //double smlTol(1.0);
    double rhs(cutoff);
       
    for(i = 0; i < tCols; i++){
      objCon.insert(i, oSolver->getObjCoefficients()[i] 
		    * oSolver->getObjSense());
    }
    
    hSolver->addRow(objCon, - hSolver->getInfinity(), rhs);
  }
  
  if(0)
     hSolver->writeLp("lobjheurstic");

  if(0){
    dynamic_cast<OsiCbcSolverInterface *> 
      (hSolver)->getModelPtr()->messageHandler()->setLogLevel(0);
  }    
  else{
    dynamic_cast<OsiSymSolverInterface *> 
      (hSolver)->setSymParam("prep_level", -1);
    
    dynamic_cast<OsiSymSolverInterface *> 
      (hSolver)->setSymParam("verbosity", -2);

    dynamic_cast<OsiSymSolverInterface *> 
      (hSolver)->setSymParam("max_active_nodes", 1);
  }

  hSolver->branchAndBound();

  if(hSolver->isProvenOptimal()){

    double upperObjVal(0.0);

    /*****************NEW ******************/

    MibSSolution *mibSol = NULL;

    OsiSolverInterface * lSolver = model->bS_->setUpModel(hSolver, true);

    if(0){
       lSolver->writeLp("tmp");
    }

    if(0){
       dynamic_cast<OsiCbcSolverInterface *> 
	  (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0);
    }    
    else{
       dynamic_cast<OsiSymSolverInterface *> 
	  (lSolver)->setSymParam("prep_level", -1);
       
       dynamic_cast<OsiSymSolverInterface *> 
	  (lSolver)->setSymParam("verbosity", -2);
       
       dynamic_cast<OsiSymSolverInterface *> 
	  (lSolver)->setSymParam("max_active_nodes", 1);
    }

    lSolver->branchAndBound();

    if (lSolver->isProvenOptimal()){
       const double * sol = hSolver->getColSolution();
       double objVal(lSolver->getObjValue() * objSense);
       double etol(etol_);
       double lowerObj = getLowerObj(sol, objSense);  
       
       double * optUpperSolutionOrd = new double[uCols];
       double * optLowerSolutionOrd = new double[lCols];
       
       CoinZeroN(optUpperSolutionOrd, uCols);
       CoinZeroN(optLowerSolutionOrd, lCols);
       
       if(fabs(objVal - lowerObj) < etol){
	  
	  /** Current solution is bilevel feasible **/
	  
	  for(i = 0; i < tCols; i++)
	     upperObjVal += 
		hSolver->getColSolution()[i] * oSolver->getObjCoefficients()[i];
	  
	  mibSol = new MibSSolution(hSolver->getNumCols(),
				    hSolver->getColSolution(),
				    upperObjVal,
				    model);
	  
	  model->storeSolution(BlisSolutionTypeHeuristic, mibSol);
	  mibSol = NULL;
       }
       else{
	  
	  /* solution is not bilevel feasible, create one that is */
	  
	  const double * uSol = hSolver->getColSolution();
	  const double * lSol = lSolver->getColSolution();
	  int numElements(hSolver->getNumCols());
	  int i(0), pos(0), index(0);
	  double * lpSolution = new double[numElements];
	  double upperObj(0.0);
	  
	  //FIXME: problem is still here.  indices may be wrong.  
	  //also is all this necessary, or can we just paste together uSol and lSol?
	  //this may be an old comment
	  
	  for(i = 0; i < numElements; i++){
	     pos = model->bS_->binarySearch(0, lCols - 1, i, lColIndices);
	     if(pos < 0){
		pos = model->bS_->binarySearch(0, uCols - 1, i, uColIndices);
		if (pos >= 0){
		   optUpperSolutionOrd[pos] = uSol[i];
		}
	     }
	     else{
		optLowerSolutionOrd[pos] = lSol[pos];
	     }
	  }
	  
	  for(i = 0; i < uCols; i++){
	     index = uColIndices[i];
	     lpSolution[index] = optUpperSolutionOrd[i];
	     upperObj += 
		optUpperSolutionOrd[i] * oSolver->getObjCoefficients()[index];
	  }
	  
	  for(i = 0; i < lCols; i++){
	     index = lColIndices[i];
	     lpSolution[index] = optLowerSolutionOrd[i];
	     upperObj += 
		optLowerSolutionOrd[i] * oSolver->getObjCoefficients()[index];
	  }
	  
	  if(model->checkUpperFeasibility(lpSolution)){
	     mibSol = new MibSSolution(hSolver->getNumCols(),
				       lpSolution,
				       upperObj * oSolver->getObjSense(),
				       model);
	     
	     model->storeSolution(BlisSolutionTypeHeuristic, mibSol);
	     mibSol = NULL;
	  }
	  delete [] lpSolution;
       }
    }
    delete lSolver;
  }
  delete hSolver;

}
Example #4
0
//#############################################################################
mcSol 
MibSHeuristic::solveSubproblem(double beta)
{

  /* 
     optimize wrt to weighted upper-level objective 
     over current feasible lp feasible region 
  */

  MibSModel * model = MibSModel_;
  OsiSolverInterface * oSolver = model->getSolver();
  //OsiSolverInterface * sSolver = new OsiCbcSolverInterface();  
  OsiSolverInterface* sSolver = new OsiSymSolverInterface();
  //sSolver = oSolver->clone();
  //OsiSolverInterface * sSolver = tmpSolver;
  //OsiSolverInterface * tmpSolver = new OsiSolverInterface(oSolver);
  
  double uObjSense(oSolver->getObjSense());
  double lObjSense(model->getLowerObjSense());  
  int lCols(model->getLowerDim());
  int uCols(model->getUpperDim());
  int * lColIndices = model->getLowerColInd();
  int * uColIndices = model->getUpperColInd();
  double * lObjCoeffs = model->getLowerObjCoeffs();
  const double * uObjCoeffs = oSolver->getObjCoefficients();

  double etol(etol_);
  int tCols(uCols + lCols); 

  assert(tCols == oSolver->getNumCols());


  sSolver->loadProblem(*oSolver->getMatrixByCol(),
		       oSolver->getColLower(), oSolver->getColUpper(),
		       oSolver->getObjCoefficients(),
		       oSolver->getRowLower(), oSolver->getRowUpper());

  int j(0);
  for(j = 0; j < tCols; j++){
    if(oSolver->isInteger(j))
      sSolver->setInteger(j);
  }


  double * nObjCoeffs = new double[tCols];
  int i(0), index(0);
  
  CoinZeroN(nObjCoeffs, tCols);
  
  /* Multiply the UL columns of the UL objective by beta */
  for(i = 0; i < uCols; i++){
    index = uColIndices[i];
    if(fabs(uObjCoeffs[index]) > etol)
      nObjCoeffs[index] = beta * uObjCoeffs[index] * uObjSense;
    else 
      nObjCoeffs[index] = 0.0;
  }
    
  /* Multiply the LL columns of the UL objective by beta */
  for(i = 0; i < lCols; i++){
    index = lColIndices[i];
    if(fabs(uObjCoeffs[index]) > etol)
      nObjCoeffs[index] = beta* uObjCoeffs[index] * uObjSense;
    else
      nObjCoeffs[index] = 0.0;
  }
  
  /* Add the LL columns of the LL objective multiplied by (1 - beta) */
  for(i = 0; i < lCols; i++){
    index = lColIndices[i];
    if(fabs(lObjCoeffs[i]) > etol)
      nObjCoeffs[index] += (1 - beta) * lObjCoeffs[i] * lObjSense;
  }
  
  sSolver->setObjective(nObjCoeffs);

  //int i(0);
  if(0){
    for(i = 0; i < sSolver->getNumCols(); i++){
      std::cout << "betaobj " << sSolver->getObjCoefficients()[i] << std::endl;
    }
  }

  if(0){
     sSolver->writeLp("afterbeta");
     //sSolver->writeMps("afterbeta");
  }
  
  if(0){  
    for(i = 0; i < sSolver->getNumCols(); i++){
      std::cout << "obj " << sSolver->getObjCoefficients()[i] << std::endl;
      std::cout << "upper " << sSolver->getColUpper()[i] << std::endl;
      std::cout << "lower " << sSolver->getColLower()[i] << std::endl;
    }
  }

  if(0){
    dynamic_cast<OsiCbcSolverInterface *> 
      (sSolver)->getModelPtr()->messageHandler()->setLogLevel(0);
  }
  else{
    dynamic_cast<OsiSymSolverInterface *> 
      (sSolver)->setSymParam("prep_level", -1);
    
    dynamic_cast<OsiSymSolverInterface *> 
      (sSolver)->setSymParam("verbosity", -2);

    dynamic_cast<OsiSymSolverInterface *> 
      (sSolver)->setSymParam("max_active_nodes", 1);
  }

  //dynamic_cast<OsiSymSolverInterface *> (sSolver)->branchAndBound();

  sSolver->branchAndBound();

  if(sSolver->isProvenOptimal()){

    if(0){
      std::cout << "writing lp file." << std::endl;
      sSolver->writeLp("afterbeta");
      //sSolver->writeMps("afterbeta");
    }
    
    double upperObjVal(0.0);
    double lowerObjVal(0.0);
    

    for(i = 0; i < tCols; i++){
      upperObjVal += 
	sSolver->getColSolution()[i] * oSolver->getObjCoefficients()[i];
      if(0){
	std::cout << "sSolver->getColSolution()[" << i << "] :"
		  << sSolver->getColSolution()[i] << std::endl;
      }
    }
    lowerObjVal = getLowerObj(sSolver->getColSolution(), lObjSense);
    
    if(beta == 1.0){
      
      /*
	fix upper-level objective to current value and 
	reoptimize wrt to lower-level objective
      */
      
      //OsiSolverInterface * nSolver = new OsiCbcSolverInterface();
      OsiSolverInterface * nSolver = new OsiSymSolverInterface();
      nSolver->loadProblem(*oSolver->getMatrixByCol(),
			   oSolver->getColLower(), oSolver->getColUpper(),
			   oSolver->getObjCoefficients(),
			   oSolver->getRowLower(), oSolver->getRowUpper());
      for(j = 0; j < tCols; j++){
	if(oSolver->isInteger(j))
	  nSolver->setInteger(j);
      }
      

      CoinZeroN(nObjCoeffs, tCols);
      
      for(i = 0; i < lCols; i++){
	index = lColIndices[i];
	nObjCoeffs[index] = lObjCoeffs[i] * lObjSense;
      }
      
      nSolver->setObjective(nObjCoeffs);
      
      CoinPackedVector objCon;
      
      for(i = 0; i < tCols; i++){
	objCon.insert(i, uObjCoeffs[i] * uObjSense);
      }
      
      nSolver->addRow(objCon, upperObjVal, upperObjVal);
      nSolver->writeLp("beta1");
      if(0){
	dynamic_cast<OsiCbcSolverInterface *> 
	  (nSolver)->getModelPtr()->messageHandler()->setLogLevel(0);
      }
      else{
	 dynamic_cast<OsiSymSolverInterface *> 
	    (nSolver)->setSymParam("prep_level", -1);

	 dynamic_cast<OsiSymSolverInterface *> 
	    (nSolver)->setSymParam("verbosity", -2);

	 dynamic_cast<OsiSymSolverInterface *> 
	    (nSolver)->setSymParam("max_active_nodes", 1);
      }

      nSolver->branchAndBound();
     

      double * colsol = new double[tCols];

      if(nSolver->isProvenOptimal()){
	lowerObjVal = nSolver->getObjValue();
	CoinCopyN(nSolver->getColSolution(), tCols, colsol);
      }
      else{
	//just take the current solution
	lowerObjVal = sSolver->getObjValue();
	CoinCopyN(sSolver->getColSolution(), tCols, colsol);
      }

      delete[] nObjCoeffs;
      nObjCoeffs = 0;
      delete sSolver;
      delete nSolver;
      return mcSol(std::make_pair(upperObjVal, lowerObjVal), colsol);
    }
    else if(beta == 0.0){
      
      /*
	fix lower-level objective to current value and 
	reoptimize wrt to upper-level objective
      */
      
      //OsiSolverInterface * nSolver = new OsiCbcSolverInterface();
      OsiSolverInterface * nSolver = new OsiSymSolverInterface();
      nSolver->loadProblem(*oSolver->getMatrixByCol(),
			   oSolver->getColLower(), oSolver->getColUpper(),
			   oSolver->getObjCoefficients(),
			   oSolver->getRowLower(), oSolver->getRowUpper());
      for(j = 0; j < tCols; j++){
	if(oSolver->isInteger(j))
	  nSolver->setInteger(j);
      }
      
      CoinZeroN(nObjCoeffs, tCols);
	
      for(i = 0; i < tCols; i++)
	nObjCoeffs[i] = uObjCoeffs[i] * uObjSense;
      
      nSolver->setObjective(nObjCoeffs);
	
      CoinPackedVector objCon;
	
      for(i = 0; i < lCols; i++){
	index = lColIndices[i];
	objCon.insert(index, lObjCoeffs[i] * lObjSense);  
      }
      
      nSolver->addRow(objCon, lowerObjVal, lowerObjVal);
      
      if(0){
	dynamic_cast<OsiCbcSolverInterface *> 
	  (nSolver)->getModelPtr()->messageHandler()->setLogLevel(0);
      }
      else{
	 dynamic_cast<OsiSymSolverInterface *> 
	    (nSolver)->setSymParam("prep_level", -1);

	 dynamic_cast<OsiSymSolverInterface *> 
	    (nSolver)->setSymParam("verbosity", -2);

	 dynamic_cast<OsiSymSolverInterface *> 
	    (nSolver)->setSymParam("max_active_nodes", 1);
      }

      if(0)      
	nSolver->writeLp("nSolver");
      

      nSolver->branchAndBound();
	
      double * colsol = new double[tCols];
	
      if(nSolver->isProvenOptimal()){
	upperObjVal = nSolver->getObjValue();
	CoinCopyN(nSolver->getColSolution(), tCols, colsol);
      }
      else{
	upperObjVal = nSolver->getObjValue();
	CoinCopyN(nSolver->getColSolution(), tCols, colsol);
      }

      delete[] nObjCoeffs;
      nObjCoeffs = 0;
      delete sSolver;
      delete nSolver;
      return mcSol(std::make_pair(upperObjVal, lowerObjVal), colsol);
	
    }
    else{
      
      //no optimality cut needed here.  all solutions are supported.
      
      double * colsol = new double[tCols];
      CoinCopyN(sSolver->getColSolution(), tCols, colsol);	
      
      delete[] nObjCoeffs;
      nObjCoeffs = 0;
      delete sSolver;
      return mcSol(std::make_pair(upperObjVal, lowerObjVal), colsol);
      
    }
    
  }
  else{
    //FIXME:SHOULD JUST TAKE THIS OUT.  DELETE sSolver and remove it from above
    
    nObjCoeffs = 0;
    delete[] nObjCoeffs;
    delete sSolver;
    std::cout << "Subproblem is not proven optimal." << std::endl;
    //return NULL;
    //abort();
  }
}
Example #5
0
//#############################################################################
void 
MibSHeuristic::objCutHeuristic()
{

  /* Solve the LP relaxation with the new constraint d^2 y <= d^y* */

  MibSModel * model = MibSModel_;

  //OsiSolverInterface * oSolver = model->origLpSolver_;
  OsiSolverInterface * oSolver = model->getSolver();
  //OsiSolverInterface * hSolver = new OsiCbcSolverInterface();
  OsiSolverInterface * hSolver = new OsiSymSolverInterface();

  double objSense(model->getLowerObjSense());  
  int lCols(model->getLowerDim());
  int uCols(model->getUpperDim());
  int tCols(lCols + uCols);
  int * lColIndices = model->getLowerColInd();
  int * uColIndices = model->getUpperColInd();
  double * lObjCoeffs = model->getLowerObjCoeffs();

  hSolver->loadProblem(*oSolver->getMatrixByCol(),
		       oSolver->getColLower(), oSolver->getColUpper(),
		       oSolver->getObjCoefficients(),
		       oSolver->getRowLower(), oSolver->getRowUpper());

  int j(0);
  for(j = 0; j < tCols; j++){
    if(oSolver->isInteger(j))
      hSolver->setInteger(j);
  }

  double * optLowerSolutionOrd = model->bS_->optLowerSolutionOrd_;

  CoinPackedVector objCon;
  int i(0), index(0);
  double rhs(0.0);

  for(i = 0; i < lCols; i++){
    index = lColIndices[i];
    objCon.insert(index, lObjCoeffs[i] * objSense);
    //should this be ordered? and should lObjCoeffs by at index?
    //rhs += optLowerSolutionOrd_[i] * lObjCoeffs[i] * objSense;
    rhs += optLowerSolutionOrd[i] * lObjCoeffs[i] * objSense;
  }

  //Hmm, I think this was wrong before...?
  //  hSolver->addRow(objCon, - hSolver->getInfinity(), rhs);
  hSolver->addRow(objCon, rhs, hSolver->getInfinity());

  /* optimize w.r.t. to the UL objective with the new row */
  if(0){
    dynamic_cast<OsiCbcSolverInterface *> 
      (hSolver)->getModelPtr()->messageHandler()->setLogLevel(0);
  }
  else{
    dynamic_cast<OsiSymSolverInterface *> 
      (hSolver)->setSymParam("prep_level", -1);
    
    dynamic_cast<OsiSymSolverInterface *> 
      (hSolver)->setSymParam("verbosity", -2);

    dynamic_cast<OsiSymSolverInterface *> 
      (hSolver)->setSymParam("max_active_nodes", 1);
  }

  hSolver->branchAndBound();

  if(0)
    hSolver->writeLp("objcutheuristic");

  if(hSolver->isProvenOptimal()){

    MibSSolution *mibSol = NULL;

    OsiSolverInterface * lSolver = model->bS_->setUpModel(hSolver, true);

    if(0){
       dynamic_cast<OsiCbcSolverInterface *> 
	  (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0);
    }    
    else{
       dynamic_cast<OsiSymSolverInterface *> 
	  (lSolver)->setSymParam("prep_level", -1);
       
       dynamic_cast<OsiSymSolverInterface *> 
	  (lSolver)->setSymParam("verbosity", -2);
       
       dynamic_cast<OsiSymSolverInterface *> 
	  (lSolver)->setSymParam("max_active_nodes", 1);
    }

    lSolver->branchAndBound();

    const double * sol = hSolver->getColSolution();
    double objVal(lSolver->getObjValue() * objSense);
    double etol(etol_);
    double lowerObj = getLowerObj(sol, objSense);  
    
    double * optUpperSolutionOrd = new double[uCols];
    double * optLowerSolutionOrd = new double[lCols];
    
    CoinZeroN(optUpperSolutionOrd, uCols);
    CoinZeroN(optLowerSolutionOrd, lCols);

    if(fabs(objVal - lowerObj) < etol){
    
      /** Current solution is bilevel feasible **/
     
      mibSol = new MibSSolution(hSolver->getNumCols(),
				hSolver->getColSolution(),
				hSolver->getObjValue(),
				model);

     model->storeSolution(BlisSolutionTypeHeuristic, mibSol);
     mibSol = NULL;
 
    }
    else{

      /* solution is not bilevel feasible, create one that is */

     const double * uSol = hSolver->getColSolution();
     const double * lSol = lSolver->getColSolution();
     //int numElements(lSolver->getNumCols());
     int numElements(hSolver->getNumCols());
     int i(0), pos(0), index(0);
     double * lpSolution = new double[numElements];
     double upperObj(0.0);

     //FIXME: problem is still here.  indices may be wrong.  
     //also is all this necessary, or can we just paste together uSol and lSol?
     
     for(i = 0; i < numElements; i++){
       //index = indices[i];
       pos = model->bS_->binarySearch(0, lCols - 1, i, lColIndices);
       if(pos < 0){
	 pos = model->bS_->binarySearch(0, uCols - 1, i, uColIndices);
	 //optUpperSolutionOrd[pos] = values[i];
	 //optUpperSolutionOrd[pos] = uSol[pos];
	 if (pos >= 0){
	    optUpperSolutionOrd[pos] = uSol[i];
	 }
       }
       else{
	 //optLowerSolutionOrd[pos] = lSol[i];
	 optLowerSolutionOrd[pos] = lSol[pos];
       }
     }

     for(i = 0; i < uCols; i++){
       index = uColIndices[i];
       lpSolution[index] = optUpperSolutionOrd[i];
       upperObj += 
	 optUpperSolutionOrd[i] * hSolver->getObjCoefficients()[index];
     }

     for(i = 0; i < lCols; i++){
       index = lColIndices[i];
       lpSolution[index] = optLowerSolutionOrd[i];
       upperObj += 
	 optLowerSolutionOrd[i] * hSolver->getObjCoefficients()[index];
     }

     if(model->checkUpperFeasibility(lpSolution)){
       mibSol = new MibSSolution(hSolver->getNumCols(),
				 lpSolution,
				 upperObj * hSolver->getObjSense(),
				 model);

       model->storeSolution(BlisSolutionTypeHeuristic, mibSol);
       mibSol = NULL;
     }
     delete [] lpSolution;
    }
    delete lSolver;
  }

  delete hSolver;

}
Example #6
0
//#############################################################################
bfSol*
MibSHeuristic::getBilevelSolution1(const double * sol)
{

  /* 
     Find a bilevel feasible solution by solving the LL problem
     for a fixed UL solution, given by the UL portion of sol
  */


  MibSModel * model = MibSModel_;
  OsiSolverInterface * oSolver = model->getSolver();
  OsiSolverInterface * lSolver = new OsiCbcSolverInterface(oSolver);
  
  //double uObjSense(model->getSolver()->getObjSense());
  double lObjSense(model->getLowerObjSense());  
  int lCols(model->getLowerDim());
  int uCols(model->getUpperDim());
  int * lColIndices = model->getLowerColInd();
  int uRowNum = model->getUpperRowNum();
  int lRowNum = model->getLowerRowNum();
  int * uRowIndices = model->getUpperRowInd();
  int * lRowIndices = model->getLowerRowInd();
  int * uColIndices = model->getUpperColInd();
  double * lObjCoeffs = model->getLowerObjCoeffs();

  int tCols(uCols + lCols); 
  int i(0), index(0);

  /* delete the UL rows */
  lSolver->deleteRows(uRowNum, uRowIndices);

  /* Fix the UL variables to their current value in sol */

  for(i = 0; i < uCols; i++){
    index = uColIndices[i];
    lSolver->setColLower(index, sol[index]);
    lSolver->setColUpper(index, sol[index]);
  }

  /* Set the objective to the LL objective coefficients */

  double * nObjCoeffs = new double[tCols];
  CoinZeroN(nObjCoeffs, tCols);
      
  for(i = 0; i < lCols; i++){
    index = lColIndices[i];
    nObjCoeffs[index] = lObjCoeffs[i] * lObjSense;
  }
  
  lSolver->setObjective(nObjCoeffs);

  if(0){
    dynamic_cast<OsiCbcSolverInterface *> 
      (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0);
  }
  else{
     dynamic_cast<OsiSymSolverInterface *> 
	(lSolver)->setSymParam("prep_level", -1);
     
     dynamic_cast<OsiSymSolverInterface *> 
	(lSolver)->setSymParam("verbosity", -2);
     
     dynamic_cast<OsiSymSolverInterface *> 
	(lSolver)->setSymParam("max_active_nodes", 1);
  }

  lSolver->branchAndBound();

  if(lSolver->isProvenOptimal()){

    double objVal(0.0);

    for(i = 0; i < tCols; i++)
      objVal += lSolver->getColSolution()[i] * oSolver->getObjCoefficients()[i];
    
    double * colsol = new double[tCols];
    CoinCopyN(lSolver->getColSolution(), tCols, colsol);
 
    bfSol * bfsol = 
      new bfSol(objVal, colsol);
    delete lSolver;
    return bfsol;
  }
  else{
    delete lSolver;
    return NULL;
  }

}
Example #7
0
// mex function usage:
//  [x,y,status] = mexosi(n_vars,n_cons,A,x_lb,x_ub,c,Ax_lb,Ax_ub,isMIP,isQP,vartype,Q,options)
//                        0      1      2 3    4    5 6     7     8     9    10     11 12
void mexFunction(int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[])
{
	// Enable printing in MATLAB
	int loglevel = 0;
	DerivedHandler *mexprinter = new DerivedHandler(); // assumed open	
	mexprinter->setLogLevel(loglevel);		 
	// check that we have the right number of inputs
	if(nrhs < 10) mexErrMsgTxt("At least 10 inputs required in call to mexosi. Bug in osi.m?...");
	// check that we have the right number of outputs
	if(nlhs < 3) mexErrMsgTxt("At least 3 ouptuts required in call to mexosi. Bug in osi.m?...");

    // Get pointers to input values
	const int    n_vars = (int)*mxGetPr(prhs[0]);
	const int    n_cons = (int)*mxGetPr(prhs[1]);
	const mxArray    *A =  prhs[2];
	const double  *x_lb =  mxGetPr(prhs[3]);
	const double  *x_ub =  mxGetPr(prhs[4]);
	const double     *c =  mxGetPr(prhs[5]);
	const double *Ax_lb =  mxGetPr(prhs[6]);
	const double *Ax_ub =  mxGetPr(prhs[7]);
	const bool    isMIP = (bool)*(mxLogical*)mxGetData(prhs[8]);
	const bool     isQP = (bool)*(mxLogical*)mxGetData(prhs[9]);
	mxLogical *isinteger = (mxLogical*)mxGetData(prhs[10]);
	const mxArray*    Q = prhs[11];
	// process the options
	int  returnStatus = 0;
	// extract row/col/value data from A
	const mwIndex * A_col_starts = mxGetJc(A);
	const mwIndex * A_row_index  = mxGetIr(A);
	const double  * A_data       = mxGetPr(A);
    // figure out the number of non-zeros in A
    int nnz = (int)(A_col_starts[n_vars] - A_col_starts[0]); // number of non-zeros
    //mexPrintf("nnz = %d, n_vars = %d, n_cons = %d\n",nnz,n_vars,n_cons);

    // we need to convert these into other types of indices for Coin to use them
    std::vector<CoinBigIndex> A_col_starts_coin(A_col_starts,A_col_starts+n_vars+1);
    std::vector<int>          A_row_index_coin(A_row_index,A_row_index+nnz);
    
    // declare the solver
    OsiSolverInterface* pSolver;
// 	initialize the solver
    if ( isMIP ) {
        pSolver = new OsiCbcSolverInterface;
    } else {
        pSolver = new OsiClpSolverInterface;
    }
   
//	OsiCbcSolverInterface is deprecated and CbcModel should be used instead but don't
//	know how to get that working with loadProblem. 
//     OsiCbcSolverInterface solver1;
//     CbcModel model(solver1);
//     CbcMain0(model);
//     OsiSolverInterface * pSolver = model.solver();
    
	if (nrhs>12) { // get stuff out of the options structure if provided
		// Finish me
	}
    
//     mexPrintf("Setting Log Level to 0.\n");
	// load the problem
	mexPrintf("Loading the problem.\n");
	pSolver->loadProblem( n_vars, n_cons, // problem size
						  &A_col_starts_coin[0], &A_row_index_coin[0], A_data, // the A matrix
						  x_lb,  x_ub, c, // the objective and bounds
						  Ax_lb, Ax_ub ); // the constraint bounds
    
//     pSolver->messageHandler()->setLogLevel(0); // This doesn't seem to work
    pSolver->setHintParam(OsiDoReducePrint,true,OsiHintTry);
    
	// deal with integer inputs
	if ( isMIP ) {
		for(int i=0;i<n_vars;i++) {
			if (isinteger[i]) pSolver->setInteger(i);
		}
	}
	if (isQP) {
		error("QP is not working yet");
		// need to call loadQuadraticObjective here ???
	}
    
//     CbcModel model(pSolver);
//     model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
    
    
	// solve the problem
	//mexPrintf("Trying to solve the problem.\n");
    if (isMIP) {
        pSolver->branchAndBound();
//         model.branchAndBound();
    } else {
//         model.initialSolve();
        pSolver->initialSolve();
    }
	
	// Allocate memory for return data
    plhs[0] = mxCreateDoubleMatrix(n_vars,1, mxREAL); // for the solution
    plhs[1] = mxCreateDoubleMatrix(n_cons,1, mxREAL); // for the constraint prices
    plhs[2] = mxCreateDoubleMatrix(1,1, mxREAL);      // for the return status
    double *x = mxGetPr(plhs[0]);
    double *y = mxGetPr(plhs[1]);
    double *returncode = mxGetPr(plhs[2]);
	
	// Copy solutions if available
	if ( pSolver->isProvenOptimal() ) {
//     if ( model.isProvenOptimal() ) {
//     if ( model.solver()->isProvenOptimal() ) {
        //mexPrintf("Solution found.\n");
		// extract the solutions
		const double * solution = pSolver->getColSolution();
		const double * dualvars = pSolver->getRowPrice();
		// copy the solution to the outpus
		memcpy(x,solution,n_vars*sizeof(double));
		memcpy(y,dualvars,n_cons*sizeof(double));
		*returncode = 1;
	} else {
		if ( pSolver->isProvenPrimalInfeasible() ) {
			mexPrintf("Primal problem is proven infeasible.\n");
			*returncode = 0;
		} else if ( pSolver->isProvenDualInfeasible() ) {
			mexPrintf("Dual problem is proven infeasible.\n");
			*returncode = -1;
		} else if ( pSolver->isPrimalObjectiveLimitReached() ) {
			mexPrintf("The primal objective limit was reached.\n");
			*returncode = -2;
		} else if ( pSolver->isDualObjectiveLimitReached() ) {
			mexPrintf("The dual objective limit was reached.\n");
			*returncode = -3;
		} else if ( pSolver->isIterationLimitReached() ) {
			mexPrintf("The iteration limit was reached\n");
			*returncode = -4;
		}
	}
	// clean up memory
	if ( mexprinter!= NULL) delete mexprinter;	
	delete pSolver;
}
Example #8
0
//#############################################################################
void 
MibSBilevel::checkBilevelFeasiblity(bool isRoot)
{
  
  int cutStrategy =
    model_->MibSPar_->entry(MibSParams::cutStrategy);

  bool warmStartLL =
    model_->MibSPar_->entry(MibSParams::warmStartLL);

  int maxThreadsLL =
    model_->MibSPar_->entry(MibSParams::maxThreadsLL);

  int whichCutsLL =
    model_->MibSPar_->entry(MibSParams::whichCutsLL);

  int probType =
    model_->MibSPar_->entry(MibSParams::bilevelProblemType);

  std::string feasCheckSolver =
     model_->MibSPar_->entry(MibSParams::feasCheckSolver);

  if (warmStartLL && (feasCheckSolver == "SYMPHONY") && solver_){
     solver_ = setUpModel(model_->getSolver(), false);
  }else{
     if (solver_){
	delete solver_;
     }
     solver_ = setUpModel(model_->getSolver(), true);
  }

  OsiSolverInterface *lSolver = solver_;

  //CoinWarmStart * ws = getWarmStart();
  //if (ws != NULL){
  //   lSolver->setWarmStart(ws);
  //}
  //delete ws;

  if(1)
    lSolver->writeLp("lowerlevel");

  if (feasCheckSolver == "Cbc"){
    dynamic_cast<OsiCbcSolverInterface *> 
      (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0);
  }else if (feasCheckSolver == "SYMPHONY"){
     //dynamic_cast<OsiSymSolverInterface *> 
     // (lSolver)->setSymParam("prep_level", -1);
    
     sym_environment *env = dynamic_cast<OsiSymSolverInterface *> 
	(lSolver)->getSymphonyEnvironment();

     if (warmStartLL){
	sym_set_int_param(env, "keep_warm_start", TRUE);
	if (probType == 1){ //Interdiction
	   sym_set_int_param(env, "should_use_rel_br", FALSE);
	   sym_set_int_param(env, "use_hot_starts", FALSE);
	   sym_set_int_param(env, "should_warmstart_node", TRUE);
	   sym_set_int_param(env, "sensitivity_analysis", TRUE);
	   sym_set_int_param(env, "sensitivity_bounds", TRUE);
	   sym_set_int_param(env, "set_obj_upper_lim", FALSE);
	}
     }
     //Always uncomment for debugging!!
     sym_set_int_param(env, "do_primal_heuristic", FALSE);
     sym_set_int_param(env, "verbosity", -2);
     sym_set_int_param(env, "prep_level", -1);
     sym_set_int_param(env, "max_active_nodes", maxThreadsLL);
     sym_set_int_param(env, "tighten_root_bounds", FALSE);
     sym_set_int_param(env, "max_sp_size", 100);
     sym_set_int_param(env, "do_reduced_cost_fixing", FALSE);
     if (whichCutsLL == 0){
	sym_set_int_param(env, "generate_cgl_cuts", FALSE);
     }else{
	sym_set_int_param(env, "generate_cgl_gomory_cuts", GENERATE_DEFAULT);
     }
     if (whichCutsLL == 1){
	sym_set_int_param(env, "generate_cgl_knapsack_cuts", 
			  DO_NOT_GENERATE);
	sym_set_int_param(env, "generate_cgl_probing_cuts", 
			  DO_NOT_GENERATE);
	sym_set_int_param(env, "generate_cgl_clique_cuts", 
			  DO_NOT_GENERATE);
	sym_set_int_param(env, "generate_cgl_twomir_cuts", 
			  DO_NOT_GENERATE);
	sym_set_int_param(env, "generate_cgl_flowcover_cuts", 
			  DO_NOT_GENERATE);
     }
  }else if (feasCheckSolver == "CPLEX"){
#ifdef USE_CPLEX
     lSolver->setHintParam(OsiDoReducePrint);
     lSolver->messageHandler()->setLogLevel(0);
     CPXENVptr cpxEnv = 
	dynamic_cast<OsiCpxSolverInterface*>(lSolver)->getEnvironmentPtr();
     assert(cpxEnv);
     CPXsetintparam(cpxEnv, CPX_PARAM_SCRIND, CPX_OFF);
     CPXsetintparam(cpxEnv, CPX_PARAM_THREADS, maxThreadsLL);
#endif
  }
  
  if (warmStartLL && feasCheckSolver == "SYMPHONY"){
     lSolver->resolve();
     setWarmStart(lSolver->getWarmStart());
  }else{
     lSolver->branchAndBound();
  }

  const double * sol = model_->solver()->getColSolution();
  double objVal(lSolver->getObjValue() * model_->getLowerObjSense());
  
  MibSTreeNode * node = static_cast<MibSTreeNode *>(model_->activeNode_);
  MibSTreeNode * parent = 
    static_cast<MibSTreeNode *>(model_->activeNode_->getParent());

  if((!node->isBoundSet()) 
     && (node->getIndex() != 0)){
    double parentBound = parent->getLowerUB();
    node->setLowerUB(parentBound);
    node->setIsBoundSet(true);
  }
  
  if(objVal > node->getLowerUB()){
    
    node->setLowerUB(objVal);
    node->setIsBoundSet(true);
    
  }

  double etol(model_->etol_);
  double lowerObj = getLowerObj(sol, model_->getLowerObjSense());  

  int lN(model_->lowerDim_); // lower-level dimension
  int uN(model_->upperDim_); // lower-level dimension
  if(!optLowerSolution_)
    optLowerSolution_ = new double[lN];

  if(!optLowerSolutionOrd_)
    optLowerSolutionOrd_ = new double[lN];
  
  CoinZeroN(optLowerSolution_, lN);
  CoinZeroN(optLowerSolutionOrd_, lN);
  int * lowerColInd = model_->getLowerColInd();
  int * upperColInd = model_->getUpperColInd();

  int index(0);
  
  if(0){
    std::cout << "objVal: " << objVal << std::endl;
    std::cout << "lowerObj: " << lowerObj << std::endl;
  }

  if(fabs(objVal - lowerObj) < etol){
     /** Current solution is bilevel feasible **/
     
     const double * values = lSolver->getColSolution();
     int lN(model_->getLowerDim());
     int i(0);
     
     // May want to take out this update and keep current - both optimal
     // changed this 7/1 to allow for continuous vars
     /*
     for(i = 0; i < lN; i++){
	lowerSolution_[i] = (double) floor(values[i] + 0.5);
     } 
     */
 
    for(i = 0; i < lN; i++){
	if(lSolver->isInteger(i))
	   lowerSolution_[i] = (double) floor(values[i] + 0.5);
	else
	   lowerSolution_[i] = (double) values[i];
     } 

     isBilevelFeasible_ = true;
     useBilevelBranching_ = false;
     
  }else if (lSolver->isProvenOptimal()){
     /** Current solution is not bilevel feasible, 
	 but we may still have a solution **/
     
     //std::cout << "Solution is not bilevel feasible." << std::endl;

     const double * values = lSolver->getColSolution();
     int lN(model_->getLowerDim());
     int i(0);

     //added this 7/1 to store y* for val func cut
     for(i = 0; i < lN; i++){
	if(lSolver->isInteger(i))
	   optLowerSolution_[i] = (double) floor(values[i] + 0.5);
	else
	   optLowerSolution_[i] = (double) values[i];
     }
     
     int numCols = model_->solver()->getNumCols();
     int pos(0);

#if 1
     for(i = 0; i < numCols; i++){
	if ((pos = model_->bS_->binarySearch(0, lN - 1, i, lowerColInd)) >= 0){
	   optLowerSolutionOrd_[pos] = optLowerSolution_[pos];
	}
     }
#else
     double upperObj(0);
     double * newSolution = new double[numCols];  
     const double * upperObjCoeffs = model_->solver()->getObjCoefficients();
     for(i = 0; i < numCols; i++){
	pos = model_->bS_->binarySearch(0, lN - 1, i, lowerColInd);
	if(pos < 0){
	   pos = model_->bS_->binarySearch(0, uN - 1, i, upperColInd);
	   newSolution[i] = sol[i];
	}
	else{
	   newSolution[i] = optLowerSolution_[pos];
	   optLowerSolutionOrd_[pos] = optLowerSolution_[pos];
	}
	upperObj += newSolution[i] * upperObjCoeffs[i];
     }

     if(model_->checkUpperFeasibility(newSolution)){
	MibSSolution *mibsSol = new MibSSolution(numCols, newSolution,
						 upperObj,
						 model_);
	
	model_->storeSolution(BlisSolutionTypeHeuristic, mibsSol);
     }
     delete [] newSolution;
#endif	  
     
     /* run a heuristic to find a better feasible solution */
     heuristic_->findHeuristicSolutions();


     isBilevelFeasible_ = false;
     if(cutStrategy != 1)
       useBilevelBranching_ = true;
  }

  //delete lSolver;
  
}
Example #9
0
int main(int argc, char **argv)
{
    VRPH_version();

    int i, j, k, n, status, num_attempts, *sol_buff, *IP_sol_buff;
    char in_file[200];
    double lambda, best_heur_sol=VRP_INFINITY;
    bool first_sol=false, bootstrap=false;;
    VRPSolution *fresh_solution;
    OsiSolverInterface *si;
    const double *x;
    int last_num_cols=0, route_id=0;
    time_t start, stop;
    int *orderings[MAX_ROUTES];
    for(i=0;i<MAX_ROUTES;i++)
        orderings[i]=NULL;
    

    // Set timing counters to 0
    heur_time=mip_time=0;

    // Check arguments
    if(argc<5)
    {
        fprintf(stderr,"Usage: %s -f input_file -n num_runs [-v,-b,-c max_columns -d cols_to_delete]\n",
            argv[0]);
        fprintf(stderr,"\t Will solve the problem num_solutions times and add the routes\n");
        fprintf(stderr,"\t to a set partitioning problem.\n");
        fprintf(stderr,"\t Other options:\n");
        fprintf(stderr,"\t -v runs in verbose mode\n");
        fprintf(stderr,"\t -b will use bootstrapping where we send the set partitioning\n"
                       "\t    solution back to the metaheuristic solver\n");
        fprintf(stderr,"\t -c max_columns will allow this many active columns/variables in the IP.\n");
        fprintf(stderr,"\t    Default value is max_columns=500\n");
        fprintf(stderr,"\t -d num_cols_to_delete will delete this many columns once we have too many\n");
        fprintf(stderr,"\t    in the IP. Default value is num_cols_to_delete=100\n");
        exit(-1);
    }

    // Set defaults
    verbose=false;
    max_columns=500;
    num_cols_to_delete=100;

    // Parse command line
    for(i=0;i<argc;i++)
    {
        if(strcmp(argv[i],"-f")==0)
            strcpy(in_file,argv[i+1]);
        if(strcmp(argv[i],"-n")==0)
            num_attempts=atoi(argv[i+1]);
        if(strcmp(argv[i],"-v")==0)
            verbose=true;
         if(strcmp(argv[i],"-b")==0)
            bootstrap=true;
         if(strcmp(argv[i],"-c")==0)
             max_columns=atoi(argv[i+1]);
         if(strcmp(argv[i],"-d")==0)
             num_cols_to_delete=atoi(argv[i+1]);
    }

    // This is the # of non-VRPH_DEPOT nodes
    n=VRPGetDimension(in_file);
    // This will be used to import/export solutions
    fresh_solution = new VRPSolution(n);
    // Create buffers for importing solutions
    sol_buff= new int[n+2];
    IP_sol_buff = new int[n+2];

    // Declare an OSI interface
    si=new OsiGlpkSolverInterface;
    si->setIntParam(OsiNameDiscipline,2);

    for(i=0;i<n;i++)
    {
        si->addRow(0,NULL,NULL,1,1);
    }

    // Declare a VRP of the right size and import the file
    VRP V(n);
    ClarkeWright CW(n);
    VRPRoute route(n);
    V.read_TSPLIB_file(in_file);
    // Set up a "route warehouse" to store the routes to be added to the IP
    V.route_wh=new VRPRouteWarehouse(HASH_TABLE_SIZE);
  
    // Set up a minimization problem
    si->setObjSense(1);
    // Set to error only output
    si->setHintParam(OsiDoReducePrint,true, OsiHintDo);
    // Unfortunately GLPK still prints out something regarding the conflict graph

    for(i=0;i<num_attempts;i++)
    {
        if(i==0 || !bootstrap) 
        {
            lambda=.5+1.5*lcgrand(0);
            // Start with a clean VRP object
            V.reset();
            CW.Construct(&V, lambda, false);
            if(verbose)
                printf("CW solution %d[%5.3f]: %f\n",i,lambda,V.get_total_route_length()-V.get_total_service_time());
        }
        else
            // Use the solution from the IP
            V.import_solution_buff(IP_sol_buff);
        
        // Run VRPH's RTR algorithm to improve the solution
        start=clock();
        V.RTR_solve(ONE_POINT_MOVE | TWO_POINT_MOVE | TWO_OPT | VRPH_USE_NEIGHBOR_LIST,
            30, 5, 2, .01, 30, VRPH_LI_PERTURB, VRPH_FIRST_ACCEPT,false);
        stop=clock();
        heur_time += (stop-start);

        if(verbose)
            printf("RTR Metaheuristic found solution %5.3f\n",V.get_total_route_length()-V.get_total_service_time());
        
        // The RTR algorithm keeps a "warehouse" of the best solutions discovered during
        // the algorithm's search
        // Now go through the solutions in the solution warehouse and add the new routes
        // discovered to the IP
        for(j=0;j<V.solution_wh->num_sols;j++)
        {
            // Import solution j from the warehouse 
            V.import_solution_buff(V.solution_wh->sols[j].sol);
                
            if(V.get_total_route_length()-V.get_total_service_time() < best_heur_sol)
                best_heur_sol = V.get_total_route_length()-V.get_total_service_time() ;

            // Now add the routes from this solution to the IP
            for(k=1;k<=V.get_total_number_of_routes();k++)
            {
                // Clean up the route by running INTRA_ROUTE optimizations only
                // using the route_search method of the different local search
                // heuristics, accepting improving moves only (VRPH_DOWNHILL)
                OnePointMove OPM;
                TwoOpt TO;
                ThreeOpt ThO;
                while(OPM.route_search(&V,k,k,VRPH_DOWNHILL|VRPH_INTRA_ROUTE_ONLY )){}
                while(TO.route_search(&V,k,k,VRPH_DOWNHILL|VRPH_INTRA_ROUTE_ONLY  )){};
                while(ThO.route_search(&V,k,VRPH_DOWNHILL|VRPH_INTRA_ROUTE_ONLY )){};

                // Copy route k from the solution to the VRPRoute R
                V.update_route(k,&route);
                route.create_name();
                // Add it to the "route warehouse" - this uses a hash table to keep track
                // of duplicate columns
                status=V.route_wh->add_route(&route);

                if(status!=DUPLICATE_ROUTE)
                {
                    // This route is not currently in the WH and so it cannot be in the
                    // set partitioning problem
                    //OSI_add_route(si,&V,&route);
                    OSI_add_route(si,&V,&route,route_id,orderings);
                    route_id++;
                }
            }
            
            // Set the row RHS's if we need to
            if(first_sol)
            {
                first_sol=false;
                for(int rownum=0;rownum<n;rownum++)
                    si->setRowBounds(rownum,1,1);
                // Note that changing this to >= would be a set covering problem
                // where each customer can be visited by more than one route
            }
        }

        // Now erase all the solutions from the WH
        V.solution_wh->liquidate();

        if(verbose)
        {
            printf("Attempt %02d:  Solving IP with %d columns\n",i,si->getNumCols());
            printf("%d routes in the WH\n",V.route_wh->num_unique_routes);
        }

        // Solve the current set partitioning problem using the MIP solver
        start=clock();
        si->branchAndBound();
        stop=clock();
        mip_time += (stop-start);

        double opt=si->getObjValue();
        x=si->getColSolution();
        last_num_cols=si->getNumCols();
        if(verbose)
            printf("Optimal solution (%d columns) is %f\n",last_num_cols,opt);

        
        // Now recover the solution from the IP solution
        OSI_recover_solution(si, orderings, IP_sol_buff);
       
        if(verbose)
            printf("IP solution has obj. function value: %5.2f\n"
            "Best heuristic  obj. function value: %5.2f\n",
            si->getObjValue(),best_heur_sol);     
    }

    if(verbose)
        printf(
        "\nResults\n"
        "--------\n"
        "After %d runs\n"
        "IP solution has obj. function value: %5.2f\n"
        "Best heuristic  obj. function value: %5.2f\n",
        num_attempts,si->getObjValue(),best_heur_sol);

    // print to stderr since GLPK prints "conflict graph" to stdout (a known bug...)
    // best_heur_sol best_mip_sol heur_time mip_time
    fprintf(stderr,"%5.3f %5.3f %5.3f %5.3f\n", best_heur_sol, si->getObjValue(),
        (double)(heur_time)/CLOCKS_PER_SEC, (double)(mip_time)/CLOCKS_PER_SEC);

    delete V.route_wh;
    delete fresh_solution;
    delete [] sol_buff;
    delete [] IP_sol_buff;
    delete si;

    for(i=0;i<MAX_ROUTES;i++)
        if(orderings[i])
            delete [] orderings[i];

     
    return 0;
}
/*
 * Class:     thebeast_osi_OsiSolverJNI
 * Method:    branchAndBound
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_thebeast_osi_OsiSolverJNI_branchAndBound
  (JNIEnv *, jobject, jint ptr){
  OsiSolverInterface* solver = (OsiSolverInterface*) ptr;
  solver->branchAndBound();
}