示例#1
0
文件: TssBd.cpp 项目: ctjandra/DSP
/** construct master problem */
STO_RTN_CODE TssBd::constructMasterProblem(TssBdSub * tssbdsub, double lowerbound)
{
#define FREE_MEMORY       \
	FREE_PTR(mat)         \
	FREE_ARRAY_PTR(clbd)  \
	FREE_ARRAY_PTR(cubd)  \
	FREE_ARRAY_PTR(ctype) \
	FREE_ARRAY_PTR(obj)   \
	FREE_ARRAY_PTR(rlbd)  \
	FREE_ARRAY_PTR(rubd)  \
	FREE_ARRAY_PTR(auxind)  \
	FREE_ARRAY_PTR(auxcoef)

	assert(model_);

	if (naux_ <= 0 || !obj_aux_ || !clbd_aux_ || !cubd_aux_)
	{
		printf("Warning: Auxiliary column information is required.\n");
		return 1;
	}

	/** master problem */
	CoinPackedMatrix * mat = NULL;
	double * clbd   = NULL;
	double * cubd   = NULL;
	double * obj    = NULL;
	char *   ctype  = NULL;
	double * rlbd   = NULL;
	double * rubd   = NULL;
	/** for recourse lower bound */
	int * auxind     = NULL;
	double * auxcoef = NULL;

	BGN_TRY_CATCH

	int ncols = model_->getNumCols(0) + naugs_ * model_->getNumCols(1) + naux_;

	/** number of integer variables in the core */
	int nIntegers = model_->getNumCoreIntegers();

	/** allocate memory */
	auxind = new int [ncols];
	auxcoef = new double [ncols];

	/** decompose model */
	STO_RTN_CHECK_THROW(model_->decompose(
			naugs_, augs_, naux_, clbd_aux_, cubd_aux_, obj_aux_,
			mat, clbd, cubd, ctype, obj, rlbd, rubd),
			"decompose", "TssModel");

	/** convert column types */
	if (par_->relaxIntegrality_[0])
	{
		for (int j = 0; j < model_->getNumCols(0); ++j)
		{
			if (ctype[j] != 'C')
				nIntegers--;
			ctype[j] = 'C';
		}
	}
	if (par_->relaxIntegrality_[1] && naugs_ > 0)
	{
		for (int j = 0; j < model_->getNumCols(1); ++j)
		{
			if (ctype[model_->getNumCols(0) + j] != 'C')
				nIntegers--;
		}
		CoinFillN(ctype + model_->getNumCols(0), naugs_ * model_->getNumCols(1), 'C');
	}

	if (nIntegers > 0)
	{
		si_ = new SolverInterfaceScip(par_);
		si_->setPrintLevel(CoinMin(par_->logLevel_ + 1, 5));
	}
	else
	{
		si_ = new SolverInterfaceSpx(par_);
		si_->setPrintLevel(CoinMax(par_->logLevel_ - 1, 0));
	}

	/** load problem data */
	si_->loadProblem(mat, clbd, cubd, obj, ctype, rlbd, rubd, "BdMaster");

	/** add row for lower bound */
	for (int j = 0; j < ncols; ++j)
		auxind[j] = j;
	CoinCopyN(obj, ncols, auxcoef);
	si_->addRow(ncols, auxind, auxcoef, lowerbound, COIN_DBL_MAX);

	/** save memory */
	FREE_MEMORY

	END_TRY_CATCH_RTN(FREE_MEMORY,STO_RTN_ERR)

	return STO_RTN_OK;

#undef FREE_MEMORY
}
示例#2
0
template <class T> inline void
CoinMemcpyN(register const T* from, const int size, register T* to)
{
#ifndef _MSC_VER
#ifdef USE_MEMCPY
    // Use memcpy - seems a lot faster on Intel with gcc
#ifndef NDEBUG
    // Some debug so check
    if (size < 0)
	throw CoinError("trying to copy negative number of entries",
			"CoinMemcpyN", "");
  
#if 0
    /* There is no point to do this test. If to and from are from different
       blocks then dist is undefined, so this can crash correct code. It's
       better to trust the user that the arrays are really disjoint. */
    const long dist = to - from;
    if (-size < dist && dist < size)
	throw CoinError("overlapping arrays", "CoinMemcpyN", "");
#endif
#endif
    std::memcpy(to,from,size*sizeof(T));
#else
    if (size == 0 || from == to)
	return;

#ifndef NDEBUG
    if (size < 0)
	throw CoinError("trying to copy negative number of entries",
			"CoinMemcpyN", "");
#endif

#if 0
    /* There is no point to do this test. If to and from are from different
       blocks then dist is undefined, so this can crash correct code. It's
       better to trust the user that the arrays are really disjoint. */
    const long dist = to - from;
    if (-size < dist && dist < size)
	throw CoinError("overlapping arrays", "CoinMemcpyN", "");
#endif

    for (register int n = size / 8; n > 0; --n, from += 8, to += 8) {
	to[0] = from[0];
	to[1] = from[1];
	to[2] = from[2];
	to[3] = from[3];
	to[4] = from[4];
	to[5] = from[5];
	to[6] = from[6];
	to[7] = from[7];
    }
    switch (size % 8) {
    case 7: to[6] = from[6];
    case 6: to[5] = from[5];
    case 5: to[4] = from[4];
    case 4: to[3] = from[3];
    case 3: to[2] = from[2];
    case 2: to[1] = from[1];
    case 1: to[0] = from[0];
    case 0: break;
    }
#endif
#else
    CoinCopyN(from, size, to);
#endif
}
示例#3
0
/** This helper function copies an array to another location using Duff's
    device (for a speedup of ~2). The source array is given by its first and
    "after last" entry; the target array is given by its first entry.
    Overlapping arrays are handled correctly.

    All of the various CoinCopyN variants use an int for size. On 64-bit
    architectures, the address diff last-first will be a 64-bit quantity.
    Given that everything else uses an int, I'm going to choose to kick
    the difference down to int.  -- lh, 100823 --
*/
template <class T> inline void
CoinCopy(register const T* first, register const T* last, register T* to)
{
    CoinCopyN(first, static_cast<int>(last-first), to);
}
示例#4
0
//#############################################################################
void 
MibSHeuristic::greedyHeuristic()
{

  MibSModel * model = MibSModel_;
  //OsiSolverInterface * oSolver = model->getSolver();
  OsiSolverInterface * oSolver = model->solver();
  
  double uObjSense(oSolver->getObjSense());
  double lObjSense(model->getLowerObjSense());  
  int lCols(model->getLowerDim());
  int uCols(model->getUpperDim());
  int * uColIndices = model->getUpperColInd();
  int * lColIndices = model->getLowerColInd();
  double * lObjCoeffs = model->getLowerObjCoeffs();
  double * intCost = model->getInterdictCost();
  double intBudget = model->getInterdictBudget();

  int tCols(uCols + lCols); 

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

  int i(0), ind_min_wt(0);
  double usedBudget(0.0); 
  double * fixedVars = new double[lCols];
  double * testsol = new double[tCols];
  CoinZeroN(fixedVars, lCols);
  CoinZeroN(testsol, tCols);

  std::multimap<double, int> lObjCoeffsOrd;

  for(i = 0; i < lCols; i++)
    lObjCoeffsOrd.insert(std::pair<double, int>(lObjCoeffs[i] * lObjSense, i));
  
  if(!bestSol_)
    bestSol_ = new double[tCols];

  //initialize the best solution information
  //bestObjVal_ = model->getSolver()->getInfinity() * uObjSense;
  //CoinZeroN(bestSol_, tCols);

  std::multimap<double, int>::iterator iter;
  //std::multimap<double, int>::iterator first;
  //std::multimap<double, int>::iterator last;
  //int dist = std::distance(first, last);
  SRANDOM((unsigned) time(NULL));

  int randchoice(0); 
  if(0)
    std::cout << "randchoice " << randchoice << std::endl;


  double cost(0.0);

  //starting from the largest, fix corr upper-level variables
  //then, with these fixed, solve the lower-level problem
  //this yields a feasible solution

  iter = lObjCoeffsOrd.begin(); 
  
  while((usedBudget < intBudget) && (iter != lObjCoeffsOrd.end())){
    
    ind_min_wt = iter->second;
    cost = intCost[ind_min_wt];
    testsol[uColIndices[ind_min_wt]] = 1.0;
    double min_wt = iter->first;
    
    if(0){
      std::cout << "upper: " << ind_min_wt << " " 
		<< uColIndices[ind_min_wt] << " "  
		<< oSolver->getColUpper()[uColIndices[ind_min_wt]] << " " 
		<< oSolver->getColLower()[uColIndices[ind_min_wt]] << std::endl;
      
      std::cout << "lower: " << ind_min_wt << " " 
		<< lColIndices[ind_min_wt] << " "  
		<< oSolver->getColUpper()[lColIndices[ind_min_wt]] << std::endl;
    }

    //if((oSolver->getColUpper()[uColIndices[ind_min_wt]] == 1.0) 
       //&& (oSolver->getColUpper()[lColIndices[ind_min_wt]] > 0)){
    if(oSolver->getColUpper()[uColIndices[ind_min_wt]] > etol_){ 
      
      //if(((usedBudget + cost) <= intBudget) 
      // && checkLowerFeasibility(oSolver, testsol)){
      if((usedBudget + cost) <= intBudget){
	
	//FIXME: SHOULD BE CHECKING FOR CURRENT BOUNDS HERE  
	//fix the corresponding upper-level variable to 1
	 randchoice = RANDOM() % 2;
	if(0)
	  std::cout << "randchoice " << randchoice << std::endl;
	if(randchoice){
	  fixedVars[ind_min_wt] = 1.0;
	  usedBudget += intCost[ind_min_wt];
	}
      }
    }
    else{
      
      testsol[uColIndices[ind_min_wt]] = 0;
      //break;
      
    }
    iter++;
  }
  
  /*
    now we find a feasible solution by fixing upper-level vars
    and solving the lower-level problem
  */
  
  double * incumbentSol = new double[tCols];
  double * colsol = new double[tCols];

  CoinZeroN(colsol, tCols);

  for(i = 0; i < uCols; i++){
    colsol[uColIndices[i]] = fixedVars[i];
    if(fixedVars[i] == 1.0)
      if(0)
	std::cout << "fixed " << i << std::endl;
  }

  bfSol * sol = getBilevelSolution(colsol, lObjSense * oSolver->getInfinity());

  if(sol){
    double incumbentObjVal = sol->getObjVal();
    CoinCopyN(sol->getColumnSol(), tCols, incumbentSol);
    
    MibSSolution * mibSol = new MibSSolution(tCols,
					     incumbentSol,
					     incumbentObjVal,
					     model);
    
    model->storeSolution(BlisSolutionTypeHeuristic, mibSol);
  }

  //bestObjVal_ = incumbentObjVal;
  //CoinCopyN(incumbentSol, tCols, bestSol_);

  delete [] incumbentSol;
  delete [] testsol;
  //delete [] colsol;
  //delete [] fixedVars;
  //delete sol;
}
示例#5
0
//#############################################################################
void 
MibSHeuristic::createBilevelSolutions(std::map<double, mcSol> mcSolutions)
{

  MibSModel * model = MibSModel_;
  double uObjSense(model->getSolver()->getObjSense());
  int lCols(model->getLowerDim());
  int uCols(model->getUpperDim());

  int tCols(uCols + lCols); 

  double incumbentObjVal(model->getSolver()->getInfinity() * uObjSense);
  double * incumbentSol = new double[tCols];

  int i(0);

  if(!bestSol_)
    bestSol_ = new double[tCols];

  //initialize the best solution information
  //bestObjVal_ = model->getSolver()->getInfinity() * uObjSense;
  //CoinZeroN(bestSol_, tCols);

  std::map<double, mcSol >::iterator iter = mcSolutions.begin();

  for(iter = mcSolutions.begin(); iter != mcSolutions.end(); iter++){
    
    mcSol tmpsol = iter->second;
    const double * colsol = tmpsol.getColumnSol();
    double origLower = tmpsol.getObjPair().second;
    if(0){
      std::cout << "Candidate solution value: " << origLower << std::endl;
      for(i = 0; i < tCols; i++){
	std::cout << "colsol[" << i << "] :" 
		  << colsol[i] << std::endl;
      }
    }
    
    bfSol * sol = getBilevelSolution(colsol, origLower);

    if(sol){
      

      if(0){
	std::cout << "Returned solution: " << std::endl;
	for(i = 0; i < tCols; i++){
	  std::cout << "sol->getColumnSol[" << i << "]" 
		    << sol->getColumnSol()[i] << std::endl;
	}
	std::cout << "sol->getObjVal: " << sol->getObjVal() << std::endl;
      }
      
      if(sol->getObjVal() < incumbentObjVal){

	incumbentObjVal = sol->getObjVal();
	CoinCopyN(sol->getColumnSol(), tCols, incumbentSol);

	if(0){
	  std::cout << "New incumbent found." << std::endl;
	  for(i = 0; i < tCols; i++){
	    std::cout << "incumbentSol[" << i 
		      << "]: " << incumbentSol[i] << std::endl;
	  }
	  std::cout << "incumbentObjVal: " << incumbentObjVal << std::endl;
	}
	
      }
    }

  }


 
  if(0){
    std::cout << "This solution comes from MibSHeuristic.cpp:742" << std::endl;
  }
  MibSSolution * mibSol = new MibSSolution(tCols,
					   incumbentSol,
					   incumbentObjVal,
					   model);
  
  model->storeSolution(BlisSolutionTypeHeuristic, mibSol);

  //need to add this solution to mibssolutions instead
  //bestObjVal_ = incumbentObjVal;
  //CoinCopyN(incumbentSol, tCols, bestSol_);

  //delete bfSol;
  delete [] incumbentSol;

}
示例#6
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();
#ifndef COIN_HAS_SYMPHONY
  OsiSolverInterface * sSolver = new OsiCbcSolverInterface();
#else
  OsiSolverInterface* sSolver = new OsiSymSolverInterface();
  //sSolver = oSolver->clone();
  //OsiSolverInterface * sSolver = tmpSolver;
  //OsiSolverInterface * tmpSolver = new OsiSolverInterface(oSolver);
#endif
  
  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;
    }
  }

#ifndef COIN_HAS_SYMPHONY
  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);
#endif

  //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
      */
      
#ifndef COIN_HAS_SYMPHONY
       OsiSolverInterface * nSolver = new OsiCbcSolverInterface();
#else
       OsiSolverInterface * nSolver = new OsiSymSolverInterface();
#endif

       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");

#ifndef COIN_HAS_SYMPHONY
      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);
#endif

      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
      */
      
#ifndef COIN_HAS_SYMPHONY
      OsiSolverInterface * nSolver = new OsiCbcSolverInterface();
#else
      OsiSolverInterface * nSolver = new OsiSymSolverInterface();
#endif

      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);
      
#ifndef COIN_HAS_SYMPHONY
      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);
#endif

      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();
  }
}
示例#7
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);

#ifndef COIN_HAS_SYMPHONY
  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);
#endif

  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;
  }

}
示例#8
0
void CouenneCutGenerator::generateCuts (const OsiSolverInterface &si,
					OsiCuts &cs, 
					const CglTreeInfo info)
#if CGL_VERSION_MAJOR == 0 && CGL_VERSION_MINOR <= 57
  const
#endif
  {

  // check if out of time or if an infeasibility cut (iis of type 0)
  // was added as a result of, e.g., pruning on BT. If so, no need to
  // run this.

  if (isWiped (cs) || 
     (CoinCpuTime () > problem_ -> getMaxCpuTime ()))
    return;

#ifdef FM_TRACE_OPTSOL
  double currCutOff = problem_->getCutOff();
  double bestVal = 1e50;
  CouenneRecordBestSol *rs = problem_->getRecordBestSol();
  if(rs->getHasSol()) {
    bestVal = rs->getVal(); 
  }
  if(currCutOff > bestVal) {
    //problem_ -> setCutOff (bestVal - 1e-6); // FIXME: don't add numerical constants
    problem_ -> setCutOff (bestVal);

    int indObj = problem_->Obj(0)->Body()->Index();

    if (indObj >= 0) {
      OsiColCut *objCut = new OsiColCut;
      objCut->setUbs(1, &indObj, &bestVal);
      cs.insert(objCut);
      delete objCut;
    }
  }
#endif

#ifdef FM_PRINT_INFO
  if((BabPtr_ != NULL) && (info.level >= 0) && (info.pass == 0) && 
     (BabPtr_->model().getNodeCount() > lastPrintLine)) {
    printLineInfo();
    lastPrintLine += 1;
  }
#endif

  const int infeasible = 1;

  int nInitCuts = cs.sizeRowCuts ();

  CouNumber
    *&realOpt = problem_ -> bestSol (),
    *saveOptimum = realOpt;

  if (!firstcall_ && realOpt) { 

    // have a debug optimal solution. Check if current bounds
    // contain it, otherwise pretend it does not exist

    CouNumber *opt = realOpt;

    const CouNumber 
      *sol = si.getColSolution (),
      *lb  = si.getColLower (),
      *ub  = si.getColUpper ();

    int objind = problem_ -> Obj (0) -> Body () -> Index ();

    for (int j=0, i=problem_ -> nVars (); i--; j++, opt++, lb++, ub++)
      if ((j != objind) && 
	  ((*opt < *lb - COUENNE_EPS * (1 + CoinMin (fabs (*opt), fabs (*lb)))) || 
	   (*opt > *ub + COUENNE_EPS * (1 + CoinMin (fabs (*opt), fabs (*ub)))))) {
	
	jnlst_ -> Printf (J_VECTOR, J_CONVEXIFYING, 
			  "out of bounds, ignore x%d = %g [%g,%g] opt = %g\n", 
			  problem_ -> nVars () - i - 1, *sol, *lb, *ub, *opt);

	// optimal point is not in current bounding box,
	// pretend realOpt is NULL until we return from this procedure
	realOpt = NULL;
	break;
      }
  }

  /*static int count = 0;
  char fname [20];
  sprintf (fname, "relax_%d", count++);
  si.writeLp (fname);
  printf ("writing %s\n", fname);*/

  jnlst_ -> Printf (J_DETAILED, J_CONVEXIFYING,
		    "generateCuts: level = %d, pass = %d, intree = %d\n",
		    info.level, info.pass, info.inTree);

  Bonmin::BabInfo * babInfo = dynamic_cast <Bonmin::BabInfo *> (si.getAuxiliaryInfo ());

  if (babInfo)
    babInfo -> setFeasibleNode ();

  double now   = CoinCpuTime ();
  int    ncols = problem_ -> nVars ();

  // This vector contains variables whose bounds have changed due to
  // branching, reduced cost fixing, or bound tightening below. To be
  // used with malloc/realloc/free

  t_chg_bounds *chg_bds = new t_chg_bounds [ncols];

  /*for (int i=0; i < ncols; i++) 
    if (problem_ -> Var (i) -> Multiplicity () <= 0) {
      chg_bds [i].setLower (t_chg_bounds::UNCHANGED);
      chg_bds [i].setUpper (t_chg_bounds::UNCHANGED);
      }*/

  problem_ -> installCutOff (); // install upper bound

  if (firstcall_) {

    // First convexification //////////////////////////////////////

    // OsiSolverInterface is empty yet, no information can be obtained
    // on variables or bounds -- and none is needed since our
    // constructor populated *problem_ with variables and bounds. We
    // only need to update the auxiliary variables and bounds with
    // their current value.

    for (int i=0; i < ncols; i++) 
      if (problem_ -> Var (i) -> Multiplicity () > 0) {
	chg_bds [i].setLower (t_chg_bounds::CHANGED);
	chg_bds [i].setUpper (t_chg_bounds::CHANGED);
      }

    // start with FBBT, should take advantage of cutoff found by NLP
    // run AFTER initial FBBT...
    if (problem_ -> doFBBT () &&
	(! (problem_ -> boundTightening (chg_bds, babInfo))))
          jnlst_ -> Printf (J_STRONGWARNING, J_CONVEXIFYING,
            "Couenne: WARNING, first convexification is infeasible\n");

    // For each auxiliary variable replacing the original (nonlinear)
    // constraints, check if corresponding bounds are violated, and
    // add cut to cs

    int nnlc = problem_ -> nCons ();

    for (int i=0; i<nnlc; i++) {

      if (CoinCpuTime () > problem_ -> getMaxCpuTime ())
	break;

      // for each constraint
      CouenneConstraint *con = problem_ -> Con (i);

      // (which has an aux as its body)
      int objindex = con -> Body () -> Index ();

      if ((objindex >= 0) && 
	  ((con -> Body () -> Type () == AUX) ||
	   (con -> Body () -> Type () == VAR))) {

	// get the auxiliary that is at the lhs
	exprVar *conaux = problem_ -> Var (objindex);

	if (conaux &&
	    (conaux -> Type () == AUX) &&
	    (conaux -> Image ()) && 
	    (conaux -> Image () -> Linearity () <= LINEAR)) {

	  // reduce density of problem by adding w >= l rather than
	  // ax + b >= l for any linear auxiliary defined as w := ax+b

	  double 
	    lb = (*(con -> Lb ())) (), 
	    ub = (*(con -> Ub ())) ();

	  OsiColCut newBound;
	  if (lb > -COUENNE_INFINITY) newBound.setLbs (1, &objindex, &lb);
	  if (ub <  COUENNE_INFINITY) newBound.setUbs (1, &objindex, &ub);

	  cs.insert (newBound);

	  // the auxiliary w of constraint w <= b is associated with a
	  // linear expression w = ax: add constraint ax <= b
	  /*conaux -> Image () -> generateCuts (conaux, si, cs, this, chg_bds, 
					      conaux -> Index (), 
					      (*(con -> Lb ())) (), 
					      (*(con -> Ub ())) ());*/

	  // take it from the list of the variables to be linearized
	  // 
	  // DO NOT decrease multiplicity. Even if it is a linear
	  // term, its bounds can still be used in implied bounds
	  //
	  // Are we sure? That will happen only if its multiplicity is
	  // nonzero, for otherwise this aux is only used here, and is
	  // useless elsewhere
	  //
	  //conaux -> decreaseMult (); // !!!
	}

	// also, add constraint w <= b

	// not now, do it later

// 	// if there exists violation, add constraint
// 	CouNumber l = con -> Lb () -> Value (),	
// 	          u = con -> Ub () -> Value ();

// 	// tighten bounds in Couenne's problem representation
// 	problem_ -> Lb (index) = CoinMax (l, problem_ -> Lb (index));
// 	problem_ -> Ub (index) = CoinMin (u, problem_ -> Ub (index));

      } else { // body is more than just a variable, but it should be
	       // linear. If so, generate equivalent linear cut

	assert (false);	// TODO
      }
    }

    if (jnlst_ -> ProduceOutput (J_ITERSUMMARY, J_CONVEXIFYING)) {
      if (cs.sizeRowCuts ()) {
	jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,"Couenne: %d constraint row cuts\n",
			  cs.sizeRowCuts ());
	for (int i=0; i<cs.sizeRowCuts (); i++) 
	  cs.rowCutPtr (i) -> print ();
      }
      if (cs.sizeColCuts ()) {
	jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,"Couenne: %d constraint col cuts\n",
			  cs.sizeColCuts ());
	for (int i=0; i<cs.sizeColCuts (); i++) 
	  cs.colCutPtr (i) -> print ();
      }
    }
  } else {

    // use new optimum as lower bound for variable associated w/objective
    int indobj = problem_ -> Obj (0) -> Body () -> Index ();

    // transmit solution from OsiSolverInterface to problem
    problem_ -> domain () -> push (&si, &cs);

    if (indobj >= 0) {

      // Use current value of objvalue's x as a lower bound for bound
      // tightening
      double lp_bound = problem_ -> domain () -> x (indobj);

      //if (problem_ -> Obj (0) -> Sense () == MINIMIZE) 
      {if (lp_bound > problem_ -> Lb (indobj)) problem_ -> Lb (indobj) = lp_bound;}
	   //else {if (lp_bound < problem_ -> Ub (indobj)) problem_ -> Ub (indobj) = lp_bound;}
    }

    updateBranchInfo (si, problem_, chg_bds, info); // info.depth >= 0 || info.pass >= 0
  }

  // restore constraint bounds before tightening and cut generation
  for (int i = problem_ -> nCons (); i--;) {

    // for each constraint
    CouenneConstraint *con = problem_ -> Con (i);

    // (which has an aux as its body)
    int objindex = con -> Body () -> Index ();

    if ((objindex >= 0) && 
	((con -> Body () -> Type () == AUX) ||
	 (con -> Body () -> Type () == VAR))) {

      // if there exists violation, add constraint
      CouNumber 
	l = con -> Lb () -> Value (),	
	u = con -> Ub () -> Value ();

      // tighten bounds in Couenne's problem representation
      problem_ -> Lb (objindex) = CoinMax (l, problem_ -> Lb (objindex));
      problem_ -> Ub (objindex) = CoinMin (u, problem_ -> Ub (objindex));
    }
  }

  problem_ -> installCutOff (); // install upper bound

  fictitiousBound (cs, problem_, false); // install finite lower bound, if currently -inf

  int *changed = NULL, nchanged;

  // Bound tightening ///////////////////////////////////////////

  // do bound tightening only at first pass of cutting plane in a node
  // of BB tree (info.pass == 0) or if first call (creation of RLT,
  // info.pass == -1)

  try {

    // Before bound tightening, compute symmetry group. After bound
    // tightening is done, we can apply further tightening using orbit
    // information.

#ifdef COIN_HAS_NTY
    //    ChangeBounds (psi -> getColLower (),  
    //		  psi -> getColUpper (), 
    //		  psi -> getNumCols ());
    if (problem_ -> orbitalBranching ())
      problem_ -> Compute_Symmetry ();
#endif

    // Bound tightening ////////////////////////////////////

    /*printf ("== BT ================\n");
      for (int i = 0; i < problem_ -> nVars (); i++)
      if (problem_ -> Var (i) -> Multiplicity () > 0)
      printf ("%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
      problem_ -> X  (i), problem_ -> Lb (i), problem_ -> Ub (i));
      printf("=============================\n");*/

    // Reduced Cost BT -- to be done first to use rcost correctly
    if (!firstcall_  &&                         // have a linearization already
	problem_ -> doRCBT () &&                // authorized to do reduced cost tightening
	problem_ -> redCostBT (&si, chg_bds) && // some variables were tightened with reduced cost
	!(problem_ -> btCore (chg_bds)))        // in this case, do another round of FBBT
      throw infeasible;

    // FBBT
    if (problem_ -> doFBBT () && 
	//(info.pass <= 0) && // do it in subsequent rounds too
	(! (problem_ -> boundTightening (chg_bds, babInfo))))
      throw infeasible;

    // OBBT
    if (!firstcall_ && // no obbt if first call (there is no LP to work with)
	problem_ -> obbt (this, si, cs, info, babInfo, chg_bds) < 0)
      throw infeasible;

    // Bound tightening done /////////////////////////////

    if ((problem_ -> doFBBT () ||
	 problem_ -> doOBBT () ||
	 problem_ -> doABT  ()) &&
	(jnlst_ -> ProduceOutput (J_VECTOR, J_CONVEXIFYING))) {

      jnlst_ -> Printf(J_VECTOR, J_CONVEXIFYING,"== after bt =============\n");
      for (int i = 0; i < problem_ -> nVars (); i++)
	if (problem_ -> Var (i) -> Multiplicity () > 0)
	  jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
			 problem_ -> X  (i), problem_ -> Lb (i), problem_ -> Ub (i));
      jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"=============================\n");
    }

    // Use orbit info to tighten bounds

#ifdef COIN_HAS_NTY

    // TODO: when independent bound tightener, can get original bounds
    // through si.getCol{Low,Upp}er()

    if (problem_ -> orbitalBranching () && !firstcall_) {

      CouNumber 
	*lb = problem_ -> Lb (),
	*ub = problem_ -> Ub ();

      std::vector<std::vector<int> > *new_orbits = problem_ -> getNtyInfo () -> getOrbits();

      for (int i=0, ii = problem_ -> getNtyInfo () -> getNumOrbits (); ii--; i++){

	CouNumber
	  ll = -COUENNE_INFINITY,
	  uu =  COUENNE_INFINITY; 
	
	std::vector <int> orbit = (*new_orbits)[i];

	if (orbit.size () <= 1)
	  continue; // not much to do when only one variable in this orbit

	if (jnlst_ -> ProduceOutput (J_VECTOR, J_BOUNDTIGHTENING)) {
	  printf ("orbit bounds: "); fflush (stdout);
	  for(int j = 0; j < orbit.size (); j++) {
	    printf ("x_%d [%g,%g] ", orbit[j], lb [orbit [j]], ub [orbit [j]]);
	    fflush (stdout);
	  }
	  printf ("\n");
	}

	for (int j = 0; j < orbit.size (); j++) {
 
	  int indOrb = orbit [j];

	  if (indOrb < problem_ -> nVars ()) {

	    if (lb [indOrb] > ll) ll = lb [indOrb];
	    if (ub [indOrb] < uu) uu = ub [indOrb];
	  }
	}

	jnlst_ -> Printf (J_VECTOR, J_BOUNDTIGHTENING, 
			  " --> new common lower bounds: [%g,--]\n", ll);

	for(int j = 0; j < orbit.size (); j++) {

	  int indOrb = orbit [j];

	  if (indOrb < problem_ -> nVars ()){

	    lb [indOrb] = ll;
	    ub [indOrb] = uu;
	  }
	}
      }

      delete new_orbits;
    }

#endif

    // Generate convexification cuts //////////////////////////////

    sparse2dense (ncols, chg_bds, changed, nchanged);

    double *nlpSol = NULL;

    //--------------------------------------------

    if (true) {

      if (babInfo) 
	nlpSol = const_cast <double *> (babInfo -> nlpSolution ());

      // Aggressive Bound Tightening ////////////////////////////////

      int logAbtLev = problem_ -> logAbtLev ();

      if (problem_ -> doABT () &&             // flag is checked, AND
	  ((logAbtLev != 0) ||                // (parameter is nonzero OR
	   (info.level == 0)) &&              //  we are at root node), AND
	  (info.pass == 0) &&                 // at first round of cuts, AND 
	  ((logAbtLev < 0) ||                 // (logAbtLev = -1, OR
	   (info.level <= logAbtLev) ||       //  depth is lower than COU_OBBT_CUTOFF_LEVEL, OR
	   (CoinDrand48 () <                  //  probability inversely proportional to the level)
	    pow (2., (double) logAbtLev - (info.level + 1))))) {

	jnlst_ -> Printf(J_VECTOR, J_BOUNDTIGHTENING,"  performing ABT\n");
	if (! (problem_ -> aggressiveBT (nlp_, chg_bds, info, babInfo)))
	  throw infeasible;

	sparse2dense (ncols, chg_bds, changed, nchanged);
      }

      // obtain solution just found by nlp solver

      // Auxiliaries should be correct. solution should be the one found
      // at the node even if not as good as the best known.

      // save violation flag and disregard it while adding cut at NLP
      // point (which are not violated by the current, NLP, solution)
      bool save_av = addviolated_;
      addviolated_ = false;

      // save values
      problem_ -> domain () -> push 
	(problem_ -> nVars (), 
	 problem_ -> domain () -> x  (), 
	 problem_ -> domain () -> lb (), 
	 problem_ -> domain () -> ub (), false);

      // fill originals with nlp values
      if (nlpSol) {
	CoinCopyN (nlpSol, problem_ -> nOrigVars (), problem_ -> domain () -> x ());
      //problem_ -> initAuxs ();

      problem_ -> getAuxs (problem_ -> domain () -> x ());
      }

      if (jnlst_ -> ProduceOutput (J_VECTOR, J_CONVEXIFYING)) {
	jnlst_ -> Printf(J_VECTOR, J_CONVEXIFYING,"== genrowcuts on NLP =============\n");
	for (int i = 0; i < problem_ -> nVars (); i++)
	  if (problem_ -> Var (i) -> Multiplicity () > 0)
	    jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
			   problem_ -> X  (i),
			   problem_ -> Lb (i),
			   problem_ -> Ub (i));
	jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"=============================\n");
      }

      problem_ -> domain () -> current () -> isNlp () = true;
      genRowCuts (si, cs, nchanged, changed, chg_bds);  // add cuts

      problem_ -> domain () -> pop (); // restore point

      addviolated_ = save_av;     // restore previous value

      //    if (!firstcall_) // keep solution if called from extractLinearRelaxation()
      if (babInfo) 
	babInfo -> setHasNlpSolution (false); // reset it after use //AW HERE

    } else {

      if (jnlst_ -> ProduceOutput (J_VECTOR, J_CONVEXIFYING)) {
	jnlst_ -> Printf(J_VECTOR, J_CONVEXIFYING,"== genrowcuts on LP =============\n");
	for (int i = 0; i < problem_ -> nVars (); i++)
	  if (problem_ -> Var (i) -> Multiplicity () > 0)
	    jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
			   problem_ -> X  (i),
			   problem_ -> Lb (i),
			   problem_ -> Ub (i));
	jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"=============================\n");
      }

      genRowCuts (si, cs, nchanged, changed, chg_bds);
    }

    // change tightened bounds through OsiCuts
    if (nchanged)
      genColCuts (si, cs, nchanged, changed);

    if (firstcall_ && (cs.sizeRowCuts () >= 1))
      jnlst_->Printf(J_ITERSUMMARY, J_CONVEXIFYING,
		     "Couenne: %d initial row cuts\n", cs.sizeRowCuts ());

    if (realOpt && // this is a good time to check if we have cut the optimal solution
	isOptimumCut (realOpt, cs, problem_))
      jnlst_->Printf(J_ITERSUMMARY, J_CONVEXIFYING,
		     "Warning: Optimal solution was cut\n");
  }

  catch (int exception) {

    if ((exception == infeasible) && (!firstcall_)) {

      jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,
			"Couenne: Infeasible node\n");

      WipeMakeInfeas (cs);
    }

    if (babInfo) // set infeasibility to true in order to skip NLP heuristic
      babInfo -> setInfeasibleNode ();
  }

  delete [] chg_bds;

  if (changed) 
    free (changed);

  if (firstcall_) {

    jnlst_ -> Printf (J_SUMMARY, J_CONVEXIFYING, 
		      "Couenne: %d cuts (%d row, %d col) for linearization\n", 
		      cs.sizeRowCuts () + cs.sizeColCuts (),
		      cs.sizeRowCuts (),  cs.sizeColCuts ());

    fictitiousBound (cs, problem_, true);
    firstcall_  = false;
    ntotalcuts_ = nrootcuts_ = cs.sizeRowCuts ();

  } else { 

    problem_ -> domain () -> pop ();

    ntotalcuts_ += (cs.sizeRowCuts () - nInitCuts);

    if (saveOptimum)
      realOpt = saveOptimum; // restore debug optimum
  }

  septime_ += CoinCpuTime () - now;

  if (jnlst_ -> ProduceOutput (J_ITERSUMMARY, J_CONVEXIFYING)) {

    if (cs.sizeColCuts ()) {
      jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,"Couenne col cuts:\n");
      for (int i=0; i<cs.sizeColCuts (); i++) 
	cs.colCutPtr (i) -> print ();
    }
  }

  if (!(info.inTree)) 
    rootTime_ = CoinCpuTime ();
}
示例#9
0
bool calModel::search (CalCubeHeur &calCube, FILE *f, int repl) {

  int
    N = instance_ -> N (),
    n = instance_ -> n (),
    n_iter = (calInstance::GLOBAL == instance_ -> algType ()) ? 1 : instance_ -> nSolves ();

  double
    *bestSol = new double [1 + 2*N],
     bestObj = COIN_DBL_MAX;

  double *s0 = NULL;

  for (int nRetries = 0; !GLOBAL_interrupt && (nRetries < n_iter) && (square (bestObj) > instance_ -> eps ()); ++nRetries) {

    setMaximumSeconds
      (CoinMin (instance_ ->  maxTime       () < 0. ? COIN_DBL_MAX : instance_ -> maxTime (),
		instance_ ->  maxTotalTime  () < 0. ? COIN_DBL_MAX :
		(instance_ -> maxTotalTime  () - CoinCpuTime ()) /
		(instance_ -> nReplications () - repl)));

    calModel *b = clone ();

    OsiSolverInterface *si = b -> solver ();

    for (int i=0; i<N; ++i) {
      si -> setColLower (1 + N + i, 0.);
      si -> setColUpper (1 + N + i, 1.);
    }

    if (calInstance::GLOBAL == instance_ -> algType ()) {

      // do nothing: just run the BB

    } else if (0 == nRetries) {

      //
      // First step: generate initial solution, either from input
      // vector or through the Cube variant
      //
      // Generate initial point ON SUBSPACE. Does nothing if algtype
      // in {RANDOM, GLOBAL}
      //

      s0 = calCube. generateInitS (*si); 

      calCube. standalone (s0); // call Cube method

      b -> changeLU (*si, s0); // fixes some of the s variables after
                               // cube's flight phase

    } else { // change LU bounds based on current solution

#ifdef DEBUG
      printVec (s0, N, "s0");
#endif
      
      const double
	// reduce changes when random and solution available
	fraction    = FRACTION * (((calInstance::RANDOM == instance_ -> algType ()) && (instance_ -> d () [0] >= 0.)) ? RANDOM_MOBILITY : 1.), 
	multiplier  = fraction * (double) (N_RESTART - (nRetries % N_RESTART)) / N_RESTART,
	threshold_0 = multiplier * (double) (N-n) / N, // free half 0-fixed at beginning
	threshold_1 = multiplier * (double)    n  / N; // free half 1-fixed
      //threshold_0 = CoinMax (1. / CoinMax (1., (double) (N-n)), multiplier * (double) (N-n) / N), // free half 0-fixed at beginning
      //threshold_1 = CoinMax (1. / CoinMax (1., (double) n),     multiplier * (double)    n  / N); // free half 1-fixed

      bool one_changed = false;

      for (int nAttempts = 0; nAttempts < 20 && !one_changed; ++nAttempts)
	for (int i=0; i<N; ++i)
	  if      (s0 [i] <     1e-5) {if (drand48 () > threshold_0) si -> setColUpper (1 + N + i, 0.); else one_changed = true;}
	  else if (s0 [i] > 1 - 1e-5) {if (drand48 () > threshold_1) si -> setColLower (1 + N + i, 1.); else one_changed = true;}

#ifdef DEBUG
      char filename [40];
      sprintf (filename, "lp_%d_%d", repl, nRetries);
      si -> writeLp (filename);
#endif

      // int nChanges = CoinMax (1, n / nRetries); // <------------------ Number of changed variables
      // for (int i=0; i<nChanges;) {
      // 	int indChange = floor ((N - 1e-4) * drand48 ());
      // 	printf ("trying %d [%g,%g], i=%d\n", indChange, lb [1 + N + indChange], ub [1 + N + indChange], i);
      // 	if (ub [1 + N + indChange] <     1e-5) {si -> setColUpper (1 + N + indChange, 1.); ++i;}
      // 	if (lb [1 + N + indChange] > 1 - 1e-5) {si -> setColLower (1 + N + indChange, 0.); ++i;}
      // }
    }

    GLOBAL_curBB = b;

                             //    /|
                             //   / |--------+
    b -> branchAndBound ();  //  <  |        |
                             //   \ |--------+
                             //    \|

    //assert (fabs (b -> bestObj () - val [0]) < 1e-5);

    printf ("BB iteration %4d done (%10.2fs). ", 1+nRetries, CoinCpuTime ());

    //optimal = b -> isProvenOptimal(); 
    //const double *val = b -> getColSolution();

    //int numberColumns = model.getNumCols();

    if (b -> bestObj () < 1e20)
      printf ("Best solution: value %10.4f\n", square (b -> bestObj ()));
    else printf ("No solution found :-(\n");

    if (b -> bestSol ()) {

      if (b -> bestObj () < bestObj) {

	bestObj = b -> bestObj ();
	CoinCopyN (b -> bestSol (), 2*N+1, bestSol);
      }

      if (!s0)
	s0 = new double [N];

      CoinCopyN (b -> bestSol () + 1 + N, N, s0);
    }

    delete b;
  }

  bool 
    retval = true,
    row_format = (calInstance::ROW_BASED == instance_ -> outFormat ());

  delete [] s0;

  double w0 = (double) N / instance_ -> n ();

  if (bestObj < 1e20) {

    const double *val = bestSol;

    if (row_format) 
      fprintf (f, "%lf,", square (bestObj));

    //double *d = instance_ -> d ();

    printf ("sample:\n");

    for (int j=N+1, np=0; j<=2*N; ++j) {

      char strNum [5];

      sprintf (strNum, "%d", j-N);

      if (!row_format) 

	fprintf (f, "%d,%g,%s,%d,%g,\n",
		 1+repl,
		 square (bestObj),
		 instance_ -> id (j-N-1) ? instance_ -> id (j-N-1) : strNum,
		 (fabs (val [j]) > 1e-6) ? 1 : 0,
		 w0 + val [j-N]);

      if (fabs (val [j]) > 1e-6) {

	if (row_format) 
	  fprintf (f, "1,");

	printf     ("%d ",  j-N);
	if (!(++np % 10))
	  printf ("\n");
      } else 
	if (row_format) 
	  fprintf (f, "0,");
    }

    printf ("\nweights:\n");

    for (int j=1, np=0; j<=N; ++j) {

      if (row_format) 
	fprintf (f, "%g,", w0 + val [j]);

      if (fabs (val [j]) > 1e-6) {

	printf    ("[%d,%g] ", j, w0 + val [j]);
	if (!(++np % 10))
	  printf ("\n");
      }
    }

    if (square (bestObj) > instance_ -> eps ()) {

      printf ("(warning: solution has large objective at replication %d)", 1 + repl);
      //retval = false;
    }

    printf ("\n");

    if (row_format) 
      fprintf (f, "\n");

    fflush (f);
  }

  delete [] bestSol;

  return retval;
}
// Returns type
int
CbcFathomDynamicProgramming::checkPossible(int allowableSize)
{
    algorithm_ = -1;
    assert(model_->solver());
    OsiSolverInterface * solver = model_->solver();
    const CoinPackedMatrix * matrix = solver->getMatrixByCol();

    int numberIntegers = model_->numberIntegers();
    int numberColumns = solver->getNumCols();
    size_ = 0;
    if (numberIntegers != numberColumns)
        return -1; // can't do dynamic programming

    const double * lower = solver->getColLower();
    const double * upper = solver->getColUpper();
    const double * rowUpper = solver->getRowUpper();

    int numberRows = model_->getNumRows();
    int i;

    // First check columns to see if possible
    double * rhs = new double [numberRows];
    CoinCopyN(rowUpper, numberRows, rhs);

    // Column copy
    const double * element = matrix->getElements();
    const int * row = matrix->getIndices();
    const CoinBigIndex * columnStart = matrix->getVectorStarts();
    const int * columnLength = matrix->getVectorLengths();
    bool bad = false;
    /* It is just possible that we could say okay as
       variables may get fixed but seems unlikely */
    for (i = 0; i < numberColumns; i++) {
        int j;
        double lowerValue = lower[i];
        assert (lowerValue == floor(lowerValue));
        for (j = columnStart[i];
                j < columnStart[i] + columnLength[i]; j++) {
            int iRow = row[j];
            double value = element[j];
            if (upper[i] > lowerValue && (value <= 0.0 || value != floor(value)))
                bad = true;
            if (lowerValue)
                rhs[iRow] -= lowerValue * value;
        }
    }
    // check possible (at present do not allow covering)
    int numberActive = 0;
    bool infeasible = false;
    bool saveBad = bad;
    for (i = 0; i < numberRows; i++) {
        if (rhs[i] < 0)
            infeasible = true;
        else if (rhs[i] > 1.0e5 || fabs(rhs[i] - floor(rhs[i] + 0.5)) > 1.0e-7)
            bad = true;
        else if (rhs[i] > 0.0)
            numberActive++;
    }
    if (bad || infeasible) {
        delete [] rhs;
        if (!saveBad && infeasible)
            return -2;
        else
            return -1;
    }
    // check size of array needed
    double size = 1.0;
    double check = COIN_INT_MAX;
    for (i = 0; i < numberRows; i++) {
        int n = static_cast<int> (floor(rhs[i] + 0.5));
        if (n) {
            n++; // allow for 0,1... n
            if (numberActive != 1) {
                // power of 2
                int iBit = 0;
                int k = n;
                k &= ~1;
                while (k) {
                    iBit++;
                    k &= ~(1 << iBit);
                }
                // See if exact power
                if (n != (1 << iBit)) {
                    // round up to next power of 2
                    n = 1 << (iBit + 1);
                }
                size *= n;
                if (size >= check)
                    break;
            } else {
                size = n; // just one constraint
            }
        }
    }
    // set size needed
    if (size >= check)
        size_ = COIN_INT_MAX;
    else
        size_ = static_cast<int> (size);

    int n01 = 0;
    int nbadcoeff = 0;
    // See if we can tighten bounds
    for (i = 0; i < numberColumns; i++) {
        int j;
        double lowerValue = lower[i];
        double gap = upper[i] - lowerValue;
        for (j = columnStart[i];
                j < columnStart[i] + columnLength[i]; j++) {
            int iRow = row[j];
            double value = element[j];
            if (value != 1.0)
                nbadcoeff++;
            if (gap*value > rhs[iRow] + 1.0e-8)
                gap = rhs[iRow] / value;
        }
        gap = lowerValue + floor(gap + 1.0e-7);
        if (gap < upper[i])
            solver->setColUpper(i, gap);
        if (gap <= 1.0)
            n01++;
    }
    if (allowableSize && size_ <= allowableSize) {
        if (n01 == numberColumns && !nbadcoeff)
            algorithm_ = 0; // easiest
        else
            algorithm_ = 1;
    }
    if (allowableSize && size_ <= allowableSize) {
        numberActive_ = numberActive;
        indices_ = new int [numberActive_];
        cost_ = new double [size_];
        CoinFillN(cost_, size_, COIN_DBL_MAX);
        // but do nothing is okay
        cost_[0] = 0.0;
        back_ = new int[size_];
        CoinFillN(back_, size_, -1);
        startBit_ = new int[numberActive_];
        numberBits_ = new int[numberActive_];
        lookup_ = new int [numberRows];
        rhs_ = new int [numberActive_];
        numberActive = 0;
        int kBit = 0;
        for (i = 0; i < numberRows; i++) {
            int n = static_cast<int> (floor(rhs[i] + 0.5));
            if (n) {
                lookup_[i] = numberActive;
                rhs_[numberActive] = n;
                startBit_[numberActive] = kBit;
                n++; // allow for 0,1... n
                int iBit = 0;
                // power of 2
                int k = n;
                k &= ~1;
                while (k) {
                    iBit++;
                    k &= ~(1 << iBit);
                }
                // See if exact power
                if (n != (1 << iBit)) {
                    // round up to next power of 2
                    iBit++;
                }
                if (numberActive != 1) {
                    n = 1 << iBit;
                    size *= n;
                    if (size >= check)
                        break;
                } else {
                    size = n; // just one constraint
                }
                numberBits_[numberActive++] = iBit;
                kBit += iBit;
            } else {
                lookup_[i] = -1;
            }
        }
        const double * rowLower = solver->getRowLower();
        if (algorithm_ == 0) {
            // rhs 1 and coefficients 1
            // Get first possible solution for printing
            target_ = -1;
            int needed = 0;
            int numberActive = 0;
            for (i = 0; i < numberRows; i++) {
                int newRow = lookup_[i];
                if (newRow >= 0) {
                    if (rowLower[i] == rowUpper[i]) {
                        needed += 1 << numberActive;
                        numberActive++;
                    }
                }
            }
            for (i = 0; i < size_; i++) {
                if ((i&needed) == needed) {
                    break;
                }
            }
            target_ = i;
        } else {
            coefficients_ = new int[numberActive_];
            // If not too many general rhs then we can be more efficient
            numberNonOne_ = 0;
            for (i = 0; i < numberActive_; i++) {
                if (rhs_[i] != 1)
                    numberNonOne_++;
            }
            if (numberNonOne_*2 < numberActive_) {
                // put rhs >1 every second
                int * permute = new int[numberActive_];
                int * temp = new int[numberActive_];
                // try different ways
                int k = 0;
                for (i = 0; i < numberRows; i++) {
                    int newRow = lookup_[i];
                    if (newRow >= 0 && rhs_[newRow] > 1) {
                        permute[newRow] = k;
                        k += 2;
                    }
                }
                // adjust so k points to last
                k -= 2;
                // and now rest
                int k1 = 1;
                for (i = 0; i < numberRows; i++) {
                    int newRow = lookup_[i];
                    if (newRow >= 0 && rhs_[newRow] == 1) {
                        permute[newRow] = k1;
                        k1++;
                        if (k1 <= k)
                            k1++;
                    }
                }
                for (i = 0; i < numberActive_; i++) {
                    int put = permute[i];
                    temp[put] = rhs_[i];
                }
                memcpy(rhs_, temp, numberActive_*sizeof(int));
                for (i = 0; i < numberActive_; i++) {
                    int put = permute[i];
                    temp[put] = numberBits_[i];
                }
                memcpy(numberBits_, temp, numberActive_*sizeof(int));
                k = 0;
                for (i = 0; i < numberActive_; i++) {
                    startBit_[i] = k;
                    k += numberBits_[i];
                }
                for (i = 0; i < numberRows; i++) {
                    int newRow = lookup_[i];
                    if (newRow >= 0)
                        lookup_[i] = permute[newRow];
                }
                delete [] permute;
                delete [] temp;
                // mark new method
                algorithm_ = 2;
            }
            // Get first possible solution for printing
            target_ = -1;
            int needed = 0;
            int * lower2 = new int[numberActive_];
            for (i = 0; i < numberRows; i++) {
                int newRow = lookup_[i];
                if (newRow >= 0) {
                    int gap = static_cast<int> (rowUpper[i] - CoinMax(0.0, rowLower[i]));
                    lower2[newRow] = rhs_[newRow] - gap;
                    int numberBits = numberBits_[newRow];
                    int startBit = startBit_[newRow];
                    if (numberBits == 1 && !gap) {
                        needed |= 1 << startBit;
                    }
                }
            }
            for (i = 0; i < size_; i++) {
                if ((i&needed) == needed) {
                    // this one may do
                    bool good = true;
                    for (int kk = 0; kk < numberActive_; kk++) {
                        int numberBits = numberBits_[kk];
                        int startBit = startBit_[kk];
                        int size = 1 << numberBits;
                        int start = 1 << startBit;
                        int mask = start * (size - 1);
                        int level = (i & mask) >> startBit;
                        if (level < lower2[kk]) {
                            good = false;
                            break;
                        }
                    }
                    if (good) {
                        break;
                    }
                }
            }
            delete [] lower2;
            target_ = i;
        }