Exemplo n.º 1
0
/*
 * It is always the case that one of the variables of a doubleton
 * will be (implied) free, but neither will necessarily be a singleton.
 * Since in the case of a doubleton the number of non-zero entries
 * will never increase, though, it makes sense to always eliminate them.
 *
 * The col rep and row rep must be consistent.
 */
const CoinPresolveAction
  *doubleton_action::presolve (CoinPresolveMatrix *prob,
			      const CoinPresolveAction *next)

{
  double startTime = 0.0;
  int startEmptyRows=0;
  int startEmptyColumns = 0;
  if (prob->tuning_) {
    startTime = CoinCpuTime();
    startEmptyRows = prob->countEmptyRows();
    startEmptyColumns = prob->countEmptyCols();
  }
  double *colels	= prob->colels_;
  int *hrow		= prob->hrow_;
  CoinBigIndex *mcstrt	= prob->mcstrt_;
  int *hincol		= prob->hincol_;
  int ncols		= prob->ncols_;

  double *clo	= prob->clo_;
  double *cup	= prob->cup_;

  double *rowels	= prob->rowels_;
  int *hcol		= prob->hcol_;
  CoinBigIndex *mrstrt	= prob->mrstrt_;
  int *hinrow		= prob->hinrow_;
  int nrows		= prob->nrows_;

  double *rlo	= prob->rlo_;
  double *rup	= prob->rup_;

  presolvehlink *clink = prob->clink_;
  presolvehlink *rlink = prob->rlink_;

  const unsigned char *integerType = prob->integerType_;

  double *cost	= prob->cost_;

  int numberLook = prob->numberRowsToDo_;
  int iLook;
  int * look = prob->rowsToDo_;
  const double ztolzb	= prob->ztolzb_;

  action * actions = new action [nrows];
  int nactions = 0;

  int *zeros	= prob->usefulColumnInt_; //new int[ncols];
  int nzeros	= 0;

  int *fixed	= zeros+ncols; //new int[ncols];
  int nfixed	= 0;

  unsigned char *rowstat = prob->rowstat_;
  double *acts	= prob->acts_;
  double * sol = prob->sol_;

  bool fixInfeasibility = (prob->presolveOptions_&16384)!=0;
# if PRESOLVE_CONSISTENCY
  presolve_consistent(prob) ;
  presolve_links_ok(prob) ;
# endif

  // wasfor (int irow=0; irow<nrows; irow++)
  for (iLook=0;iLook<numberLook;iLook++) {
    int irow = look[iLook];
    if (hinrow[irow] == 2 &&
	fabs(rup[irow] - rlo[irow]) <= ZTOLDP) {
      double rhs = rlo[irow];
      CoinBigIndex krs = mrstrt[irow];
      int icolx, icoly;
      CoinBigIndex k;
      
      icolx = hcol[krs];
      icoly = hcol[krs+1];
      if (hincol[icolx]<=0||hincol[icoly]<=0) {
        // should never happen ?
        //printf("JJF - doubleton column %d has %d entries and %d has %d\n",
        //     icolx,hincol[icolx],icoly,hincol[icoly]);
        continue;
      }
      // check size
      if (fabs(rowels[krs]) < ZTOLDP2 || fabs(rowels[krs+1]) < ZTOLDP2)
	continue;
      // See if prohibited for any reason
      if (prob->colProhibited(icolx) || prob->colProhibited(icolx))
	continue;
      
      // don't bother with fixed variables
      if (!(fabs(cup[icolx] - clo[icolx]) < ZTOLDP) &&
	  !(fabs(cup[icoly] - clo[icoly]) < ZTOLDP)) {
	double coeffx, coeffy;
	/* find this row in each of the columns */
	CoinBigIndex krowx = presolve_find_row(irow, mcstrt[icolx], mcstrt[icolx] + hincol[icolx], hrow);
	CoinBigIndex krowy = presolve_find_row(irow, mcstrt[icoly], mcstrt[icoly] + hincol[icoly], hrow);

/*
  Check for integrality: If one variable is integer, keep it and substitute
  for the continuous variable. If both are integer, substitute only for the
  forms x = k * y (k integral and non-empty intersection on bounds on x)
  or x = 1-y, where both x and y are binary.

  flag bits for integerStatus: 1>>0	x integer
			       1>>1	y integer
*/
	int integerStatus=0;
	if (integerType[icolx]) {
	  if (integerType[icoly]) {
	    // both integer
	    int good = 0;
	    double rhs2 = rhs;
	    double value;
	    value=colels[krowx];
	    if (value<0.0) {
	      value = - value;
	      rhs2 += 1;
	    }
	    if (cup[icolx]==1.0&&clo[icolx]==0.0&&fabs(value-1.0)<1.0e-7)
	      good =1;
	    value=colels[krowy];
	    if (value<0.0) {
	      value = - value;
	      rhs2 += 1;
	    }
	    if (cup[icoly]==1.0&&clo[icoly]==0.0&&fabs(value-1.0)<1.0e-7)
	      good  |= 2;
	    if (good==3&&fabs(rhs2-1.0)<1.0e-7)
	      integerStatus = 3;
	    else
	      integerStatus=-1;
	    if (integerStatus==-1&&!rhs) {
	      // maybe x = k * y;
	      double value1 = colels[krowx];
	      double value2 = colels[krowy];
	      double ratio;
	      bool swap=false;
	      if (fabs(value1)>fabs(value2)) {
		ratio = value1/value2;
	      } else {
		ratio = value2/value1;
		swap=true;
	      }
	      ratio=fabs(ratio);
	      if (fabs(ratio-floor(ratio+0.5))<1.0e-12) {
		// possible
		integerStatus = swap ? 2 : 1;
		//printf("poss type %d\n",integerStatus);
	      }
	    }
	  } else {
	    integerStatus = 1;
	  }
	} else if (integerType[icoly]) {
	  integerStatus = 2;
	}
	if (integerStatus<0) {
	  // can still take in some cases
	  bool canDo=false;
	  double value1 = colels[krowx];
	  double value2 = colels[krowy];
	  double ratio;
	  bool swap=false;
	  double rhsRatio;
	  if (fabs(value1)>fabs(value2)) {
	    ratio = value1/value2;
	    rhsRatio = rhs/value1;
	  } else {
	    ratio = value2/value1;
	    rhsRatio = rhs/value2;
	    swap=true;
	  }
	  ratio=fabs(ratio);
	  if (fabs(ratio-floor(ratio+0.5))<1.0e-12) {
	    // possible
	    integerStatus = swap ? 2 : 1;
	    // but check rhs
	    if (rhsRatio==floor(rhsRatio+0.5))
	      canDo=true;
	  }
#ifdef COIN_DEVELOP2
	  if (canDo)
	    printf("Good CoinPresolveDoubleton icolx %d (%g and bounds %g %g) icoly %d (%g and bound %g %g) - rhs %g\n",
		   icolx,colels[krowx],clo[icolx],cup[icolx],
		   icoly,colels[krowy],clo[icoly],cup[icoly],rhs);
	  else
	  printf("Bad CoinPresolveDoubleton icolx %d (%g) icoly %d (%g) - rhs %g\n",
		 icolx,colels[krowx],icoly,colels[krowy],rhs);
#endif
	  if (!canDo)
	  continue;
	}
	if (integerStatus == 2) {
	  CoinSwap(icoly,icolx);
	  CoinSwap(krowy,krowx);
	}

	// HAVE TO JIB WITH ABOVE swapS
	// if x's coefficient is something like 1000, but y's only something like -1,
	// then when we postsolve, if x's is close to being out of tolerance,
	// then y is very likely to be (because y==1000x) . (55)
	// It it interesting that the number of doubletons found may depend
	// on which column is substituted away (this is true of baxter.mps).
	if (!integerStatus) {
	  if (fabs(colels[krowy]) < fabs(colels[krowx])) {
	    CoinSwap(icoly,icolx);
	    CoinSwap(krowy,krowx);
	  }
	}

#if 0
	//?????
	if (integerType[icolx] &&
	    clo[icoly] != -PRESOLVE_INF &&
	    cup[icoly] != PRESOLVE_INF) {
	  continue;
	}
#endif

	{
	  CoinBigIndex kcs = mcstrt[icoly];
	  CoinBigIndex kce = kcs + hincol[icoly];
	  for (k=kcs; k<kce; k++) {
	    if (hinrow[hrow[k]] == 1) {
	      break;
	    }
	  }
	  // let singleton rows be taken care of first
	  if (k<kce)
	    continue;
	}

	coeffx = colels[krowx];
	coeffy = colels[krowy];

	// it is possible that both x and y are singleton columns
	// that can cause problems
	if (hincol[icolx] == 1 && hincol[icoly] == 1)
	  continue;

	// BE CAUTIOUS and avoid very large relative differences
	// if this is not done in baxter, then the computed solution isn't optimal,
	// but gets it in 11995 iterations; the postsolve goes to iteration 16181.
	// with this, the solution is optimal, but takes 18825 iters; postsolve 18871.
#if 0
	if (fabs(coeffx) * max_coeff_factor <= fabs(coeffy))
	  continue;
#endif

#if 0
	if (only_zero_rhs && rhs != 0)
	  continue;

	if (reject_doubleton(mcstrt, colels, hrow, hincol,
			     -coeffx / coeffy,
			     max_coeff_ratio,
			     irow, icolx, icoly))
	  continue;
#endif

	// common equations are of the form ax + by = 0, or x + y >= lo
	{
	  PRESOLVE_DETAIL_PRINT(printf("pre_doubleton %dC %dC %dR E\n",
				       icoly,icolx,irow));
	  action *s = &actions[nactions];	  
	  nactions++;
	  
	  s->row = irow;
	  s->icolx = icolx;
	  
	  s->clox = clo[icolx];
	  s->cupx = cup[icolx];
	  s->costx = cost[icolx];
	  
	  s->icoly = icoly;
	  s->costy = cost[icoly];
	  
	  s->rlo = rlo[irow];
	  
	  s->coeffx = coeffx;
	  
	  s->coeffy = coeffy;
	  
	  s->ncolx	= hincol[icolx];
	  
	  s->ncoly	= hincol[icoly];
	  if (s->ncoly<s->ncolx) {
	    // Take out row 
	    s->colel	= presolve_dupmajor(colels,hrow,hincol[icoly],
					    mcstrt[icoly],irow) ;
	    s->ncolx=0;
	  } else {
	    s->colel	= presolve_dupmajor(colels,hrow,hincol[icolx],
					    mcstrt[icolx],irow) ;
	    s->ncoly=0;
	  }
	}

	/*
	 * This moves the bounds information for y onto x,
	 * making y free and allowing us to substitute it away.
	 *
	 * a x + b y = c
	 * l1 <= x <= u1
	 * l2 <= y <= u2	==>
	 *
	 * l2 <= (c - a x) / b <= u2
	 * b/-a > 0 ==> (b l2 - c) / -a <= x <= (b u2 - c) / -a
	 * b/-a < 0 ==> (b u2 - c) / -a <= x <= (b l2 - c) / -a
	 */
	{
	  double lo1 = -PRESOLVE_INF;
	  double up1 = PRESOLVE_INF;
	  
	  //PRESOLVEASSERT((coeffx < 0) == (coeffy/-coeffx < 0));
	  // (coeffy/-coeffx < 0) == (coeffy<0 == coeffx<0) 
	  if (-PRESOLVE_INF < clo[icoly]) {
	    if (coeffx * coeffy < 0)
	      lo1 = (coeffy * clo[icoly] - rhs) / -coeffx;
	    else 
	      up1 = (coeffy * clo[icoly] - rhs) / -coeffx;
	  }
	  
	  if (cup[icoly] < PRESOLVE_INF) {
	    if (coeffx * coeffy < 0)
	      up1 = (coeffy * cup[icoly] - rhs) / -coeffx;
	    else 
	      lo1 = (coeffy * cup[icoly] - rhs) / -coeffx;
	  }
	  
	  // costy y = costy ((c - a x) / b) = (costy c)/b + x (costy -a)/b
	  // the effect of maxmin cancels out
	  cost[icolx] += cost[icoly] * (-coeffx / coeffy);
	  
	  prob->change_bias(cost[icoly] * rhs / coeffy);
	  
	  if (0    /*integerType[icolx]*/) {
	    abort();
	    /* no change possible for now */
#if 0
	    lo1 = trunc(lo1);
	    up1 = trunc(up1);
	    
	    /* trunc(3.5) == 3.0 */
	    /* trunc(-3.5) == -3.0 */
	    
	    /* I think this is ok */
	    if (lo1 > clo[icolx]) {
	      (clo[icolx] <= 0.0)
		clo[icolx] =  ? ilo

		clo[icolx] = ilo;
	      cup[icolx] = iup;
	    }
#endif
	  } else {
Exemplo n.º 2
0
bool
BlisConGenerator::generateCons(OsiCuts & coinCuts , bool fullScan)
{
    bool status = false;

    if (strategy_ == -2) {
        // This con generator has been disabled.
        return false;
    }

    OsiSolverInterface * solver = model_->solver();

#if defined(BLIS_DEBUG_MORE)
    std::cout << "model_->getNodeCount() = " << model_->getNodeCount()
              << std::endl;
#endif

    if ( fullScan ||
         ((strategy_ > 0) && (model_->getNumNodes() % strategy_) == 0) ) {

        //--------------------------------------------------
        // Start to generate cons ...
        //--------------------------------------------------

	int j;
        double start = CoinCpuTime();
        int numConsBefore = coinCuts.sizeCuts();
        int numRowsBefore = coinCuts.sizeRowCuts();

        assert(generator_ != NULL);

        CglProbing* generator = dynamic_cast<CglProbing *>(generator_);

        if (!generator) {
            generator_->generateCuts(*solver, coinCuts);
        }
        else {
            // It is probing - return tight column bound
 	    CglTreeInfo info;
            generator->generateCutsAndModify(*solver, coinCuts, &info);
            const double * tightLower = generator->tightLower();
            const double * lower = solver->getColLower();
            const double * tightUpper = generator->tightUpper();
            const double * upper = solver->getColUpper();
            const double * solution = solver->getColSolution();

            int numberColumns = solver->getNumCols();
            double primalTolerance = 1.0e-8;
            for (j = 0; j < numberColumns; ++j) {
                if ( (tightUpper[j] == tightLower[j]) &&
                     (upper[j] > lower[j]) ) {
                    // fix column j
                    solver->setColLower(j, tightLower[j]);
                    solver->setColUpper(j, tightUpper[j]);
                    if ( (tightLower[j] > solution[j] + primalTolerance) ||
                         (tightUpper[j] < solution[j] - primalTolerance) ) {
                        status = true;
                    }
                }
            }
        } // EOF probing.

        //--------------------------------------------------
        // Remove zero length row cuts.
        //--------------------------------------------------

	int numRowCons = coinCuts.sizeRowCuts();
	for (j = numRowsBefore; j < numRowCons; ++j) {
	    OsiRowCut & rCut = coinCuts.rowCut(j);
	    int len = rCut.row().getNumElements();
#ifdef BLIS_DEBUG_MORE
	    std::cout << "Cut " << j<<": length = " << len << std::endl;
#endif
	    if (len == 0) {
		// Empty cuts
		coinCuts.eraseRowCut(j);
		--j;
		--numRowCons;
#ifdef BLIS_DEBUG
		std::cout << "WARNING: Empty cut from " << name_ << std::endl;
#endif
	    }
	    else if (len < 0) {
#ifdef BLIS_DEBUG
		std::cout << "ERROR: Cut length = " << len << std::endl;
#endif
		// Error
		assert(0);
	    }
	}

        //--------------------------------------------------
        // Update statistics.
        //--------------------------------------------------

        ++calls_;
        numConsGenerated_ += (coinCuts.sizeCuts() - numConsBefore);
        time_ += (CoinCpuTime() - start);
        if (numConsGenerated_ == 0) {
            ++noConsCalls_;
        }
    }

    return status;
}
Exemplo n.º 3
0
int main (int argc, const char *argv[])
{

  // Define your favorite OsiSolver
  
  OsiClpSolverInterface solver1;

  // Read in model using argv[1]
  // and assert that it is a clean model
  std::string dirsep(1,CoinFindDirSeparator());
  std::string mpsFileName;
# if defined(SAMPLEDIR)
  mpsFileName = SAMPLEDIR ;
  mpsFileName += dirsep+"p0033.mps";
# else
  if (argc < 2) {
    fprintf(stderr, "Do not know where to find sample MPS files.\n");
    exit(1);
  }
# endif
  if (argc>=2) mpsFileName = argv[1];
  int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),"");
  if( numMpsReadErrors != 0 )
  {
     printf("%d errors reading MPS file\n", numMpsReadErrors);
     return numMpsReadErrors;
  }
  double time1 = CoinCpuTime();

  /* Options are:
     preprocess to do preprocessing
     time in minutes
     if 2 parameters and numeric taken as time
  */
  bool preProcess=false;
  double minutes=-1.0;
  int nGoodParam=0;
  for (int iParam=2; iParam<argc;iParam++) {
    if (!strcmp(argv[iParam],"preprocess")) {
      preProcess=true;
      nGoodParam++;
    } else if (!strcmp(argv[iParam],"time")) {
      if (iParam+1<argc&&isdigit(argv[iParam+1][0])) {
        minutes=atof(argv[iParam+1]);
        if (minutes>=0.0) {
          nGoodParam+=2;
          iParam++; // skip time
        }
      }
    }
  }
  if (nGoodParam==0&&argc==3&&isdigit(argv[2][0])) {
    // If time is given then stop after that number of minutes
    minutes = atof(argv[2]);
    if (minutes>=0.0) 
      nGoodParam=1;
  }
  if (nGoodParam!=argc-2&&argc>=2) {
    printf("Usage <file> [preprocess] [time <minutes>] or <file> <minutes>\n");
    exit(1);
  }
  solver1.initialSolve();
  // Reduce printout
  solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry);
  // See if we want preprocessing
  OsiSolverInterface * solver2=&solver1;
#if PREPROCESS==1
  CglPreProcess process;
  if (preProcess) {
    /* Do not try and produce equality cliques and
       do up to 5 passes */
    solver2 = process.preProcess(solver1,false,5);
    if (!solver2) {
      printf("Pre-processing says infeasible\n");
      exit(2);
    }
    solver2->resolve();
  }
#endif
  CbcModel model(*solver2);
  model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
  // Set up some cut generators and defaults
  // Probing first as gets tight bounds on continuous

  CglProbing generator1;
  generator1.setUsingObjective(true);
  generator1.setMaxPass(1);
  generator1.setMaxPassRoot(5);
  // Number of unsatisfied variables to look at
  generator1.setMaxProbe(10);
  generator1.setMaxProbeRoot(1000);
  // How far to follow the consequences
  generator1.setMaxLook(50);
  generator1.setMaxLookRoot(500);
  // Only look at rows with fewer than this number of elements
  generator1.setMaxElements(200);
  generator1.setRowCuts(3);

  CglGomory generator2;
  // try larger limit
  generator2.setLimit(300);

  CglKnapsackCover generator3;

  CglRedSplit generator4;
  // try larger limit
  generator4.setLimit(200);

  CglClique generator5;
  generator5.setStarCliqueReport(false);
  generator5.setRowCliqueReport(false);

  CglMixedIntegerRounding2 mixedGen;
  CglFlowCover flowGen;
  
  // Add in generators
  // Experiment with -1 and -99 etc
  model.addCutGenerator(&generator1,-1,"Probing");
  model.addCutGenerator(&generator2,-1,"Gomory");
  model.addCutGenerator(&generator3,-1,"Knapsack");
  // model.addCutGenerator(&generator4,-1,"RedSplit");
  model.addCutGenerator(&generator5,-1,"Clique");
  model.addCutGenerator(&flowGen,-1,"FlowCover");
  model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding");
  // Say we want timings
  int numberGenerators = model.numberCutGenerators();
  int iGenerator;
  for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
    generator->setTiming(true);
  }
  OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (model.solver());
  // go faster stripes
  if (osiclp) {
    // Turn this off if you get problems
    // Used to be automatically set
    osiclp->setSpecialOptions(128);
    if(osiclp->getNumRows()<300&&osiclp->getNumCols()<500) {
      //osiclp->setupForRepeatedUse(2,0);
      osiclp->setupForRepeatedUse(0,0);
    }
  } 
  // Uncommenting this should switch off all CBC messages
  // model.messagesPointer()->setDetailMessages(10,10000,NULL);
  // Allow rounding heuristic

  CbcRounding heuristic1(model);
  model.addHeuristic(&heuristic1);

  // And local search when new solution found

  CbcHeuristicLocal heuristic2(model);
  model.addHeuristic(&heuristic2);

  // Redundant definition of default branching (as Default == User)
  CbcBranchUserDecision branch;
  model.setBranchingMethod(&branch);

  // Definition of node choice
  CbcCompareUser compare;
  model.setNodeComparison(compare);

  // Do initial solve to continuous
  model.initialSolve();

  // Could tune more
  double objValue = model.solver()->getObjSense()*model.solver()->getObjValue();
  double minimumDropA=CoinMin(1.0,fabs(objValue)*1.0e-3+1.0e-4);
  double minimumDrop= fabs(objValue)*1.0e-4+1.0e-4;
  printf("min drop %g (A %g)\n",minimumDrop,minimumDropA);
  model.setMinimumDrop(minimumDrop);

  if (model.getNumCols()<500)
    model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible
  else if (model.getNumCols()<5000)
    model.setMaximumCutPassesAtRoot(100); // use minimum drop
  else
    model.setMaximumCutPassesAtRoot(20);
  model.setMaximumCutPasses(10);
  //model.setMaximumCutPasses(2);

  // Switch off strong branching if wanted
  // model.setNumberStrong(0);
  // Do more strong branching if small
  if (model.getNumCols()<5000)
    model.setNumberStrong(10);
  model.setNumberStrong(20);
  //model.setNumberStrong(5);
  model.setNumberBeforeTrust(5);

  model.solver()->setIntParam(OsiMaxNumIterationHotStart,100);

  // If time is given then stop after that number of minutes
  if (minutes>=0.0) {
    std::cout<<"Stopping after "<<minutes<<" minutes"<<std::endl;
    model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes);
  }
  // Switch off most output
  if (model.getNumCols()<3000) {
    model.messageHandler()->setLogLevel(1);
    //model.solver()->messageHandler()->setLogLevel(0);
  } else {
    model.messageHandler()->setLogLevel(2);
    model.solver()->messageHandler()->setLogLevel(1);
  }
  //model.messageHandler()->setLogLevel(2);
  //model.solver()->messageHandler()->setLogLevel(2);
  //model.setPrintFrequency(50);
  //#define DEBUG_CUTS
#ifdef DEBUG_CUTS
  // Set up debugger by name (only if no preprocesing)
  if (!preProcess) {
    std::string problemName ;
    model.solver()->getStrParam(OsiProbName,problemName) ;
    model.solver()->activateRowCutDebugger(problemName.c_str()) ;
  }
#endif
#if PREPROCESS==2
  // Default strategy will leave cut generators as they exist already
  // so cutsOnlyAtRoot (1) ignored
  // numberStrong (2) is 5 (default)
  // numberBeforeTrust (3) is 5 (default is 0)
  // printLevel (4) defaults (0)
  CbcStrategyDefault strategy(true,5,5);
  // Set up pre-processing to find sos if wanted
  if (preProcess)
    strategy.setupPreProcessing(2);
  model.setStrategy(strategy);
#endif
  // Do complete search
  
  model.branchAndBound();

  std::cout<<mpsFileName<<" took "<<CoinCpuTime()-time1<<" seconds, "
	   <<model.getNodeCount()<<" nodes with objective "
	   <<model.getObjValue()
	   <<(!model.status() ? " Finished" : " Not finished")
	   <<std::endl;

  // Print more statistics
  std::cout<<"Cuts at root node changed objective from "<<model.getContinuousObjective()
	   <<" to "<<model.rootObjectiveAfterCuts()<<std::endl;

  for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
    std::cout<<generator->cutGeneratorName()<<" was tried "
	     <<generator->numberTimesEntered()<<" times and created "
	     <<generator->numberCutsInTotal()<<" cuts of which "
	     <<generator->numberCutsActive()<<" were active after adding rounds of cuts";
    if (generator->timing())
      std::cout<<" ( "<<generator->timeInCutGenerator()<<" seconds)"<<std::endl;
    else
      std::cout<<std::endl;
  }
  // Print solution if finished - we can't get names from Osi! - so get from OsiClp

  if (model.getMinimizationObjValue()<1.0e50) {
#if PREPROCESS==1
    // post process
    OsiSolverInterface * solver;
    if (preProcess) {
      process.postProcess(*model.solver());
      // Solution now back in solver1
      solver = & solver1;
    } else {
      solver = model.solver();
    }
#else
    OsiSolverInterface * solver = model.solver();
#endif
    int numberColumns = solver->getNumCols();
    
    const double * solution = solver->getColSolution();

    // Get names from solver1 (as OsiSolverInterface may lose)
    std::vector<std::string> columnNames = *solver1.getModelPtr()->columnNames();
    
    int iColumn;
    std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
    
    std::cout<<"--------------------------------------"<<std::endl;
    for (iColumn=0;iColumn<numberColumns;iColumn++) {
      double value=solution[iColumn];
      if (fabs(value)>1.0e-7&&solver->isInteger(iColumn)) 
	std::cout<<std::setw(6)<<iColumn<<" "
                 <<columnNames[iColumn]<<" "
                 <<value<<std::endl;
    }
    std::cout<<"--------------------------------------"<<std::endl;
  
    std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);
  }
  return 0;
}    
Exemplo n.º 4
0
int main (int argc, const char *argv[])
{
  // Get data
  std::string fileName = "./sudoku_sample.csv";
  if (argc>=2) fileName = argv[1];
  FILE * fp = fopen(fileName.c_str(),"r");
  if (!fp) {
    printf("Unable to open file %s\n",fileName.c_str());
    exit(0);
  }
#define MAX_SIZE 16
  int valueOffset=1;
  double lo[MAX_SIZE*MAX_SIZE],up[MAX_SIZE*MAX_SIZE];
  char line[80];
  int row,column;
  /*************************************** 
     Read .csv file and see if 9 or 16 Su Doku
  ***************************************/
  int size=9;
  for (row=0;row<size;row++) {
    fgets(line,80,fp);
    // Get size of sudoku puzzle (9 or 16)
    if (!row) {
      int get=0;
      size=1;
      while (line[get]>=32) {
        if (line[get]==',')
          size++;
        get++;
      }
      assert (size==9||size==16);
      printf("Solving Su Doku of size %d\n",size);
      if (size==16)
        valueOffset=0;
    }
    int get=0;
    for (column=0;column<size;column++) {
      lo[size*row+column]=valueOffset;
      up[size*row+column]=valueOffset-1+size;
      if (line[get]!=','&&line[get]>=32) {
        // skip blanks
        if (line[get]==' ') {
          get++;
          continue;
        }
        int value = line[get]-'0';
        if (size==9) {
          assert (value>=1&&value<=9);
        } else {
          assert (size==16);
          if (value<0||value>9) {
            if (line[get]=='"') {
              get++;
              value = 10 + line[get]-'A';
              if (value<10||value>15) {
                value = 10 + line[get]-'a';
              }
              get++;
            } else {
              value = 10 + line[get]-'A';
              if (value<10||value>15) {
                value = 10 + line[get]-'a';
              }
          }
          }
          assert (value>=0&&value<=15);
        }
        lo[size*row+column]=value;
        up[size*row+column]=value;
        get++;
      }
      get++;
    }
  }
  int block_size = (int) sqrt ((double) size);
  /*************************************** 
     Now build rules for all different
     3*9 or 3*16 sets of variables
     Number variables by row*size+column
  ***************************************/
  int starts[3*MAX_SIZE+1];
  int which[3*MAX_SIZE*MAX_SIZE];
  int put=0;
  int set=0;
  starts[0]=0;
  // By row
  for (row=0;row<size;row++) {
    for (column=0;column<size;column++) 
      which[put++]=row*size+column;
    starts[set+1]=put;
    set++;
  }
  // By column
  for (column=0;column<size;column++) {
    for (row=0;row<size;row++) 
      which[put++]=row*size+column;
    starts[set+1]=put;
    set++;
  }
  // By box
  for (row=0;row<size;row+=block_size) {
    for (column=0;column<size;column+=block_size) {
      for (int row2=row;row2<row+block_size;row2++) {
        for (int column2=column;column2<column+block_size;column2++) 
          which[put++]=row2*size+column2;
      }
      starts[set+1]=put;
      set++;
    }
  }
  OsiClpSolverInterface solver1;

  /*************************************** 
     Create model
     Set variables to be general integer variables although
     priorities probably mean that it won't matter
  ***************************************/
  CoinModel build;
  // Columns
  char name[4];
  for (row=0;row<size;row++) {
    for (column=0;column<size;column++) {
      if (row<10) {
        if (column<10) 
          sprintf(name,"X%d%d",row,column);
        else
          sprintf(name,"X%d%c",row,'A'+(column-10));
      } else {
        if (column<10) 
          sprintf(name,"X%c%d",'A'+(row-10),column);
        else
          sprintf(name,"X%c%c",'A'+(row-10),'A'+(column-10));
      }
      double value = CoinDrand48()*100.0;
      build.addColumn(0,NULL,NULL,lo[size*row+column],
                      up[size*row+column], value, name,true);
    }
  }
  /*************************************** 
     Now add in extra variables for N way branching
  ***************************************/
  for (row=0;row<size;row++) {
    for (column=0;column<size;column++) {
      int iColumn = size*row+column;
      double value = lo[iColumn];
      if (value<up[iColumn]) {
        for (int i=0;i<size;i++)
          build.addColumn(0,NULL,NULL,0.0,1.0,0.0);
      } else {
        // fixed
        // obviously could do better  if we missed out variables
        int which = ((int) value) - valueOffset;
        for (int i=0;i<size;i++) {
          if (i!=which)
            build.addColumn(0,NULL,NULL,0.0,0.0,0.0);
          else
            build.addColumn(0,NULL,NULL,0.0,1.0,0.0);
        }
      }
    }
  }
  
  /*************************************** 
     Now rows
  ***************************************/
  double values[]={1.0,1.0,1.0,1.0,
                   1.0,1.0,1.0,1.0,
                   1.0,1.0,1.0,1.0,
                   1.0,1.0,1.0,1.0};
  int indices[MAX_SIZE+1];
  double rhs = size==9 ? 45.0 : 120.0;
  for (row=0;row<3*size;row++) {
    int iStart = starts[row];
    for (column=0;column<size;column++) 
      indices[column]=which[column+iStart];
    build.addRow(size,indices,values,rhs,rhs);
  }
  double values2[MAX_SIZE+1];
  values2[0]=-1.0;
  for (row=0;row<size;row++) 
    values2[row+1]=row+valueOffset;
  // Now add rows for extra variables
  for (row=0;row<size;row++) {
    for (column=0;column<size;column++) {
      int iColumn = row*size+column;
      int base = size*size + iColumn*size;
      indices[0]=iColumn;
      for (int i=0;i<size;i++)
        indices[i+1]=base+i;
      build.addRow(size+1,indices,values2,0.0,0.0);
    }
  }
  solver1.loadFromCoinModel(build);
  build.writeMps("xx.mps");
  
  double time1 = CoinCpuTime();
  solver1.initialSolve();
  CbcModel model(solver1);
  model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
  model.solver()->setHintParam(OsiDoScale,false,OsiHintTry);
  /*************************************** 
    Add in All different cut generator and All different branching
    So we will have integers then cut branching then N way branching
    in reverse priority order
  ***************************************/
  
  // Cut generator
  CglAllDifferent allDifferent(3*size,starts,which);
  model.addCutGenerator(&allDifferent,-99,"allDifferent");
  model.cutGenerator(0)->setWhatDepth(5);
  CbcObject ** objects = new CbcObject * [4*size*size];
  int nObj=0;
  for (row=0;row<3*size;row++) {
    int iStart = starts[row];
    objects[row]= new CbcBranchAllDifferent(&model,size,which+iStart);
    objects[row]->setPriority(2000+nObj); // do after rest satisfied
    nObj++;
  }
  /*************************************** 
     Add in N way branching and while we are at it add in cuts
  ***************************************/
  CglStored stored;
  for (row=0;row<size;row++) {
    for (column=0;column<size;column++) {
      int iColumn = row*size+column;
      int base = size*size + iColumn*size;
      int i;
      for ( i=0;i<size;i++)
        indices[i]=base+i;
      CbcNWay * obj = new CbcNWay(&model,size,indices,nObj);
      int seq[200];
      int newUpper[200];
      memset(newUpper,0,sizeof(newUpper));
      for (i=0;i<size;i++) {
        int state=9999;
        int one=1;
        int nFix=1;
        // Fix real variable
        seq[0]=iColumn;
        newUpper[0]=valueOffset+i;
        int kColumn = base+i;
        int j;
        // same row
        for (j=0;j<size;j++) {
          int jColumn = row*size+j;
          int jjColumn = size*size+jColumn*size+i;
          if (jjColumn!=kColumn) {
            seq[nFix++]=jjColumn; // must be zero
          }
        }
        // same column
        for (j=0;j<size;j++) {
          int jColumn = j*size+column;
          int jjColumn = size*size+jColumn*size+i;
          if (jjColumn!=kColumn) {
            seq[nFix++]=jjColumn; // must be zero
          }
        }
        // same block
        int kRow = row/block_size;
        kRow *= block_size;
        int kCol = column/block_size;
        kCol *= block_size;
        for (j=kRow;j<kRow+block_size;j++) {
          for (int jc=kCol;jc<kCol+block_size;jc++) {
            int jColumn = j*size+jc;
            int jjColumn = size*size+jColumn*size+i;
            if (jjColumn!=kColumn) {
              seq[nFix++]=jjColumn; // must be zero
            }
          }
        }
        // seem to need following?
        const int * upperAddress = newUpper;
        const int * seqAddress = seq;
        CbcFixVariable fix(1,&state,&one,&upperAddress,&seqAddress,&nFix,&upperAddress,&seqAddress);
        obj->setConsequence(indices[i],fix);
        // Now do as cuts
        for (int kk=1;kk<nFix;kk++) {
          int jColumn = seq[kk];
          int cutInd[2];
          cutInd[0]=kColumn;
          if (jColumn>kColumn) {
            cutInd[1]=jColumn;
            stored.addCut(-COIN_DBL_MAX,1.0,2,cutInd,values);
          }
        }
      }
      objects[nObj]= obj;
      objects[nObj]->setPriority(nObj);
      nObj++;
    }
  }
  model.addObjects(nObj,objects);
  for (row=0;row<nObj;row++) 
    delete objects[row];
  delete [] objects;
  model.messageHandler()->setLogLevel(1);
  model.addCutGenerator(&stored,1,"stored");
  // Say we want timings
  int numberGenerators = model.numberCutGenerators();
  int iGenerator;
  for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
    generator->setTiming(true);
  }
  // Set this to get all solutions (all ones in newspapers should only have one)
  //model.setCutoffIncrement(-1.0e6);
  /*************************************** 
     Do branch and bound
  ***************************************/
  // Do complete search
  model.branchAndBound();
  std::cout<<"took "<<CoinCpuTime()-time1<<" seconds, "
	   <<model.getNodeCount()<<" nodes with objective "
	   <<model.getObjValue()
	   <<(!model.status() ? " Finished" : " Not finished")
	   <<std::endl;


  /*************************************** 
     Print solution and check it is feasible
     We could modify output so could be imported by spreadsheet
  ***************************************/
  if (model.getMinimizationObjValue()<1.0e50) {
    
    const double * solution = model.bestSolution();
    int put=0;
    for (row=0;row<size;row++) {
      for (column=0;column<size;column++) {
        int value = (int) floor(solution[row*size+column]+0.5);
        assert (value>=lo[put]&&value<=up[put]);
        // save for later test
        lo[put++]=value;
        printf("%d ",value);
      }
      printf("\n");
    }
    // check valid
    bool valid=true;
    // By row
    for (row=0;row<size;row++) {
      put=0;
      for (column=0;column<size;column++) 
        which[put++]=row*size+column;
      assert (put==size);
      int i;
      for (i=0;i<put;i++) 
        which[i]=(int) lo[which[i]];
      std::sort(which,which+put);
      int last = valueOffset-1;
      for (i=0;i<put;i++) {
        int value=which[i];
        if (value!=last+1)
          valid=false;
        last=value;
      }
    }
    // By column
    for (column=0;column<size;column++) {
      put=0;
      for (row=0;row<size;row++) 
        which[put++]=row*size+column;
      assert (put==size);
      int i;
      for (i=0;i<put;i++) 
        which[i]=(int) lo[which[i]];
      std::sort(which,which+put);
      int last = valueOffset-1;
      for (i=0;i<put;i++) {
        int value=which[i];
        if (value!=last+1)
          valid=false;
        last=value;
      }
    }
    // By box
    for (row=0;row<size;row+=block_size) {
      for (column=0;column<size;column+=block_size) {
        put=0;
        for (int row2=row;row2<row+block_size;row2++) {
          for (int column2=column;column2<column+block_size;column2++) 
            which[put++]=row2*size+column2;
        }
        assert (put==size);
        int i;
        for (i=0;i<put;i++) 
          which[i]=(int) lo[which[i]];
        std::sort(which,which+put);
        int last = valueOffset-1;
        for (i=0;i<put;i++) {
          int value=which[i];
          if (value!=last+1)
          valid=false;
          last=value;
        }
      }
    }
    if (valid) {
      printf("solution is valid\n");
    } else {
      printf("solution is not valid\n");
      abort();
    }
  }
  return 0;
}    
Exemplo n.º 5
0
// ** Temporary version
int
ClpPdco::pdco( ClpPdcoBase * stuff, Options &options, Info &info, Outfo &outfo)
{
//    D1, D2 are positive-definite diagonal matrices defined from d1, d2.
//           In particular, d2 indicates the accuracy required for
//           satisfying each row of Ax = b.
//
// D1 and D2 (via d1 and d2) provide primal and dual regularization
// respectively.  They ensure that the primal and dual solutions
// (x,r) and (y,z) are unique and bounded.
//
// A scalar d1 is equivalent to d1 = ones(n,1), D1 = diag(d1).
// A scalar d2 is equivalent to d2 = ones(m,1), D2 = diag(d2).
// Typically, d1 = d2 = 1e-4.
// These values perturb phi(x) only slightly  (by about 1e-8) and request
// that A*x = b be satisfied quite accurately (to about 1e-8).
// Set d1 = 1e-4, d2 = 1 for least-squares problems with bound constraints.
// The problem is then
//
//    minimize    phi(x) + 1/2 norm(d1*x)^2 + 1/2 norm(A*x - b)^2
//    subject to  bl <= x <= bu.
//
// More generally, d1 and d2 may be n and m vectors containing any positive
// values (preferably not too small, and typically no larger than 1).
// Bigger elements of d1 and d2 improve the stability of the solver.
//
// At an optimal solution, if x(j) is on its lower or upper bound,
// the corresponding z(j) is positive or negative respectively.
// If x(j) is between its bounds, z(j) = 0.
// If bl(j) = bu(j), x(j) is fixed at that value and z(j) may have
// either sign.
//
// Also, r and y satisfy r = D2 y, so that Ax + D2^2 y = b.
// Thus if d2(i) = 1e-4, the i-th row of Ax = b will be satisfied to
// approximately 1e-8.  This determines how large d2(i) can safely be.
//
//
// EXTERNAL FUNCTIONS:
// options         = pdcoSet;                  provided with pdco.m
// [obj,grad,hess] = pdObj( x );               provided by user
//               y = pdMat( name,mode,m,n,x ); provided by user if pdMat
//                                             is a string, not a matrix
//
// INPUT ARGUMENTS:
// pdObj      is a string containing the name of a function pdObj.m
//            or a function_handle for such a function
//            such that [obj,grad,hess] = pdObj(x) defines
//            obj  = phi(x)              : a scalar,
//            grad = gradient of phi(x)  : an n-vector,
//            hess = diag(Hessian of phi): an n-vector.
//         Examples:
//            If phi(x) is the linear function c"x, pdObj should return
//               [obj,grad,hess] = [c"*x, c, zeros(n,1)].
//            If phi(x) is the entropy function E(x) = sum x(j) log x(j),
//               [obj,grad,hess] = [E(x), log(x)+1, 1./x].
// pdMat      may be an ifexplicit m x n matrix A (preferably sparse!),
//            or a string containing the name of a function pdMat.m
//            or a function_handle for such a function
//            such that y = pdMat( name,mode,m,n,x )
//            returns   y = A*x (mode=1)  or  y = A"*x (mode=2).
//            The input parameter "name" will be the string pdMat.
// b          is an m-vector.
// bl         is an n-vector of lower bounds.  Non-existent bounds
//            may be represented by bl(j) = -Inf or bl(j) <= -1e+20.
// bu         is an n-vector of upper bounds.  Non-existent bounds
//            may be represented by bu(j) =  Inf or bu(j) >=  1e+20.
// d1, d2     may be positive scalars or positive vectors (see above).
// options    is a structure that may be set and altered by pdcoSet
//            (type help pdcoSet).
// x0, y0, z0 provide an initial solution.
// xsize, zsize are estimates of the biggest x and z at the solution.
//            They are used to scale (x,y,z).  Good estimates
//            should improve the performance of the barrier method.
//
//
// OUTPUT ARGUMENTS:
// x          is the primal solution.
// y          is the dual solution associated with Ax + D2 r = b.
// z          is the dual solution associated with bl <= x <= bu.
// inform = 0 if a solution is found;
//        = 1 if too many iterations were required;
//        = 2 if the linesearch failed too often.
// PDitns     is the number of Primal-Dual Barrier iterations required.
// CGitns     is the number of Conjugate-Gradient  iterations required
//            if an iterative solver is used (LSQR).
// time       is the cpu time used.
//----------------------------------------------------------------------

// PRIVATE FUNCTIONS:
//    pdxxxbounds
//    pdxxxdistrib
//    pdxxxlsqr
//    pdxxxlsqrmat
//    pdxxxmat
//    pdxxxmerit
//    pdxxxresid1
//    pdxxxresid2
//    pdxxxstep
//
// GLOBAL VARIABLES:
//    global pdDDD1 pdDDD2 pdDDD3
//
//
// NOTES:
// The matrix A should be reasonably well scaled: norm(A,inf) =~ 1.
// The vector b and objective phi(x) may be of any size, but ensure that
// xsize and zsize are reasonably close to norm(x,inf) and norm(z,inf)
// at the solution.
//
// The files defining pdObj  and pdMat
// must not be called Fname.m or Aname.m!!
//
//
// AUTHOR:
//    Michael Saunders, Systems Optimization Laboratory (SOL),
//    Stanford University, Stanford, California, USA.
//    [email protected]
//
// CONTRIBUTORS:
//    Byunggyoo Kim, SOL, Stanford University.
//    [email protected]
//
// DEVELOPMENT:
// 20 Jun 1997: Original version of pdsco.m derived from pdlp0.m.
// 29 Sep 2002: Original version of pdco.m  derived from pdsco.m.
//              Introduced D1, D2 in place of gamma*I, delta*I
//              and allowed for general bounds bl <= x <= bu.
// 06 Oct 2002: Allowed for fixed variabes: bl(j) = bu(j) for any j.
// 15 Oct 2002: Eliminated some work vectors (since m, n might be LARGE).
//              Modularized residuals, linesearch
// 16 Oct 2002: pdxxx..., pdDDD... names rationalized.
//              pdAAA eliminated (global copy of A).
//              Aname is now used directly as an ifexplicit A or a function.
//              NOTE: If Aname is a function, it now has an extra parameter.
// 23 Oct 2002: Fname and Aname can now be function handles.
// 01 Nov 2002: Bug fixed in feval in pdxxxmat.
//-----------------------------------------------------------------------

//  global pdDDD1 pdDDD2 pdDDD3
     double inf = 1.0e30;
     double eps = 1.0e-15;
     double atolold = -1.0, r3ratio = -1.0, Pinf, Dinf, Cinf, Cinf0;

     printf("\n   --------------------------------------------------------");
     printf("\n   pdco.m                            Version of 01 Nov 2002");
     printf("\n   Primal-dual barrier method to minimize a convex function");
     printf("\n   subject to linear constraints Ax + r = b,  bl <= x <= bu");
     printf("\n   --------------------------------------------------------\n");

     int m = numberRows_;
     int n = numberColumns_;
     bool ifexplicit = true;

     CoinDenseVector<double> b(m, rhs_);
     CoinDenseVector<double> x(n, x_);
     CoinDenseVector<double> y(m, y_);
     CoinDenseVector<double> z(n, dj_);
     //delete old arrays
     delete [] rhs_;
     delete [] x_;
     delete [] y_;
     delete [] dj_;
     rhs_ = NULL;
     x_ = NULL;
     y_ = NULL;
     dj_ = NULL;

     // Save stuff so available elsewhere
     pdcoStuff_ = stuff;

     double normb  = b.infNorm();
     double normx0 = x.infNorm();
     double normy0 = y.infNorm();
     double normz0 = z.infNorm();

     printf("\nmax |b | = %8g     max |x0| = %8g", normb , normx0);
     printf(                "      xsize   = %8g", xsize_);
     printf("\nmax |y0| = %8g     max |z0| = %8g", normy0, normz0);
     printf(                "      zsize   = %8g", zsize_);

     //---------------------------------------------------------------------
     // Initialize.
     //---------------------------------------------------------------------
     //true   = 1;
     //false  = 0;
     //zn     = zeros(n,1);
     //int nb     = n + m;
     int CGitns = 0;
     int inform = 0;
     //---------------------------------------------------------------------
     //  Only allow scalar d1, d2 for now
     //---------------------------------------------------------------------
     /*
     if (d1_->size()==1)
         d1_->resize(n, d1_->getElements()[0]);  // Allow scalar d1, d2
     if (d2_->size()==1)
         d2->resize(m, d2->getElements()[0]);  // to mean dk * unit vector
      */
     assert (stuff->sizeD1() == 1);
     double d1 = stuff->getD1();
     double d2 = stuff->getD2();

     //---------------------------------------------------------------------
     // Grab input options.
     //---------------------------------------------------------------------
     int  maxitn    = options.MaxIter;
     double featol    = options.FeaTol;
     double opttol    = options.OptTol;
     double steptol   = options.StepTol;
     int  stepSame  = 1;  /* options.StepSame;   // 1 means stepx == stepz */
     double x0min     = options.x0min;
     double z0min     = options.z0min;
     double mu0       = options.mu0;
     int  LSproblem = options.LSproblem;  // See below
     int  LSmethod  = options.LSmethod;   // 1=Cholesky    2=QR    3=LSQR
     int  itnlim    = options.LSQRMaxIter * CoinMin(m, n);
     double atol1     = options.LSQRatol1;  // Initial  atol
     double atol2     = options.LSQRatol2;  // Smallest atol,unless atol1 is smaller
     double conlim    = options.LSQRconlim;
     //int  wait      = options.wait;

     // LSproblem:
     //  1 = dy          2 = dy shifted, DLS
     // 11 = s          12 =  s shifted, DLS    (dx = Ds)
     // 21 = dx
     // 31 = 3x3 system, symmetrized by Z^{1/2}
     // 32 = 2x2 system, symmetrized by X^{1/2}

     //---------------------------------------------------------------------
     // Set other parameters.
     //---------------------------------------------------------------------
     int  kminor    = 0;      // 1 stops after each iteration
     double eta       = 1e-4;   // Linesearch tolerance for "sufficient descent"
     double maxf      = 10;     // Linesearch backtrack limit (function evaluations)
     double maxfail   = 1;      // Linesearch failure limit (consecutive iterations)
     double bigcenter = 1e+3;   // mu is reduced if center < bigcenter.

     // Parameters for LSQR.
     double atolmin   = eps;    // Smallest atol if linesearch back-tracks
     double btol      = 0;      // Should be small (zero is ok)
     double show      = false;  // Controls lsqr iteration log
     /*
     double gamma     = d1->infNorm();
     double delta     = d2->infNorm();
     */
     double gamma = d1;
     double delta = d2;

     printf("\n\nx0min    = %8g     featol   = %8.1e", x0min, featol);
     printf(                  "      d1max   = %8.1e", gamma);
     printf(  "\nz0min    = %8g     opttol   = %8.1e", z0min, opttol);
     printf(                  "      d2max   = %8.1e", delta);
     printf(  "\nmu0      = %8.1e     steptol  = %8g", mu0  , steptol);
     printf(                  "     bigcenter= %8g"  , bigcenter);

     printf("\n\nLSQR:");
     printf("\natol1    = %8.1e     atol2    = %8.1e", atol1 , atol2 );
     printf(                  "      btol    = %8.1e", btol );
     printf("\nconlim   = %8.1e     itnlim   = %8d"  , conlim, itnlim);
     printf(                  "      show    = %8g"  , show );

// LSmethod  = 3;  ////// Hardwire LSQR
// LSproblem = 1;  ////// and LS problem defining "dy".
     /*
       if wait
         printf("\n\nReview parameters... then type "return"\n")
         keyboard
       end
     */
     if (eta < 0)
          printf("\n\nLinesearch disabled by eta < 0");

     //---------------------------------------------------------------------
     // All parameters have now been set.
     //---------------------------------------------------------------------
     double time    = CoinCpuTime();
     //bool useChol = (LSmethod == 1);
     //bool useQR   = (LSmethod == 2);
     bool direct  = (LSmethod <= 2 && ifexplicit);
     char solver[6];
     strcpy(solver, "  LSQR");


     //---------------------------------------------------------------------
     // Categorize bounds and allow for fixed variables by modifying b.
     //---------------------------------------------------------------------

     int nlow, nupp, nfix;
     int *bptrs[3] = {0};
     getBoundTypes(&nlow, &nupp, &nfix, bptrs );
     int *low = bptrs[0];
     int *upp = bptrs[1];
     int *fix = bptrs[2];

     int nU = n;
     if (nupp == 0) nU = 1;  //Make dummy vectors if no Upper bounds

     //---------------------------------------------------------------------
     //  Get pointers to local copy of model bounds
     //---------------------------------------------------------------------

     CoinDenseVector<double> bl(n, columnLower_);
     double *bl_elts = bl.getElements();
     CoinDenseVector<double> bu(nU, columnUpper_);  // this is dummy if no UB
     double *bu_elts = bu.getElements();

     CoinDenseVector<double> r1(m, 0.0);
     double *r1_elts = r1.getElements();
     CoinDenseVector<double> x1(n, 0.0);
     double *x1_elts = x1.getElements();

     if (nfix > 0) {
          for (int k = 0; k < nfix; k++)
               x1_elts[fix[k]] = bl[fix[k]];
          matVecMult(1, r1, x1);
          b = b - r1;
          // At some stage, might want to look at normfix = norm(r1,inf);
     }

     //---------------------------------------------------------------------
     // Scale the input data.
     // The scaled variables are
     //    xbar     = x/beta,
     //    ybar     = y/zeta,
     //    zbar     = z/zeta.
     // Define
     //    theta    = beta*zeta;
     // The scaled function is
     //    phibar   = ( 1   /theta) fbar(beta*xbar),
     //    gradient = (beta /theta) grad,
     //    Hessian  = (beta2/theta) hess.
     //---------------------------------------------------------------------
     double beta = xsize_;
     if (beta == 0) beta = 1; // beta scales b, x.
     double zeta = zsize_;
     if (zeta == 0) zeta = 1; // zeta scales y, z.
     double theta  = beta * zeta;                          // theta scales obj.
     // (theta could be anything, but theta = beta*zeta makes
     // scaled grad = grad/zeta = 1 approximately if zeta is chosen right.)

     for (int k = 0; k < nlow; k++)
          bl_elts[low[k]] = bl_elts[low[k]] / beta;
     for (int k = 0; k < nupp; k++)
          bu_elts[upp[k]] = bu_elts[upp[k]] / beta;
     d1     = d1 * ( beta / sqrt(theta) );
     d2     = d2 * ( sqrt(theta) / beta );

     double beta2  = beta * beta;
     b.scale( (1.0 / beta) );
     y.scale( (1.0 / zeta) );
     x.scale( (1.0 / beta) );
     z.scale( (1.0 / zeta) );

     //---------------------------------------------------------------------
     // Initialize vectors that are not fully used if bounds are missing.
     //---------------------------------------------------------------------
     CoinDenseVector<double> rL(n, 0.0);
     CoinDenseVector<double> cL(n, 0.0);
     CoinDenseVector<double> z1(n, 0.0);
     CoinDenseVector<double> dx1(n, 0.0);
     CoinDenseVector<double> dz1(n, 0.0);
     CoinDenseVector<double> r2(n, 0.0);

     // Assign upper bd regions (dummy if no UBs)

     CoinDenseVector<double> rU(nU, 0.0);
     CoinDenseVector<double> cU(nU, 0.0);
     CoinDenseVector<double> x2(nU, 0.0);
     CoinDenseVector<double> z2(nU, 0.0);
     CoinDenseVector<double> dx2(nU, 0.0);
     CoinDenseVector<double> dz2(nU, 0.0);

     //---------------------------------------------------------------------
     // Initialize x, y, z, objective, etc.
     //---------------------------------------------------------------------
     CoinDenseVector<double> dx(n, 0.0);
     CoinDenseVector<double> dy(m, 0.0);
     CoinDenseVector<double> Pr(m);
     CoinDenseVector<double> D(n);
     double *D_elts = D.getElements();
     CoinDenseVector<double> w(n);
     double *w_elts = w.getElements();
     CoinDenseVector<double> rhs(m + n);


     //---------------------------------------------------------------------
     // Pull out the element array pointers for efficiency
     //---------------------------------------------------------------------
     double *x_elts  = x.getElements();
     double *x2_elts = x2.getElements();
     double *z_elts  = z.getElements();
     double *z1_elts = z1.getElements();
     double *z2_elts = z2.getElements();

     for (int k = 0; k < nlow; k++) {
          x_elts[low[k]]  = CoinMax( x_elts[low[k]], bl[low[k]]);
          x1_elts[low[k]] = CoinMax( x_elts[low[k]] - bl[low[k]], x0min  );
          z1_elts[low[k]] = CoinMax( z_elts[low[k]], z0min  );
     }
     for (int k = 0; k < nupp; k++) {
          x_elts[upp[k]]  = CoinMin( x_elts[upp[k]], bu[upp[k]]);
          x2_elts[upp[k]] = CoinMax(bu[upp[k]] -  x_elts[upp[k]], x0min  );
          z2_elts[upp[k]] = CoinMax(-z_elts[upp[k]], z0min  );
     }
     //////////////////// Assume hessian is diagonal. //////////////////////

//  [obj,grad,hess] = feval( Fname, (x*beta) );
     x.scale(beta);
     double obj = getObj(x);
     CoinDenseVector<double> grad(n);
     getGrad(x, grad);
     CoinDenseVector<double> H(n);
     getHessian(x , H);
     x.scale((1.0 / beta));

     //double * g_elts = grad.getElements();
     double * H_elts = H.getElements();

     obj /= theta;                       // Scaled obj.
     grad = grad * (beta / theta) + (d1 * d1) * x; // grad includes x regularization.
     H  = H * (beta2 / theta) + (d1 * d1)      ; // H    includes x regularization.


     /*---------------------------------------------------------------------
     // Compute primal and dual residuals:
     // r1 =  b - Aprod(x) - d2*d2*y;
     // r2 =  grad - Atprod(y) + z2 - z1;
     //  rL =  bl - x + x1;
     //  rU =  x + x2 - bu; */
     //---------------------------------------------------------------------
     //  [r1,r2,rL,rU,Pinf,Dinf] = ...
     //      pdxxxresid1( Aname,fix,low,upp, ...
     //                   b,bl,bu,d1,d2,grad,rL,rU,x,x1,x2,y,z1,z2 );
     pdxxxresid1( this, nlow, nupp, nfix, low, upp, fix,
                  b, bl_elts, bu_elts, d1, d2, grad, rL, rU, x, x1, x2, y, z1, z2,
                  r1, r2, &Pinf, &Dinf);
     //---------------------------------------------------------------------
     // Initialize mu and complementarity residuals:
     //    cL   = mu*e - X1*z1.
     //    cU   = mu*e - X2*z2.
     //
     // 25 Jan 2001: Now that b and obj are scaled (and hence x,y,z),
     //              we should be able to use mufirst = mu0 (absolute value).
     //              0.1 worked poorly on StarTest1 with x0min = z0min = 0.1.
     // 29 Jan 2001: We might as well use mu0 = x0min * z0min;
     //              so that most variables are centered after a warm start.
     // 29 Sep 2002: Use mufirst = mu0*(x0min * z0min),
     //              regarding mu0 as a scaling of the initial center.
     //---------------------------------------------------------------------
     //  double mufirst = mu0*(x0min * z0min);
     double mufirst = mu0;   // revert to absolute value
     double mulast  = 0.1 * opttol;
     mulast  = CoinMin( mulast, mufirst );
     double mu      = mufirst;
     double center,  fmerit;
     pdxxxresid2( mu, nlow, nupp, low, upp, cL, cU, x1, x2,
                  z1, z2, &center, &Cinf, &Cinf0 );
     fmerit = pdxxxmerit(nlow, nupp, low, upp, r1, r2, rL, rU, cL, cU );

     // Initialize other things.

     bool  precon   = true;
     double PDitns    = 0;
     //bool converged = false;
     double atol      = atol1;
     atol2     = CoinMax( atol2, atolmin );
     atolmin   = atol2;
     //  pdDDD2    = d2;    // Global vector for diagonal matrix D2

     //  Iteration log.

     int nf      = 0;
     int itncg   = 0;
     int nfail   = 0;

     printf("\n\nItn   mu   stepx   stepz  Pinf  Dinf");
     printf("  Cinf   Objective    nf  center");
     if (direct) {
          printf("\n");
     } else {
          printf("  atol   solver   Inexact\n");
     }

     double regx = (d1 * x).twoNorm();
     double regy = (d2 * y).twoNorm();
     //  regterm = twoNorm(d1.*x)^2  +  norm(d2.*y)^2;
     double regterm = regx * regx + regy * regy;
     double objreg  = obj  +  0.5 * regterm;
     double objtrue = objreg * theta;

     printf("\n%3g                     ", PDitns        );
     printf("%6.1f%6.1f" , log10(Pinf ), log10(Dinf));
     printf("%6.1f%15.7e", log10(Cinf0), objtrue    );
     printf("   %8.1f\n"   , center                   );
     /*
     if kminor
       printf("\n\nStart of first minor itn...\n");
       keyboard
     end
     */
     //---------------------------------------------------------------------
     // Main loop.
     //---------------------------------------------------------------------
     // Lsqr
     ClpLsqr  thisLsqr(this);
     //  while (converged) {
     while(PDitns < maxitn) {
          PDitns = PDitns + 1;

          // 31 Jan 2001: Set atol according to progress, a la Inexact Newton.
          // 07 Feb 2001: 0.1 not small enough for Satellite problem.  Try 0.01.
          // 25 Apr 2001: 0.01 seems wasteful for Star problem.
          //              Now that starting conditions are better, go back to 0.1.

          double r3norm = CoinMax(Pinf,   CoinMax(Dinf,  Cinf));
          atol   = CoinMin(atol,  r3norm * 0.1);
          atol   = CoinMax(atol,  atolmin   );
          info.r3norm = r3norm;

          //-------------------------------------------------------------------
          //  Define a damped Newton iteration for solving f = 0,
          //  keeping  x1, x2, z1, z2 > 0.  We eliminate dx1, dx2, dz1, dz2
          //  to obtain the system
          //
          //     [-H2  A"  ] [ dx ] = [ w ],   H2 = H + D1^2 + X1inv Z1 + X2inv Z2,
          //     [ A   D2^2] [ dy ] = [ r1]    w  = r2 - X1inv(cL + Z1 rL)
          //                                           + X2inv(cU + Z2 rU),
          //
          //  which is equivalent to the least-squares problem
          //
          //     min || [ D A"]dy  -  [  D w   ] ||,   D = H2^{-1/2}.         (*)
          //         || [  D2 ]       [D2inv r1] ||
          //-------------------------------------------------------------------
          for (int k = 0; k < nlow; k++)
               H_elts[low[k]]  = H_elts[low[k]] + z1[low[k]] / x1[low[k]];
          for (int k = 0; k < nupp; k++)
               H[upp[k]]  = H[upp[k]] + z2[upp[k]] / x2[upp[k]];
          w = r2;
          for (int k = 0; k < nlow; k++)
               w[low[k]]  = w[low[k]] - (cL[low[k]] + z1[low[k]] * rL[low[k]]) / x1[low[k]];
          for (int k = 0; k < nupp; k++)
               w[upp[k]]  = w[upp[k]] + (cU[upp[k]] + z2[upp[k]] * rU[upp[k]]) / x2[upp[k]];

          if (LSproblem == 1) {
               //-----------------------------------------------------------------
               //  Solve (*) for dy.
               //-----------------------------------------------------------------
               H      = 1.0 / H;  // H is now Hinv (NOTE!)
               for (int k = 0; k < nfix; k++)
                    H[fix[k]] = 0;
               for (int k = 0; k < n; k++)
                    D_elts[k] = sqrt(H_elts[k]);
               thisLsqr.borrowDiag1(D_elts);
               thisLsqr.diag2_ = d2;

               if (direct) {
                    // Omit direct option for now
               } else {// Iterative solve using LSQR.
                    //rhs     = [ D.*w; r1./d2 ];
                    for (int k = 0; k < n; k++)
                         rhs[k] = D_elts[k] * w_elts[k];
                    for (int k = 0; k < m; k++)
                         rhs[n+k] = r1_elts[k] * (1.0 / d2);
                    double damp    = 0;

                    if (precon) {   // Construct diagonal preconditioner for LSQR
                         matPrecon(d2, Pr, D);
                    }
                    /*
                    	rw(7)        = precon;
                            info.atolmin = atolmin;
                            info.r3norm  = fmerit;  // Must be the 2-norm here.

                            [ dy, istop, itncg, outfo ] = ...
                       pdxxxlsqr( nb,m,"pdxxxlsqrmat",Aname,rw,rhs,damp, ...
                                  atol,btol,conlim,itnlim,show,info );


                    	thisLsqr.input->rhs_vec = &rhs;
                    	thisLsqr.input->sol_vec = &dy;
                    	thisLsqr.input->rel_mat_err = atol;
                    	thisLsqr.do_lsqr(this);
                    	*/
                    //  New version of lsqr

                    int istop;
                    dy.clear();
                    show = false;
                    info.atolmin = atolmin;
                    info.r3norm  = fmerit;  // Must be the 2-norm here.

                    thisLsqr.do_lsqr( rhs, damp, atol, btol, conlim, itnlim,
                                      show, info, dy , &istop, &itncg, &outfo, precon, Pr);
                    if (precon)
                         dy = dy * Pr;

                    if (!precon && itncg > 999999)
                         precon = true;

                    if (istop == 3  ||  istop == 7 )  // conlim or itnlim
                         printf("\n    LSQR stopped early:  istop = //%d", istop);


                    atolold   = outfo.atolold;
                    atol      = outfo.atolnew;
                    r3ratio   = outfo.r3ratio;
               }// LSproblem 1

               //      grad      = pdxxxmat( Aname,2,m,n,dy );   // grad = A"dy
               grad.clear();
               matVecMult(2, grad, dy);
               for (int k = 0; k < nfix; k++)
                    grad[fix[k]] = 0;                            // grad is a work vector
               dx = H * (grad - w);

          } else {
               perror( "This LSproblem not yet implemented\n" );
          }
          //-------------------------------------------------------------------

          CGitns += itncg;

          //-------------------------------------------------------------------
          // dx and dy are now known.  Get dx1, dx2, dz1, dz2.
          //-------------------------------------------------------------------
          for (int k = 0; k < nlow; k++) {
               dx1[low[k]] = - rL[low[k]] + dx[low[k]];
               dz1[low[k]] =  (cL[low[k]] - z1[low[k]] * dx1[low[k]]) / x1[low[k]];
          }
          for (int k = 0; k < nupp; k++) {
               dx2[upp[k]] = - rU[upp[k]] - dx[upp[k]];
               dz2[upp[k]] =  (cU[upp[k]] - z2[upp[k]] * dx2[upp[k]]) / x2[upp[k]];
          }
          //-------------------------------------------------------------------
          // Find the maximum step.
          //--------------------------------------------------------------------
          double stepx1 = pdxxxstep(nlow, low, x1, dx1 );
          double stepx2 = inf;
          if (nupp > 0)
               stepx2 = pdxxxstep(nupp, upp, x2, dx2 );
          double stepz1 = pdxxxstep( z1     , dz1      );
          double stepz2 = inf;
          if (nupp > 0)
               stepz2 = pdxxxstep( z2     , dz2      );
          double stepx  = CoinMin( stepx1, stepx2 );
          double stepz  = CoinMin( stepz1, stepz2 );
          stepx  = CoinMin( steptol * stepx, 1.0 );
          stepz  = CoinMin( steptol * stepz, 1.0 );
          if (stepSame) {                  // For NLPs, force same step
               stepx = CoinMin( stepx, stepz );   // (true Newton method)
               stepz = stepx;
          }

          //-------------------------------------------------------------------
          // Backtracking linesearch.
          //-------------------------------------------------------------------
          bool fail     =  true;
          nf       =  0;

          while (nf < maxf) {
               nf      = nf + 1;
               x       = x        +  stepx * dx;
               y       = y        +  stepz * dy;
               for (int k = 0; k < nlow; k++) {
                    x1[low[k]] = x1[low[k]]  +  stepx * dx1[low[k]];
                    z1[low[k]] = z1[low[k]]  +  stepz * dz1[low[k]];
               }
               for (int k = 0; k < nupp; k++) {
                    x2[upp[k]] = x2[upp[k]]  +  stepx * dx2[upp[k]];
                    z2[upp[k]] = z2[upp[k]]  +  stepz * dz2[upp[k]];
               }
               //      [obj,grad,hess] = feval( Fname, (x*beta) );
               x.scale(beta);
               obj = getObj(x);
               getGrad(x, grad);
               getHessian(x, H);
               x.scale((1.0 / beta));

               obj        /= theta;
               grad       = grad * (beta / theta)  +  d1 * d1 * x;
               H          = H * (beta2 / theta)  +  d1 * d1;

               //      [r1,r2,rL,rU,Pinf,Dinf] = ...
               pdxxxresid1( this, nlow, nupp, nfix, low, upp, fix,
                            b, bl_elts, bu_elts, d1, d2, grad, rL, rU, x, x1, x2,
                            y, z1, z2, r1, r2, &Pinf, &Dinf );
               //double center, Cinf, Cinf0;
               //      [cL,cU,center,Cinf,Cinf0] = ...
               pdxxxresid2( mu, nlow, nupp, low, upp, cL, cU, x1, x2, z1, z2,
                            &center, &Cinf, &Cinf0);
               double fmeritnew = pdxxxmerit(nlow, nupp, low, upp, r1, r2, rL, rU, cL, cU );
               double step      = CoinMin( stepx, stepz );

               if (fmeritnew <= (1 - eta * step)*fmerit) {
                    fail = false;
                    break;
               }

               // Merit function didn"t decrease.
               // Restore variables to previous values.
               // (This introduces a little error, but save lots of space.)

               x       = x        -  stepx * dx;
               y       = y        -  stepz * dy;
               for (int k = 0; k < nlow; k++) {
                    x1[low[k]] = x1[low[k]]  -  stepx * dx1[low[k]];
                    z1[low[k]] = z1[low[k]]  -  stepz * dz1[low[k]];
               }
               for (int k = 0; k < nupp; k++) {
                    x2[upp[k]] = x2[upp[k]]  -  stepx * dx2[upp[k]];
                    z2[upp[k]] = z2[upp[k]]  -  stepz * dz2[upp[k]];
               }
               // Back-track.
               // If it"s the first time,
               // make stepx and stepz the same.

               if (nf == 1 && stepx != stepz) {
                    stepx = step;
               } else if (nf < maxf) {
                    stepx = stepx / 2;
               }
               stepz = stepx;
          }

          if (fail) {
               printf("\n     Linesearch failed (nf too big)");
               nfail += 1;
          } else {
               nfail = 0;
          }

          //-------------------------------------------------------------------
          // Set convergence measures.
          //--------------------------------------------------------------------
          regx = (d1 * x).twoNorm();
          regy = (d2 * y).twoNorm();
          regterm = regx * regx + regy * regy;
          objreg  = obj  +  0.5 * regterm;
          objtrue = objreg * theta;

          bool primalfeas    = Pinf  <=  featol;
          bool dualfeas      = Dinf  <=  featol;
          bool complementary = Cinf0 <=  opttol;
          bool enough        = PDitns >=       4; // Prevent premature termination.
          bool converged     = primalfeas  &  dualfeas  &  complementary  &  enough;

          //-------------------------------------------------------------------
          // Iteration log.
          //-------------------------------------------------------------------
          char str1[100], str2[100], str3[100], str4[100], str5[100];
          sprintf(str1, "\n%3g%5.1f" , PDitns      , log10(mu)   );
          sprintf(str2, "%8.5f%8.5f" , stepx       , stepz       );
          if (stepx < 0.0001 || stepz < 0.0001) {
               sprintf(str2, " %6.1e %6.1e" , stepx       , stepz       );
          }

          sprintf(str3, "%6.1f%6.1f" , log10(Pinf) , log10(Dinf));
          sprintf(str4, "%6.1f%15.7e", log10(Cinf0), objtrue     );
          sprintf(str5, "%3d%8.1f"   , nf          , center      );
          if (center > 99999) {
               sprintf(str5, "%3d%8.1e"   , nf          , center      );
          }
          printf("%s%s%s%s%s", str1, str2, str3, str4, str5);
          if (direct) {
               // relax
          } else {
               printf(" %5.1f%7d%7.3f", log10(atolold), itncg, r3ratio);
          }
          //-------------------------------------------------------------------
          // Test for termination.
          //-------------------------------------------------------------------
          if (kminor) {
               printf( "\nStart of next minor itn...\n");
               //      keyboard;
          }

          if (converged) {
               printf("\n   Converged");
               break;
          } else if (PDitns >= maxitn) {
               printf("\n   Too many iterations");
               inform = 1;
               break;
          } else if (nfail  >= maxfail) {
               printf("\n   Too many linesearch failures");
               inform = 2;
               break;
          } else {

               // Reduce mu, and reset certain residuals.

               double stepmu  = CoinMin( stepx , stepz   );
               stepmu  = CoinMin( stepmu, steptol );
               double muold   = mu;
               mu      = mu   -  stepmu * mu;
               if (center >= bigcenter)
                    mu = muold;

               // mutrad = mu0*(sum(Xz)/n); // 24 May 1998: Traditional value, but
               // mu     = CoinMin(mu,mutrad ); // it seemed to decrease mu too much.

               mu      = CoinMax(mu, mulast); // 13 Jun 1998: No need for smaller mu.
               //      [cL,cU,center,Cinf,Cinf0] = ...
               pdxxxresid2( mu, nlow, nupp, low, upp, cL, cU, x1, x2, z1, z2,
                            &center, &Cinf, &Cinf0 );
               fmerit = pdxxxmerit( nlow, nupp, low, upp, r1, r2, rL, rU, cL, cU );

               // Reduce atol for LSQR (and SYMMLQ).
               // NOW DONE AT TOP OF LOOP.

               atolold = atol;
               // if atol > atol2
               //   atolfac = (mu/mufirst)^0.25;
               //   atol    = CoinMax( atol*atolfac, atol2 );
               // end

               // atol = CoinMin( atol, mu );     // 22 Jan 2001: a la Inexact Newton.
               // atol = CoinMin( atol, 0.5*mu ); // 30 Jan 2001: A bit tighter

               // If the linesearch took more than one function (nf > 1),
               // we assume the search direction needed more accuracy
               // (though this may be true only for LPs).
               // 12 Jun 1998: Ask for more accuracy if nf > 2.
               // 24 Nov 2000: Also if the steps are small.
               // 30 Jan 2001: Small steps might be ok with warm start.
               // 06 Feb 2001: Not necessarily.  Reinstated tests in next line.

               if (nf > 2  ||  CoinMin( stepx, stepz ) <= 0.01)
                    atol = atolold * 0.1;
          }
          //---------------------------------------------------------------------
          // End of main loop.
          //---------------------------------------------------------------------
     }


     for (int k = 0; k < nfix; k++)
          x[fix[k]] = bl[fix[k]];
     z      = z1;
     if (nupp > 0)
          z = z - z2;
     printf("\n\nmax |x| =%10.3f", x.infNorm() );
     printf("    max |y| =%10.3f", y.infNorm() );
     printf("    max |z| =%10.3f", z.infNorm() );
     printf("   scaled");

     x.scale(beta);
     y.scale(zeta);
     z.scale(zeta);   // Unscale x, y, z.

     printf(  "\nmax |x| =%10.3f", x.infNorm() );
     printf("    max |y| =%10.3f", y.infNorm() );
     printf("    max |z| =%10.3f", z.infNorm() );
     printf(" unscaled\n");

     time   = CoinCpuTime() - time;
     char str1[100], str2[100];
     sprintf(str1, "\nPDitns  =%10g", PDitns );
     sprintf(str2, "itns =%10d", CGitns );
     //  printf( [str1 " " solver str2] );
     printf("    time    =%10.1f\n", time);
     /*
     pdxxxdistrib( abs(x),abs(z) );   // Private function

     if (wait)
       keyboard;
     */
//-----------------------------------------------------------------------
// End function pdco.m
//-----------------------------------------------------------------------
     /*  printf("Solution x values:\n\n");
       for (int k=0; k<n; k++)
         printf(" %d   %e\n", k, x[k]);
     */
// Print distribution
     double thresh[9] = { 0.00000001, 0.0000001, 0.000001, 0.00001, 0.0001, 0.001, 0.01, 0.1, 1.00001};
     int counts[9] = {0};
     for (int ij = 0; ij < n; ij++) {
          for (int j = 0; j < 9; j++) {
               if(x[ij] < thresh[j]) {
                    counts[j] += 1;
                    break;
               }
          }
     }
     printf ("Distribution of Solution Values\n");
     for (int j = 8; j > 1; j--)
          printf(" %g  to  %g %d\n", thresh[j-1], thresh[j], counts[j]);
     printf("   Less than   %g %d\n", thresh[2], counts[0]);

     return inform;
}
Exemplo n.º 6
0
/** solve */
STO_RTN_CODE TssBd::solve()
{
#define FREE_MEMORY    \
	FREE_PTR(tssbdsub)

	assert(model_);

	/** subproblems */
	const double * probability = NULL; /**< probability */
	TssBdSub *     tssbdsub    = NULL; /**< cut generator */
	double lowerbound = 0.0;

	BGN_TRY_CATCH

	/** solution time */
	double swtime = CoinGetTimeOfDay();

	/** time limit */
	time_remains_ = par_->wtimeLimit_;

	/** get number of scenarios */
	probability = model_->getProbability();

	/** configure Benders cut generator */
	/** This does NOT make deep copies. So, DO NOT RELEASE POINTERS. */
	tssbdsub = new TssBdSub(par_);
	for (int s = 0; s < model_->getNumScenarios(); ++s)
		tssbdsub->scenarios_.push_back(s);
	STO_RTN_CHECK_THROW(tssbdsub->loadProblem(model_, naugs_, augs_, naux_), "loadProblem", "TssBdSub");

	if (par_->logLevel_ > 0) printf("Phase 1:\n");

	/** solution time */
	double stime = clockType_ ? CoinGetTimeOfDay() : CoinCpuTime();

	/** find lower bound */
	/** TODO: replace this with TssDd */
	STO_RTN_CHECK_THROW(findLowerBound(probability, lowerbound), "findLowerBound", "TssBd");

	/** We should have a lower bound here. */
	if (par_->logLevel_ > 0) printf(" -> Found lower bound %e\n", lowerbound);

	/** construct master problem */
	STO_RTN_CHECK_THROW(constructMasterProblem(tssbdsub, lowerbound), "constructMasterProblem", "TssBd");

	if (par_->logLevel_ > 0) printf("Phase 2:\n");

	time_remains_ -= CoinGetTimeOfDay() - swtime;

	/** use L-shaped method to find lower bound */
	if (model_->getNumCoreIntegers() == 0)
	{
		/** configure LP */
		STO_RTN_CHECK_THROW(configureSLP(), "configureSLP", "TssBd");

		/** solve LP */
		STO_RTN_CHECK_THROW(solveSLP(tssbdsub), "solveSLP", "TssBd");
	}
	else
	{
		/** configure MILP */
		STO_RTN_CHECK_THROW(configureSMILP(tssbdsub), "configureSMILP", "TssBd");

		/** solve MILP */
		STO_RTN_CHECK_THROW(solveSMILP(), "solveSMILP", "TssBd");
	}

	/** solution time */
	solutionTime_ = (clockType_ ? CoinGetTimeOfDay() : CoinCpuTime()) - stime;

	/** collect solution */
	switch (status_)
	{
	case STO_STAT_OPTIMAL:
	case STO_STAT_LIM_ITERorTIME:
	case STO_STAT_STOPPED_GAP:
	case STO_STAT_STOPPED_NODE:
	case STO_STAT_STOPPED_TIME:
		{
			const double * solution = si_->getSolution();
			if (solution)
			{
				/** first-stage solution */
				assert(solution_);
				CoinCopyN(solution, model_->getNumCols(0), solution_);

				/** second-stage solution */
				double * objval_reco = new double [model_->getNumScenarios()];
				double ** solution_reco = new double * [model_->getNumScenarios()];
				for (int s = 0; s < model_->getNumScenarios(); ++s)
					solution_reco[s] = new double [model_->getNumCols(1)];

				for (int s = 0; s < naugs_; ++s)
					CoinCopyN(solution + model_->getNumCols(0) + s * model_->getNumCols(1),
							model_->getNumCols(1), solution_reco[augs_[s]]);

				/** collect solution */
				tssbdsub->solveRecourse(solution_, objval_reco, solution_reco, par_->numCores_);
				for (int s = 0; s < model_->getNumScenarios(); ++s)
				{
					if (tssbdsub->excludedScenarios_[s]) continue;
					CoinCopyN(solution_reco[s], model_->getNumCols(1),
							solution_ + model_->getNumCols(0) + model_->getNumCols(1) * s);

				}

				/** compute primal bound */
				primalBound_ = 0.0;
				for (int j = 0; j < model_->getNumCols(0); ++j)
					primalBound_ += model_->getObjCore(0)[j] * solution_[j];
				for (int s = 0; s < model_->getNumScenarios(); ++s)
				{
					primalBound_ += objval_reco[s] * model_->getProbability()[s];
				}
				//printf("primalBound %e\n", primalBound_);

				/** free memory */
				FREE_ARRAY_PTR(objval_reco);
				FREE_2D_ARRAY_PTR(model_->getNumScenarios(), solution_reco);
			}
			break;
		}
		break;
	default:
		printf("Solution status (%d).\n", status_);
		break;
	}

	END_TRY_CATCH_RTN(FREE_MEMORY,STO_RTN_ERR)

	/** free memory */
	FREE_MEMORY

	return STO_RTN_OK;

#undef FREE_MEMORY
}
Exemplo n.º 7
0
int main (int argc, const char *argv[])
{
     ClpSimplex  model;
     int status;
     int maxFactor = 100;
     if (argc < 2) {
          status = model.readMps("../../Data/Netlib/czprob.mps");
          if (status) {
               printf("Unable to read matrix - trying gzipped version\n");
               status = model.readMps("../../Data/Netlib/czprob.mps.gz");
          }
     } else {
          status = model.readMps(argv[1]);
     }
     if (status) {
          printf("errors on input\n");
          exit(77);
     }
     if (argc > 2) {
          maxFactor = atoi(argv[2]);
          printf("max factor %d\n", maxFactor);
     }
     if (argc > 3) {
          printf("Using ClpDynamicMatrix\n");
     } else {
          printf("Using ClpDynamicExampleMatrix\n");
     }
     // find gub
     int numberRows = model.numberRows();
     int * gubStart = new int[numberRows+1];
     int * gubEnd = new int[numberRows];
     int * which = new int[numberRows];
     int * whichGub = new int[numberRows];
     int numberColumns = model.numberColumns();
     int * mark = new int[numberColumns];
     int iRow, iColumn;
     // delete variables fixed to zero
     const double * columnLower = model.columnLower();
     const double * columnUpper = model.columnUpper();
     int numberDelete = 0;
     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
          if (columnUpper[iColumn] == 0.0 && columnLower[iColumn] == 0.0)
               mark[numberDelete++] = iColumn;
     }
     if (numberDelete) {
          model.deleteColumns(numberDelete, mark);
          numberColumns -= numberDelete;
          columnLower = model.columnLower();
          columnUpper = model.columnUpper();
     }
     double * lower = new double[numberRows];
     double * upper = new double[numberRows];
     const double * rowLower = model.rowLower();
     const double * rowUpper = model.rowUpper();
     for (iColumn = 0; iColumn < numberColumns; iColumn++)
          mark[iColumn] = -1;
     CoinPackedMatrix * matrix = model.matrix();
     // get row copy
     CoinPackedMatrix rowCopy = *matrix;
     rowCopy.reverseOrdering();
     const int * column = rowCopy.getIndices();
     const int * rowLength = rowCopy.getVectorLengths();
     const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
     const double * element = rowCopy.getElements();
     int putGub = numberRows;
     int putNonGub = numberRows;
     int * rowIsGub = new int [numberRows];
     for (iRow = numberRows - 1; iRow >= 0; iRow--) {
          bool gubRow = true;
          int first = numberColumns + 1;
          int last = -1;
          for (int j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
               if (element[j] != 1.0) {
                    gubRow = false;
                    break;
               } else {
                    int iColumn = column[j];
                    if (mark[iColumn] >= 0) {
                         gubRow = false;
                         break;
                    } else {
                         last = CoinMax(last, iColumn);
                         first = CoinMin(first, iColumn);
                    }
               }
          }
          if (last - first + 1 != rowLength[iRow] || !gubRow) {
               which[--putNonGub] = iRow;
               rowIsGub[iRow] = 0;
          } else {
               for (int j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
                    int iColumn = column[j];
                    mark[iColumn] = iRow;
               }
               rowIsGub[iRow] = -1;
               putGub--;
               gubStart[putGub] = first;
               gubEnd[putGub] = last + 1;
               lower[putGub] = rowLower[iRow];
               upper[putGub] = rowUpper[iRow];
               whichGub[putGub] = iRow;
          }
     }
     int numberNonGub = numberRows - putNonGub;
     int numberGub = numberRows - putGub;
     if (numberGub > 0) {
          printf("** %d gub rows\n", numberGub);
          int numberNormal = 0;
          const int * row = matrix->getIndices();
          const int * columnLength = matrix->getVectorLengths();
          const CoinBigIndex * columnStart = matrix->getVectorStarts();
          const double * elementByColumn = matrix->getElements();
          int numberElements = 0;
          bool doLower = false;
          bool doUpper = false;
          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
               if (mark[iColumn] < 0) {
                    mark[numberNormal++] = iColumn;
               } else {
                    numberElements += columnLength[iColumn];
                    if (columnLower[iColumn] != 0.0)
                         doLower = true;
                    if (columnUpper[iColumn] < 1.0e20)
                         doUpper = true;
               }
          }
          if (!numberNormal) {
               printf("Putting back one gub row to make non-empty\n");
               for (iColumn = gubStart[putGub]; iColumn < gubEnd[putGub]; iColumn++)
                    mark[numberNormal++] = iColumn;
               putGub++;
               numberGub--;
          }
          ClpSimplex model2(&model, numberNonGub, which + putNonGub, numberNormal, mark);
          // and copy for restart test
          ClpSimplex model3 = model2;
          int numberGubColumns = numberColumns - numberNormal;
          // sort gubs so monotonic
          int * which = new int[numberGub];
          int i;
          for (i = 0; i < numberGub; i++)
               which[i] = i;
          CoinSort_2(gubStart + putGub, gubStart + putGub + numberGub, which);
          // move to bottom if we want to use later
          memmove(gubStart, gubStart + putGub, numberGub * sizeof(int));
          int * temp1 = new int [numberGub];
          for (i = 0; i < numberGub; i++) {
               int k = which[i];
               temp1[i] = gubEnd[putGub+k];
          }
          memcpy(gubEnd, temp1, numberGub * sizeof(int));
          delete [] temp1;
          double * temp2 = new double [numberGub];
          for (i = 0; i < numberGub; i++) {
               int k = which[i];
               temp2[i] = lower[putGub+k];
          }
          memcpy(lower, temp2, numberGub * sizeof(double));
          for (i = 0; i < numberGub; i++) {
               int k = which[i];
               temp2[i] = upper[putGub+k];
          }
          memcpy(upper, temp2, numberGub * sizeof(double));
          delete [] temp2;
          delete [] which;
          numberElements -= numberGubColumns;
          int * start2 = new int[numberGubColumns+1];
          int * row2 = new int[numberElements];
          double * element2 = new double[numberElements];
          double * cost2 = new double [numberGubColumns];
          double * lowerColumn2 = NULL;
          if (doLower) {
               lowerColumn2 = new double [numberGubColumns];
               CoinFillN(lowerColumn2, numberGubColumns, 0.0);
          }
          double * upperColumn2 = NULL;
          if (doUpper) {
               upperColumn2 = new double [numberGubColumns];
               CoinFillN(upperColumn2, numberGubColumns, COIN_DBL_MAX);
          }
          numberElements = 0;
          int numberNonGubRows = 0;
          for (iRow = 0; iRow < numberRows; iRow++) {
               if (!rowIsGub[iRow])
                    rowIsGub[iRow] = numberNonGubRows++;
          }
          numberColumns = 0;
          int iStart = gubStart[0];
          gubStart[0] = 0;
          start2[0] = 0;
          const double * cost = model.objective();
          for (int iSet = 0; iSet < numberGub; iSet++) {
               int iEnd = gubEnd[iSet];
               for (int k = iStart; k < iEnd; k++) {
                    cost2[numberColumns] = cost[k];
                    if (columnLower[k])
                         lowerColumn2[numberColumns] = columnLower[k];
                    if (columnUpper[k] < 1.0e20)
                         upperColumn2[numberColumns] = columnUpper[k];
                    for (int j = columnStart[k]; j < columnStart[k] + columnLength[k]; j++) {
                         int iRow = rowIsGub[row[j]];
                         if (iRow >= 0) {
                              row2[numberElements] = iRow;
                              element2[numberElements++] = elementByColumn[j];
                         }
                    }
                    start2[++numberColumns] = numberElements;
               }
               if (iSet < numberGub - 1)
                    iStart = gubStart[iSet+1];
               gubStart[iSet+1] = numberColumns;
          }
          printf("** Before adding matrix there are %d rows and %d columns\n",
                 model2.numberRows(), model2.numberColumns());
          if (argc > 3) {
               ClpDynamicMatrix * newMatrix = new ClpDynamicMatrix(&model2, numberGub,
                         numberColumns, gubStart,
                         lower, upper,
                         start2, row2, element2, cost2,
                         lowerColumn2, upperColumn2);
               model2.replaceMatrix(newMatrix);
               newMatrix->switchOffCheck();
               newMatrix->setRefreshFrequency(1000);
          } else {
               ClpDynamicExampleMatrix * newMatrix = new ClpDynamicExampleMatrix(&model2, numberGub,
                         numberColumns, gubStart,
                         lower, upper,
                         start2, row2, element2, cost2,
                         lowerColumn2, upperColumn2);
               model2.replaceMatrix(newMatrix);
               newMatrix->switchOffCheck();
               newMatrix->setRefreshFrequency(1000);
          }
          printf("** While after adding matrix there are %d rows and %d columns\n",
                 model2.numberRows(), model2.numberColumns());
          model2.setSpecialOptions(4); // exactly to bound
          // For now scaling off
          model2.scaling(0);
          ClpPrimalColumnSteepest steepest(5);
          model2.setPrimalColumnPivotAlgorithm(steepest);
          //model2.messageHandler()->setLogLevel(63);
          model2.setFactorizationFrequency(maxFactor);
          model2.setMaximumIterations(4000000);
          double time1 = CoinCpuTime();
          model2.primal();
          // can't use values pass
          model2.primal(0);
          // test proper restart
          if (argc > 3) {
               ClpDynamicMatrix * oldMatrix =
                    dynamic_cast< ClpDynamicMatrix*>(model2.clpMatrix());
               assert (oldMatrix);
               ClpDynamicMatrix * newMatrix = new
               ClpDynamicMatrix(&model3, numberGub,
                                numberColumns, gubStart,
                                lower, upper,
                                start2, row2, element2, cost2,
                                lowerColumn2, upperColumn2,
                                oldMatrix->gubRowStatus(), oldMatrix->dynamicStatus());
               model3.replaceMatrix(newMatrix);
               // and ordinary status (but only NON gub rows)
               memcpy(model3.statusArray(), model2.statusArray(),
                      (newMatrix->numberStaticRows() + model3.numberColumns())*sizeof(unsigned char));
               newMatrix->switchOffCheck();
               newMatrix->setRefreshFrequency(1000);
          } else {
               ClpDynamicExampleMatrix * oldMatrix =
                    dynamic_cast< ClpDynamicExampleMatrix*>(model2.clpMatrix());
               assert (oldMatrix);
               ClpDynamicExampleMatrix * newMatrix = new
               ClpDynamicExampleMatrix(&model3, numberGub,
                                       numberColumns, gubStart,
                                       lower, upper,
                                       start2, row2, element2, cost2,
                                       lowerColumn2, upperColumn2,
                                       oldMatrix->gubRowStatus(), oldMatrix->dynamicStatus(),
                                       oldMatrix->numberGubColumns(), oldMatrix->idGen());
               model3.replaceMatrix(newMatrix);
               // and ordinary status (but only NON gub rows)
               memcpy(model3.statusArray(), model2.statusArray(),
                      (newMatrix->numberStaticRows() + model3.numberColumns())*sizeof(unsigned char));
               newMatrix->switchOffCheck();
               newMatrix->setRefreshFrequency(1000);
          }
          model3.setSpecialOptions(4); // exactly to bound
          // For now scaling off
          model3.scaling(0);
          model3.setPrimalColumnPivotAlgorithm(steepest);
          model3.messageHandler()->setLogLevel(63);
          model3.setFactorizationFrequency(maxFactor);
          model3.setMaximumIterations(4000000);
          delete [] rowIsGub;
          delete [] start2;
          delete [] row2;
          delete [] element2;
          delete [] cost2;
          delete [] lowerColumn2;
          delete [] upperColumn2;
          model3.primal();
          // this code expects non gub first in original matrix
          // and only works at present for ClpDynamicMatrix
          ClpDynamicMatrix * gubMatrix =
               dynamic_cast< ClpDynamicMatrix*>(model2.clpMatrix());
          assert (gubMatrix);
          ClpDynamicExampleMatrix * gubMatrix2 =
               dynamic_cast< ClpDynamicExampleMatrix*>(model2.clpMatrix());
          if (!gubMatrix2) {
               const double * solution = model2.primalColumnSolution();
               const double * cost = model.objective();
               int numberGubColumns = gubMatrix->numberGubColumns();
               int firstOdd = gubMatrix->firstDynamic();
               int lastOdd = gubMatrix->firstAvailable();
               int numberTotalColumns = firstOdd + numberGubColumns;
               int originalNumberRows = model.numberRows();
               int numberStaticRows = gubMatrix->numberStaticRows();
               char * status = new char [numberTotalColumns];
               double * gubSolution = new double [numberTotalColumns];
               int numberSets = gubMatrix->numberSets();
               const int * id = gubMatrix->id();
               int i;
               const float * columnLower = gubMatrix->columnLower();
               const float * columnUpper = gubMatrix->columnUpper();
               for (i = 0; i < numberGubColumns; i++) {
                    if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::atUpperBound) {
                         gubSolution[i+firstOdd] = columnUpper[i];
                         status[i+firstOdd] = 2;
                    } else if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::atLowerBound && columnLower) {
                         gubSolution[i+firstOdd] = columnLower[i];
                         status[i+firstOdd] = 1;
                    } else if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::soloKey) {
                         int iSet = gubMatrix->whichSet(i);
                         gubSolution[i+firstOdd] = gubMatrix->keyValue(iSet);
                         status[i+firstOdd] = 0;
                    } else {
                         gubSolution[i+firstOdd] = 0.0;
                         status[i+firstOdd] = 1;
                    }
               }
               for (i = 0; i < firstOdd; i++) {
                    ClpSimplex::Status thisStatus = model2.getStatus(i);
                    if (thisStatus == ClpSimplex::basic)
                         status[i] = 0;
                    else if (thisStatus == ClpSimplex::atLowerBound)
                         status[i] = 1;
                    else if (thisStatus == ClpSimplex::atUpperBound)
                         status[i] = 2;
                    else if (thisStatus == ClpSimplex::isFixed)
                         status[i] = 3;
                    else
                         abort();
                    gubSolution[i] = solution[i];
               }
               for (i = firstOdd; i < lastOdd; i++) {
                    int iBig = id[i-firstOdd] + firstOdd;
                    ClpSimplex::Status thisStatus = model2.getStatus(i);
                    if (thisStatus == ClpSimplex::basic)
                         status[iBig] = 0;
                    else if (thisStatus == ClpSimplex::atLowerBound)
                         status[iBig] = 1;
                    else if (thisStatus == ClpSimplex::atUpperBound)
                         status[iBig] = 2;
                    else if (thisStatus == ClpSimplex::isFixed)
                         status[iBig] = 3;
                    else
                         abort();
                    gubSolution[iBig] = solution[i];
               }
               char * rowStatus = new char[originalNumberRows];
               for (i = 0; i < numberStaticRows; i++) {
                    ClpSimplex::Status thisStatus = model2.getRowStatus(i);
                    if (thisStatus == ClpSimplex::basic)
                         rowStatus[i] = 0;
                    else if (thisStatus == ClpSimplex::atLowerBound)
                         rowStatus[i] = 1;
                    else if (thisStatus == ClpSimplex::atUpperBound)
                         rowStatus[i] = 2;
                    else if (thisStatus == ClpSimplex::isFixed)
                         rowStatus[i] = 3;
                    else
                         abort();
               }
               double objValue = 0.0;
               for (i = 0; i < numberTotalColumns; i++)
                    objValue += cost[i] * gubSolution[i];
               printf("objective value is %g\n", objValue);
               for (i = 0; i < numberSets; i++) {
                    ClpSimplex::Status thisStatus = gubMatrix->getStatus(i);
                    if (thisStatus == ClpSimplex::basic)
                         rowStatus[numberStaticRows+i] = 0;
                    else if (thisStatus == ClpSimplex::atLowerBound)
                         rowStatus[numberStaticRows+i] = 1;
                    else if (thisStatus == ClpSimplex::atUpperBound)
                         rowStatus[numberStaticRows+i] = 2;
                    else if (thisStatus == ClpSimplex::isFixed)
                         rowStatus[numberStaticRows+i] = 3;
                    else
                         abort();
               }
               // Coding below may not work if gub rows not at end
               FILE * fp = fopen ("xx.sol", "w");
               fwrite(gubSolution, sizeof(double), numberTotalColumns, fp);
               fwrite(status, sizeof(char), numberTotalColumns, fp);
               const double * rowsol = model2.primalRowSolution();
               double * rowsol2 = new double[originalNumberRows];
               memset(rowsol2, 0, originalNumberRows * sizeof(double));
               model.times(1.0, gubSolution, rowsol2);
               for (i = 0; i < numberStaticRows; i++)
                    assert (fabs(rowsol[i] - rowsol2[i]) < 1.0e-3);
               for (; i < originalNumberRows; i++)
                    assert (rowsol2[i] > lower[i-numberStaticRows] - 1.0e-3 &&
                            rowsol2[i] < upper[i-numberStaticRows] + 1.0e-3);
               //for (;i<originalNumberRows;i++)
               //printf("%d %g\n",i,rowsol2[i]);
               fwrite(rowsol2, sizeof(double), originalNumberRows, fp);
               delete [] rowsol2;
               fwrite(rowStatus, sizeof(char), originalNumberRows, fp);
               fclose(fp);
               delete [] status;
               delete [] gubSolution;
               // ** if going to rstart as dynamic need id_
               // also copy coding in useEf.. from ClpGubMatrix (i.e. test for basis)
          }
          printf("obj offset is %g\n", model2.objectiveOffset());
          printf("Primal took %g seconds\n", CoinCpuTime() - time1);
     }
     delete [] mark;
     delete [] gubStart;
     delete [] gubEnd;
     delete [] which;
     delete [] whichGub;
     delete [] lower;
     delete [] upper;
     return 0;
}
Exemplo n.º 8
0
int main(int argc, const char *argv[])
{
     try {
          // Empty model
          ClpSimplex  model;

          // Objective - just nonzeros
          int objIndex[] = {0, 2};
          double objValue[] = {1.0, 4.0};
          // Upper bounds - as dense vector
          double upper[] = {2.0, COIN_DBL_MAX, 4.0};

          // Create space for 3 columns
          model.resize(0, 3);
          // Fill in
          int i;
          // Virtuous way
          // First objective
          for (i = 0; i < 2; i++)
               model.setObjectiveCoefficient(objIndex[i], objValue[i]);
          // Now bounds (lower will be zero by default but do again)
          for (i = 0; i < 3; i++) {
               model.setColumnLower(i, 0.0);
               model.setColumnUpper(i, upper[i]);
          }
          /*
            We could also have done in non-virtuous way e.g.
            double * objective = model.objective();
            and then set directly
          */
          // Faster to add rows all at once - but this is easier to show
          // Now add row 1 as >= 2.0
          int row1Index[] = {0, 2};
          double row1Value[] = {1.0, 1.0};
          model.addRow(2, row1Index, row1Value,
                       2.0, COIN_DBL_MAX);
          // Now add row 2 as == 1.0
          int row2Index[] = {0, 1, 2};
          double row2Value[] = {1.0, -5.0, 1.0};
          model.addRow(3, row2Index, row2Value,
                       1.0, 1.0);
          // solve
          model.dual();

          /*
            Adding one row at a time has a significant overhead so let's
            try a more complicated but faster way

            First time adding in 10000 rows one by one
          */
          model.allSlackBasis();
          ClpSimplex modelSave = model;
          double time1 = CoinCpuTime();
          int k;
          for (k = 0; k < 10000; k++) {
               int row2Index[] = {0, 1, 2};
               double row2Value[] = {1.0, -5.0, 1.0};
               model.addRow(3, row2Index, row2Value,
                            1.0, 1.0);
          }
          printf("Time for 10000 addRow is %g\n", CoinCpuTime() - time1);
          model.dual();
          model = modelSave;
          // Now use build
          CoinBuild buildObject;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int row2Index[] = {0, 1, 2};
               double row2Value[] = {1.0, -5.0, 1.0};
               buildObject.addRow(3, row2Index, row2Value,
                                  1.0, 1.0);
          }
          model.addRows(buildObject);
          printf("Time for 10000 addRow using CoinBuild is %g\n", CoinCpuTime() - time1);
          model.dual();
          model = modelSave;
          int del[] = {0, 1, 2};
          model.deleteRows(2, del);
          // Now use build +-1
          CoinBuild buildObject2;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int row2Index[] = {0, 1, 2};
               double row2Value[] = {1.0, -1.0, 1.0};
               buildObject2.addRow(3, row2Index, row2Value,
                                   1.0, 1.0);
          }
          model.addRows(buildObject2, true);
          printf("Time for 10000 addRow using CoinBuild+-1 is %g\n", CoinCpuTime() - time1);
          model.dual();
          model = modelSave;
          model.deleteRows(2, del);
          // Now use build +-1
          CoinModel modelObject2;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int row2Index[] = {0, 1, 2};
               double row2Value[] = {1.0, -1.0, 1.0};
               modelObject2.addRow(3, row2Index, row2Value,
                                   1.0, 1.0);
          }
          model.addRows(modelObject2, true);
          printf("Time for 10000 addRow using CoinModel+-1 is %g\n", CoinCpuTime() - time1);
          model.dual();
          model = ClpSimplex();
          // Now use build +-1
          CoinModel modelObject3;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int row2Index[] = {0, 1, 2};
               double row2Value[] = {1.0, -1.0, 1.0};
               modelObject3.addRow(3, row2Index, row2Value,
                                   1.0, 1.0);
          }
          model.loadProblem(modelObject3, true);
          printf("Time for 10000 addRow using CoinModel load +-1 is %g\n", CoinCpuTime() - time1);
          model.writeMps("xx.mps");
          model.dual();
          model = modelSave;
          // Now use model
          CoinModel modelObject;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int row2Index[] = {0, 1, 2};
               double row2Value[] = {1.0, -5.0, 1.0};
               modelObject.addRow(3, row2Index, row2Value,
                                  1.0, 1.0);
          }
          model.addRows(modelObject);
          printf("Time for 10000 addRow using CoinModel is %g\n", CoinCpuTime() - time1);
          model.dual();
          model.writeMps("b.mps");
          // Method using least memory - but most complicated
          time1 = CoinCpuTime();
          // Assumes we know exact size of model and matrix
          // Empty model
          ClpSimplex  model2;
          {
               // Create space for 3 columns and 10000 rows
               int numberRows = 10000;
               int numberColumns = 3;
               // This is fully dense - but would not normally be so
               int numberElements = numberRows * numberColumns;
               // Arrays will be set to default values
               model2.resize(numberRows, numberColumns);
               double * elements = new double [numberElements];
               CoinBigIndex * starts = new CoinBigIndex [numberColumns+1];
               int * rows = new int [numberElements];;
               int * lengths = new int[numberColumns];
               // Now fill in - totally unsafe but ....
               // no need as defaults to 0.0 double * columnLower = model2.columnLower();
               double * columnUpper = model2.columnUpper();
               double * objective = model2.objective();
               double * rowLower = model2.rowLower();
               double * rowUpper = model2.rowUpper();
               // Columns - objective was packed
               for (k = 0; k < 2; k++) {
                    int iColumn = objIndex[k];
                    objective[iColumn] = objValue[k];
               }
               for (k = 0; k < numberColumns; k++)
                    columnUpper[k] = upper[k];
               // Rows
               for (k = 0; k < numberRows; k++) {
                    rowLower[k] = 1.0;
                    rowUpper[k] = 1.0;
               }
               // Now elements
               double row2Value[] = {1.0, -5.0, 1.0};
               CoinBigIndex put = 0;
               for (k = 0; k < numberColumns; k++) {
                    starts[k] = put;
                    lengths[k] = numberRows;
                    double value = row2Value[k];
                    for (int i = 0; i < numberRows; i++) {
                         rows[put] = i;
                         elements[put] = value;
                         put++;
                    }
               }
               starts[numberColumns] = put;
               // assign to matrix
               CoinPackedMatrix * matrix = new CoinPackedMatrix(true, 0.0, 0.0);
               matrix->assignMatrix(true, numberRows, numberColumns, numberElements,
                                    elements, rows, starts, lengths);
               ClpPackedMatrix * clpMatrix = new ClpPackedMatrix(matrix);
               model2.replaceMatrix(clpMatrix, true);
               printf("Time for 10000 addRow using hand written code is %g\n", CoinCpuTime() - time1);
               // If matrix is really big could switch off creation of row copy
               // model2.setSpecialOptions(256);
          }
          model2.dual();
          model2.writeMps("a.mps");
          // Print column solution
          int numberColumns = model.numberColumns();

          // Alternatively getColSolution()
          double * columnPrimal = model.primalColumnSolution();
          // Alternatively getReducedCost()
          double * columnDual = model.dualColumnSolution();
          // Alternatively getColLower()
          double * columnLower = model.columnLower();
          // Alternatively getColUpper()
          double * columnUpper = model.columnUpper();
          // Alternatively getObjCoefficients()
          double * columnObjective = model.objective();

          int iColumn;

          std::cout << "               Primal          Dual         Lower         Upper          Cost"
                    << std::endl;

          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
               double value;
               std::cout << std::setw(6) << iColumn << " ";
               value = columnPrimal[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value;
               value = columnDual[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value;
               value = columnLower[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value;
               value = columnUpper[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value;
               value = columnObjective[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value;

               std::cout << std::endl;
          }
          std::cout << "--------------------------------------" << std::endl;
          // Test CoinAssert
          std::cout << "If Clp compiled without NDEBUG below should give assert, if with NDEBUG or COIN_ASSERT CoinError" << std::endl;
          model = modelSave;
          model.deleteRows(2, del);
          // Deliberate error
          model.deleteColumns(1, del + 2);
          // Now use build +-1
          CoinBuild buildObject3;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int row2Index[] = {0, 1, 2};
               double row2Value[] = {1.0, -1.0, 1.0};
               buildObject3.addRow(3, row2Index, row2Value,
                                   1.0, 1.0);
          }
          model.addRows(buildObject3, true);
     } catch (CoinError e) {
          e.print();
          if (e.lineNumber() >= 0)
               std::cout << "This was from a CoinAssert" << std::endl;
     }
     return 0;
}
Exemplo n.º 9
0
int main (int argc, const char *argv[])
{

  // Define your favorite OsiSolver
  
  OsiClpSolverInterface solver1;

  // Read in model using argv[1]
  // and assert that it is a clean model
  std::string mpsFileName;
#if defined(SAMPLEDIR)
  mpsFileName = SAMPLEDIR "/p0033.mps";
#else
  if (argc < 2) {
    fprintf(stderr, "Do not know where to find sample MPS files.\n");
    exit(1);
  }
#endif
  if (argc>=2) mpsFileName = argv[1];
  int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),"");
  assert(numMpsReadErrors==0);
  double time1 = CoinCpuTime();
  OsiClpSolverInterface solverSave = solver1;

  /* Options are:
     preprocess to do preprocessing
     time in minutes
     if 2 parameters and numeric taken as time
  */
  bool preProcess=false;
  double minutes=-1.0;
  int nGoodParam=0;
  for (int iParam=2; iParam<argc;iParam++) {
    if (!strcmp(argv[iParam],"preprocess")) {
      preProcess=true;
      nGoodParam++;
    } else if (!strcmp(argv[iParam],"time")) {
      if (iParam+1<argc&&isdigit(argv[iParam+1][0])) {
        minutes=atof(argv[iParam+1]);
        if (minutes>=0.0) {
          nGoodParam+=2;
          iParam++; // skip time
        }
      }
    }
  }
  if (nGoodParam==0&&argc==3&&isdigit(argv[2][0])) {
    // If time is given then stop after that number of minutes
    minutes = atof(argv[2]);
    if (minutes>=0.0) 
      nGoodParam=1;
  }
  if (nGoodParam!=argc-2&&argc>=2) {
    printf("Usage <file> [preprocess] [time <minutes>] or <file> <minutes>\n");
    exit(1);
  }
  // Reduce printout
  solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry);
  // See if we want preprocessing
  OsiSolverInterface * solver2=&solver1;
  CglPreProcess process;
  // Never do preprocessing until dual tests out as can fix incorrectly
  preProcess=false;
  if (preProcess) {
    /* Do not try and produce equality cliques and
       do up to 5 passes */
    solver2 = process.preProcess(solver1,false,5);
    if (!solver2) {
      printf("Pre-processing says infeasible\n");
      exit(2);
    }
    solver2->resolve();
  }
  // Turn L rows into cuts
  CglStoredUser stored;
 {
  int numberRows = solver2->getNumRows();

  int * whichRow = new int[numberRows];
  // get row copy
  const CoinPackedMatrix * rowCopy = solver2->getMatrixByRow();
  const int * column = rowCopy->getIndices();
  const int * rowLength = rowCopy->getVectorLengths();
  const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
  const double * rowLower = solver2->getRowLower();
  const double * rowUpper = solver2->getRowUpper();
  const double * element = rowCopy->getElements();
  int iRow,nDelete=0;
  for (iRow=0;iRow<numberRows;iRow++) {
    if (rowLower[iRow]<-1.0e20||rowUpper[iRow]>1.0e20) {
      // take out
      whichRow[nDelete++]=iRow;
    }
  }
  // leave some rows to avoid empty problem (Gomory does not like)
  nDelete = CoinMax(CoinMin(nDelete,numberRows-5),0);
  for (int jRow=0;jRow<nDelete;jRow++) {
    iRow=whichRow[jRow];
    int start = rowStart[iRow];
    stored.addCut(rowLower[iRow],rowUpper[iRow],rowLength[iRow],
		  column+start,element+start);
  }
  /* The following is problem specific.
     Normally cuts are deleted if slack on cut basic.
     On some problems you may wish to leave cuts in as long
     as slack value zero
  */
  int numberCuts=stored.sizeRowCuts();
  for (int iCut=0;iCut<numberCuts;iCut++) {
    //stored.mutableRowCutPointer(iCut)->setEffectiveness(1.0e50);
  }
  solver2->deleteRows(nDelete,whichRow);
  delete [] whichRow;
 }
  CbcModel model(*solver2);
  model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
  // Set up some cut generators and defaults
  // Probing first as gets tight bounds on continuous

  CglProbing generator1;
  generator1.setUsingObjective(true);
  generator1.setMaxPass(1);
  generator1.setMaxPassRoot(5);
  // Number of unsatisfied variables to look at
  generator1.setMaxProbe(10);
  generator1.setMaxProbeRoot(1000);
  // How far to follow the consequences
  generator1.setMaxLook(50);
  generator1.setMaxLookRoot(500);
  // Only look at rows with fewer than this number of elements
  generator1.setMaxElements(200);
  generator1.setRowCuts(3);

  CglGomory generator2;
  // try larger limit
  generator2.setLimit(300);

  CglKnapsackCover generator3;

  CglRedSplit generator4;
  // try larger limit
  generator4.setLimit(200);

  CglClique generator5;
  generator5.setStarCliqueReport(false);
  generator5.setRowCliqueReport(false);

  CglMixedIntegerRounding2 mixedGen;
  CglFlowCover flowGen;
  
  // Add in generators
  // Experiment with -1 and -99 etc
  // This is just for one particular model
  model.addCutGenerator(&generator1,-1,"Probing");
  //model.addCutGenerator(&generator2,-1,"Gomory");
  model.addCutGenerator(&generator2,1,"Gomory");
  model.addCutGenerator(&generator3,-1,"Knapsack");
  // model.addCutGenerator(&generator4,-1,"RedSplit");
  //model.addCutGenerator(&generator5,-1,"Clique");
  model.addCutGenerator(&generator5,1,"Clique");
  model.addCutGenerator(&flowGen,-1,"FlowCover");
  model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding");
  // Add stored cuts (making sure at all depths)
  model.addCutGenerator(&stored,1,"Stored",true,false,false,-100,1,-1);
  
  int numberGenerators = model.numberCutGenerators();
  int iGenerator;
  // Say we want timings
  for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
    generator->setTiming(true);
  }
  OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (model.solver());
  // go faster stripes
  if (osiclp) { 
    if(osiclp->getNumRows()<300&&osiclp->getNumCols()<500) {
      //osiclp->setupForRepeatedUse(2,0);
      osiclp->setupForRepeatedUse(0,0);
    }
    // Don't allow dual stuff
    osiclp->setSpecialOptions(osiclp->specialOptions()|262144);
  } 
  // Uncommenting this should switch off all CBC messages
  // model.messagesPointer()->setDetailMessages(10,10000,NULL);
  // No heuristics
  // Do initial solve to continuous
  model.initialSolve();
  /*  You need the next few lines -
      a) so that cut generator will always be called again if it generated cuts
      b) it is known that matrix is not enough to define problem so do cuts even
         if it looks integer feasible at continuous optimum.
      c) a solution found by strong branching will be ignored.
      d) don't recompute a solution once found
  */
  // Make sure cut generator called correctly (a)
  iGenerator=numberGenerators-1;
  model.cutGenerator(iGenerator)->setMustCallAgain(true);
  // Say cuts needed at continuous (b)
  OsiBabSolver oddCuts;
  oddCuts.setSolverType(4);
  // owing to bug must set after initialSolve
  model.passInSolverCharacteristics(&oddCuts);
  // Say no to all solutions by strong branching (c)
  CbcFeasibilityNoStrong noStrong;
  model.setProblemFeasibility(noStrong);
  // Say don't recompute solution d)
  model.setSpecialOptions(4);

  // Could tune more
  double objValue = model.solver()->getObjSense()*model.solver()->getObjValue();
  double minimumDropA=CoinMin(1.0,fabs(objValue)*1.0e-3+1.0e-4);
  double minimumDrop= fabs(objValue)*1.0e-4+1.0e-4;
  printf("min drop %g (A %g)\n",minimumDrop,minimumDropA);
  model.setMinimumDrop(minimumDrop);

  if (model.getNumCols()<500)
    model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible
  else if (model.getNumCols()<5000)
    model.setMaximumCutPassesAtRoot(100); // use minimum drop
  else
    model.setMaximumCutPassesAtRoot(20);
  model.setMaximumCutPasses(10);
  //model.setMaximumCutPasses(2);

  // Switch off strong branching if wanted
  // model.setNumberStrong(0);
  // Do more strong branching if small
  if (model.getNumCols()<5000)
    model.setNumberStrong(10);
  model.setNumberStrong(20);
  //model.setNumberStrong(5);
  model.setNumberBeforeTrust(5);

  model.solver()->setIntParam(OsiMaxNumIterationHotStart,100);

  // If time is given then stop after that number of minutes
  if (minutes>=0.0) {
    std::cout<<"Stopping after "<<minutes<<" minutes"<<std::endl;
    model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes);
  }
  // Switch off most output
  if (model.getNumCols()<30000) {
    model.messageHandler()->setLogLevel(1);
    //model.solver()->messageHandler()->setLogLevel(0);
  } else {
    model.messageHandler()->setLogLevel(2);
    model.solver()->messageHandler()->setLogLevel(1);
  }
  //model.messageHandler()->setLogLevel(2);
  //model.solver()->messageHandler()->setLogLevel(2);
  //model.setPrintFrequency(50);
  //#define DEBUG_CUTS
#ifdef DEBUG_CUTS
  // Set up debugger by name (only if no preprocesing)
  if (!preProcess) {
    std::string problemName ;
    model.solver()->getStrParam(OsiProbName,problemName) ;
    model.solver()->activateRowCutDebugger(problemName.c_str()) ;
  }
#endif
  // Do complete search
  
  model.branchAndBound();

  std::cout<<mpsFileName<<" took "<<CoinCpuTime()-time1<<" seconds, "
	   <<model.getNodeCount()<<" nodes with objective "
	   <<model.getObjValue()
	   <<(!model.status() ? " Finished" : " Not finished")
	   <<std::endl;

  // Print more statistics
  std::cout<<"Cuts at root node changed objective from "<<model.getContinuousObjective()
	   <<" to "<<model.rootObjectiveAfterCuts()<<std::endl;

  for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
    std::cout<<generator->cutGeneratorName()<<" was tried "
	     <<generator->numberTimesEntered()<<" times and created "
	     <<generator->numberCutsInTotal()<<" cuts of which "
	     <<generator->numberCutsActive()<<" were active after adding rounds of cuts";
    if (generator->timing())
      std::cout<<" ( "<<generator->timeInCutGenerator()<<" seconds)"<<std::endl;
    else
      std::cout<<std::endl;
  }
  // Print solution if finished - we can't get names from Osi! - so get from OsiClp

  if (model.getMinimizationObjValue()<1.0e50) {
    // post process
    OsiSolverInterface * solver;
    if (preProcess) {
      process.postProcess(*model.solver());
      // Solution now back in solver1
      solver = & solver1;
    } else {
      solver = model.solver();
    }
    int numberColumns = solver->getNumCols();
    
    const double * solution = solver->getColSolution();

    // Get names from solver1 (as OsiSolverInterface may lose)
    std::vector<std::string> columnNames = *solver1.getModelPtr()->columnNames();
    
    int iColumn;
    std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
    
    std::cout<<"--------------------------------------"<<std::endl;
    for (iColumn=0;iColumn<numberColumns;iColumn++) {
      double value=solution[iColumn];
      if (fabs(value)>1.0e-7&&solver->isInteger(iColumn)) {
	std::cout<<std::setw(6)<<iColumn<<" "
                 <<columnNames[iColumn]<<" "
                 <<value<<std::endl;
	solverSave.setColLower(iColumn,value);
	solverSave.setColUpper(iColumn,value);
      }
    }
    std::cout<<"--------------------------------------"<<std::endl;
  
    std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);
    solverSave.initialSolve();
  }
  return 0;
}    
Exemplo n.º 10
0
/************************************************************************

This main program reads in an integer model from an mps file.

It then replaces all 0-1 variables by lotsizing variables
which can take values 0.0,0.45-0.55 or 1.0

*************************************************************************/
int main (int argc, const char *argv[])
{
  
  // Define your favorite OsiSolver
  
  OsiClpSolverInterface solver1;
  
  // Read in model using argv[1]
  // and assert that it is a clean model
  std::string mpsFileName;
#if defined(MIPLIB3DIR)
  mpsFileName = MIPLIB3DIR "/10teams";
#else
  if (argc < 2) {
    fprintf(stderr, "Do not know where to find miplib3 MPS files.\n");
    exit(1);
  }
#endif
  if (argc>=2) mpsFileName = argv[1];
  int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),"");
  if( numMpsReadErrors != 0 )
  {
     printf("%d errors reading MPS file\n", numMpsReadErrors);
     return numMpsReadErrors;
  }
  
  int iColumn;
  int numberColumns = solver1.getNumCols();
  int numberLot=0;
  char * mark = new char[numberColumns];
  // take off integers but find where they are
  for (iColumn=0;iColumn<numberColumns;iColumn++) {
    if (solver1.isBinary(iColumn)) {
      solver1.setContinuous(iColumn);
      mark[iColumn]=1;
      numberLot++;
    } else {
      mark[iColumn]=0;
    }
  }
  CbcModel model(solver1);
  // Do lotsizing
  CbcObject ** objects = new CbcObject * [numberLot];
  numberLot=0;
  /* For semi-continuous variables numberRanges is 2
     and ranges[]={0.0,0.0,K,COIN_DBL_MAX};
  */
  // valid ranges are 0.0 to 0.0, 0.45 to 0.55, 1.0 to 1.0
  double ranges[]={0.0,0.0,0.45,0.55,1.0,1.0};
  for (iColumn=0;iColumn<numberColumns;iColumn++) {
    if (mark[iColumn])
    objects[numberLot++]= new CbcLotsize(&model,iColumn,3,ranges,true);
  }
  delete [] mark;
  model.addObjects(numberLot,objects);
  for (iColumn=0;iColumn<numberLot;iColumn++)
    delete objects[iColumn];
  delete [] objects;

  // If time is given then stop after that number of minutes
  if (argc>2) {
    int minutes = atoi(argv[2]);
    std::cout<<"Stopping after "<<minutes<<" minutes"<<std::endl;
    assert (minutes>=0);
    model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes);
  }
  // Switch off most output
  model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
  if (model.getNumCols()<3000) {
    model.messageHandler()->setLogLevel(1);
    //model.solver()->messageHandler()->setLogLevel(0);
  } else {
    model.messageHandler()->setLogLevel(2);
    model.solver()->messageHandler()->setLogLevel(1);
  }
  model.messageHandler()->setLogLevel(1);
  
  double time1 = CoinCpuTime();

  // Do complete search
  
  model.branchAndBound();

  std::cout<<mpsFileName<<" took "<<CoinCpuTime()-time1<<" seconds, "
	   <<model.getNodeCount()<<" nodes with objective "
	   <<model.getObjValue()
	   <<(!model.status() ? " Finished" : " Not finished")
	   <<std::endl;

  // Print solution - we can't get names from Osi!

  if (model.getMinimizationObjValue()<1.0e50) {
    int numberColumns = model.solver()->getNumCols();
    
    const double * solution = model.solver()->getColSolution();
    
    int iColumn;
    std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
    
    std::cout<<"--------------------------------------"<<std::endl;
    for (iColumn=0;iColumn<numberColumns;iColumn++) {
      double value=solution[iColumn];
      if (fabs(value)>1.0e-7) 
	std::cout<<std::setw(6)<<iColumn<<" "<<value<<std::endl;
    }
    std::cout<<"--------------------------------------"<<std::endl;
  
    std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);
  }
  return 0;
}    
Exemplo n.º 11
0
const CoinPresolveAction
    *forcing_constraint_action::presolve(CoinPresolveMatrix *prob,
					 const CoinPresolveAction *next)
{
  double startTime = 0.0;
  int startEmptyRows=0;
  int startEmptyColumns = 0;
  if (prob->tuning_) {
    startTime = CoinCpuTime();
    startEmptyRows = prob->countEmptyRows();
    startEmptyColumns = prob->countEmptyCols();
  }
  double *clo	= prob->clo_;
  double *cup	= prob->cup_;
  double *csol  = prob->sol_ ;

  const double *rowels	= prob->rowels_;
  const int *hcol	= prob->hcol_;
  const CoinBigIndex *mrstrt	= prob->mrstrt_;
  const int *hinrow	= prob->hinrow_;
  const int nrows	= prob->nrows_;

  const double *rlo	= prob->rlo_;
  const double *rup	= prob->rup_;

  //  const char *integerType = prob->integerType_;

  const double tol	= ZTOLDP;
  const double inftol	= prob->feasibilityTolerance_;
  const int ncols	= prob->ncols_;

  int *fixed_cols	= new int[ncols];
  int nfixed_cols	= 0;

  action *actions	= new action [nrows];
  int nactions = 0;

  int *useless_rows	= new int[nrows];
  int nuseless_rows	= 0;

  int numberLook = prob->numberRowsToDo_;
  int iLook;
  int * look = prob->rowsToDo_;
  bool fixInfeasibility = (prob->presolveOptions_&16384)!=0;

# if PRESOLVE_DEBUG
  std::cout << "Entering forcing_constraint_action::presolve." << std::endl ;
  presolve_check_sol(prob) ;
# endif
/*
  Open a loop to scan the constraints of interest. There must be variables
  left in the row.
*/
  for (iLook=0;iLook<numberLook;iLook++) {
    int irow = look[iLook];
    if (hinrow[irow] > 0) {
      CoinBigIndex krs = mrstrt[irow];
      CoinBigIndex kre = krs + hinrow[irow];
/*
  Calculate upper and lower bounds on the row activity based on upper and lower
  bounds on the variables. If these are finite and incompatible with the given
  row bounds, we have infeasibility.
*/
      double maxup, maxdown;
      implied_row_bounds(rowels, clo, cup, hcol, krs, kre,
			 &maxup, &maxdown);

      if (maxup < PRESOLVE_INF && maxup + inftol < rlo[irow]&&!fixInfeasibility) {
	/* max row activity below the row lower bound */
	prob->status_|= 1;
	prob->messageHandler()->message(COIN_PRESOLVE_ROWINFEAS,
					     prob->messages())
				 	       <<irow
					       <<rlo[irow]
					       <<rup[irow]
					       <<CoinMessageEol;
	break;
      } else if (-PRESOLVE_INF < maxdown && rup[irow] < maxdown - inftol&&!fixInfeasibility) {
	/* min row activity above the row upper bound */
	prob->status_|= 1;
	prob->messageHandler()->message(COIN_PRESOLVE_ROWINFEAS,
					     prob->messages())
					       <<irow
					       <<rlo[irow]
					       <<rup[irow]
					       <<CoinMessageEol;
	break;
      }
      // ADD TOLERANCE TO THESE TESTS
      else if ((rlo[irow] <= -PRESOLVE_INF ||
		(-PRESOLVE_INF < maxdown && rlo[irow] <= maxdown)) &&
	       (rup[irow] >= PRESOLVE_INF ||
		(maxup < PRESOLVE_INF && rup[irow] >= maxup))) {

/*
  Original comment: I'm not sure that these transforms don't intefere with
		    each other. We can get it next time.

  Well, I'll argue that bounds are never really loosened (at worst, they're
  transferred onto some other variable, or inferred to be unnecessary.
  Once useless, always useless. Leaving this hook in place allows for a sort
  of infinite loop where this routine keeps queuing the same constraints over
  and over.  -- lh, 040901 --

	 if (some_col_was_fixed(hcol, krs, kre, clo, cup)) {
	   prob->addRow(irow);
	   continue;
	 }
*/

	// this constraint must always be satisfied - drop it
	useless_rows[nuseless_rows++] = irow;

      } else if ((maxup < PRESOLVE_INF && fabs(rlo[irow] - maxup) < tol) ||
		 (-PRESOLVE_INF < maxdown && fabs(rup[irow] - maxdown) < tol)) {

	// the lower bound can just be reached, or
	// the upper bound can just be reached;
	// called a "forcing constraint" in the paper (p. 226)
	const int lbound_tight = (maxup < PRESOLVE_INF &&
				  fabs(rlo[irow] - maxup) < tol);

/*
  Original comment and rebuttal as above.
	if (some_col_was_fixed(hcol, krs, kre, clo, cup)) {
	  // make sure on next time
	  prob->addRow(irow);
	  continue;
	}
*/
	// out of space - this probably never happens (but this routine will
	// often put duplicates in the fixed column list)
	if (nfixed_cols + (kre-krs) >= ncols)
	  break;

	double *bounds = new double[hinrow[irow]];
	int *rowcols = new int[hinrow[irow]];
	int lk = krs;	// load fix-to-down in front
	int uk = kre;	// load fix-to-up in back
        CoinBigIndex k;
	for ( k=krs; k<kre; k++) {
	  int jcol = hcol[k];
	  prob->addCol(jcol);
	  double coeff = rowels[k];

	  PRESOLVEASSERT(fabs(coeff) > ZTOLDP);

	  // one of the two contributed to maxup - set the other to that
	  if (lbound_tight == (coeff > 0.0)) {
	    --uk;
	    bounds[uk-krs] = clo[jcol];
	    rowcols[uk-krs] = jcol;
	    if (csol != 0) {
	      csol[jcol] = cup[jcol] ;
	    }
	    clo[jcol] = cup[jcol];
	  } else {
	    bounds[lk-krs] = cup[jcol];
	    rowcols[lk-krs] = jcol;
	    ++lk;
	    if (csol != 0) {
	      csol[jcol] = clo[jcol] ;
	    }
	    cup[jcol] = clo[jcol];
	  }

	  fixed_cols[nfixed_cols++] = jcol;
	}
	PRESOLVEASSERT(uk == lk);

	action *f = &actions[nactions];
	nactions++;

	f->row = irow;
	f->nlo = lk-krs;
	f->nup = kre-uk;
	f->rowcols = rowcols;
	f->bounds = bounds;
      }
    }
  }


  if (nactions) {
#if	PRESOLVE_SUMMARY
    printf("NFORCED:  %d\n", nactions);
#endif
    next = new forcing_constraint_action(nactions, 
					 CoinCopyOfArray(actions,nactions), next);
  }
  deleteAction(actions,action*);
  if (nuseless_rows) {
    next = useless_constraint_action::presolve(prob,
					       useless_rows, nuseless_rows,
					       next);
  }
  delete[]useless_rows;
/*
  We need to remove duplicates here, or we get into trouble in
  remove_fixed_action::postsolve when we try to reinstate a column multiple
  times.
*/
  if (nfixed_cols)
  { if (nfixed_cols > 1)
    { std::sort(fixed_cols,fixed_cols+nfixed_cols) ;
      int *end = std::unique(fixed_cols,fixed_cols+nfixed_cols) ;
      nfixed_cols = static_cast<int>(end-fixed_cols) ; }
    next = remove_fixed_action::presolve(prob,fixed_cols,nfixed_cols,next) ; }
  delete[]fixed_cols ;

  if (prob->tuning_) {
    double thisTime=CoinCpuTime();
    int droppedRows = prob->countEmptyRows() - startEmptyRows ;
    int droppedColumns =  prob->countEmptyCols() - startEmptyColumns;
    printf("CoinPresolveForcing(32) - %d rows, %d columns dropped in time %g, total %g\n",
	   droppedRows,droppedColumns,thisTime-startTime,thisTime-prob->startTime_);
  }

# if PRESOLVE_DEBUG
  presolve_check_sol(prob) ;
  std::cout << "Leaving forcing_constraint_action::presolve." << std::endl ;
# endif

  return (next);
}
Exemplo n.º 12
0
int main(int argc, const char *argv[])
{
     ClpSimplex  model;
     int status;
     // Keep names
     if (argc < 2) {
          status = model.readMps("small.mps", true);
     } else {
          status = model.readMps(argv[1], false);
     }
     if (status)
          exit(10);
     /*
       This driver implements a method of treating a problem as all cuts.
       So it adds in all E rows, solves and then adds in violated rows.
     */

     double time1 = CoinCpuTime();
     ClpSimplex * model2;
     ClpPresolve pinfo;
     int numberPasses = 5; // can change this
     /* Use a tolerance of 1.0e-8 for feasibility, treat problem as
        not being integer, do "numberpasses" passes and throw away names
        in presolved model */
     model2 = pinfo.presolvedModel(model, 1.0e-8, false, numberPasses, false);
     if (!model2) {
          fprintf(stderr, "ClpPresolve says %s is infeasible with tolerance of %g\n",
                  argv[1], 1.0e-8);
          fprintf(stdout, "ClpPresolve says %s is infeasible with tolerance of %g\n",
                  argv[1], 1.0e-8);
          // model was infeasible - maybe try again with looser tolerances
          model2 = pinfo.presolvedModel(model, 1.0e-7, false, numberPasses, false);
          if (!model2) {
               fprintf(stderr, "ClpPresolve says %s is infeasible with tolerance of %g\n",
                       argv[1], 1.0e-7);
               fprintf(stdout, "ClpPresolve says %s is infeasible with tolerance of %g\n",
                       argv[1], 1.0e-7);
               exit(2);
          }
     }
     // change factorization frequency from 200
     model2->setFactorizationFrequency(100 + model2->numberRows() / 50);

     int numberColumns = model2->numberColumns();
     int originalNumberRows = model2->numberRows();

     // We will need arrays to choose rows to add
     double * weight = new double [originalNumberRows];
     int * sort = new int [originalNumberRows];
     int numberSort = 0;
     char * take = new char [originalNumberRows];

     const double * rowLower = model2->rowLower();
     const double * rowUpper = model2->rowUpper();
     int iRow, iColumn;
     // Set up initial list
     numberSort = 0;
     for (iRow = 0; iRow < originalNumberRows; iRow++) {
          weight[iRow] = 1.123e50;
          if (rowLower[iRow] == rowUpper[iRow]) {
               sort[numberSort++] = iRow;
               weight[iRow] = 0.0;
          }
     }
     numberSort /= 2;
     // Just add this number of rows each time in small problem
     int smallNumberRows = 2 * numberColumns;
     smallNumberRows = CoinMin(smallNumberRows, originalNumberRows / 20);
     // and pad out with random rows
     double ratio = ((double)(smallNumberRows - numberSort)) / ((double) originalNumberRows);
     for (iRow = 0; iRow < originalNumberRows; iRow++) {
          if (weight[iRow] == 1.123e50 && CoinDrand48() < ratio)
               sort[numberSort++] = iRow;
     }
     /* This is optional.
        The best thing to do is to miss out random rows and do a set which makes dual feasible.
        If that is not possible then make sure variables have bounds.

        One way that normally works is to automatically tighten bounds.
     */
#if 0
     // However for some we need to do anyway
     double * columnLower = model2->columnLower();
     double * columnUpper = model2->columnUpper();
     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
          columnLower[iColumn] = CoinMax(-1.0e6, columnLower[iColumn]);
          columnUpper[iColumn] = CoinMin(1.0e6, columnUpper[iColumn]);
     }
#endif
     model2->tightenPrimalBounds(-1.0e4, true);
     printf("%d rows in initial problem\n", numberSort);
     double * fullSolution = model2->primalRowSolution();

     // Just do this number of passes
     int maxPass = 50;
     // And take out slack rows until this pass
     int takeOutPass = 30;
     int iPass;

     const int * start = model2->clpMatrix()->getVectorStarts();
     const int * length = model2->clpMatrix()->getVectorLengths();
     const int * row = model2->clpMatrix()->getIndices();
     int * whichColumns = new int [numberColumns];
     for (iColumn = 0; iColumn < numberColumns; iColumn++)
          whichColumns[iColumn] = iColumn;
     int numberSmallColumns = numberColumns;
     for (iPass = 0; iPass < maxPass; iPass++) {
          printf("Start of pass %d\n", iPass);
          // Cleaner this way
          std::sort(sort, sort + numberSort);
          // Create small problem
          ClpSimplex small(model2, numberSort, sort, numberSmallColumns, whichColumns);
          small.setFactorizationFrequency(100 + numberSort / 200);
          //small.setPerturbation(50);
          //small.setLogLevel(63);
          // A variation is to just do N iterations
          //if (iPass)
          //small.setMaximumIterations(100);
          // Solve
          small.factorization()->messageLevel(8);
          if (iPass) {
               small.dual();
          } else {
               small.writeMps("continf.mps");
               ClpSolve solveOptions;
               solveOptions.setSolveType(ClpSolve::useDual);
               //solveOptions.setSolveType(ClpSolve::usePrimalorSprint);
               //solveOptions.setSpecialOption(1,2,200); // idiot
               small.initialSolve(solveOptions);
          }
          bool dualInfeasible = (small.status() == 2);
          // move solution back
          double * solution = model2->primalColumnSolution();
          const double * smallSolution = small.primalColumnSolution();
          for (int j = 0; j < numberSmallColumns; j++) {
               iColumn = whichColumns[j];
               solution[iColumn] = smallSolution[j];
               model2->setColumnStatus(iColumn, small.getColumnStatus(j));
          }
          for (iRow = 0; iRow < numberSort; iRow++) {
               int kRow = sort[iRow];
               model2->setRowStatus(kRow, small.getRowStatus(iRow));
          }
          // compute full solution
          memset(fullSolution, 0, originalNumberRows * sizeof(double));
          model2->times(1.0, model2->primalColumnSolution(), fullSolution);
          if (iPass != maxPass - 1) {
               // Mark row as not looked at
               for (iRow = 0; iRow < originalNumberRows; iRow++)
                    weight[iRow] = 1.123e50;
               // Look at rows already in small problem
               int iSort;
               int numberDropped = 0;
               int numberKept = 0;
               int numberBinding = 0;
               int numberInfeasibilities = 0;
               double sumInfeasibilities = 0.0;
               for (iSort = 0; iSort < numberSort; iSort++) {
                    iRow = sort[iSort];
                    //printf("%d %g %g\n",iRow,fullSolution[iRow],small.primalRowSolution()[iSort]);
                    if (model2->getRowStatus(iRow) == ClpSimplex::basic) {
                         // Basic - we can get rid of if early on
                         if (iPass < takeOutPass && !dualInfeasible) {
                              // may have hit max iterations so check
                              double infeasibility = CoinMax(fullSolution[iRow] - rowUpper[iRow],
                                                             rowLower[iRow] - fullSolution[iRow]);
                              weight[iRow] = -infeasibility;
                              if (infeasibility > 1.0e-8) {
                                   numberInfeasibilities++;
                                   sumInfeasibilities += infeasibility;
                              } else {
                                   weight[iRow] = 1.0;
                                   numberDropped++;
                              }
                         } else {
                              // keep
                              weight[iRow] = -1.0e40;
                              numberKept++;
                         }
                    } else {
                         // keep
                         weight[iRow] = -1.0e50;
                         numberKept++;
                         numberBinding++;
                    }
               }
               // Now rest
               for (iRow = 0; iRow < originalNumberRows; iRow++) {
                    sort[iRow] = iRow;
                    if (weight[iRow] == 1.123e50) {
                         // not looked at yet
                         double infeasibility = CoinMax(fullSolution[iRow] - rowUpper[iRow],
                                                        rowLower[iRow] - fullSolution[iRow]);
                         weight[iRow] = -infeasibility;
                         if (infeasibility > 1.0e-8) {
                              numberInfeasibilities++;
                              sumInfeasibilities += infeasibility;
                         }
                    }
               }
               // sort
               CoinSort_2(weight, weight + originalNumberRows, sort);
               numberSort = CoinMin(originalNumberRows, smallNumberRows + numberKept);
               memset(take, 0, originalNumberRows);
               for (iRow = 0; iRow < numberSort; iRow++)
                    take[sort[iRow]] = 1;
               numberSmallColumns = 0;
               for (iColumn = 0; iColumn < numberColumns; iColumn++) {
                    int n = 0;
                    for (int j = start[iColumn]; j < start[iColumn] + length[iColumn]; j++) {
                         int iRow = row[j];
                         if (take[iRow])
                              n++;
                    }
                    if (n)
                         whichColumns[numberSmallColumns++] = iColumn;
               }
               printf("%d rows binding, %d rows kept, %d rows dropped - new size %d rows, %d columns\n",
                      numberBinding, numberKept, numberDropped, numberSort, numberSmallColumns);
               printf("%d rows are infeasible - sum is %g\n", numberInfeasibilities,
                      sumInfeasibilities);
               if (!numberInfeasibilities) {
                    printf("Exiting as looks optimal\n");
                    break;
               }
               numberInfeasibilities = 0;
               sumInfeasibilities = 0.0;
               for (iSort = 0; iSort < numberSort; iSort++) {
                    if (weight[iSort] > -1.0e30 && weight[iSort] < -1.0e-8) {
                         numberInfeasibilities++;
                         sumInfeasibilities += -weight[iSort];
                    }
               }
               printf("in small model %d rows are infeasible - sum is %g\n", numberInfeasibilities,
                      sumInfeasibilities);
          }
     }
     delete [] weight;
     delete [] sort;
     delete [] whichColumns;
     delete [] take;
     // If problem is big you may wish to skip this
     model2->dual();
     int numberBinding = 0;
     for (iRow = 0; iRow < originalNumberRows; iRow++) {
          if (model2->getRowStatus(iRow) != ClpSimplex::basic)
               numberBinding++;
     }
     printf("%d binding rows at end\n", numberBinding);
     pinfo.postsolve(true);

     int numberIterations = model2->numberIterations();;
     delete model2;
     /* After this postsolve model should be optimal.
        We can use checkSolution and test feasibility */
     model.checkSolution();
     if (model.numberDualInfeasibilities() ||
               model.numberPrimalInfeasibilities())
          printf("%g dual %g(%d) Primal %g(%d)\n",
                 model.objectiveValue(),
                 model.sumDualInfeasibilities(),
                 model.numberDualInfeasibilities(),
                 model.sumPrimalInfeasibilities(),
                 model.numberPrimalInfeasibilities());
     // But resolve for safety
     model.primal(1);

     numberIterations += model.numberIterations();;
     printf("Solve took %g seconds\n", CoinCpuTime() - time1);
     return 0;
}
Exemplo n.º 13
0
int main (int argc, const char *argv[])
{

  CbcSolver3 solver1;

  // Read in model using argv[1]
  // and assert that it is a clean model
  std::string mpsFileName;
  if (argc>=2) mpsFileName = argv[1];
  int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),"");
  assert(numMpsReadErrors==0);
  double time1 = CoinCpuTime();

  /* Options are:
     preprocess to do preprocessing
     time in minutes
     if 2 parameters and numeric taken as time
  */
  bool preProcess=false;
  double minutes=-1.0;
  int nGoodParam=0;
  for (int iParam=2; iParam<argc;iParam++) {
    if (!strcmp(argv[iParam],"preprocess")) {
      preProcess=true;
      nGoodParam++;
    } else if (!strcmp(argv[iParam],"time")) {
      if (iParam+1<argc&&isdigit(argv[iParam+1][0])) {
        minutes=atof(argv[iParam+1]);
        if (minutes>=0.0) {
          nGoodParam+=2;
          iParam++; // skip time
        }
      }
    }
  }
  if (nGoodParam==0&&argc==3&&isdigit(argv[2][0])) {
    // If time is given then stop after that number of minutes
    minutes = atof(argv[2]);
    if (minutes>=0.0) 
      nGoodParam=1;
  }
  if (nGoodParam!=argc-2) {
    printf("Usage <file> [preprocess] [time <minutes>] or <file> <minutes>\n");
    exit(1);
  }
  solver1.initialSolve();
  // Reduce printout
  solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry);
  // Say we want scaling
  //solver1.setHintParam(OsiDoScale,true,OsiHintTry);
  //solver1.setCleanupScaling(1);
  // See if we want preprocessing
  OsiSolverInterface * solver2=&solver1;
  CglPreProcess process;
  if (preProcess) {
    /* Do not try and produce equality cliques and
       do up to 5 passes */
    solver2 = process.preProcess(solver1,false,5);
    if (!solver2) {
      printf("Pre-processing says infeasible\n");
      exit(2);
    }
    solver2->resolve();
  }
  CbcModel model(*solver2);
  // Point to solver
  OsiSolverInterface * solver3 = model.solver();
  CbcSolver3 * osiclp = dynamic_cast< CbcSolver3*> (solver3);
  assert (osiclp);
  const double fractionFix=0.985;
  osiclp->initialize(&model,NULL);
  osiclp->setAlgorithm(2);
  osiclp->setMemory(1000);
  osiclp->setNested(fractionFix);
  //osiclp->setNested(1.0); //off
  // Set up some cut generators and defaults
  // Probing first as gets tight bounds on continuous

  CglProbing generator1;
  generator1.setUsingObjective(true);
  generator1.setMaxPass(3);
  // Number of unsatisfied variables to look at
  generator1.setMaxProbe(10);
  // How far to follow the consequences
  generator1.setMaxLook(50);
  // Only look at rows with fewer than this number of elements
  generator1.setMaxElements(200);
  generator1.setRowCuts(3);

  CglGomory generator2;
  // try larger limit
  generator2.setLimit(300);

  CglKnapsackCover generator3;

  CglOddHole generator4;
  generator4.setMinimumViolation(0.005);
  generator4.setMinimumViolationPer(0.00002);
  // try larger limit
  generator4.setMaximumEntries(200);

  CglClique generator5;
  generator5.setStarCliqueReport(false);
  generator5.setRowCliqueReport(false);

  CglMixedIntegerRounding mixedGen;
  /* This is same as default constructor - 
     (1,true,1)
      I presume if maxAggregate larger then slower but maybe better
      criterion can be  1 through 3
      Reference: 
      Hugues Marchand and Laurence A. Wolsey
      Aggregation and Mixed Integer Rounding to Solve MIPs
      Operations Research, 49(3), May-June 2001.
   */
  int maxAggregate=1;
  bool multiply=true;
  int criterion=1;
  CglMixedIntegerRounding2 mixedGen2(maxAggregate,multiply,criterion);
  CglFlowCover flowGen;
  
  // Add in generators
  // Experiment with -1 and -99 etc
  model.addCutGenerator(&generator1,-99,"Probing");
  //model.addCutGenerator(&generator2,-1,"Gomory");
  //model.addCutGenerator(&generator3,-1,"Knapsack");
  //model.addCutGenerator(&generator4,-1,"OddHole");
  //model.addCutGenerator(&generator5,-1,"Clique");
  //model.addCutGenerator(&flowGen,-1,"FlowCover");
  //model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding");
  //model.addCutGenerator(&mixedGen2,-1,"MixedIntegerRounding2");
  // Say we want timings
  int numberGenerators = model.numberCutGenerators();
  int iGenerator;
  for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
    generator->setTiming(true);
  }

  // Allow rounding heuristic

  CbcRounding heuristic1(model);
  model.addHeuristic(&heuristic1);

  // And Greedy heuristic

  CbcHeuristicGreedyCover heuristic2(model);
  // Use original upper and perturb more
  heuristic2.setAlgorithm(11);
  model.addHeuristic(&heuristic2);

  // Redundant definition of default branching (as Default == User)
  CbcBranchUserDecision branch;
  model.setBranchingMethod(&branch);

  // Definition of node choice
  CbcCompareUser compare;
  model.setNodeComparison(compare);

  int iColumn;
  int numberColumns = solver3->getNumCols();
  // do pseudo costs
  CbcObject ** objects = new CbcObject * [numberColumns+1];
  const CoinPackedMatrix * matrix = solver3->getMatrixByCol();
  // Column copy
  const int * columnLength = matrix->getVectorLengths();
  const double * objective = model.getObjCoefficients();
  int n=0;
  for (iColumn=0;iColumn<numberColumns;iColumn++) {
    if (solver3->isInteger(iColumn)) {
      double costPer = objective[iColumn]/ ((double) columnLength[iColumn]);
      CbcSimpleIntegerPseudoCost * newObject =
        new CbcSimpleIntegerPseudoCost(&model,n,iColumn,
                                       costPer,costPer);
      newObject->setMethod(3);
      objects[n++]= newObject;
    }
  }
  // and special fix lots branch
  objects[n++]=new CbcBranchToFixLots(&model,-1.0e-6,fractionFix+0.01,1,0,NULL);
  model.addObjects(n,objects);
  for (iColumn=0;iColumn<n;iColumn++)
    delete objects[iColumn];
  delete [] objects;
  // High priority for odd object
  int followPriority=1;
  model.passInPriorities(&followPriority,true);

  // Do initial solve to continuous
  model.initialSolve();

  // Could tune more
  model.setMinimumDrop(CoinMin(1.0,
			     fabs(model.getMinimizationObjValue())*1.0e-3+1.0e-4));

  if (model.getNumCols()<500)
    model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible
  else if (model.getNumCols()<5000)
    model.setMaximumCutPassesAtRoot(100); // use minimum drop
  else
    model.setMaximumCutPassesAtRoot(20);
  //model.setMaximumCutPasses(1);

  // Do more strong branching if small
  //if (model.getNumCols()<5000)
  //model.setNumberStrong(10);
  // Switch off strong branching if wanted
  model.setNumberStrong(0);

  model.solver()->setIntParam(OsiMaxNumIterationHotStart,100);

  // If time is given then stop after that number of minutes
  if (minutes>=0.0) {
    std::cout<<"Stopping after "<<minutes<<" minutes"<<std::endl;
    model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes);
  }
  // Switch off most output
  if (model.getNumCols()<300000) {
    model.messageHandler()->setLogLevel(1);
    //model.solver()->messageHandler()->setLogLevel(0);
  } else {
    model.messageHandler()->setLogLevel(2);
    model.solver()->messageHandler()->setLogLevel(1);
  }
  //model.messageHandler()->setLogLevel(2);
  //model.solver()->messageHandler()->setLogLevel(2);
  //model.setPrintFrequency(50);
#define DEBUG_CUTS
#ifdef DEBUG_CUTS
  // Set up debugger by name (only if no preprocesing)
  if (!preProcess) {
    std::string problemName ;
    //model.solver()->getStrParam(OsiProbName,problemName) ;
    //model.solver()->activateRowCutDebugger(problemName.c_str()) ;
    model.solver()->activateRowCutDebugger("cap6000a") ;
  }
#endif

  // Do complete search
  try {
    model.branchAndBound();
  }
  catch (CoinError e) {
    e.print();
    if (e.lineNumber()>=0)
      std::cout<<"This was from a CoinAssert"<<std::endl;
    exit(0);
  }
  //void printHowMany();
  //printHowMany();
  std::cout<<mpsFileName<<" took "<<CoinCpuTime()-time1<<" seconds, "
	   <<model.getNodeCount()<<" nodes with objective "
	   <<model.getObjValue()
	   <<(!model.status() ? " Finished" : " Not finished")
	   <<std::endl;

  // Print more statistics
  std::cout<<"Cuts at root node changed objective from "<<model.getContinuousObjective()
	   <<" to "<<model.rootObjectiveAfterCuts()<<std::endl;

  for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
    std::cout<<generator->cutGeneratorName()<<" was tried "
	     <<generator->numberTimesEntered()<<" times and created "
	     <<generator->numberCutsInTotal()<<" cuts of which "
	     <<generator->numberCutsActive()<<" were active after adding rounds of cuts";
    if (generator->timing())
      std::cout<<" ( "<<generator->timeInCutGenerator()<<" seconds)"<<std::endl;
    else
      std::cout<<std::endl;
  }
  // Print solution if finished - we can't get names from Osi!

  if (model.getMinimizationObjValue()<1.0e50) {
    // post process
    if (preProcess)
      process.postProcess(*model.solver());
    int numberColumns = model.solver()->getNumCols();
    
    const double * solution = model.solver()->getColSolution();
    
    int iColumn;
    std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
    
    std::cout<<"--------------------------------------"<<std::endl;
    for (iColumn=0;iColumn<numberColumns;iColumn++) {
      double value=solution[iColumn];
      if (fabs(value)>1.0e-7&&model.solver()->isInteger(iColumn)) 
	std::cout<<std::setw(6)<<iColumn<<" "<<value<<std::endl;
    }
    std::cout<<"--------------------------------------"<<std::endl;
  
    std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);
  }
  return 0;
}    
Exemplo n.º 14
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;
}
Exemplo n.º 15
0
int main (int argc, const char *argv[])
{
     // Empty model
     ClpSimplex  model;
     std::string mpsFileName = "../../Data/Netlib/25fv47.mps";
     if (argc >= 2) mpsFileName = argv[1];
     int status = model.readMps(mpsFileName.c_str(), true);

     if (status) {
          fprintf(stderr, "Bad readMps %s\n", mpsFileName.c_str());
          fprintf(stdout, "Bad readMps %s\n", mpsFileName.c_str());
          exit(1);
     }
     // Point to data
     int numberRows = model.numberRows();
     const double * rowLower = model.rowLower();
     const double * rowUpper = model.rowUpper();
     int numberColumns = model.numberColumns();
     const double * columnLower = model.columnLower();
     const double * columnUpper = model.columnUpper();
     const double * columnObjective = model.objective();
     CoinPackedMatrix * matrix = model.matrix();
     // get row copy
     CoinPackedMatrix rowCopy = *matrix;
     rowCopy.reverseOrdering();
     const int * column = rowCopy.getIndices();
     const int * rowLength = rowCopy.getVectorLengths();
     const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
     const double * element = rowCopy.getElements();
     //const int * row = matrix->getIndices();
     //const int * columnLength = matrix->getVectorLengths();
     //const CoinBigIndex * columnStart = matrix->getVectorStarts();
     //const double * elementByColumn = matrix->getElements();

     // solve
     model.dual();
     // Now build new model
     CoinModel build;
     double time1 = CoinCpuTime();
     // Row bounds
     int iRow;
     for (iRow = 0; iRow < numberRows; iRow++) {
          build.setRowBounds(iRow, rowLower[iRow], rowUpper[iRow]);
          // optional name
          build.setRowName(iRow, model.rowName(iRow).c_str());
     }
     // Column bounds and objective
     int iColumn;
     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
          build.setColumnLower(iColumn, columnLower[iColumn]);
          build.setColumnUpper(iColumn, columnUpper[iColumn]);
          build.setObjective(iColumn, columnObjective[iColumn]);
          // optional name
          build.setColumnName(iColumn, model.columnName(iColumn).c_str());
     }
     // Adds elements one by one by row (backwards by row)
     for (iRow = numberRows - 1; iRow >= 0; iRow--) {
          int start = rowStart[iRow];
          for (int j = start; j < start + rowLength[iRow]; j++)
               build(iRow, column[j], element[j]);
     }
     double time2 = CoinCpuTime();
     // Now create clpsimplex
     ClpSimplex model2;
     model2.loadProblem(build);
     double time3 = CoinCpuTime();
     printf("Time for build using CoinModel is %g (%g for loadproblem)\n", time3 - time1,
            time3 - time2);
     model2.dual();
     // Now do with strings attached
     // Save build to show how to go over rows
     CoinModel saveBuild = build;
     build = CoinModel();
     time1 = CoinCpuTime();
     // Column bounds
     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
          build.setColumnLower(iColumn, columnLower[iColumn]);
          build.setColumnUpper(iColumn, columnUpper[iColumn]);
     }
     // Objective - half the columns as is and half with multiplier of "1.0+multiplier"
     // Pick up from saveBuild (for no reason at all)
     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
          double value = saveBuild.objective(iColumn);
          if (iColumn * 2 < numberColumns) {
               build.setObjective(iColumn, columnObjective[iColumn]);
          } else {
               // create as string
               char temp[100];
               sprintf(temp, "%g + abs(%g*multiplier)", value, value);
               build.setObjective(iColumn, temp);
          }
     }
     // It then adds rows one by one but for half the rows sets their values
     //      with multiplier of "1.0+1.5*multiplier"
     for (iRow = 0; iRow < numberRows; iRow++) {
          if (iRow * 2 < numberRows) {
               // add row in simple way
               int start = rowStart[iRow];
               build.addRow(rowLength[iRow], column + start, element + start,
                            rowLower[iRow], rowUpper[iRow]);
          } else {
               // As we have to add one by one let's get from saveBuild
               CoinModelLink triple = saveBuild.firstInRow(iRow);
               while (triple.column() >= 0) {
                    int iColumn = triple.column();
                    if (iColumn * 2 < numberColumns) {
                         // just value as normal
                         build(iRow, triple.column(), triple.value());
                    } else {
                         // create as string
                         char temp[100];
                         sprintf(temp, "%g + (1.5*%g*multiplier)", triple.value(), triple.value());
                         build(iRow, iColumn, temp);
                    }
                    triple = saveBuild.next(triple);
               }
               // but remember to do rhs
               build.setRowLower(iRow, rowLower[iRow]);
               build.setRowUpper(iRow, rowUpper[iRow]);
          }
     }
     time2 = CoinCpuTime();
     // Now create ClpSimplex
     // If small switch on error printing
     if (numberColumns < 50)
          build.setLogLevel(1);
     int numberErrors = model2.loadProblem(build);
     // should fail as we never set multiplier
     assert (numberErrors);
     time3 = CoinCpuTime() - time2;
     // subtract out unsuccessful times
     time1 += time3;
     time2 += time3;
     build.associateElement("multiplier", 0.0);
     numberErrors = model2.loadProblem(build);
     assert (!numberErrors);
     time3 = CoinCpuTime();
     printf("Time for build using CoinModel is %g (%g for successful loadproblem)\n", time3 - time1,
            time3 - time2);
     build.writeMps("zero.mps");
     // It then loops with multiplier going from 0.0 to 2.0 in increments of 0.1
     for (double multiplier = 0.0; multiplier < 2.0; multiplier += 0.1) {
          build.associateElement("multiplier", multiplier);
          numberErrors = model2.loadProblem(build, true);
          assert (!numberErrors);
          model2.dual();
     }

     return 0;
}
Exemplo n.º 16
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 ();
}
/*
  Randomized Rounding Heuristic
  Returns 1 if solution, 0 if not
*/
int
CbcHeuristicRandRound::solution(double & solutionValue,
                                double * betterSolution)
{
    // rlh: Todo: Memory Cleanup

    //  std::cout << "Entering the Randomized Rounding Heuristic" << std::endl;

    setWhen(1);  // setWhen(1) didn't have the effect I expected (e.g., run once).

    // Run only once.
    //
    //    See if at root node
    bool atRoot = model_->getNodeCount() == 0;
    int passNumber = model_->getCurrentPassNumber();
    //    Just do once
    if (!atRoot || passNumber > 1) {
        // std::cout << "Leaving the Randomized Rounding Heuristic" << std::endl;
        return 0;
    }

    std::cout << "Entering the Randomized Rounding Heuristic" << std::endl;
    typedef struct {
        int numberSolutions;
        int maximumSolutions;
        int numberColumns;
        double ** solution;
        int * numberUnsatisfied;
    } clpSolution;

    double start = CoinCpuTime();
    numCouldRun_++; //
#ifdef HEURISTIC_INFORM
    printf("Entering heuristic %s - nRuns %d numCould %d when %d\n",
	   heuristicName(),numRuns_,numCouldRun_,when_);
#endif
    // Todo: Ask JJHF what "number of times
    // the heuristic could run" means.

    OsiSolverInterface * solver = model_->solver()->clone();
    double primalTolerance ;
    solver->getDblParam(OsiPrimalTolerance, primalTolerance) ;
    OsiClpSolverInterface * clpSolver = dynamic_cast<OsiClpSolverInterface *> (solver);
    assert (clpSolver);
    ClpSimplex * simplex = clpSolver->getModelPtr();

    // Initialize the structure holding the solutions for the Simplex iterations
    clpSolution solutions;
    // Set typeStruct field of ClpTrustedData struct to 1 to indicate
    // desired behavior for  RandRound heuristic (which is what?)
    ClpTrustedData trustedSolutions;
    trustedSolutions.typeStruct = 1;
    trustedSolutions.data = &solutions;
    solutions.numberSolutions = 0;
    solutions.maximumSolutions = 0;
    solutions.numberColumns = simplex->numberColumns();
    solutions.solution = NULL;
    solutions.numberUnsatisfied = NULL;
    simplex->setTrustedUserPointer(&trustedSolutions);

    // Solve from all slack to get some points
    simplex->allSlackBasis();

    // Calling primal() invalidates pointers to some rim vectors,
    // like...row sense (!)
    simplex->primal();

    // 1. Okay - so a workaround would be to copy the data I want BEFORE
    // calling primal.
    // 2. Another approach is to ask the simplex solvers NOT to mess up my
    // rims.
    // 3. See freeCachedResults() for what is getting
    // deleted. Everything else points into the structure.
    // ...or use collower and colupper rather than rowsense.
    // ..store address of where one of these

    // Store the basic problem information
    // -Get the number of columns, rows and rhs vector
    int numCols = clpSolver->getNumCols();
    int numRows = clpSolver->getNumRows();

    // Find the integer variables (use columnType(?))
    // One if not continuous, that is binary or general integer)
    // columnType() = 0 continuous
    //              = 1 binary
    //              = 2 general integer
    bool * varClassInt = new bool[numCols];
    const char* columnType = clpSolver->columnType();
    int numGenInt = 0;
    for (int i = 0; i < numCols; i++) {
        if (clpSolver->isContinuous(i))
            varClassInt[i] = 0;
        else
            varClassInt[i] = 1;
        if (columnType[i] == 2) numGenInt++;
    }

    // Heuristic is for problems with general integer variables.
    // If there are none, quit.
    if (numGenInt++ < 1) {
        delete [] varClassInt ;
        std::cout << "Leaving the Randomized Rounding Heuristic" << std::endl;
        return 0;
    }


    // -Get the rows sense
    const char * rowSense;
    rowSense = clpSolver->getRowSense();

    // -Get the objective coefficients
    double *originalObjCoeff = CoinCopyOfArray(clpSolver->getObjCoefficients(), numCols);

    // -Get the matrix of the problem
    // rlh: look at using sparse representation
    double ** matrix = new double * [numRows];
    for (int i = 0; i < numRows; i++) {
        matrix[i] = new double[numCols];
        for (int j = 0; j < numCols; j++)
            matrix[i][j] = 0;
    }

    const CoinPackedMatrix* matrixByRow = clpSolver->getMatrixByRow();
    const double * matrixElements = matrixByRow->getElements();
    const int * matrixIndices = matrixByRow->getIndices();
    const int * matrixStarts = matrixByRow->getVectorStarts();
    for (int j = 0; j < numRows; j++) {
        for (int i = matrixStarts[j]; i < matrixStarts[j+1]; i++) {
            matrix[j][matrixIndices[i]] = matrixElements[i];
        }
    }

    double * newObj = new double [numCols];
    srand ( static_cast<unsigned int>(time(NULL) + 1));
    int randNum;

    // Shuffle the rows:
    // Put the rows in a random order
    // so that the optimal solution is a different corner point than the
    // starting point.
    int * index = new int [numRows];
    for (int i = 0; i < numRows; i++)
        index[i] = i;
    for (int i = 0; i < numRows; i++) {
        int temp = index[i];
        int randNumTemp = i + intRand(numRows - i);
        index[i] = index[randNumTemp];
        index[randNumTemp] = temp;
    }

    // Start finding corner points by iteratively doing the following:
    // - contruct a randomly tilted objective
    // - solve
    for (int i = 0; i < numRows; i++) {
        // TODO: that 10,000 could be a param in the member data
        if (solutions.numberSolutions  > 10000)
            break;
        randNum = intRand(2);
        for (int j = 0; j < numCols; j++) {
            // for row i and column j vary the coefficient "a bit"
            if (randNum == 1)
                // if the element is zero, then set the new obj
                // coefficient to 0.1 (i.e., round up)
                if (fabs(matrix[index[i]][j]) < primalTolerance)
                    newObj[j] = 0.1;
                else
                    // if the element is nonzero, then increase the new obj
                    // coefficient "a bit"
                    newObj[j] = matrix[index[i]][j] * 1.1;
            else
                // if randnum is 2, then
                // if the element is zero, then set the new obj coeffient
                // to NEGATIVE 0.1 (i.e., round down)
                if (fabs(matrix[index[i]][j]) < primalTolerance)
                    newObj[j] = -0.1;
                else
                    // if the element is nonzero, then DEcrease the new obj coeffienct "a bit"
                    newObj[j] = matrix[index[i]][j] * 0.9;
        }
        // Use the new "tilted" objective
        clpSolver->setObjective(newObj);

        // Based on the row sense, we decide whether to max or min
        if (rowSense[i] == 'L')
            clpSolver->setObjSense(-1);
        else
            clpSolver->setObjSense(1);

        // Solve with primal simplex
        simplex->primal(1);
        // rlh+ll: This was the original code. But we already have the
        // model pointer (it's in simplex). And, calling getModelPtr()
        // invalidates the cached data in the OsiClpSolverInterface
        // object, which means our precious rowsens is lost. So let's
        // not use the line below...
        /******* clpSolver->getModelPtr()->primal(1); */
        printf("---------------------------------------------------------------- %d\n", i);
    }
    // Iteratively do this process until...
    // either you reach the max number of corner points (aka 10K)
    // or all the rows have been used as an objective.

    // Look at solutions
    int numberSolutions = solutions.numberSolutions;
    //const char * integerInfo = simplex->integerInformation();
    //const double * columnLower = simplex->columnLower();
    //const double * columnUpper = simplex->columnUpper();
    printf("there are %d solutions\n", numberSolutions);

    // Up to here we have all the corner points
    // Now we need to do the random walks and roundings

    double ** cornerPoints = new double * [numberSolutions];
    for (int j = 0; j < numberSolutions; j++)
        cornerPoints[j] = solutions.solution[j];

    bool feasibility = 1;
    // rlh: use some COIN max instead of 1e30 (?)
    double bestObj = 1e30;
    std::vector< std::vector <double> > feasibles;
    int numFeasibles = 0;

    // Check the feasibility of the corner points
    int numCornerPoints = numberSolutions;

    const double * rhs = clpSolver->getRightHandSide();
    // rlh: row sense hasn't changed. why a fresh copy?
    // Delete next line.
    rowSense = clpSolver->getRowSense();

    for (int i = 0; i < numCornerPoints; i++) {
        //get the objective value for this this point
        double objValue = 0;
        for (int k = 0; k < numCols; k++)
            objValue += cornerPoints[i][k] * originalObjCoeff[k];

        if (objValue < bestObj) {
            // check integer feasibility
            feasibility = 1;
            for (int j = 0; j < numCols; j++) {
                if (varClassInt[j]) {
                    double closest = floor(cornerPoints[i][j] + 0.5);
                    if (fabs(cornerPoints[i][j] - closest) > primalTolerance) {
                        feasibility = 0;
                        break;
                    }
                }
            }
            // check all constraints satisfied
            if (feasibility) {
                for (int irow = 0; irow < numRows; irow++) {
                    double lhs = 0;
                    for (int j = 0; j < numCols; j++) {
                        lhs += matrix[irow][j] * cornerPoints[i][j];
                    }
                    if (rowSense[irow] == 'L' && lhs > rhs[irow] + primalTolerance) {
                        feasibility = 0;
                        break;
                    }
                    if (rowSense[irow] == 'G' && lhs < rhs[irow] - primalTolerance) {
                        feasibility = 0;
                        break;
                    }
                    if (rowSense[irow] == 'E' && (lhs - rhs[irow] > primalTolerance || lhs - rhs[irow] < -primalTolerance)) {
                        feasibility = 0;
                        break;
                    }
                }
            }

            if (feasibility) {
                numFeasibles++;
                feasibles.push_back(std::vector <double> (numCols));
                for (int k = 0; k < numCols; k++)
                    feasibles[numFeasibles-1][k] = cornerPoints[i][k];
                printf("obj: %f\n", objValue);
                if (objValue < bestObj)
                    bestObj = objValue;
            }
        }
    }
    int numFeasibleCorners;
    numFeasibleCorners = numFeasibles;
    //find the center of gravity of the corner points as the first random point
    double * rp = new double[numCols];
    for (int i = 0; i < numCols; i++) {
        rp[i] = 0;
        for (int j = 0; j < numCornerPoints; j++) {
            rp[i] += cornerPoints[j][i];
        }
        rp[i] = rp[i] / numCornerPoints;
    }

    //-------------------------------------------
    //main loop:
    // -generate the next random point
    // -round the random point
    // -check the feasibility of the random point
    //-------------------------------------------

    srand ( static_cast<unsigned int>(time(NULL) + 1));
    int numRandomPoints = 0;
    while (numRandomPoints < 50000) {
        numRandomPoints++;
        //generate the next random point
        int randomIndex = intRand(numCornerPoints);
        double random = CoinDrand48();
        for (int i = 0; i < numCols; i++) {
            rp[i] = (random * (cornerPoints[randomIndex][i] - rp[i])) + rp[i];
        }

        //CRISP ROUNDING
        //round the random point just generated
        double * roundRp = new double[numCols];
        for (int i = 0; i < numCols; i++) {
            roundRp[i] = rp[i];
            if (varClassInt[i]) {
                if (rp[i] >= 0) {
                    if (fmod(rp[i], 1) > 0.5)
                        roundRp[i] = floor(rp[i]) + 1;
                    else
                        roundRp[i] = floor(rp[i]);
                } else {
                    if (fabs(fmod(rp[i], 1)) > 0.5)
                        roundRp[i] = floor(rp[i]);
                    else
                        roundRp[i] = floor(rp[i]) + 1;

                }
            }
        }


        //SOFT ROUNDING
        // Look at original files for the "how to" on soft rounding;
        // Soft rounding omitted here.

        //Check the feasibility of the rounded random point
        // -Check the feasibility
        // -Get the rows sense
        rowSense = clpSolver->getRowSense();
        rhs = clpSolver->getRightHandSide();

        //get the objective value for this feasible point
        double objValue = 0;
        for (int i = 0; i < numCols; i++)
            objValue += roundRp[i] * originalObjCoeff[i];

        if (objValue < bestObj) {
            feasibility = 1;
            for (int i = 0; i < numRows; i++) {
                double lhs = 0;
                for (int j = 0; j < numCols; j++) {
                    lhs += matrix[i][j] * roundRp[j];
                }
                if (rowSense[i] == 'L' && lhs > rhs[i] + primalTolerance) {
                    feasibility = 0;
                    break;
                }
                if (rowSense[i] == 'G' && lhs < rhs[i] - primalTolerance) {
                    feasibility = 0;
                    break;
                }
                if (rowSense[i] == 'E' && (lhs - rhs[i] > primalTolerance || lhs - rhs[i] < -primalTolerance)) {
                    feasibility = 0;
                    break;
                }
            }
            if (feasibility) {
                printf("Feasible Found.\n");
                printf("%.2f\n", CoinCpuTime() - start);
                numFeasibles++;
                feasibles.push_back(std::vector <double> (numCols));
                for (int i = 0; i < numCols; i++)
                    feasibles[numFeasibles-1][i] = roundRp[i];
                printf("obj: %f\n", objValue);
                if (objValue < bestObj)
                    bestObj = objValue;
            }
        }
        delete [] roundRp;
    }
    printf("Number of Feasible Corners: %d\n", numFeasibleCorners);
    printf("Number of Feasibles Found: %d\n", numFeasibles);
    if (numFeasibles > 0)
        printf("Best Objective: %f\n", bestObj);
    printf("time: %.2f\n", CoinCpuTime() - start);

    if (numFeasibles == 0) {
        // cleanup
        delete [] varClassInt;
        for (int i = 0; i < numRows; i++)
            delete matrix[i];
        delete [] matrix;
        delete [] newObj;
        delete [] index;
        for (int i = 0; i < numberSolutions; i++)
            delete cornerPoints[i];
        delete [] cornerPoints;
        delete [] rp;
        return 0;
    }

    // We found something better
    solutionValue = bestObj;
    for (int k = 0; k < numCols; k++) {
        betterSolution[k] =  feasibles[numFeasibles-1][k];
    }
    delete [] varClassInt;
    for (int i = 0; i < numRows; i++)
        delete matrix[i];
    delete [] matrix;
    delete [] newObj;
    delete [] index;
    for (int i = 0; i < numberSolutions; i++)
        delete cornerPoints[i];
    delete [] cornerPoints;
    delete [] rp;
    std::cout << "Leaving the Randomized Rounding Heuristic" << std::endl;
    return 1;

}
Exemplo n.º 18
0
const CoinPresolveAction *subst_constraint_action::presolve (
    CoinPresolveMatrix *prob,
    const int *implied_free, const int *whichFree, int numberFree,
    const CoinPresolveAction *next, int maxLook)
{

# if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0
# if PRESOLVE_DEBUG > 0
  std::cout
    << "Entering subst_constraint_action::presolve, fill level "
    << maxLook << ", " << numberFree << " candidates." << std::endl ;
# endif
  presolve_consistent(prob) ;
  presolve_links_ok(prob) ;
  presolve_check_sol(prob) ;
  presolve_check_nbasic(prob) ;
# endif

# if PRESOLVE_DEBUG > 0 || COIN_PRESOLVE_TUNING > 0
  int startEmptyRows = 0 ;
  int startEmptyColumns = 0 ;
  startEmptyRows = prob->countEmptyRows() ;
  startEmptyColumns = prob->countEmptyCols() ;
# if COIN_PRESOLVE_TUNING > 0
  double startTime = 0.0 ;
  if (prob->tuning_) startTime = CoinCpuTime() ;
# endif
# endif

/*
  Unpack the row- and column-major representations.
*/
  const int ncols = prob->ncols_ ;
  const int nrows = prob->nrows_ ;

  CoinBigIndex *rowStarts = prob->mrstrt_ ;
  int *rowLengths = prob->hinrow_ ;
  double *rowCoeffs = prob->rowels_ ;
  int *colIndices = prob->hcol_ ;
  presolvehlink *rlink = prob->rlink_ ;

  CoinBigIndex *colStarts = prob->mcstrt_ ;
  int *colLengths = prob->hincol_ ;
  double *colCoeffs = prob->colels_ ;
  int *rowIndices = prob->hrow_ ;
  presolvehlink *clink = prob->clink_ ;

/*
  Row bounds and activity, objective.
*/
  double *rlo = prob->rlo_ ;
  double *rup = prob->rup_ ;
  double *acts = prob->acts_ ;
  double *cost = prob->cost_ ;


  const double tol = prob->feasibilityTolerance_ ;

  action *actions = new action [ncols] ;
# ifdef ZEROFAULT
  CoinZeroN(reinterpret_cast<char *>(actions),ncols*sizeof(action)) ;
# endif
  int nactions = 0 ;
/*
  This array is used to hold the indices of columns involved in substitutions,
  where we have the potential for cancellation. At the end they'll be
  checked to eliminate any actual zeros that may result. At the end of
  processing of each target row, the column indices of the target row are
  copied into zerocols.

  NOTE that usefulColumnInt_ is already in use for parameters implied_free and
  whichFree when this routine is called from implied_free.
*/
  int *zerocols = new int[ncols] ;
  int nzerocols = 0 ;

  int *x_to_y = new int[ncols] ;

  int *rowsUsed = &prob->usefulRowInt_[0] ;
  int nRowsUsed = 0 ;
/*
  Open a loop to process the (equality r, implied free variable t) pairs
  in whichFree and implied_free.

  It can happen that removal of (row, natural singleton) pairs back in
  implied_free will reduce the length of column t. It can also happen
  that previous processing here has resulted in fillin or cancellation. So
  check again for column length and exclude natural singletons and overly
  dense columns.
*/
  for (int iLook = 0 ; iLook < numberFree ; iLook++) {
    const int tgtcol = whichFree[iLook] ;
    const int tgtcol_len = colLengths[tgtcol] ;
    const int tgtrow = implied_free[iLook] ;
    const int tgtrow_len = rowLengths[tgtrow] ;

    assert(fabs(rlo[tgtrow]-rup[tgtrow]) < tol) ;

    if (colLengths[tgtcol] < 2 || colLengths[tgtcol] > maxLook) {
#     if PRESOLVE_DEBUG > 3
      std::cout
        << "    skipping eqn " << tgtrow << " x(" << tgtcol
	<< "); length now " << colLengths[tgtcol] << "." << std::endl ;
#     endif
      continue ;
    }

    CoinBigIndex tgtcs = colStarts[tgtcol] ;
    CoinBigIndex tgtce = tgtcs+colLengths[tgtcol] ;
/*
  A few checks to make sure that the candidate pair is still suitable.
  Processing candidates earlier in the list can eliminate coefficients.
    * Don't use this pair if any involved row i has become a row singleton
      or empty.
    * Don't use this pair if any involved row has been modified as part of
      the processing for a previous candidate pair on this call.
    * Don't use this pair if a(i,tgtcol) has become zero.

  The checks on a(i,tgtcol) seem superfluous but it's possible that
  implied_free identified two candidate pairs to eliminate the same column. If
  we've already processed one of them, we could be in trouble.
*/
    double tgtcoeff = 0.0 ;
    bool dealBreaker = false ;
    for (CoinBigIndex kcol = tgtcs ; kcol < tgtce ; ++kcol) {
      const int i = rowIndices[kcol] ;
      if (rowLengths[i] < 2 || prob->rowUsed(i)) {
        dealBreaker = true ;
	break ;
      }
      const double aij = colCoeffs[kcol] ;
      if (fabs(aij) <= ZTOLDP2) {
	dealBreaker = true ;
	break ;
      }
      if (i == tgtrow) tgtcoeff = aij ;
    }

    if (dealBreaker == true) {
#     if PRESOLVE_DEBUG > 3
      std::cout
        << "    skipping eqn " << tgtrow << " x(" << tgtcol
	<< "); deal breaker (1)." << std::endl ;
#     endif
      continue ;
    }
/*
  Check for numerical stability.A large coeff_factor will inflate the
  coefficients in the substitution formula.
*/
    dealBreaker = false ;
    for (CoinBigIndex kcol = tgtcs ; kcol < tgtce ; ++kcol) {
      const double coeff_factor = fabs(colCoeffs[kcol]/tgtcoeff) ;
      if (coeff_factor > 10.0)
	dealBreaker = true ;
    }
/*
  Given enough target rows with sufficient overlap, there's an outside chance
  we could overflow zerocols. Unlikely to ever happen.
*/
    if (!dealBreaker && nzerocols+rowLengths[tgtrow] >= ncols)
      dealBreaker = true ;
    if (dealBreaker == true) {
#     if PRESOLVE_DEBUG > 3
      std::cout
        << "    skipping eqn " << tgtrow << " x(" << tgtcol
	<< "); deal breaker (2)." << std::endl ;
#     endif
      continue ;
    }
/*
  If c(t) != 0, we will need to modify the objective coefficients and remember
  the original objective.
*/
    const bool nonzero_cost = (fabs(cost[tgtcol]) > tol) ;
    double *costsx = (nonzero_cost?new double[rowLengths[tgtrow]]:0) ;

#   if PRESOLVE_DEBUG > 1
    std::cout << "  Eliminating row " << tgtrow << ", col " << tgtcol ;
    if (nonzero_cost) std::cout << ", cost " << cost[tgtcol] ;
    std::cout << "." << std::endl ;
#   endif

/*
  Count up the total number of coefficients in entangled rows and mark them as
  contaminated.
*/
    int ntotels = 0 ;
    for (CoinBigIndex kcol = tgtcs ; kcol < tgtce ; ++kcol) {
      const int i = rowIndices[kcol] ;
      ntotels += rowLengths[i] ;
      PRESOLVEASSERT(!prob->rowUsed(i)) ;
      prob->setRowUsed(i) ;
      rowsUsed[nRowsUsed++] = i ;
    }
/*
  Create the postsolve object. Copy in all the affected rows. Take the
  opportunity to mark the entangled rows as changed and put them on the list
  of rows to process in the next round.

  coeffxs in particular holds the coefficients of the target column.
*/
    action *ap = &actions[nactions++] ;

    ap->col = tgtcol ;
    ap->rowy = tgtrow ;
    PRESOLVE_DETAIL_PRINT(printf("pre_subst %dC %dR E\n",tgtcol,tgtrow)) ;

    ap->nincol = tgtcol_len ;
    ap->rows = new int[tgtcol_len] ;
    ap->rlos = new double[tgtcol_len] ;
    ap->rups = new double[tgtcol_len] ;

    ap->costsx = costsx ;
    ap->coeffxs = new double[tgtcol_len] ;

    ap->ninrowxs = new int[tgtcol_len] ;
    ap->rowcolsxs = new int[ntotels] ;
    ap->rowelsxs = new double[ntotels] ;

    ntotels = 0 ;
    for (CoinBigIndex kcol = tgtcs ; kcol < tgtce ; ++kcol) {
      const int ndx = kcol-tgtcs ;
      const int i = rowIndices[kcol] ;
      const CoinBigIndex krs = rowStarts[i] ;
      prob->addRow(i) ;
      ap->rows[ndx] = i ;
      ap->ninrowxs[ndx] = rowLengths[i] ;
      ap->rlos[ndx] = rlo[i] ;
      ap->rups[ndx] = rup[i] ;
      ap->coeffxs[ndx] = colCoeffs[kcol] ;

      CoinMemcpyN(&colIndices[krs],rowLengths[i],&ap->rowcolsxs[ntotels]) ;
      CoinMemcpyN(&rowCoeffs[krs],rowLengths[i],&ap->rowelsxs[ntotels]) ;

      ntotels += rowLengths[i] ;
    }

    CoinBigIndex tgtrs = rowStarts[tgtrow] ;
    CoinBigIndex tgtre = tgtrs+rowLengths[tgtrow] ;

/*
  Adjust the objective coefficients based on the substitution formula
    c'(j) = c(j) - a(rj)c(t)/a(rt)
*/
    if (nonzero_cost) {
      const double tgtcost = cost[tgtcol] ;
      for (CoinBigIndex krow = tgtrs ; krow < tgtre ; krow ++) {
	const int j = colIndices[krow] ;
	prob->addCol(j) ;
	costsx[krow-tgtrs] = cost[j] ;
	double coeff = rowCoeffs[krow] ;
	cost[j] -= (tgtcost*coeff)/tgtcoeff ;
      }
      prob->change_bias(tgtcost*rlo[tgtrow]/tgtcoeff) ;
      cost[tgtcol] = 0.0 ;
    }

#   if PRESOLVE_DEBUG > 1
    std::cout << "  tgt (" << tgtrow << ") (" << tgtrow_len << "): " ;
    for (CoinBigIndex krow = tgtrs ; krow < tgtre ; ++krow) {
      const int j = colIndices[krow] ;
      const double arj = rowCoeffs[krow] ;
      std::cout
	<< "x(" << j << ") = " << arj << " (" << colLengths[j] << ") " ;
    }
    std::cout << std::endl ;
#   endif
    // kill small if wanted
    int relax= (prob->presolveOptions()&0x60000)>>17;
    double tolerance = 1.0e-12;
    for (int i=0;i<relax;i++)
      tolerance *= 10.0;

/*
  Sort the target row for efficiency when doing elimination.
*/
      CoinSort_2(colIndices+tgtrs,colIndices+tgtre,rowCoeffs+tgtrs) ;
/*
  Get down to the business of substituting for tgtcol in the entangled rows.
  Open a loop to walk the target column. We walk the saved column because the
  bulk store can change as we work. We don't want to repeat or miss a row.
*/
    for (int colndx = 0 ; colndx < tgtcol_len ; ++colndx) {
      int i = ap->rows[colndx] ;
      if (i == tgtrow) continue ;

      double ait = ap->coeffxs[colndx] ;
      double coeff_factor = -ait/tgtcoeff ;
      
      CoinBigIndex krs = rowStarts[i] ;
      CoinBigIndex kre = krs+rowLengths[i] ;

#     if PRESOLVE_DEBUG > 1
      std::cout
	<< "  subst pre (" << i << ") (" << rowLengths[i] << "): " ;
      for (CoinBigIndex krow = krs ; krow < kre ; ++krow) {
	const int j = colIndices[krow] ;
	const double aij = rowCoeffs[krow] ;
	std::cout
	  << "x(" << j << ") = " << aij << " (" << colLengths[j] << ") " ;
      }
      std::cout << std::endl ;
#     endif

/*
  Sort the row for efficiency and call add_row to do the actual business of
  changing coefficients due to substitution. This has the potential to trigger
  compaction of the row-major bulk store, so update bulk store indices.
*/
      CoinSort_2(colIndices+krs,colIndices+kre,rowCoeffs+krs) ;
      
      bool outOfSpace = add_row(rowStarts,rlo,acts,rup,rowCoeffs,colIndices,
				rowLengths,rlink,nrows,coeff_factor,tolerance,i,tgtrow,
				x_to_y) ;
      if (outOfSpace)
	throwCoinError("out of memory","CoinImpliedFree::presolve") ;

      krs = rowStarts[i] ;
      kre = krs+rowLengths[i] ;
      tgtrs = rowStarts[tgtrow] ;
      tgtre = tgtrs+rowLengths[tgtrow] ;

#     if PRESOLVE_DEBUG > 1
      std::cout
	<< "  subst aft (" << i << ") (" << rowLengths[i] << "): " ;
      for (CoinBigIndex krow = krs ; krow < kre ; ++krow) {
	const int j = colIndices[krow] ;
	const double aij = rowCoeffs[krow] ;
	std::cout
	  << "x(" << j << ") = " << aij << " (" << colLengths[j] << ") " ;
      }
      std::cout << std::endl ;
#     endif

/*
  Now update the column-major representation from the row-major
  representation. This is easy if the coefficient already exists, but
  painful if there's fillin. presolve_find_row1 will return the index of
  the row in the column vector, or one past the end if it's missing. If the
  coefficient is fill, presolve_expand_col will make sure that there's room in
  the column for one more coefficient. This may require that the column be
  moved in the bulk store, so we need to update kcs and kce.

  Once we're done, a(it) = 0 (i.e., we've eliminated x(t) from row i).
  Physically remove the explicit zero from the row-major representation
  with presolve_delete_from_row.
*/
      for (CoinBigIndex rowndx = 0 ; rowndx < tgtrow_len ; ++rowndx) {
	const CoinBigIndex ktgt = tgtrs+rowndx ;
	const int j = colIndices[ktgt] ;
	CoinBigIndex kcs = colStarts[j] ;
	CoinBigIndex kce = kcs+colLengths[j] ;

	assert(colIndices[krs+x_to_y[rowndx]] == j) ;

	const double coeff = rowCoeffs[krs+x_to_y[rowndx]] ;

	CoinBigIndex kcol = presolve_find_row1(i,kcs,kce,rowIndices) ;
	
	if (kcol < kce) {
	  colCoeffs[kcol] = coeff ;
	} else {
	  outOfSpace = presolve_expand_col(colStarts,colCoeffs,rowIndices,
	  				   colLengths,clink,ncols,j) ;
	  if (outOfSpace)
	    throwCoinError("out of memory","CoinImpliedFree::presolve") ;
	  kcs = colStarts[j] ;
	  kce = kcs+colLengths[j] ;
	  
	  rowIndices[kce] = i ;
	  colCoeffs[kce] = coeff ;
	  colLengths[j]++ ;
	}
      }
      presolve_delete_from_row(i,tgtcol,
      			       rowStarts,rowLengths,colIndices,rowCoeffs) ;
#     if PRESOLVE_DEBUG > 1
      kre-- ;
      std::cout
	<< "  subst fin (" << i << ") (" << rowLengths[i] << "): " ;
      for (CoinBigIndex krow = krs ; krow < kre ; ++krow) {
	const int j = colIndices[krow] ;
	const double aij = rowCoeffs[krow] ;
	std::cout
	  << "x(" << j << ") = " << aij << " (" << colLengths[j] << ") " ;
      }
      std::cout << std::endl ;
#     endif
      
    }
/*
  End of the substitution loop.

  Record the column indices of the target row so we can groom these columns
  later to remove possible explicit zeros.
*/
    CoinMemcpyN(&colIndices[rowStarts[tgtrow]],rowLengths[tgtrow],
    		&zerocols[nzerocols]) ;
    nzerocols += rowLengths[tgtrow] ;
/*
  Remove the target equality from the column- and row-major representations
  Somewhat painful in the colum-major representation.  We have to walk the
  target row in the row-major representation and look up each coefficient
  in the column-major representation.
*/
    for (CoinBigIndex krow = tgtrs ; krow < tgtre ; ++krow) {
      const int j = colIndices[krow] ;
#     if PRESOLVE_DEBUG > 1
      std::cout
        << "  removing row " << tgtrow << " from col " << j << std::endl ;
#     endif
      presolve_delete_from_col(tgtrow,j,
      			       colStarts,colLengths,rowIndices,colCoeffs) ;
      if (colLengths[j] == 0) {
        PRESOLVE_REMOVE_LINK(clink,j) ;
      }
    }
/*
  Finally, physically remove the column from the column-major representation
  and the row from the row-major representation.
*/
    PRESOLVE_REMOVE_LINK(clink, tgtcol) ;
    colLengths[tgtcol] = 0 ;

    PRESOLVE_REMOVE_LINK(rlink, tgtrow) ;
    rowLengths[tgtrow] = 0 ;

    rlo[tgtrow] = 0.0 ;
    rup[tgtrow] = 0.0 ;

#   if PRESOLVE_CONSISTENCY > 0
    presolve_links_ok(prob) ;
    presolve_consistent(prob) ;
#   endif

  }
/*
  That's it, we've processed all the candidate pairs.

  Clear the row used flags.
*/
  for (int i = 0 ; i < nRowsUsed ; i++) prob->unsetRowUsed(rowsUsed[i]) ;
/*
  Trim the array of substitution transforms and queue up objects for postsolve.
  Also groom the problem representation to remove explicit zeros.
*/
  if (nactions) {
#   if PRESOLVE_SUMMARY > 0
    std::cout << "NSUBSTS: " << nactions << std::endl ;
#   endif
    next = new subst_constraint_action(nactions,
				   CoinCopyOfArray(actions,nactions),next) ;
    next = drop_zero_coefficients_action::presolve(prob,zerocols,
    						   nzerocols, next) ;
#   if PRESOLVE_CONSISTENCY > 0
    presolve_links_ok(prob) ;
    presolve_consistent(prob) ;
#   endif
  }

  deleteAction(actions,action*) ;
  delete [] x_to_y ;
  delete [] zerocols ;

# if COIN_PRESOLVE_TUNING > 0
  if (prob->tuning_) double thisTime = CoinCpuTime() ;
# endif
# if PRESOLVE_CONSISTENCY > 0 || PRESOLVE_DEBUG > 0
  presolve_check_sol(prob) ;
# endif
# if PRESOLVE_DEBUG > 0 || COIN_PRESOLVE_TUNING > 0
  int droppedRows = prob->countEmptyRows()-startEmptyRows ;
  int droppedColumns = prob->countEmptyCols()-startEmptyColumns ;
  std::cout
    << "Leaving subst_constraint_action::presolve, "
    << droppedRows << " rows, " << droppedColumns << " columns dropped" ;
# if COIN_PRESOLVE_TUNING > 0
  std::cout << " in " << thisTime-startTime << "s" ;
# endif
  std::cout << "." << std::endl ;
# endif

  return (next) ;
}
Exemplo n.º 19
0
int main (int argc, const char *argv[])
{

  OsiClpSolverInterface solver1;

  /*
    We are going to treat x1 and x2 as integer and x3 and x4 as a set.
    We define two new variables y1 == x1*x4 and y2 == x2*x3.
    We define a variable z == x1*x4/x2*x3 so y2*z == y1
    (we will treat y2 as a set)
    Then we have objective - minimize w1 + w2 where
    w1 - w2 = 1.0/6.931 - z

    The model would be a lot smaller if we had column generation.
  */
  // Create model 
  CoinModel build;
  // Keep values of all variables for reporting purposes even if not necessary
  /*
    z is first, then x then y1,y2 then w1,w2 
    then y1 stuff, y2 stuff and finally y2 -> z stuff.
    For rows same but 2 per y then rest of z stuff
  */
  int loInt=12;
  int hiInt=60;
  int ybaseA=5, ybaseB=9, ylen=hiInt-loInt+1;
  int base = ybaseB+2*2*ylen;
  int yylen = hiInt*hiInt-loInt*loInt+1;
  int zbase = 10;
  int i;
  // Do single variables
  double value[] ={1.0,1.0};
  int row[2];
  /* z - obviously we can't choose bounds too tight but we need bounds
     so choose 20% off as obviously feasible.
     fastest way to solve would be too run for a few seconds to get
     tighter bounds then re-formulate and solve.  */
  double loose=0.2;
  double loZ = (1-loose)*(1.0/6.931), hiZ = (1+loose)*(1.0/6.931);
  row[0]=0; // for reporting
  row[1]=zbase+1; // for real use
  build.addColumn(2,row,value,loZ, hiZ, 0.0);
  // x
  for (i=0;i<4;i++) {
    row[0]=i+1;
    build.addColumn(1,row,value,loInt, hiInt,0.0);
    // we don't need to say x2, x3 integer but won't hurt
    build.setInteger(i+1);
  }
  // y
  for (i=0;i<2;i++) {
    // y from x*x, and convexity
    row[0]=ybaseA+2*i;
    if (i==0)
      row[1]=zbase+2; // yb*z == ya
    else
      row[1]=zbase-1; // to feed into z
    build.addColumn(2,row,value,loInt*loInt, hiInt*hiInt,0.0);
    // we don't need to say integer but won't hurt
    build.setInteger(ybaseA+i);
  }
  // skip z convexity put w in final equation
  row[0]=zbase+1;
  build.addColumn(1,row,value,0.0,1.0,1.0);
  value[0]=-1.0;
  build.addColumn(1,row,value,0.0,1.0,1.0);
  // Do columns so we know where each is
  for (i=ybaseB;i<base+(2*yylen);i++)
    build.setColumnBounds(i,0.0,1.0);
  // Now do rows
  // z definition
  build.setRowBounds(0,0.0,0.0);
  for (i=0;i<yylen;i++) {
    // l
    build.setElement(0,base+2*i,-loZ);
    // u
    build.setElement(0,base+2*i+1,-hiZ);
  }
  // x
  for (i=0;i<2;i++) {
    int iVarRow = 1+i;
    int iSetRow = 4-i; // as it is x1*x4 and x2*x3
    build.setRowBounds(iVarRow,0.0,0.0);
    build.setRowBounds(iSetRow,0.0,0.0);
    int j;
    int base2 = ybaseB + 2*ylen*i;
    for (j=0;j<ylen;j++) {
      // l
      build.setElement(iVarRow,base2+2*j,-loInt);
      build.setElement(iSetRow,base2+2*j,-loInt-j);
      // u
      build.setElement(iVarRow,base2+2*j+1,-hiInt);
      build.setElement(iSetRow,base2+2*j+1,-loInt-j);
    }
  }
  // y
  for (i=0;i<2;i++) {
    int iRow = 5+2*i;
    int iConvex = iRow+1;
    build.setRowBounds(iRow,0.0,0.0);
    build.setRowBounds(iConvex,1.0,1.0);
    int j;
    int base2 = ybaseB + 2*ylen*i;
    for (j=0;j<ylen;j++) {
      // l
      build.setElement(iRow,base2+2*j,-loInt*(j+loInt));
      build.setElement(iConvex,base2+2*j,1.0);
      // u
      build.setElement(iRow,base2+2*j+1,-hiInt*(j+loInt));
      build.setElement(iConvex,base2+2*j+1,1.0);
    }
  }
  // row that feeds into z and convexity
  build.setRowBounds(zbase-1,0.0,0.0);
  build.setRowBounds(zbase,1.0,1.0);
  for (i=0;i<yylen;i++) {
    // l
    build.setElement(zbase-1,base+2*i,-(i+loInt*loInt));
    build.setElement(zbase,base+2*i,1.0);
    // u
    build.setElement(zbase-1,base+2*i+1,-(i+loInt*loInt));
    build.setElement(zbase,base+2*i+1,1.0);
  }
  // and real equation rhs
  build.setRowBounds(zbase+1,1.0/6.931,1.0/6.931);
  // z*y
  build.setRowBounds(zbase+2,0.0,0.0);
  for (i=0;i<yylen;i++) {
    // l
    build.setElement(zbase+2,base+2*i,-(i+loInt*loInt)*loZ);
    // u
    build.setElement(zbase+2,base+2*i+1,-(i+loInt*loInt)*hiZ);
  }
  // And finally two more rows to break symmetry
  build.setRowBounds(zbase+3,-COIN_DBL_MAX,0.0);
  build.setElement(zbase+3,1,1.0);
  build.setElement(zbase+3,4,-1.0);
  build.setRowBounds(zbase+4,-COIN_DBL_MAX,0.0);
  build.setElement(zbase+4,2,1.0);
  build.setElement(zbase+4,3,-1.0);
  solver1.loadFromCoinModel(build);
  // To make CbcBranchLink simpler assume that all variables with same i are consecutive
  
  double time1 = CoinCpuTime();
  solver1.initialSolve();
  solver1.writeMps("bad");
  CbcModel model(solver1);
  model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
  model.solver()->setHintParam(OsiDoScale,false,OsiHintTry);

  CbcObject ** objects = new CbcObject * [3];
  /* Format is number in sets, number in each link, first variable in matrix)
      and then a weight for each in set to say where to branch.  
      In this case use NULL to say 0,1,2 ...
      Finally a set number as ID.
  */
  objects[0]=new CbcLink(&model,ylen,2,ybaseB,NULL,0);
  objects[0]->setPriority(10);
  objects[1]=new CbcLink(&model,ylen,2,ybaseB+2*ylen,NULL,0);
  objects[1]->setPriority(20);
  objects[2]=new CbcLink(&model,yylen,2,base,NULL,0);
  objects[2]->setPriority(1);
  model.addObjects(3,objects);
  for (i=0;i<3;i++)
    delete objects[i];
  delete [] objects;
  model.messageHandler()->setLogLevel(1);
  // Do complete search
  
  model.setDblParam(CbcModel::CbcMaximumSeconds,1200.0);
  model.setDblParam(CbcModel::CbcCutoffIncrement,1.0e-8);
  model.branchAndBound();

  std::cout<<"took "<<CoinCpuTime()-time1<<" seconds, "
	   <<model.getNodeCount()<<" nodes with objective "
	   <<model.getObjValue()
	   <<(!model.status() ? " Finished" : " Not finished")
	   <<std::endl;


  if (model.getMinimizationObjValue()<1.0e50) {
    
    const double * solution = model.bestSolution();
    int numberColumns = model.solver()->getNumCols();
    double x1=solution[1];
    double x2=solution[2];
    double x3=solution[3];
    double x4=solution[4];
    printf("Optimal solution %g %g %g %g\n",x1,x2,x3,x4);
    for (int iColumn=0;iColumn<numberColumns;iColumn++) {
      double value=solution[iColumn];
      if (fabs(value)>1.0e-7) 
	std::cout<<iColumn<<" "<<value<<std::endl;
    }
  }
  return 0;
}    
Exemplo n.º 20
0
bool
BlisHeurRound::searchSolution(double & solutionValue, double * betterSolution)
{
    bool foundBetter = false;
    
    if (strategy_ == -2) {
        // This heuristic has been disabled.
        return foundBetter;
    }

    //------------------------------------------------------
    // Start to search solution ...
    //------------------------------------------------------

    double start = CoinCpuTime();
    
    // Get a copy of original matrix (and by row for rounding);
    matrix_ = *(model_->solver()->getMatrixByCol());
    matrixByRow_ = *(model_->solver()->getMatrixByRow());
    seed_ = 1;

    OsiSolverInterface * solver = model_->solver();
    const double * lower = solver->getColLower();
    const double * upper = solver->getColUpper();
    const double * rowLower = solver->getRowLower();
    const double * rowUpper = solver->getRowUpper();
    const double * solution = solver->getColSolution();
    const double * objective = solver->getObjCoefficients();
    double integerTolerance = 1.0e-5;
    //model_->getDblParam(BlisModel::BlisIntegerTolerance);
    double primalTolerance;
    solver->getDblParam(OsiPrimalTolerance, primalTolerance);

    int numberRows = matrix_.getNumRows();

    int numberIntegers = model_->getNumIntVars();
    const int * integerVariable = model_->getIntVars();
    int i;
    double direction = solver->getObjSense();
    double newSolutionValue = direction * solver->getObjValue();

    // Column copy
    const double * element = matrix_.getElements();
    const int * row = matrix_.getIndices();
    const int * columnStart = matrix_.getVectorStarts();
    const int * columnLength = matrix_.getVectorLengths();
    // Row copy
    const double * elementByRow = matrixByRow_.getElements();
    const int * column = matrixByRow_.getIndices();
    const int * rowStart = matrixByRow_.getVectorStarts();
    const int * rowLength = matrixByRow_.getVectorLengths();

    // Get solution array for heuristic solution
    int numberColumns = solver->getNumCols();
    double * newSolution = new double [numberColumns];
    memcpy(newSolution, solution, numberColumns * sizeof(double));

    double * rowActivity = new double[numberRows];
    memset(rowActivity, 0, numberRows*sizeof(double));
    for (i = 0; i < numberColumns; i++) {
	int j;
	double value = newSolution[i];
	if (value) {
	    for (j = columnStart[i];
		 j < columnStart[i] + columnLength[i]; j++) {
		int iRow = row[j];
		rowActivity[iRow] += value*element[j];
	    }
	}
    }
    // check was feasible - if not adjust (cleaning may move)
    for (i = 0; i < numberRows; i++) {
	if(rowActivity[i] < rowLower[i]) {
	    //assert (rowActivity[i]>rowLower[i]-1000.0*primalTolerance);
	    rowActivity[i] = rowLower[i];
	} else if(rowActivity[i] > rowUpper[i]) {
	    //assert (rowActivity[i]<rowUpper[i]+1000.0*primalTolerance);
	    rowActivity[i] = rowUpper[i];
	}
    }
    for (i = 0; i < numberIntegers; i++) {
	int iColumn = integerVariable[i];
	double value = newSolution[iColumn];
	if (fabs(floor(value + 0.5) - value) > integerTolerance) {
	    double below = floor(value);
	    double newValue = newSolution[iColumn];
	    double cost = direction * objective[iColumn];
	    double move;
	    if (cost > 0.0) {
		// try up
		move = 1.0 - (value - below);
	    } else if (cost < 0.0) {
		// try down
		move = below - value;
	    } else {
		// won't be able to move unless we can grab another variable
		// just for now go down
		move = below-value;
	    }
	    newValue += move;
	    newSolution[iColumn] = newValue;
	    newSolutionValue += move * cost;
	    int j;
	    for (j = columnStart[iColumn];
		 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
		int iRow = row[j];
		rowActivity[iRow] += move * element[j];
	    }
	}
    }

    double penalty = 0.0;
  
    // see if feasible
    for (i = 0; i < numberRows; i++) {
	double value = rowActivity[i];
	double thisInfeasibility = 0.0;
	if (value < rowLower[i] - primalTolerance)
	    thisInfeasibility = value - rowLower[i];
	else if (value > rowUpper[i] + primalTolerance)
	    thisInfeasibility = value - rowUpper[i];
	if (thisInfeasibility) {
	    // See if there are any slacks I can use to fix up
	    // maybe put in coding for multiple slacks?
	    double bestCost = 1.0e50;
	    int k;
	    int iBest = -1;
	    double addCost = 0.0;
	    double newValue = 0.0;
	    double changeRowActivity = 0.0;
	    double absInfeasibility = fabs(thisInfeasibility);
	    for (k = rowStart[i]; k < rowStart[i] + rowLength[i]; k++) {
		int iColumn = column[k];
		if (columnLength[iColumn] == 1) {
		    double currentValue = newSolution[iColumn];
		    double elementValue = elementByRow[k];
		    double lowerValue = lower[iColumn];
		    double upperValue = upper[iColumn];
		    double gap = rowUpper[i] - rowLower[i];
		    double absElement = fabs(elementValue);
		    if (thisInfeasibility * elementValue > 0.0) {
			// we want to reduce
			if ((currentValue - lowerValue) * absElement >= 
			    absInfeasibility) {
			    
			    // possible - check if integer
			    double distance = absInfeasibility / absElement;
			    double thisCost = 
				-direction * objective[iColumn] * distance;
			    if (solver->isInteger(iColumn)) {
				distance = ceil(distance - primalTolerance);
				assert (currentValue - distance >= 
					lowerValue - primalTolerance);
				if (absInfeasibility - distance * absElement 
				    < -gap - primalTolerance)
				    thisCost = 1.0e100; // no good
				else
				    thisCost = 
					-direction*objective[iColumn]*distance;
			    }
			    if (thisCost < bestCost) {
				bestCost = thisCost;
				iBest = iColumn;
				addCost = thisCost;
				newValue = currentValue - distance;
				changeRowActivity = -distance * elementValue;
			    }
			}
		    } else {
			// we want to increase
			if ((upperValue - currentValue) * absElement >= 
			    absInfeasibility) {
			    // possible - check if integer
			    double distance = absInfeasibility / absElement;
			    double thisCost = 
				direction * objective[iColumn] * distance;
			    if (solver->isInteger(iColumn)) {
				distance = ceil(distance - 1.0e-7);
				assert (currentValue - distance <= 
					upperValue + primalTolerance);
				if (absInfeasibility - distance * absElement 
				    < -gap - primalTolerance)
				    thisCost = 1.0e100; // no good
				else
				    thisCost = 
					direction*objective[iColumn]*distance;
			    }
			    if (thisCost < bestCost) {
				bestCost = thisCost;
				iBest = iColumn;
				addCost = thisCost;
				newValue = currentValue + distance;
				changeRowActivity = distance * elementValue;
			    }
			}
		    }
		}
	    }
	    if (iBest >= 0) {
		/*printf("Infeasibility of %g on row %d cost %g\n",
		  thisInfeasibility,i,addCost);*/
		newSolution[iBest] = newValue;
		thisInfeasibility = 0.0;
		newSolutionValue += addCost;
		rowActivity[i] += changeRowActivity;
	    }
	    penalty += fabs(thisInfeasibility);
	}
    }

    // Could also set SOS (using random) and repeat
    if (!penalty) {
	// Got a feasible solution. Try to improve.
	//seed_++;
	//CoinSeedRandom(seed_);
	// Random number between 0 and 1.
        
	double randomNumber = CoinDrand48();
	int iPass;
	int start[2];
	int end[2];
	int iRandom = (int) (randomNumber * ((double) numberIntegers));
	start[0] = iRandom;
	end[0] = numberIntegers;
	start[1] = 0;
	end[1] = iRandom;
	for (iPass = 0; iPass < 2; iPass++) {
	    int i;
	    for (i = start[iPass]; i < end[iPass]; i++) {
		int iColumn = integerVariable[i];
#ifdef BLIS_DEBUG
		double value = newSolution[iColumn];
		assert(fabs(floor(value + 0.5) - value) < integerTolerance);
#endif
		double cost = direction * objective[iColumn];
		double move = 0.0;
		if (cost > 0.0)
		    move = -1.0;
		else if (cost < 0.0)
		    move = 1.0;
		while (move) {
		    bool good = true;
		    double newValue = newSolution[iColumn] + move;
		    if (newValue < lower[iColumn] - primalTolerance||
			newValue > upper[iColumn] + primalTolerance) {
			move = 0.0;
		    } else {
			// see if we can move
			int j;
			for (j = columnStart[iColumn];
			     j < columnStart[iColumn] + columnLength[iColumn];
			     j++) {
			    int iRow = row[j];
			    double newActivity = 
				rowActivity[iRow] + move*element[j];
			    if (newActivity < rowLower[iRow] - primalTolerance
				||
				newActivity > rowUpper[iRow]+primalTolerance) {
				good = false;
				break;
			    }
			}
			if (good) {
			    newSolution[iColumn] = newValue;
			    newSolutionValue += move * cost;
			    int j;
			    for (j = columnStart[iColumn];
				 j < columnStart[iColumn] + 
				     columnLength[iColumn]; j++) {
				int iRow = row[j];
				rowActivity[iRow] += move*element[j];
			    }
			} else {
			    move=0.0;
			}
		    }
		}
	    }
	}
	if (newSolutionValue < solutionValue) {
	    // paranoid check
	    memset(rowActivity, 0, numberRows * sizeof(double));
	    for (i = 0; i < numberColumns; i++) {
		int j;
		double value = newSolution[i];
		if (value) {
		    for (j = columnStart[i];
			 j < columnStart[i] + columnLength[i]; j++) {
			int iRow = row[j];
			rowActivity[iRow] += value * element[j];
		    }
		}
	    }
	    // check was approximately feasible
	    bool feasible = true;
	    for (i = 0; i < numberRows; i++) {
		if(rowActivity[i] < rowLower[i]) {
		    if (rowActivity[i] < rowLower[i] - 1000.0*primalTolerance)
			feasible = false;
		} else if(rowActivity[i] > rowUpper[i]) {
		    if (rowActivity[i] > rowUpper[i] + 1000.0*primalTolerance)
			feasible = false;
		}
	    }
	    if (feasible) {
		// new solution
		memcpy(betterSolution, newSolution, 
		       numberColumns * sizeof(double));
		solutionValue = newSolutionValue;
		//printf("** Solution of %g found by rounding\n",newSolutionValue);
		foundBetter = true;
                
	    } else {
		// Can easily happen
		//printf("Debug BlisHeurRound giving bad solution\n");
	    }
	}
    }
    delete [] newSolution;
    delete [] rowActivity;

    //------------------------------------------------------
    // Update statistics.
    //------------------------------------------------------

    ++calls_;
    if (foundBetter) ++numSolutions_;
    time_ += (CoinCpuTime() - start);
    
    return foundBetter;
}
Exemplo n.º 21
0
  /*  This is a utility function which does strong branching on
      one nway object and stores the results in appropriate arrays of the class
      and maybe more.
      It returns -
      -1 - branch was infeasible both ways
       0 - nothing can be fixed
       1 - object can be fixed (returnCriterion==0)
       3 - time limit
  */
  int 
  BonNWayChoose::doStrongBranching( OsiSolverInterface * solver, 
  				    OsiBranchingInformation *info,
  				    int objectIndex,
                                    double * saveLower,
                                    double * saveUpper, double & score)
  {
    int nwayIndex = objectIndex - start_nway_;
    const double * lower = info->lower_;
    const double * upper = info->upper_;

    int numberColumns = solver->getNumCols();
    double timeStart = CoinCpuTime();

    int numberObjects = info->solver_->numberObjects();
    const BonNWayObject * nway = ASSERTED_CAST<const BonNWayObject *>(solver->object(objectIndex));
    assert(nway);
    BonNWayBranchingObject * branch = ASSERTED_CAST<BonNWayBranchingObject *>(nway->createBranch(solver, info, 1));

    int branches_left = branch->numberBranchesLeft();
    int number_branches = branch->numberBranchesLeft();
    int n_can_be_fixed = 0;

    double big_val = cutoff_multiplier_*info->cutoff_;// For infeasibles
    if(big_val > 1e10){ big_val = 10*info->objectiveValue_;}
    big_val += fabs(big_val)*1e-5;
    std::vector<double> unit_changes(numberObjects - start_nway_, -DBL_MAX);
    //std::vector<double> unit_changes(numberObjects - start_nway_, 0);
    while(branches_left){ 

      branch->branch(solver);
      int v_br = branch->var_branched_on();
      int s_br = branch->seq_branched_on();
      double residual = upper[v_br] - info->solution_[v_br];
      solver->solveFromHotStart() ;
      numberStrongIterations_ += solver->getIterationCount();
      numberStrongDone_++;

      double obj_val = solver->getObjValue();

      if(solver->isProvenPrimalInfeasible() ||
         (solver->isProvenOptimal() && obj_val > info->cutoff_)){//infeasible
         if(info->depth_ == 0){
         bounds_[nwayIndex][s_br] = big_val;
         }
         unit_changes[s_br] = (big_val - info->objectiveValue_)/residual;
         if(do_fixings_ > 1){
           n_can_be_fixed++;
           if(log_ > 0)
           printf("Fixing variable %i to 0 the cutoff is %g\n", v_br, big_val);
           saveUpper[v_br] = saveLower[v_br];
         }
      }
      else{
         if(info->depth_ == 0){
          bounds_[nwayIndex][s_br] = obj_val;
         }
         unit_changes[s_br] = (obj_val - info->objectiveValue_)/residual;
      }

      // Restore bounds
      for (int j=0;j<numberColumns;j++) {
        if (saveLower[j] != lower[j])
  	solver->setColLower(j,saveLower[j]);
        if (saveUpper[j] != upper[j])
  	solver->setColUpper(j,saveUpper[j]);
      }
      branches_left = branch->numberBranchesLeft();
    }

    score = compute_usefulness(info, nway->numberMembers(), nway->members(), bounds_[nwayIndex], unit_changes);
    if(info->depth_ == 0){//At root bounds contains valid bound on obj after branching, remember
        if(do_fixings_ == 1 || do_fixings_ == 3)
        nway->set_bounds(bounds_[nwayIndex]);
        for(size_t k = 0 ; k < unit_changes.size() ; k++){
           num_ps_costs_[nwayIndex][k]=1;
        }
        unit_changes_[nwayIndex] = unit_changes;
        num_eval_[nwayIndex] = 1;
    }
    else if (n_can_be_fixed < number_branches -1){
       num_eval_[nwayIndex]++;
       for(size_t k = 0 ; k < unit_changes.size() ; k++){
         if(unit_changes[k] > 0.){
           if(geo_means_)
              unit_changes_[nwayIndex][k] *= unit_changes[k];
           else
              unit_changes_[nwayIndex][k] += unit_changes[k];
           num_ps_costs_[nwayIndex][k]++;
         }
       }
    }
    if(n_can_be_fixed == number_branches){
       return -1;
    }
   if(n_can_be_fixed){
     return 1;
    }
    bool hitMaxTime = ( CoinCpuTime()-timeStart > info->timeRemaining_)
    		|| ( CoinCpuTime() - start_time_ > time_limit_);
    if (hitMaxTime) {
    return 3;
    }
    return 0;
}
Exemplo n.º 22
0
int main (int argc, const char *argv[])
{

  // Define your favorite OsiSolver
  
  OsiClpSolverInterface solver1;
  //solver1.messageHandler()->setLogLevel(0);
  CbcModel model(solver1);
  model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);

  // Read in rgn.mps
  std::string mpsFileName;
#if defined(MIPLIB3DIR)
  mpsFileName = MIPLIB3DIR "/rgn";
#else
  if (argc < 2) {
    fprintf(stderr, "Do not know where to find miplib3 MPS files.\n");
    exit(1);
  }
#endif
  if (argc>=2) mpsFileName = argv[1];
  int numMpsReadErrors = model.solver()->readMps(mpsFileName.c_str(),"");
  if( numMpsReadErrors != 0 )
  {
     printf("%d errors reading MPS file\n", numMpsReadErrors);
     return numMpsReadErrors;
  }

  // Definition of node choice
  CbcCompareUser compare;
  compare.setWeight(0.0);
  model.setNodeComparison(compare);
  // Reduce output
  model.messageHandler()->setLogLevel(1);
  // Get branching messages
  model.messageHandler()->setLogLevel(3);

  // Do initial solve to continuous
  model.initialSolve();

  // Save model
  CbcModel model2 = model;
  int numberColumns=model.getNumCols();
  int numberIntegers = 0;
  int * integerVariable = new int[numberColumns];
  int i;
  for ( i=0;i<numberColumns;i++) {
    if (model.isInteger(i)) {
      integerVariable[numberIntegers++]=i;
    }
  }

  if (numberColumns!=180 || numberIntegers!=100) {
    printf("Incorrect model for example\n");
    exit(1);
  }

  double time1 = CoinCpuTime() ;

  model.branchAndBound();

  std::cout<<"rgn.mps"<<" took "<<CoinCpuTime()-time1<<" seconds, "
	   <<model.getNodeCount()<<" nodes with objective "
	   <<model.getObjValue()
	   <<(!model.status() ? " Finished" : " Not finished")
	   <<std::endl;

  const double * solution = model.solver()->getColSolution();
  
  std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
  
  std::cout<<"--------------------------------------"<<std::endl;
  for (i=0;i<numberIntegers;i++) {
    int iColumn = integerVariable[i];
    double value=solution[iColumn];
    if (fabs(value)>1.0e-7) 
      std::cout<<std::setw(6)<<iColumn<<" "<<value<<std::endl;
  }
  std::cout<<"--------------------------------------"<<std::endl;
  
  std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);

  // Restore model
  model = model2;

  // Convert slacks to variables
  CoinBigIndex start[5]={0,1,2,3,4};
  int row[4]={0,1,2,3};
  double element[4]={1.0,1.0,1.0,1.0};
  double up[4]={1.0,1.0,1.0,1.0};
  model.solver()->addCols(4,start,row,element,NULL,up,NULL);
  // Now use SOS1
  int numberSets=4;
  int which[104];
  double weights[104];
  int starts[5];
  // load
  int n=0;
  starts[0]=0;
  for (int iSet=0;iSet<4;iSet++) {
    for (int i=0;i<25;i++) {
      weights[n]=i+1.0;
      which[n]=iSet*25+i;
      n++;
    }
    // slack - make sure first branch is on slack
    weights[n]=1000.0;
    which[n]=180+iSet;
    n++;
    starts[iSet+1]=n;
  }
  for (i=0;i<numberIntegers;i++) {
    int iColumn = integerVariable[i];
    // Stop being integer
    model.solver()->setContinuous(iColumn);
  }
  // save model in this state
  CbcModel modelSOS = model;
  CbcObject ** objects = new CbcObject * [numberSets];
  for (i=0;i<numberSets;i++) {
    objects[i]= new CbcSOS(&model,starts[i+1]-starts[i],which+starts[i],
			   weights,i);
  }
  model.addObjects(numberSets,objects);
  for (i=0;i<numberSets;i++)
    delete objects[i];
  delete [] objects;

  time1 = CoinCpuTime() ;

  model.branchAndBound();

  std::cout<<"rgn.mps"<<" took "<<CoinCpuTime()-time1<<" seconds, "
	   <<model.getNodeCount()<<" nodes with objective "
	   <<model.getObjValue()
	   <<(!model.status() ? " Finished" : " Not finished")
	   <<std::endl;

  solution = model.solver()->getColSolution();
  
  std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
  
  std::cout<<"--------------------------------------"<<std::endl;
  for (i=0;i<numberIntegers;i++) {
    int iColumn = integerVariable[i];
    double value=solution[iColumn];
    if (fabs(value)>1.0e-7) 
      std::cout<<std::setw(6)<<iColumn<<" "<<value<<std::endl;
  }
  std::cout<<"--------------------------------------"<<std::endl;
  
  std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);


  // Restore SOS model
  model = modelSOS;

// Now use SOS2
  objects = new CbcObject * [numberSets];
  for (i=0;i<numberSets;i++) {
    objects[i]= new CbcSOS(&model,starts[i+1]-starts[i],which+starts[i],
			   weights,i,2);
  }
  model.addObjects(numberSets,objects);
  for (i=0;i<numberSets;i++)
    delete objects[i];
  delete [] objects;

  time1 = CoinCpuTime() ;

  model.branchAndBound();

  std::cout<<"rgn.mps"<<" took "<<CoinCpuTime()-time1<<" seconds, "
	   <<model.getNodeCount()<<" nodes with objective "
	   <<model.getObjValue()
	   <<(!model.status() ? " Finished" : " Not finished")
	   <<std::endl;

  solution = model.solver()->getColSolution();
  
  std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
  
  std::cout<<"--------------------------------------"<<std::endl;

  for (i=0;i<numberIntegers;i++) {
    int iColumn = integerVariable[i];
    double value=solution[iColumn];
    if (fabs(value)>1.0e-7) 
      std::cout<<std::setw(6)<<iColumn<<" "<<value
	       <<std::endl;
  }
  std::cout<<"--------------------------------------"<<std::endl;
  
  std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);


  delete [] integerVariable;
  return 0;
}    
Exemplo n.º 23
0
int main(int argc, const char *argv[])
{
     {
          // Empty model
          ClpSimplex  model;

          // Bounds on rows - as dense vector
          double lower[] = {2.0, 1.0};
          double upper[] = {COIN_DBL_MAX, 1.0};

          // Create space for 2 rows
          model.resize(2, 0);
          // Fill in
          int i;
          // Now row bounds
          for (i = 0; i < 2; i++) {
               model.setRowLower(i, lower[i]);
               model.setRowUpper(i, upper[i]);
          }
          // Now add column 1
          int column1Index[] = {0, 1};
          double column1Value[] = {1.0, 1.0};
          model.addColumn(2, column1Index, column1Value,
                          0.0, 2, 1.0);
          // Now add column 2
          int column2Index[] = {1};
          double column2Value[] = { -5.0};
          model.addColumn(1, column2Index, column2Value,
                          0.0, COIN_DBL_MAX, 0.0);
          // Now add column 3
          int column3Index[] = {0, 1};
          double column3Value[] = {1.0, 1.0};
          model.addColumn(2, column3Index, column3Value,
                          0.0, 4.0, 4.0);
          // solve
          model.dual();

          /*
            Adding one column at a time has a significant overhead so let's
            try a more complicated but faster way

            First time adding in 10000 columns one by one

          */
          model.allSlackBasis();
          ClpSimplex modelSave = model;
          double time1 = CoinCpuTime();
          int k;
          for (k = 0; k < 10000; k++) {
               int column2Index[] = {0, 1};
               double column2Value[] = {1.0, -5.0};
               model.addColumn(2, column2Index, column2Value,
                               0.0, 1.0, 10000.0);
          }
          printf("Time for 10000 addColumn is %g\n", CoinCpuTime() - time1);
          model.dual();
          model = modelSave;
          // Now use build
          CoinBuild buildObject;
          time1 = CoinCpuTime();
          for (k = 0; k < 100000; k++) {
               int column2Index[] = {0, 1};
               double column2Value[] = {1.0, -5.0};
               buildObject.addColumn(2, column2Index, column2Value,
                                     0.0, 1.0, 10000.0);
          }
          model.addColumns(buildObject);
          printf("Time for 100000 addColumn using CoinBuild is %g\n", CoinCpuTime() - time1);
          model.dual();
          model = modelSave;
          // Now use build +-1
          int del[] = {0, 1, 2};
          model.deleteColumns(3, del);
          CoinBuild buildObject2;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int column2Index[] = {0, 1};
               double column2Value[] = {1.0, 1.0, -1.0};
               int bias = k & 1;
               buildObject2.addColumn(2, column2Index, column2Value + bias,
                                      0.0, 1.0, 10000.0);
          }
          model.addColumns(buildObject2, true);
          printf("Time for 10000 addColumn using CoinBuild+-1 is %g\n", CoinCpuTime() - time1);
          model.dual();
          model = modelSave;
          // Now use build +-1
          model.deleteColumns(3, del);
          CoinModel modelObject2;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int column2Index[] = {0, 1};
               double column2Value[] = {1.0, 1.0, -1.0};
               int bias = k & 1;
               modelObject2.addColumn(2, column2Index, column2Value + bias,
                                      0.0, 1.0, 10000.0);
          }
          model.addColumns(modelObject2, true);
          printf("Time for 10000 addColumn using CoinModel+-1 is %g\n", CoinCpuTime() - time1);
          //model.writeMps("xx.mps");
          model.dual();
          model = modelSave;
          // Now use model
          CoinModel modelObject;
          time1 = CoinCpuTime();
          for (k = 0; k < 100000; k++) {
               int column2Index[] = {0, 1};
               double column2Value[] = {1.0, -5.0};
               modelObject.addColumn(2, column2Index, column2Value,
                                     0.0, 1.0, 10000.0);
          }
          model.addColumns(modelObject);
          printf("Time for 100000 addColumn using CoinModel is %g\n", CoinCpuTime() - time1);
          model.dual();
          // Print column solution Just first 3 columns
          int numberColumns = model.numberColumns();
          numberColumns = CoinMin(3, numberColumns);

          // Alternatively getColSolution()
          double * columnPrimal = model.primalColumnSolution();
          // Alternatively getReducedCost()
          double * columnDual = model.dualColumnSolution();
          // Alternatively getColLower()
          double * columnLower = model.columnLower();  // Alternatively getColUpper()
          double * columnUpper = model.columnUpper();
          // Alternatively getObjCoefficients()
          double * columnObjective = model.objective();

          int iColumn;

          std::cout << "               Primal          Dual         Lower         Upper          Cost"
                    << std::endl;

          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
               double value;
               std::cout << std::setw(6) << iColumn << " ";
               value = columnPrimal[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value;
               value = columnDual[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value;
               value = columnLower[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value;
               value = columnUpper[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value;
               value = columnObjective[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value;

               std::cout << std::endl;
          }
          std::cout << "--------------------------------------" << std::endl;
     }
     {
          // Now copy a model
          ClpSimplex  model;
          int status;
          if (argc < 2) {
#if defined(SAMPLEDIR)
               status = model.readMps(SAMPLEDIR "/p0033.mps", true);
#else
               fprintf(stderr, "Do not know where to find sample MPS files.\n");
               exit(1);
#endif
          } else
               status = model.readMps(argv[1]);
          if (status) {
               printf("errors on input\n");
               exit(77);
          }
          model.initialSolve();
          int numberRows = model.numberRows();
          int numberColumns = model.numberColumns();
          const double * rowLower = model.rowLower();
          const double * rowUpper = model.rowUpper();

          // Start off model2
          ClpSimplex model2;
          model2.addRows(numberRows, rowLower, rowUpper, NULL);

          // Build object
          CoinBuild buildObject;
          // Add columns
          const double * columnLower = model.columnLower();
          const double * columnUpper = model.columnUpper();
          const double * objective = model.objective();
          CoinPackedMatrix * matrix = model.matrix();
          const int * row = matrix->getIndices();
          const int * columnLength = matrix->getVectorLengths();
          const CoinBigIndex * columnStart = matrix->getVectorStarts();
          const double * elementByColumn = matrix->getElements();
          for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
               CoinBigIndex start = columnStart[iColumn];
               buildObject.addColumn(columnLength[iColumn], row + start, elementByColumn + start,
                                     columnLower[iColumn], columnUpper[iColumn],
                                     objective[iColumn]);
          }

          // add in
          model2.addColumns(buildObject);
          model2.initialSolve();
     }
     {
          // and again
          ClpSimplex  model;
          int status;
          if (argc < 2) {
#if defined(SAMPLEDIR)
               status = model.readMps(SAMPLEDIR "/p0033.mps", true);
#else
               fprintf(stderr, "Do not know where to find sample MPS files.\n");
               exit(1);
#endif
          } else
               status = model.readMps(argv[1]);
          if (status) {
               printf("errors on input\n");
               exit(77);
          }
          model.initialSolve();
          int numberRows = model.numberRows();
          int numberColumns = model.numberColumns();
          const double * rowLower = model.rowLower();
          const double * rowUpper = model.rowUpper();

          // Build object
          CoinModel buildObject;
          for (int iRow = 0; iRow < numberRows; iRow++)
               buildObject.setRowBounds(iRow, rowLower[iRow], rowUpper[iRow]);

          // Add columns
          const double * columnLower = model.columnLower();
          const double * columnUpper = model.columnUpper();
          const double * objective = model.objective();
          CoinPackedMatrix * matrix = model.matrix();
          const int * row = matrix->getIndices();
          const int * columnLength = matrix->getVectorLengths();
          const CoinBigIndex * columnStart = matrix->getVectorStarts();
          const double * elementByColumn = matrix->getElements();
          for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
               CoinBigIndex start = columnStart[iColumn];
               buildObject.addColumn(columnLength[iColumn], row + start, elementByColumn + start,
                                     columnLower[iColumn], columnUpper[iColumn],
                                     objective[iColumn]);
          }

          // add in
          ClpSimplex model2;
          model2.loadProblem(buildObject);
          model2.initialSolve();
     }
     return 0;
}
Exemplo n.º 24
0
const CoinPresolveAction *do_tighten_action::presolve(CoinPresolveMatrix *prob,
					       const CoinPresolveAction *next)
{
  double *colels	= prob->colels_;
  int *hrow		= prob->hrow_;
  CoinBigIndex *mcstrt		= prob->mcstrt_;
  int *hincol		= prob->hincol_;
  int ncols		= prob->ncols_;

  double *clo	= prob->clo_;
  double *cup	= prob->cup_;

  double *rlo	= prob->rlo_;
  double *rup	= prob->rup_;

  double *dcost	= prob->cost_;

  const unsigned char *integerType = prob->integerType_;

  int *fix_cols	= prob->usefulColumnInt_;
  int nfixup_cols	= 0;

  int nfixdown_cols	= ncols;

  int *useless_rows	= prob->usefulRowInt_;
  int nuseless_rows	= 0;
  
  action *actions	= new action [ncols];
  int nactions		= 0;

  int numberLook = prob->numberColsToDo_;
  int iLook;
  int * look = prob->colsToDo_;
  bool fixInfeasibility = ((prob->presolveOptions_&0x4000) != 0) ;

# if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0
# if PRESOLVE_DEBUG > 0
  std::cout
    << "Entering do_tighten_action::presolve; considering " << numberLook
    << " rows." << std::endl ;
# endif
  presolve_consistent(prob) ;
  presolve_links_ok(prob) ;
  presolve_check_sol(prob) ;
  presolve_check_nbasic(prob) ;
# endif

# if PRESOLVE_DEBUG > 0 || COIN_PRESOLVE_TUNING > 0
  int startEmptyRows = 0 ;
  int startEmptyColumns = 0 ;
  startEmptyRows = prob->countEmptyRows() ;
  startEmptyColumns = prob->countEmptyCols() ;
# if COIN_PRESOLVE_TUNING > 0
  double startTime = 0.0;
  if (prob->tuning_) startTime = CoinCpuTime() ;
# endif
# endif


  // singleton columns are especially likely to be caught here
  for (iLook=0;iLook<numberLook;iLook++) {
    int j = look[iLook];
    // modify bounds if integer
    if (integerType[j]) {
      clo[j] = ceil(clo[j]-1.0e-12);
      cup[j] = floor(cup[j]+1.0e-12);
      if (clo[j]>cup[j]&&!fixInfeasibility) {
        // infeasible
	prob->status_|= 1;
	prob->messageHandler()->message(COIN_PRESOLVE_COLINFEAS,
					     prob->messages())
				 	       <<j
					       <<clo[j]
					       <<cup[j]
					       <<CoinMessageEol;
      }
    }
    if (dcost[j]==0.0) {
      int iflag=0; /* 1 - up is towards feasibility, -1 down is towards */
      int nonFree=0; // Number of non-free rows

      CoinBigIndex kcs = mcstrt[j];
      CoinBigIndex kce = kcs + hincol[j];

      // check constraints
      for (CoinBigIndex k=kcs; k<kce; ++k) {
	int i = hrow[k];
	double coeff = colels[k];
	double rlb = rlo[i];
	double rub = rup[i];

	if (-1.0e28 < rlb && rub < 1.0e28) {
	  // bounded - we lose
	  iflag=0;
	  break;
	} else if (-1.0e28 < rlb || rub < 1.0e28) {
	  nonFree++;
	}

	PRESOLVEASSERT(fabs(coeff) > ZTOLDP);

	// see what this particular row says
	// jflag == 1 ==> up is towards feasibility
	int jflag = (coeff > 0.0
		     ? (rub >  1.0e28 ? 1 : -1)
		     : (rlb < -1.0e28 ? 1 : -1));

	if (iflag) {
	  // check that it agrees with iflag.
	  if (iflag!=jflag) {
	    iflag=0;
	    break;
	  }
	} else {
	  // first row -- initialize iflag
	  iflag=jflag;
	}
      }
      // done checking constraints
      if (!nonFree)
	iflag=0; // all free anyway
      if (iflag) {
	if (iflag==1 && cup[j]<1.0e10) {
#if	PRESOLVE_DEBUG > 1
	  printf("TIGHTEN UP:  %d\n", j);
#endif
	  fix_cols[nfixup_cols++] = j;

	} else if (iflag==-1&&clo[j]>-1.0e10) {
	  // symmetric case
	  //mpre[j] = PRESOLVE_XUP;

#if	PRESOLVE_DEBUG > 1
	  printf("TIGHTEN DOWN:  %d\n", j);
#endif

	  fix_cols[--nfixdown_cols] = j;

	} else {
#if 0
	  static int limit;
	  static int which = atoi(getenv("WZ"));
	  if (which == -1)
	    ;
	  else if (limit != which) {
	    limit++;
	    continue;
	  } else
	    limit++;

	  printf("TIGHTEN STATS %d %g %g %d:  \n", j, clo[j], cup[j], integerType[j]); 
  double *rowels	= prob->rowels_;
  int *hcol		= prob->hcol_;
  int *mrstrt		= prob->mrstrt_;
  int *hinrow		= prob->hinrow_;
	  for (CoinBigIndex k=kcs; k<kce; ++k) {
	    int irow = hrow[k];
	    CoinBigIndex krs = mrstrt[irow];
	    CoinBigIndex kre = krs + hinrow[irow];
	    printf("%d  %g %g %g:  ",
		   irow, rlo[irow], rup[irow], colels[irow]);
	    for (CoinBigIndex kk=krs; kk<kre; ++kk)
	      printf("%d(%g) ", hcol[kk], rowels[kk]);
	    printf("\n");
	  }
#endif

	  {
	    action *s = &actions[nactions];	  
	    nactions++;
	    s->col = j;
	    PRESOLVE_DETAIL_PRINT(printf("pre_tighten %dC E\n",j));
	    if (integerType[j]) {
	      assert (iflag==-1||iflag==1);
	      iflag *= 2; // say integer
	    }
	    s->direction = iflag;

	    s->rows =   new int[hincol[j]];
	    s->lbound = new double[hincol[j]];
	    s->ubound = new double[hincol[j]];
#if         PRESOLVE_DEBUG > 1
	    printf("TIGHTEN FREE:  %d   ", j);
#endif
	    int nr = 0;
            prob->addCol(j);
	    for (CoinBigIndex k=kcs; k<kce; ++k) {
	      int irow = hrow[k];
	      // ignore this if we've already made it useless
	      if (! (rlo[irow] == -PRESOLVE_INF && rup[irow] == PRESOLVE_INF)) {
		prob->addRow(irow);
		s->rows  [nr] = irow;
		s->lbound[nr] = rlo[irow];
		s->ubound[nr] = rup[irow];
		nr++;

		useless_rows[nuseless_rows++] = irow;

		rlo[irow] = -PRESOLVE_INF;
		rup[irow] = PRESOLVE_INF;

#if             PRESOLVE_DEBUG > 1
		printf("%d ", irow);
#endif
	      }
	    }
	    s->nrows = nr;

#if         PRESOLVE_DEBUG > 1
	    printf("\n");
#endif
	  }
	}
      }
    }
  }


#if	PRESOLVE_SUMMARY > 0
  if (nfixdown_cols<ncols || nfixup_cols || nuseless_rows) {
    printf("NTIGHTENED:  %d %d %d\n", ncols-nfixdown_cols, nfixup_cols, nuseless_rows);
  }
#endif

  if (nuseless_rows) {
    next = new do_tighten_action(nactions, CoinCopyOfArray(actions,nactions), next);

    next = useless_constraint_action::presolve(prob,
					       useless_rows, nuseless_rows,
					       next);
  }
  deleteAction(actions, action*);
  //delete[]useless_rows;

  if (nfixdown_cols<ncols) {
    int * fixdown_cols = fix_cols+nfixdown_cols; 
    nfixdown_cols = ncols-nfixdown_cols;
    next = make_fixed_action::presolve(prob, fixdown_cols, nfixdown_cols,
				       true,
				       next);
  }
  //delete[]fixdown_cols;

  if (nfixup_cols) {
    next = make_fixed_action::presolve(prob, fix_cols, nfixup_cols,
				       false,
				       next);
  }
  //delete[]fixup_cols;

# if COIN_PRESOLVE_TUNING > 0
  if (prob->tuning_) double thisTime = CoinCpuTime() ;
# endif
# if PRESOLVE_CONSISTENCY > 0 || PRESOLVE_DEBUG > 0
  presolve_check_sol(prob) ;
# endif
# if PRESOLVE_DEBUG > 0 || COIN_PRESOLVE_TUNING > 0
  int droppedRows = prob->countEmptyRows()-startEmptyRows ;
  int droppedColumns = prob->countEmptyCols()-startEmptyColumns ;
  std::cout
    << "Leaving do_tighten_action::presolve, " << droppedRows << " rows, "
    << droppedColumns << " columns dropped" ;
# if COIN_PRESOLVE_TUNING > 0
  std::cout << " in " << thisTime-startTime << "s" ;
# endif
  std::cout << "." << std::endl ;
# endif

  return (next);
}
Exemplo n.º 25
0
int main (int argc, const char *argv[])
{

  /* Define your favorite OsiSolver.

     CbcModel clones the solver so use solver1 up to the time you pass it
     to CbcModel then use a pointer to cloned solver (model.solver())
  */
  
  OsiClpSolverInterface solver1;
  /* From now on we can build model in a solver independent way.
     You can add rows one at a time but for large problems this is slow so
     this example uses CoinBuild or CoinModel
  */
  OsiSolverInterface * solver = &solver1;
  // Data (is exmip1.mps in Mps/Sample
  // Objective 
  double objValue[]={1.0,2.0,0.0,0.0,0.0,0.0,0.0,-1.0};
  // Lower bounds for columns
  double columnLower[]={2.5,0.0,0.0,0.0,0.5,0.0,0.0,0.0};
  // Upper bounds for columns
  double columnUpper[]={COIN_DBL_MAX,4.1,1.0,1.0,4.0,
                  COIN_DBL_MAX,COIN_DBL_MAX,4.3};
  // Lower bounds for row activities
  double rowLower[]={2.5,-COIN_DBL_MAX,-COIN_DBL_MAX,1.8,3.0};
  // Upper bounds for row activities
  double rowUpper[]={COIN_DBL_MAX,2.1,4.0,5.0,15.0};
  // Matrix stored packed
  int column[] = {0,1,3,4,7,
                  1,2,
                  2,5,
                  3,6,
                  4,7};
  double element[] = {3.0,1.0,-2.0,-1.0,-1.0,
                      2.0,1.1,
                      1.0,1.0,
                      2.8,-1.2,
                      1.0,1.9};
  int starts[]={0,5,7,9,11,13};
  // Integer variables (note upper bound already 1.0)
  int whichInt[]={2,3};
  int numberRows=(int) (sizeof(rowLower)/sizeof(double));
  int numberColumns=(int) (sizeof(columnLower)/sizeof(double));
#define BUILD 2
#if BUILD==1
  // Using CoinBuild 
  // First do columns (objective and bounds)
  int i;
  // We are not adding elements 
  for (i=0;i<numberColumns;i++) {
    solver->addCol(0,NULL,NULL,columnLower[i],columnUpper[i],
                    objValue[i]);
  }
  // mark as integer
  for (i=0;i<(int) (sizeof(whichInt)/sizeof(int));i++)
    solver->setInteger(whichInt[i]);
  // Now build rows
  CoinBuild build;
  for (i=0;i<numberRows;i++) {
    int startRow = starts[i];
    int numberInRow = starts[i+1]-starts[i];
    build.addRow(numberInRow,column+startRow,element+startRow,
                 rowLower[i],rowUpper[i]);
  }  
  // add rows into solver
  solver->addRows(build);
#else
  /* using CoinModel - more flexible but still beta.
     Can do exactly same way but can mix and match much more.
     Also all operations are on building object
  */
  CoinModel build;
  // First do columns (objective and bounds)
  int i;
  for (i=0;i<numberColumns;i++) {
    build.setColumnBounds(i,columnLower[i],columnUpper[i]);
    build.setObjective(i,objValue[i]);
  }
  // mark as integer
  for (i=0;i<(int) (sizeof(whichInt)/sizeof(int));i++)
    build.setInteger(whichInt[i]);
  // Now build rows
  for (i=0;i<numberRows;i++) {
    int startRow = starts[i];
    int numberInRow = starts[i+1]-starts[i];
    build.addRow(numberInRow,column+startRow,element+startRow,
                 rowLower[i],rowUpper[i]);
  }  
  // add rows into solver
  solver->loadFromCoinModel(build);
#endif

  // Pass to solver
  CbcModel model(*solver);
  model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);


  // Set up some cut generators and defaults
  // Probing first as gets tight bounds on continuous

  CglProbing generator1;
  generator1.setUsingObjective(true);
  generator1.setMaxPass(3);
  generator1.setMaxProbe(100);
  generator1.setMaxLook(50);
  generator1.setRowCuts(3);
  //  generator1.snapshot(*model.solver());
  //generator1.createCliques(*model.solver(),2,1000,true);
  //generator1.setMode(0);

  CglGomory generator2;
  // try larger limit
  generator2.setLimit(300);

  CglKnapsackCover generator3;

  CglOddHole generator4;
  generator4.setMinimumViolation(0.005);
  generator4.setMinimumViolationPer(0.00002);
  // try larger limit
  generator4.setMaximumEntries(200);

  CglClique generator5;
  generator5.setStarCliqueReport(false);
  generator5.setRowCliqueReport(false);

  CglMixedIntegerRounding mixedGen;
  CglFlowCover flowGen;
  
  // Add in generators
  model.addCutGenerator(&generator1,-1,"Probing");
  model.addCutGenerator(&generator2,-1,"Gomory");
  model.addCutGenerator(&generator3,-1,"Knapsack");
  model.addCutGenerator(&generator4,-1,"OddHole");
  model.addCutGenerator(&generator5,-1,"Clique");
  model.addCutGenerator(&flowGen,-1,"FlowCover");
  model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding");

  OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (model.solver());
  // go faster stripes
  if (osiclp->getNumRows()<300&&osiclp->getNumCols()<500) {
    osiclp->setupForRepeatedUse(2,0);
    printf("trying slightly less reliable but faster version (? Gomory cuts okay?)\n");
    printf("may not be safe if doing cuts in tree which need accuracy (level 2 anyway)\n");
  }

  // Allow rounding heuristic

  CbcRounding heuristic1(model);
  model.addHeuristic(&heuristic1);

  // And local search when new solution found

  CbcHeuristicLocal heuristic2(model);
  model.addHeuristic(&heuristic2);

  // Redundant definition of default branching (as Default == User)
  CbcBranchUserDecision branch;
  model.setBranchingMethod(&branch);

  // Definition of node choice
  CbcCompareUser compare;
  model.setNodeComparison(compare);

  // Do initial solve to continuous
  model.initialSolve();

  // Could tune more
  model.setMinimumDrop(CoinMin(1.0,
			     fabs(model.getMinimizationObjValue())*1.0e-3+1.0e-4));

  if (model.getNumCols()<500)
    model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible
  else if (model.getNumCols()<5000)
    model.setMaximumCutPassesAtRoot(100); // use minimum drop
  else
    model.setMaximumCutPassesAtRoot(20);
  //model.setMaximumCutPasses(5);

  // Switch off strong branching if wanted
  // model.setNumberStrong(0);
  // Do more strong branching if small
  if (model.getNumCols()<5000)
    model.setNumberStrong(10);

  model.solver()->setIntParam(OsiMaxNumIterationHotStart,100);

  // If time is given then stop after that number of minutes
  if (argc>2) {
    int minutes = atoi(argv[2]);
    std::cout<<"Stopping after "<<minutes<<" minutes"<<std::endl;
    assert (minutes>=0);
    model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes);
  }
  // Switch off most output
  if (model.getNumCols()<3000) {
    model.messageHandler()->setLogLevel(1);
    //model.solver()->messageHandler()->setLogLevel(0);
  } else {
    model.messageHandler()->setLogLevel(2);
    model.solver()->messageHandler()->setLogLevel(1);
  }
  double time1 = CoinCpuTime();

  // Do complete search
  
  model.branchAndBound();

  std::cout<<" Branch and cut took "<<CoinCpuTime()-time1<<" seconds, "
	   <<model.getNodeCount()<<" nodes with objective "
	   <<model.getObjValue()
	   <<(!model.status() ? " Finished" : " Not finished")
	   <<std::endl;

  // Print more statistics
  std::cout<<"Cuts at root node changed objective from "<<model.getContinuousObjective()
	   <<" to "<<model.rootObjectiveAfterCuts()<<std::endl;

  int numberGenerators = model.numberCutGenerators();
  for (int iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
    std::cout<<generator->cutGeneratorName()<<" was tried "
	     <<generator->numberTimesEntered()<<" times and created "
	     <<generator->numberCutsInTotal()<<" cuts of which "
	     <<generator->numberCutsActive()<<" were active after adding rounds of cuts"
	     <<std::endl;
  }
  // Print solution if any - we can't get names from Osi!

  if (model.getMinimizationObjValue()<1.0e50) {
    int numberColumns = model.solver()->getNumCols();
    
    const double * solution = model.solver()->getColSolution();
    
    int iColumn;
    std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
    
    std::cout<<"--------------------------------------"<<std::endl;
    for (iColumn=0;iColumn<numberColumns;iColumn++) {
      double value=solution[iColumn];
      if (fabs(value)>1.0e-7&&model.solver()->isInteger(iColumn)) 
	std::cout<<std::setw(6)<<iColumn<<" "<<value<<std::endl;
    }
    std::cout<<"--------------------------------------"<<std::endl;
  
    std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);
  }
  return 0;
}    
Exemplo n.º 26
0
/*
 *
 * The col rep and row rep must be consistent.
 */
const CoinPresolveAction *tripleton_action::presolve(CoinPresolveMatrix *prob,
						  const CoinPresolveAction *next)
{
  double startTime = 0.0;
  int startEmptyRows=0;
  int startEmptyColumns = 0;
  if (prob->tuning_) {
    startTime = CoinCpuTime();
    startEmptyRows = prob->countEmptyRows();
    startEmptyColumns = prob->countEmptyCols();
  }
  double *colels	= prob->colels_;
  int *hrow		= prob->hrow_;
  CoinBigIndex *mcstrt		= prob->mcstrt_;
  int *hincol		= prob->hincol_;
  int ncols		= prob->ncols_;

  double *clo	= prob->clo_;
  double *cup	= prob->cup_;

  double *rowels	= prob->rowels_;
  int *hcol		= prob->hcol_;
  CoinBigIndex *mrstrt		= prob->mrstrt_;
  int *hinrow		= prob->hinrow_;
  int nrows		= prob->nrows_;

  double *rlo	= prob->rlo_;
  double *rup	= prob->rup_;

  presolvehlink *clink = prob->clink_;
  presolvehlink *rlink = prob->rlink_;

  const unsigned char *integerType = prob->integerType_;

  double *cost	= prob->cost_;

  int numberLook = prob->numberRowsToDo_;
  int iLook;
  int * look = prob->rowsToDo_;
  const double ztolzb	= prob->ztolzb_;

  action * actions = new action [nrows];
# ifdef ZEROFAULT
  // initialise alignment padding bytes
  memset(actions,0,nrows*sizeof(action)) ;
# endif
  int nactions = 0;

  int *zeros	= prob->usefulColumnInt_; //new int[ncols];
  char * mark = reinterpret_cast<char *>(zeros+ncols);
  memset(mark,0,ncols);
  int nzeros	= 0;

  // If rowstat exists then all do
  unsigned char *rowstat	= prob->rowstat_;
  double *acts	= prob->acts_;
  //  unsigned char * colstat = prob->colstat_;


# if PRESOLVE_CONSISTENCY
  presolve_links_ok(prob) ;
# endif

  // wasfor (int irow=0; irow<nrows; irow++)
  for (iLook=0;iLook<numberLook;iLook++) {
    int irow = look[iLook];
    if (hinrow[irow] == 3 &&
	fabs(rup[irow] - rlo[irow]) <= ZTOLDP) {
      double rhs = rlo[irow];
      CoinBigIndex krs = mrstrt[irow];
      CoinBigIndex kre = krs + hinrow[irow];
      int icolx, icoly, icolz;
      double coeffx, coeffy, coeffz;
      CoinBigIndex k;
      
      /* locate first column */
      for (k=krs; k<kre; k++) {
	if (hincol[hcol[k]] > 0) {
	  break;
	}
      }
      PRESOLVEASSERT(k<kre);
      coeffx = rowels[k];
      if (fabs(coeffx) < ZTOLDP2)
	continue;
      icolx = hcol[k];
      
      
      /* locate second column */
      for (k++; k<kre; k++) {
	if (hincol[hcol[k]] > 0) {
	  break;
	}
      }
      PRESOLVEASSERT(k<kre);
      coeffy = rowels[k];
      if (fabs(coeffy) < ZTOLDP2)
	continue;
      icoly = hcol[k];
      
      /* locate third column */
      for (k++; k<kre; k++) {
	if (hincol[hcol[k]] > 0) {
	  break;
	}
      }
      PRESOLVEASSERT(k<kre);
      coeffz = rowels[k];
      if (fabs(coeffz) < ZTOLDP2)
	continue;
      icolz = hcol[k];
      
      // For now let's do obvious one
      if (coeffx*coeffz>0.0) {
	if(coeffx*coeffy>0.0) 
	  continue;
      } else if (coeffx*coeffy>0.0) {
	int iTemp = icoly;
	icoly=icolz;
	icolz=iTemp;
	double dTemp = coeffy;
	coeffy=coeffz;
	coeffz=dTemp;
      } else {
	int iTemp = icoly;
	icoly=icolx;
	icolx=iTemp;
	double dTemp = coeffy;
	coeffy=coeffx;
	coeffx=dTemp;
      }
      // Not all same sign and y is odd one out
      // don't bother with fixed variables
      if (!(fabs(cup[icolx] - clo[icolx]) < ZTOLDP) &&
	  !(fabs(cup[icoly] - clo[icolx]) < ZTOLDP) &&
	  !(fabs(cup[icolz] - clo[icoly]) < ZTOLDP)) {
	assert (coeffx*coeffz>0.0&&coeffx*coeffy<0.0);
	// Only do if does not give implicit bounds on x and z
	double cx = - coeffx/coeffy;
	double cz = - coeffz/coeffy;
	/* don't do if y integer for now */
	if (integerType[icoly]) {
#define PRESOLVE_DANGEROUS
#ifndef PRESOLVE_DANGEROUS
	  continue;
#else
	  if (!integerType[icolx]||!integerType[icolz])
	    continue;
	  if (cx!=floor(cx+0.5)||cz!=floor(cz+0.5))
	    continue;
#endif
	}
	double rhsRatio = rhs/coeffy;
	if (clo[icoly]>-1.0e30) {
	  if (clo[icolx]<-1.0e30||clo[icolz]<-1.0e30)
	    continue;
	  if (cx*clo[icolx]+cz*clo[icolz]+rhsRatio<clo[icoly]-ztolzb)
	    continue;
	}
	if (cup[icoly]<1.0e30) {
	  if (cup[icolx]>1.0e30||cup[icolz]>1.0e30)
	    continue;
	  if (cx*cup[icolx]+cz*cup[icolz]+rhsRatio>cup[icoly]+ztolzb)
	    continue;
	}
	CoinBigIndex krowx,krowy,krowz;
	/* find this row in each of the columns and do counts */
	bool singleton=false;
	for (k=mcstrt[icoly]; k<mcstrt[icoly]+hincol[icoly]; k++) {
	  int jrow=hrow[k];
	  if (hinrow[jrow]==1)
	    singleton=true;
	  if (jrow == irow) 
	    krowy=k;
	  else
	    prob->setRowUsed(jrow);
	}
	int nDuplicate=0;
	for (k=mcstrt[icolx]; k<mcstrt[icolx]+hincol[icolx]; k++) {
	  int jrow=hrow[k];
	  if (jrow == irow) 
	    krowx=k;
	  else if (prob->rowUsed(jrow))
	    nDuplicate++;;
	}
	for (k=mcstrt[icolz]; k<mcstrt[icolz]+hincol[icolz]; k++) {
	  int jrow=hrow[k];
	  if (jrow == irow) 
	    krowz=k;
	  else if (prob->rowUsed(jrow))
	    nDuplicate++;;
	}
	int nAdded=hincol[icoly]-3-nDuplicate;
	for (k=mcstrt[icoly]; k<mcstrt[icoly]+hincol[icoly]; k++) {
	  int jrow=hrow[k];
	  prob->unsetRowUsed(jrow);
	}
	// let singleton rows be taken care of first
	if (singleton)
	  continue;
	//if (nAdded<=1) 
	//printf("%d elements added, hincol %d , dups %d\n",nAdded,hincol[icoly],nDuplicate);
	if (nAdded>2)
	  continue;

	// it is possible that both x/z and y are singleton columns
	// that can cause problems
	if ((hincol[icolx] == 1 ||hincol[icolz] == 1) && hincol[icoly] == 1)
	  continue;

	// common equations are of the form ax + by = 0, or x + y >= lo
	{
	  action *s = &actions[nactions];	  
	  nactions++;
	  PRESOLVE_DETAIL_PRINT(printf("pre_tripleton %dR %dC %dC %dC E\n",
				       irow,icoly,icolx,icolz));
	  
	  s->row = irow;
	  s->icolx = icolx;
	  s->icolz = icolz;
	  
	  s->icoly = icoly;
	  s->cloy = clo[icoly];
	  s->cupy = cup[icoly];
	  s->costy = cost[icoly];
	  
	  s->rlo = rlo[irow];
	  s->rup = rup[irow];
	  
	  s->coeffx = coeffx;
	  s->coeffy = coeffy;
	  s->coeffz = coeffz;
	  
	  s->ncoly	= hincol[icoly];
	  s->colel	= presolve_dupmajor(colels, hrow, hincol[icoly],
					    mcstrt[icoly]);
	}

	// costs
	// the effect of maxmin cancels out
	cost[icolx] += cost[icoly] * cx;
	cost[icolz] += cost[icoly] * cz;

	prob->change_bias(cost[icoly] * rhs / coeffy);
	//if (cost[icoly]*rhs)
	//printf("change %g col %d cost %g rhs %g coeff %g\n",cost[icoly]*rhs/coeffy,
	// icoly,cost[icoly],rhs,coeffy);

	if (rowstat) {
	  // update solution and basis
	  int numberBasic=0;
	  if (prob->columnIsBasic(icoly))
	    numberBasic++;
	  if (prob->rowIsBasic(irow))
	    numberBasic++;
	  if (numberBasic>1) {
	    if (!prob->columnIsBasic(icolx))
	      prob->setColumnStatus(icolx,CoinPrePostsolveMatrix::basic);
	    else
	      prob->setColumnStatus(icolz,CoinPrePostsolveMatrix::basic);
	  }
	}
	  
	// Update next set of actions
	{
	  prob->addCol(icolx);
	  int i,kcs,kce;
	  kcs = mcstrt[icoly];
	  kce = kcs + hincol[icoly];
	  for (i=kcs;i<kce;i++) {
	    int row = hrow[i];
	    prob->addRow(row);
	  }
	  kcs = mcstrt[icolx];
	  kce = kcs + hincol[icolx];
	  for (i=kcs;i<kce;i++) {
	    int row = hrow[i];
	    prob->addRow(row);
	  }
	  prob->addCol(icolz);
	  kcs = mcstrt[icolz];
	  kce = kcs + hincol[icolz];
	  for (i=kcs;i<kce;i++) {
	    int row = hrow[i];
	    prob->addRow(row);
	  }
	}

	/* transfer the colx factors to coly */
	bool no_mem = elim_tripleton("ELIMT",
				     mcstrt, rlo, acts, rup, colels,
				     hrow, hcol, hinrow, hincol,
				     clink, ncols, rlink, nrows,
				     mrstrt, rowels,
				     cx,
				     cz,
				     rhs / coeffy,
				     irow, icolx, icoly,icolz);
	if (no_mem) 
	  throwCoinError("out of memory",
			 "tripleton_action::presolve");

	// now remove irow from icolx and icolz in the col rep
	// better if this were first.
	presolve_delete_from_col(irow,icolx,mcstrt,hincol,hrow,colels) ;
	presolve_delete_from_col(irow,icolz,mcstrt,hincol,hrow,colels) ;

	// eliminate irow entirely from the row rep
	hinrow[irow] = 0;

	// eliminate irow entirely from the row rep
	PRESOLVE_REMOVE_LINK(rlink, irow);

	// eliminate coly entirely from the col rep
	PRESOLVE_REMOVE_LINK(clink, icoly);
	cost[icoly] = 0.0;

	rlo[irow] = 0.0;
	rup[irow] = 0.0;

	if (!mark[icolx]) {
	  mark[icolx]=1;
	  zeros[nzeros++]=icolx;
	}
	if (!mark[icolz]) {
	  mark[icolz]=1;
	  zeros[nzeros++]=icolz;
	}
      }
      
#     if PRESOLVE_CONSISTENCY
      presolve_links_ok(prob) ;
      presolve_consistent(prob);
#     endif
    }
  }
  if (nactions) {
#   if PRESOLVE_SUMMARY
    printf("NTRIPLETONS:  %d\n", nactions);
#   endif
    action *actions1 = new action[nactions];
    CoinMemcpyN(actions, nactions, actions1);

    next = new tripleton_action(nactions, actions1, next);

    if (nzeros) {
      next = drop_zero_coefficients_action::presolve(prob, zeros, nzeros, next);
    }
  }

  //delete[]zeros;
  deleteAction(actions,action*);

  if (prob->tuning_) {
    double thisTime=CoinCpuTime();
    int droppedRows = prob->countEmptyRows() - startEmptyRows ;
    int droppedColumns =  prob->countEmptyCols() - startEmptyColumns;
    printf("CoinPresolveTripleton(8) - %d rows, %d columns dropped in time %g, total %g\n",
	   droppedRows,droppedColumns,thisTime-startTime,thisTime-prob->startTime_);
  }
  return (next);
}
Exemplo n.º 27
0
/*
  It is always the case that one of the variables of a doubleton is, or
  can be made, implied free, but neither will necessarily be a singleton.
  Since in the case of a doubleton the number of non-zero entries will never
  increase if one is eliminated, it makes sense to always eliminate them.

  The col rep and row rep must be consistent.
 */
const CoinPresolveAction
  *doubleton_action::presolve (CoinPresolveMatrix *prob,
			      const CoinPresolveAction *next)

{
# if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0
# if PRESOLVE_DEBUG > 0
  std::cout
    << "Entering doubleton_action::presolve; considering "
    << prob->numberRowsToDo_ << " rows." << std::endl ;
# endif
  presolve_consistent(prob) ;
  presolve_links_ok(prob) ;
  presolve_check_sol(prob) ;
  presolve_check_nbasic(prob) ;
# endif
# if PRESOLVE_DEBUG > 0 || COIN_PRESOLVE_TUNING > 0
  int startEmptyRows = 0 ;
  int startEmptyColumns = 0 ;
  startEmptyRows = prob->countEmptyRows() ;
  startEmptyColumns = prob->countEmptyCols() ;
# if COIN_PRESOLVE_TUNING > 0
  double startTime = 0.0 ;
  if (prob->tuning_) startTime = CoinCpuTime() ;
# endif
# endif

  const int n = prob->ncols_ ;
  const int m = prob->nrows_ ;

/*
  Unpack column-major and row-major representations, along with rim vectors.
*/
  CoinBigIndex *colStarts = prob->mcstrt_ ;
  int *colLengths = prob->hincol_ ;
  double *colCoeffs = prob->colels_ ;
  int *rowIndices = prob->hrow_ ;
  presolvehlink *clink = prob->clink_ ;

  double *clo = prob->clo_ ;
  double *cup = prob->cup_ ;

  CoinBigIndex *rowStarts = prob->mrstrt_ ;
  int *rowLengths = prob->hinrow_ ;
  double *rowCoeffs = prob->rowels_ ;
  int *colIndices = prob->hcol_ ;
  presolvehlink *rlink = prob->rlink_ ;

  double *rlo = prob->rlo_ ;
  double *rup = prob->rup_ ;

  const unsigned char *integerType = prob->integerType_ ;

  double *cost = prob->cost_ ;

  int numberLook = prob->numberRowsToDo_ ;
  int *look = prob->rowsToDo_ ;
  const double ztolzb	= prob->ztolzb_ ;
  const double ztolzero = 1.0e-12 ;

  action *actions = new action [m] ;
  int nactions = 0 ;

/*
  zeros will hold columns that should be groomed to remove explicit zeros when
  we're finished.

  fixed will hold columns that have ended up as fixed variables.
*/
  int *zeros = prob->usefulColumnInt_ ;
  int nzeros = 0 ;

  int *fixed = zeros+n ;
  int nfixed = 0 ;

  unsigned char *rowstat = prob->rowstat_ ;
  double *acts	= prob->acts_ ;
  double *sol = prob->sol_ ;
/*
  More like `ignore infeasibility'.
*/
  bool fixInfeasibility = ((prob->presolveOptions_&0x4000) != 0) ;

/*
  Open the main loop to scan for doubleton candidates.
*/
  for (int iLook = 0 ; iLook < numberLook ; iLook++) {
    const int tgtrow = look[iLook] ;
/*
  We need an equality with two coefficients. Avoid isolated constraints, lest
  both variables vanish.

  Failure of the assert indicates that the row- and column-major
  representations are out of sync.
*/
    if ((rowLengths[tgtrow] != 2) ||
        (fabs(rup[tgtrow]-rlo[tgtrow]) > ZTOLDP)) continue ;

    const CoinBigIndex krs = rowStarts[tgtrow] ;
    int tgtcolx = colIndices[krs] ;
    int tgtcoly = colIndices[krs+1] ;

    PRESOLVEASSERT(colLengths[tgtcolx] > 0 || colLengths[tgtcoly] > 0) ;
    if (colLengths[tgtcolx] == 1 && colLengths[tgtcoly] == 1) continue ;
/*
  Avoid prohibited columns and fixed columns. Make sure the coefficients are
  nonzero.
  JJF - test should allow one to be prohibited as long as you leave that
  one.  I modified earlier code but hope I have got this right.
*/
    if (prob->colProhibited(tgtcolx) && prob->colProhibited(tgtcoly))
      continue ;
    if (fabs(rowCoeffs[krs]) < ZTOLDP2 || fabs(rowCoeffs[krs+1]) < ZTOLDP2)
      continue ;
    if ((fabs(cup[tgtcolx]-clo[tgtcolx]) < ZTOLDP) ||
	(fabs(cup[tgtcoly]-clo[tgtcoly]) < ZTOLDP)) continue ;

#   if PRESOLVE_DEBUG > 2
    std::cout
      << "  row " << tgtrow << " colx " << tgtcolx << " coly " << tgtcoly
      << " passes preliminary eval." << std::endl ;
#   endif

/*
  Find this row in each column. The indices are not const because we may flip
  them below, once we decide which column will be eliminated.
*/
    CoinBigIndex krowx =
        presolve_find_row(tgtrow,colStarts[tgtcolx],
			  colStarts[tgtcolx]+colLengths[tgtcolx],rowIndices) ;
    double coeffx = colCoeffs[krowx] ;
    CoinBigIndex krowy =
        presolve_find_row(tgtrow,colStarts[tgtcoly],
			  colStarts[tgtcoly]+colLengths[tgtcoly],rowIndices) ;
    double coeffy = colCoeffs[krowy] ;
    const double rhs = rlo[tgtrow] ;
/*
  Avoid obscuring a requirement for integrality.

  If only one variable is integer, keep it and substitute for the continuous
  variable.

  If both are integer, substitute only for the forms x = k*y (k integral
  and non-empty intersection on bounds on x) or x = 1-y, where both x and
  y are binary.

  flag bits for integerStatus: 0x01: x integer;  0x02: y integer

  This bit of code works because 0 is continuous, 1 is integer. Make sure
  that's true.
*/
    assert((integerType[tgtcolx] == 0) || (integerType[tgtcolx] == 1)) ;
    assert((integerType[tgtcoly] == 0) || (integerType[tgtcoly] == 1)) ;

    int integerX = integerType[tgtcolx];
    int integerY = integerType[tgtcoly];
    /* if one prohibited then treat that as integer. This
       may be pessimistic - but will catch SOS etc */
    if (prob->colProhibited2(tgtcolx))
      integerX=1;
    if (prob->colProhibited2(tgtcoly))
      integerY=1;
    int integerStatus = (integerY<<1)|integerX ;

    if (integerStatus == 3) {
      int good = 0 ;
      double rhs2 = rhs ;
      if (coeffx < 0.0) {
	coeffx = -coeffx ;
	rhs2 += 1 ;
      }
      if ((cup[tgtcolx] == 1.0) && (clo[tgtcolx] == 0.0) &&
	  (fabs(coeffx-1.0) < 1.0e-7) && !prob->colProhibited2(tgtcoly))
	good = 1 ;
      if (coeffy < 0.0) {
	coeffy = -coeffy ;
	rhs2 += 1 ;
      }
      if ((cup[tgtcoly] == 1.0) && (clo[tgtcoly] == 0.0) &&
	  (fabs(coeffy-1.0) < 1.0e-7) && !prob->colProhibited2(tgtcolx))
	good |= 2 ;
      if (!(good == 3 && fabs(rhs2-1.0) < 1.0e-7))
	integerStatus = -1 ;
/*
  Not x+y = 1. Try for ax+by = 0
*/
      if (integerStatus < 0 && rhs == 0.0) {
	coeffx = colCoeffs[krowx] ;
	coeffy = colCoeffs[krowy] ;
	double ratio ;
	bool swap = false ;
	if (fabs(coeffx) > fabs(coeffy)) {
	  ratio = coeffx/coeffy ;
	} else {
	  ratio = coeffy/coeffx ;
	  swap = true ;
	}
	ratio = fabs(ratio) ;
	if (fabs(ratio-floor(ratio+0.5)) < ztolzero) {
	  integerStatus = swap ? 2 : 1 ;
	}
      }
/*
  One last try --- just require an integral substitution formula.

  But ax+by = 0 above is a subset of ax+by = c below and should pass the
  test below. For that matter, so will x+y = 1. Why separate special cases
  above?  -- lh, 121106 --
*/
      if (integerStatus < 0) {
	bool canDo = false ;
	coeffx = colCoeffs[krowx] ;
	coeffy = colCoeffs[krowy] ;
	double ratio ;
	bool swap = false ;
	double rhsRatio ;
	if (fabs(coeffx) > fabs(coeffy)) {
	  ratio = coeffx/coeffy ;
	  rhsRatio = rhs/coeffx ;
	} else {
	  ratio = coeffy/coeffx ;
	  rhsRatio = rhs/coeffy ;
	  swap = true ;
	}
	ratio = fabs(ratio) ;
	if (fabs(ratio-floor(ratio+0.5)) < ztolzero) {
	  // possible
	  integerStatus = swap ? 2 : 1 ;
	  // but check rhs
	  if (rhsRatio==floor(rhsRatio+0.5))
	    canDo=true ;
	}
#       ifdef COIN_DEVELOP2
	if (canDo)
	  printf("Good CoinPresolveDoubleton tgtcolx %d (%g and bounds %g %g) tgtcoly %d (%g and bound %g %g) - rhs %g\n",
		 tgtcolx,colCoeffs[krowx],clo[tgtcolx],cup[tgtcolx],
		 tgtcoly,colCoeffs[krowy],clo[tgtcoly],cup[tgtcoly],rhs) ;
	else
	printf("Bad CoinPresolveDoubleton tgtcolx %d (%g) tgtcoly %d (%g) - rhs %g\n",
	       tgtcolx,colCoeffs[krowx],tgtcoly,colCoeffs[krowy],rhs) ;
#       endif
	if (!canDo)
	  continue ;
      }
    }
/*
  We've resolved integrality concerns. If we concluded that we need to
  switch the roles of x and y because of integrality, do that now. If both
  variables are continuous, we may still want to swap for numeric stability.
  Eliminate the variable with the larger coefficient.
*/
    if (integerStatus == 2) {
      CoinSwap(tgtcoly,tgtcolx) ;
      CoinSwap(krowy,krowx) ;
    } else if (integerStatus == 0) {
      if (fabs(colCoeffs[krowy]) < fabs(colCoeffs[krowx])) {
	CoinSwap(tgtcoly,tgtcolx) ;
	CoinSwap(krowy,krowx) ;
      }
    }
/*
  Don't eliminate y just yet if it's entangled in a singleton row (we want to
  capture that explicit bound in a column bound).
*/
    const CoinBigIndex kcsy = colStarts[tgtcoly] ;
    const CoinBigIndex kcey = kcsy+colLengths[tgtcoly] ;
    bool singletonRow = false ;
    for (CoinBigIndex kcol = kcsy ; kcol < kcey ; kcol++) {
      if (rowLengths[rowIndices[kcol]] == 1) {
        singletonRow = true ;
	break ;
      }
    }
    // skip if y prohibited
    if (singletonRow || prob->colProhibited2(tgtcoly)) continue ;

    coeffx = colCoeffs[krowx] ;
    coeffy = colCoeffs[krowy] ;
#   if PRESOLVE_DEBUG > 2
    std::cout
      << "  doubleton row " << tgtrow << ", keep x(" << tgtcolx
      << ") elim x(" << tgtcoly << ")." << std::endl ;
#   endif
    PRESOLVE_DETAIL_PRINT(printf("pre_doubleton %dC %dC %dR E\n",
				 tgtcoly,tgtcolx,tgtrow)) ;
/*
  Capture the existing columns and other information before we start to modify
  the constraint system. Save the shorter column.
*/
    action *s = &actions[nactions] ;
    nactions++ ;
    s->row = tgtrow ;
    s->icolx = tgtcolx ;
    s->clox = clo[tgtcolx] ;
    s->cupx = cup[tgtcolx] ;
    s->costx = cost[tgtcolx] ;
    s->icoly = tgtcoly ;
    s->costy = cost[tgtcoly] ;
    s->rlo = rlo[tgtrow] ;
    s->coeffx = coeffx ;
    s->coeffy = coeffy ;
    s->ncolx = colLengths[tgtcolx] ;
    s->ncoly = colLengths[tgtcoly] ;
    if (s->ncoly < s->ncolx) {
      s->colel	= presolve_dupmajor(colCoeffs,rowIndices,colLengths[tgtcoly],
				    colStarts[tgtcoly],tgtrow) ;
      s->ncolx = 0 ;
    } else {
      s->colel = presolve_dupmajor(colCoeffs,rowIndices,colLengths[tgtcolx],
				   colStarts[tgtcolx],tgtrow) ;
      s->ncoly = 0 ;
    }
/*
  Move finite bound information from y to x, so that y is implied free.
    a x + b y = c
    l1 <= x <= u1
    l2 <= y <= u2
   
    l2 <= (c - a x) / b <= u2
    b/-a > 0 ==> (b l2 - c) / -a <= x <= (b u2 - c) / -a
    b/-a < 0 ==> (b u2 - c) / -a <= x <= (b l2 - c) / -a
*/
    {
      double lo1 = -PRESOLVE_INF ;
      double up1 = PRESOLVE_INF ;
      
      if (-PRESOLVE_INF < clo[tgtcoly]) {
	if (coeffx*coeffy < 0)
	  lo1 = (coeffy*clo[tgtcoly]-rhs)/-coeffx ;
	else 
	  up1 = (coeffy*clo[tgtcoly]-rhs)/-coeffx ;
      }
      
      if (cup[tgtcoly] < PRESOLVE_INF) {
	if (coeffx*coeffy < 0)
	  up1 = (coeffy*cup[tgtcoly]-rhs)/-coeffx ;
	else 
	  lo1 = (coeffy*cup[tgtcoly]-rhs)/-coeffx ;
      }
/*
  Don't forget the objective coefficient.
    costy y = costy ((c - a x) / b) = (costy c)/b + x (costy -a)/b
*/
      cost[tgtcolx] += (cost[tgtcoly]*-coeffx)/coeffy ;
      prob->change_bias((cost[tgtcoly]*rhs)/coeffy) ;
/*
  The transfer of bounds could make x infeasible. Patch it up if the problem
  is minor or if the user was so incautious as to instruct us to ignore it.
  Prefer an integer value if there's one nearby. If there's nothing to be
  done, break out of the main loop.
*/
      {
	double lo2 = CoinMax(clo[tgtcolx],lo1) ;
	double up2 = CoinMin(cup[tgtcolx],up1) ;
	if (lo2 > up2) {
	  if (lo2 <= up2+prob->feasibilityTolerance_ || fixInfeasibility) {
	    double nearest = floor(lo2+0.5) ;
	    if (fabs(nearest-lo2) < 2.0*prob->feasibilityTolerance_) {
	      lo2 = nearest ;
	      up2 = nearest ;
	    } else {
	      lo2 = up2 ;
	    }
	  } else {
	    prob->status_ |= 1 ;
	    prob->messageHandler()->message(COIN_PRESOLVE_COLINFEAS,
	    				    prob->messages())
		 << tgtcolx << lo2 << up2 << CoinMessageEol ;
	    break ;
	  }
	}
#       if PRESOLVE_DEBUG > 2
	std::cout
	  << "  x(" << tgtcolx << ") lb " << clo[tgtcolx] << " --> " << lo2
	  << ", ub " << cup[tgtcolx] << " --> " << up2 << std::endl ;
#       endif
	clo[tgtcolx] = lo2 ;
	cup[tgtcolx] = up2 ;
/*
  Do we have a solution to maintain? If so, take a stab at it. If x ends up at
  bound, prefer to set it nonbasic, but if we're short of basic variables
  after eliminating y and the logical for the row, make it basic.

  This code will snap the value of x to bound if it's within the primal
  feasibility tolerance.
*/
	if (rowstat && sol) {
	  int numberBasic = 0 ;
	  double movement = 0 ;
	  if (prob->columnIsBasic(tgtcolx))
	    numberBasic++ ;
	  if (prob->columnIsBasic(tgtcoly))
	    numberBasic++ ;
	  if (prob->rowIsBasic(tgtrow))
	    numberBasic++ ;
	  if (sol[tgtcolx] <= lo2+ztolzb) {
	    movement = lo2-sol[tgtcolx] ;
	    sol[tgtcolx] = lo2 ;
	    prob->setColumnStatus(tgtcolx,
	    			  CoinPrePostsolveMatrix::atLowerBound) ;
	  } else if (sol[tgtcolx] >= up2-ztolzb) {
	    movement = up2-sol[tgtcolx] ;
	    sol[tgtcolx] = up2 ;
	    prob->setColumnStatus(tgtcolx,
	    			  CoinPrePostsolveMatrix::atUpperBound) ;
	  }
	  if (numberBasic > 1)
	    prob->setColumnStatus(tgtcolx,CoinPrePostsolveMatrix::basic) ;
/*
  We need to compensate if x was forced to move. Beyond that, even if x
  didn't move, we've forced y = (c-ax)/b, and that might not have been
  true before. So even if x didn't move, y may have moved. Note that the
  constant term c/b is subtracted out as the constraints are modified,
  so we don't include it when calculating movement for y.
*/
	  if (movement) { 
	    const CoinBigIndex kkcsx = colStarts[tgtcolx] ;
	    const CoinBigIndex kkcex = kkcsx+colLengths[tgtcolx] ;
	    for (CoinBigIndex kcol = kkcsx ; kcol < kkcex ; kcol++) {
	      int row = rowIndices[kcol] ;
	      if (rowLengths[row])
		acts[row] += movement*colCoeffs[kcol] ;
	    }
	  }
	  movement = ((-coeffx*sol[tgtcolx])/coeffy)-sol[tgtcoly] ;
	  if (movement) {
	    const CoinBigIndex kkcsy = colStarts[tgtcoly] ;
	    const CoinBigIndex kkcey = kkcsy+colLengths[tgtcoly] ;
	    for (CoinBigIndex kcol = kkcsy ; kcol < kkcey ; kcol++) {
	      int row = rowIndices[kcol] ;
	      if (rowLengths[row])
		acts[row] += movement*colCoeffs[kcol] ;
	    }
	  }
	}
	if (lo2 == up2)
	  fixed[nfixed++] = tgtcolx ;
      }
    }
/*
  We're done transferring bounds from y to x, and we've patched up the
  solution if one existed to patch. One last thing to do before we eliminate
  column y and the doubleton row: put column x and the entangled rows on
  the lists of columns and rows to look at in the next round of transforms.
*/
    {
      prob->addCol(tgtcolx) ;
      const CoinBigIndex kkcsy = colStarts[tgtcoly] ;
      const CoinBigIndex kkcey = kkcsy+colLengths[tgtcoly] ;
      for (CoinBigIndex kcol = kkcsy ; kcol < kkcey ; kcol++) {
	int row = rowIndices[kcol] ;
	prob->addRow(row) ;
      }
      const CoinBigIndex kkcsx = colStarts[tgtcolx] ;
      const CoinBigIndex kkcex = kkcsx+colLengths[tgtcolx] ;
      for (CoinBigIndex kcol = kkcsx ; kcol < kkcex ; kcol++) {
	int row = rowIndices[kcol] ;
	prob->addRow(row) ;
      }
    }

/*
  Empty tgtrow in the column-major matrix.  Deleting the coefficient for
  (tgtrow,tgtcoly) is a bit costly (given that we're about to drop the whole
  column), but saves the trouble of checking for it in elim_doubleton.
*/
    presolve_delete_from_col(tgtrow,tgtcolx,
    			     colStarts,colLengths,rowIndices,colCoeffs) ;
    presolve_delete_from_col(tgtrow,tgtcoly,
    			     colStarts,colLengths,rowIndices,colCoeffs) ;
/*
  Drop tgtrow in the row-major representation: set the length to 0
  and reclaim the major vector space in bulk storage.
*/
    rowLengths[tgtrow] = 0 ;
    PRESOLVE_REMOVE_LINK(rlink,tgtrow) ;

/*
  Transfer the colx factors to coly. This modifies coefficients in column x
  as it removes coefficients in column y.
*/
    bool no_mem = elim_doubleton("ELIMD",
				 colStarts,rlo,rup,colCoeffs,
				 rowIndices,colIndices,rowLengths,colLengths,
				 clink,n, 
				 rowStarts,rowCoeffs,
				 -coeffx/coeffy,
				 rhs/coeffy,
				 tgtrow,tgtcolx,tgtcoly) ;
    if (no_mem) 
      throwCoinError("out of memory","doubleton_action::presolve") ;

/*
  Eliminate coly entirely from the col rep. We'll want to groom colx to remove
  explicit zeros.
*/
    colLengths[tgtcoly] = 0 ;
    PRESOLVE_REMOVE_LINK(clink, tgtcoly) ;
    cost[tgtcoly] = 0.0 ;

    rlo[tgtrow] = 0.0 ;
    rup[tgtrow] = 0.0 ;

    zeros[nzeros++] = tgtcolx ;

#   if PRESOLVE_CONSISTENCY > 0
    presolve_consistent(prob) ;
    presolve_links_ok(prob) ;
#   endif
  }
/*
  Tidy up the collected actions and clean up explicit zeros and fixed
  variables. Don't bother unless we're feasible (status of 0).
*/
  if (nactions && !prob->status_) {
#   if PRESOLVE_SUMMARY > 0
    printf("NDOUBLETONS:  %d\n", nactions) ;
#   endif
    action *actions1 = new action[nactions] ;
    CoinMemcpyN(actions, nactions, actions1) ;

    next = new doubleton_action(nactions, actions1, next) ;

    if (nzeros)
      next = drop_zero_coefficients_action::presolve(prob, zeros, nzeros, next) ;
    if (nfixed)
      next = remove_fixed_action::presolve(prob, fixed, nfixed, next) ;
  }

  deleteAction(actions,action*) ;

# if COIN_PRESOLVE_TUNING > 0
  if (prob->tuning_) double thisTime = CoinCpuTime() ;
# endif
# if PRESOLVE_CONSISTENCY > 0 || PRESOLVE_DEBUG > 0
  presolve_check_sol(prob) ;
# endif
# if PRESOLVE_DEBUG > 0 || COIN_PRESOLVE_TUNING > 0
  int droppedRows = prob->countEmptyRows()-startEmptyRows ;
  int droppedColumns = prob->countEmptyCols()-startEmptyColumns ;
  std::cout
    << "Leaving doubleton_action::presolve, " << droppedRows << " rows, "
    << droppedColumns << " columns dropped" ;
# if COIN_PRESOLVE_TUNING > 0
  std::cout << " in " << thisTime-startTime << "s" ;
# endif
  std::cout << "." << std::endl ;
# endif

  return (next) ;
}
Exemplo n.º 28
0
int main (int argc, const char *argv[])
{

  // Define your favorite OsiSolver
  
  OsiClpSolverInterface solver1;

  // Read in model using argv[1]
  // and assert that it is a clean model
  std::string mpsFileName;
#if defined(SAMPLEDIR)
  mpsFileName = SAMPLEDIR "/p0033.mps";
#else
  if (argc < 2) {
    fprintf(stderr, "Do not know where to find sample MPS files.\n");
    exit(1);
  }
#endif
  if (argc>=2) mpsFileName = argv[1];
  int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),"");
  assert(numMpsReadErrors==0);
  double time1 = CoinCpuTime();

  /* Options are:
     preprocess to do preprocessing
     time in minutes
     if 2 parameters and numeric taken as time
  */
  bool preProcess=false;
  double minutes=-1.0;
  int nGoodParam=0;
  for (int iParam=2; iParam<argc;iParam++) {
    if (!strcmp(argv[iParam],"preprocess")) {
      preProcess=true;
      nGoodParam++;
    } else if (!strcmp(argv[iParam],"time")) {
      if (iParam+1<argc&&isdigit(argv[iParam+1][0])) {
        minutes=atof(argv[iParam+1]);
        if (minutes>=0.0) {
          nGoodParam+=2;
          iParam++; // skip time
        }
      }
    }
  }
  if (nGoodParam==0&&argc==3&&isdigit(argv[2][0])) {
    // If time is given then stop after that number of minutes
    minutes = atof(argv[2]);
    if (minutes>=0.0) 
      nGoodParam=1;
  }
  if (nGoodParam!=argc-2&&argc>=2) {
    printf("Usage <file> [preprocess] [time <minutes>] or <file> <minutes>\n");
    exit(1);
  }
  //solver1.getModelPtr()->setLogLevel(0);
  solver1.messageHandler()->setLogLevel(0);
  solver1.initialSolve();
  // Reduce printout
  solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry);
  CbcModel model(solver1);
  model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
  // Set up some cut generators and defaults
  // Probing first as gets tight bounds on continuous

  CglProbing generator1;
  generator1.setUsingObjective(true);
  generator1.setMaxPass(1);
  generator1.setMaxPassRoot(5);
  // Number of unsatisfied variables to look at
  generator1.setMaxProbe(10);
  generator1.setMaxProbeRoot(1000);
  // How far to follow the consequences
  generator1.setMaxLook(50);
  generator1.setMaxLookRoot(500);
  // Only look at rows with fewer than this number of elements
  generator1.setMaxElements(200);
  generator1.setRowCuts(3);

  CglGomory generator2;
  // try larger limit
  generator2.setLimit(300);

  CglKnapsackCover generator3;

  CglRedSplit generator4;
  // try larger limit
  generator4.setLimit(200);

  CglClique generator5;
  generator5.setStarCliqueReport(false);
  generator5.setRowCliqueReport(false);

  CglMixedIntegerRounding2 mixedGen;
  CglFlowCover flowGen;
  
  // Add in generators
  // Experiment with -1 and -99 etc
  model.addCutGenerator(&generator1,-1,"Probing");
  model.addCutGenerator(&generator2,-1,"Gomory");
  model.addCutGenerator(&generator3,-1,"Knapsack");
  // model.addCutGenerator(&generator4,-1,"RedSplit");
  model.addCutGenerator(&generator5,-1,"Clique");
  model.addCutGenerator(&flowGen,-1,"FlowCover");
  model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding");
  OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (model.solver());
  // go faster stripes
  if (osiclp) {
    // Turn this off if you get problems
    // Used to be automatically set
    osiclp->setSpecialOptions(128);
    if(osiclp->getNumRows()<300&&osiclp->getNumCols()<500) {
      //osiclp->setupForRepeatedUse(2,1);
      osiclp->setupForRepeatedUse(0,1);
    }
  } 
  // Uncommenting this should switch off most CBC messages
  //model.messagesPointer()->setDetailMessages(10,5,5000);
  // Allow rounding heuristic

  CbcRounding heuristic1(model);
  model.addHeuristic(&heuristic1);

  // And local search when new solution found

  CbcHeuristicLocal heuristic2(model);
  model.addHeuristic(&heuristic2);

  // Redundant definition of default branching (as Default == User)
  CbcBranchUserDecision branch;
  model.setBranchingMethod(&branch);

  // Definition of node choice
  CbcCompareUser compare;
  model.setNodeComparison(compare);

  // Do initial solve to continuous
  model.initialSolve();

  // Could tune more
  double objValue = model.solver()->getObjSense()*model.solver()->getObjValue();
  double minimumDropA=CoinMin(1.0,fabs(objValue)*1.0e-3+1.0e-4);
  double minimumDrop= fabs(objValue)*1.0e-4+1.0e-4;
  printf("min drop %g (A %g)\n",minimumDrop,minimumDropA);
  model.setMinimumDrop(minimumDrop);

  if (model.getNumCols()<500)
    model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible
  else if (model.getNumCols()<5000)
    model.setMaximumCutPassesAtRoot(100); // use minimum drop
  else
    model.setMaximumCutPassesAtRoot(20);
  model.setMaximumCutPasses(10);
  //model.setMaximumCutPasses(2);

  // Switch off strong branching if wanted
  // model.setNumberStrong(0);
  // Do more strong branching if small
  if (model.getNumCols()<5000)
    model.setNumberStrong(10);
  model.setNumberStrong(20);
  //model.setNumberStrong(5);
  model.setNumberBeforeTrust(5);
  //model.setSizeMiniTree(2);

  model.solver()->setIntParam(OsiMaxNumIterationHotStart,100);

  // If time is given then stop after that number of minutes
  if (minutes>=0.0) {
    std::cout<<"Stopping after "<<minutes<<" minutes"<<std::endl;
    model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes);
  }
  // Switch off most output
  if (model.getNumCols()<3000) {
    model.messageHandler()->setLogLevel(1);
    //model.solver()->messageHandler()->setLogLevel(0);
  } else {
    model.messageHandler()->setLogLevel(2);
    model.solver()->messageHandler()->setLogLevel(1);
  }
  // Default strategy will leave cut generators as they exist already
  // so cutsOnlyAtRoot (1) ignored
  // numberStrong (2) is 5 (default)
  // numberBeforeTrust (3) is 5 (default is 0)
  // printLevel (4) defaults (0)
  CbcStrategyDefault strategy(true,5,5);
  // Set up pre-processing to find sos if wanted
  if (preProcess)
    strategy.setupPreProcessing(2);
  model.setStrategy(strategy);

  // Go round adding cuts to cutoff last solution
  // Stop after finding 20 best solutions
  for (int iPass=0;iPass<20;iPass++) {
    time1 = CoinCpuTime();
    // Do complete search
    model.branchAndBound();
    
    std::cout<<mpsFileName<<" took "<<CoinCpuTime()-time1<<" seconds, "
             <<model.getNodeCount()<<" nodes with objective "
             <<model.getObjValue()
             <<(!model.status() ? " Finished" : " Not finished")
             <<std::endl;
    // Stop if infeasible
    if (model.isProvenInfeasible())
      break;
    // Print solution if finished - we can't get names from Osi! - so get from OsiClp
    
    assert (model.getMinimizationObjValue()<1.0e50);
    OsiSolverInterface * solver = model.solver();
    int numberColumns = solver->getNumCols();
    
    const double * solution = model.bestSolution();
    //const double * lower = solver->getColLower();
    //const double * upper = solver->getColUpper();

    // Get names from solver1 (as OsiSolverInterface may lose)
    std::vector<std::string> columnNames = *solver1.getModelPtr()->columnNames();
    
    int iColumn;
    std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
    
    std::cout<<"--------------------------------------"<<std::endl;
    for (iColumn=0;iColumn<numberColumns;iColumn++) {
      double value=solution[iColumn];
      if (fabs(value)>1.0e-7&&solver->isInteger(iColumn)) 
	std::cout<<std::setw(6)<<iColumn<<" "
                 <<columnNames[iColumn]<<" "
                 <<value
          //<<" "<<lower[iColumn]<<" "<<upper[iColumn]
                 <<std::endl;
    }
    std::cout<<"--------------------------------------"<<std::endl;
  
    std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);
    /* Now add cut to reference copy.
       resetting to reference copy also gets rid of best solution so we
       should either save best solution, reset, add cut OR
       add cut to reference copy then reset - this is doing latter
    */
    OsiSolverInterface * refSolver = model.referenceSolver();
    const double * bestSolution = model.bestSolution();
    const double * originalLower = refSolver->getColLower();
    const double * originalUpper = refSolver->getColUpper();
    CoinPackedVector cut;
    double rhs = 1.0;
    for (iColumn=0;iColumn<numberColumns;iColumn++) {
      double value=bestSolution[iColumn];
      if (solver->isInteger(iColumn)) {
        // only works for 0-1 variables
        assert (originalLower[iColumn]==0.0&&
                originalUpper[iColumn]==1.0);
        // double check integer
        assert (fabs(floor(value+0.5)-value)<1.0e-5);
        if (value>0.5) {
          // at 1.0
          cut.insert(iColumn,-1.0);
          rhs -= 1.0;
        } else {
          // at 0.0
          cut.insert(iColumn,1.0);
        }
      }
    }
    // now add cut
    refSolver->addRow(cut,rhs,COIN_DBL_MAX);
    model.resetToReferenceSolver();
  }
  return 0;
}    
Exemplo n.º 29
0
/*
  It may be the case that the bounds on the variables in a constraint are
  such that no matter what feasible value the variables take, the constraint
  cannot be violated. In this case we can drop the constraint as useless.

  On the other hand, it may be that the only way to satisfy a constraint
  is to jam all the variables in the constraint to one of their bounds, fixing
  the variables. This is a forcing constraint, the primary target of this
  transform.

  Detection of both useless and forcing constraints requires calculation of
  bounds on the row activity (often referred to as lhs bounds, from the common
  form ax <= b). This routine will remember useless constraints as it finds
  them and invoke useless_constraint_action to deal with them.
  
  The transform applied here simply tightens the bounds on the variables.
  Other transforms will remove the fixed variables, leaving an empty row which
  is ultimately dropped.

  A reasonable question to ask is ``If a variable is already fixed, why do
  we need a record in the postsolve object?'' The answer is that in postsolve
  we'll be dealing with a column-major representation and we may need to scan
  the row (see postsolve comments). So it's useful to record all variables in
  the constraint.
  
  On the other hand, it's definitely harmful to ask remove_fixed_action
  to process a variable more than once (causes problems in
  remove_fixed_action::postsolve).

  Original comments:

  It looks like these checks could be performed in parallel, that is,
  the tests could be carried out for all rows in parallel, and then the
  rows deleted and columns tightened afterward.  Obviously, this is true
  for useless rows.  By doing it in parallel rather than sequentially,
  we may miss transformations due to variables that were fixed by forcing
  constraints, though.

  Note that both of these operations will cause problems if the variables
  in question really need to exceed their bounds in order to make the
  problem feasible.
*/
const CoinPresolveAction*
  forcing_constraint_action::presolve (CoinPresolveMatrix *prob,
  				       const CoinPresolveAction *next)
{
# if PRESOLVE_DEBUG > 0 || COIN_PRESOLVE_TUNING
  int startEmptyRows = 0 ;
  int startEmptyColumns = 0 ;
  startEmptyRows = prob->countEmptyRows() ;
  startEmptyColumns = prob->countEmptyCols() ;
# endif
# if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0
# if PRESOLVE_DEBUG > 0
  std::cout
    << "Entering forcing_constraint_action::presolve, considering "
    << prob->numberRowsToDo_ << " rows." << std::endl ;
# endif
  presolve_check_sol(prob) ;
  presolve_check_nbasic(prob) ;
# endif
# if COIN_PRESOLVE_TUNING
  double startTime = 0.0 ;
  if (prob->tuning_) {
    startTime = CoinCpuTime() ;
  }
# endif

  // Column solution and bounds
  double *clo = prob->clo_ ;
  double *cup = prob->cup_ ;
  double *csol = prob->sol_ ;

  // Row-major representation
  const CoinBigIndex *mrstrt = prob->mrstrt_ ;
  const double *rowels = prob->rowels_ ;
  const int *hcol = prob->hcol_ ;
  const int *hinrow = prob->hinrow_ ;
  const int nrows = prob->nrows_ ;

  const double *rlo = prob->rlo_ ;
  const double *rup = prob->rup_ ;

  const double tol = ZTOLDP ;
  const double inftol = prob->feasibilityTolerance_ ;
  // for redundant rows be safe
  const double inftol2 = 0.01*prob->feasibilityTolerance_ ;
  const int ncols = prob->ncols_ ;

  int *fixed_cols = new int[ncols] ;
  int nfixed_cols = 0 ;

  action *actions = new action [nrows] ;
  int nactions = 0 ;

  int *useless_rows = new int[nrows] ;
  int nuseless_rows = 0 ;

  const int numberLook = prob->numberRowsToDo_ ;
  int *look = prob->rowsToDo_ ;

  bool fixInfeasibility = ((prob->presolveOptions_&0x4000) != 0) ;
/*
  Open a loop to scan the constraints of interest. There must be variables
  left in the row.
*/
  for (int iLook = 0 ; iLook < numberLook ; iLook++) {
    int irow = look[iLook] ;
    if (hinrow[irow] <= 0) continue ;

    const CoinBigIndex krs = mrstrt[irow] ;
    const CoinBigIndex kre = krs+hinrow[irow] ;
/*
  Calculate upper and lower bounds on the row activity based on upper and lower
  bounds on the variables. If these are finite and incompatible with the given
  row bounds, we have infeasibility.
*/
    double maxup, maxdown ;
    implied_row_bounds(rowels,clo,cup,hcol,krs,kre,maxup,maxdown) ;
#   if PRESOLVE_DEBUG > 2
    std::cout
      << "  considering row " << irow << ", rlo " << rlo[irow]
      << " LB " << maxdown << " UB " << maxup << " rup " << rup[irow] ;
#   endif
/*
  If the maximum lhs value is less than L(i) or the minimum lhs value is
  greater than U(i), we're infeasible.
*/
    if (maxup < PRESOLVE_INF &&
        maxup+inftol < rlo[irow] && !fixInfeasibility) {
      CoinMessageHandler *hdlr = prob->messageHandler() ;
      prob->status_|= 1 ;
      hdlr->message(COIN_PRESOLVE_ROWINFEAS,prob->messages())
	 << irow << rlo[irow] << rup[irow] << CoinMessageEol ;
#     if PRESOLVE_DEBUG > 2
      std::cout << "; infeasible." << std::endl ;
#     endif
      break ;
    }
    if (-PRESOLVE_INF < maxdown &&
        rup[irow] < maxdown-inftol && !fixInfeasibility) {
      CoinMessageHandler *hdlr = prob->messageHandler() ;
      prob->status_|= 1 ;
      hdlr->message(COIN_PRESOLVE_ROWINFEAS,prob->messages())
	 << irow << rlo[irow] << rup[irow] << CoinMessageEol ;
#     if PRESOLVE_DEBUG > 2
      std::cout << "; infeasible." << std::endl ;
#     endif
      break ;
    }
/*
  We've dealt with prima facie infeasibility. Now check if the constraint
  is trivially satisfied. If so, add it to the list of useless rows and move
  on.

  The reason we require maxdown and maxup to be finite if the row bound is
  finite is to guard against some subsequent transform changing a column
  bound from infinite to finite. Once finite, bounds continue to tighten,
  so we're safe.
*/
    /* Test changed to use +small tolerance rather than -tolerance
       as test fails often */
    if (((rlo[irow] <= -PRESOLVE_INF) ||
	 (-PRESOLVE_INF < maxdown && rlo[irow] <= maxdown+inftol2)) &&
	((rup[irow] >= PRESOLVE_INF) ||
	 (maxup < PRESOLVE_INF && rup[irow] >= maxup-inftol2))) {
      // check none prohibited
      if (prob->anyProhibited_) {
	bool anyProhibited=false;
	for (int k=krs; k<kre; k++) {
	  int jcol = hcol[k];
	  if (prob->colProhibited(jcol)) {
	    anyProhibited=true;
	    break;
	  }
	}
	if (anyProhibited)
	  continue; // skip row
      }
      useless_rows[nuseless_rows++] = irow ;
#     if PRESOLVE_DEBUG > 2
      std::cout << "; useless." << std::endl ;
#     endif
      continue ;
    }
/*
  Is it the case that we can just barely attain L(i) or U(i)? If so, we have a
  forcing constraint. As explained above, we need maxup and maxdown to be
  finite in order for the test to be valid.
*/
    const bool tightAtLower = ((maxup < PRESOLVE_INF) &&
    			       (fabs(rlo[irow]-maxup) < tol)) ;
    const bool tightAtUpper = ((-PRESOLVE_INF < maxdown) &&
			       (fabs(rup[irow]-maxdown) < tol)) ;
#   if PRESOLVE_DEBUG > 2
    if (tightAtLower || tightAtUpper) std::cout << "; forcing." ;
    std::cout << std::endl ;
#   endif
    if (!(tightAtLower || tightAtUpper)) continue ;
    // check none prohibited
    if (prob->anyProhibited_) {
      bool anyProhibited=false;
      for (int k=krs; k<kre; k++) {
	int jcol = hcol[k];
	if (prob->colProhibited(jcol)) {
	  anyProhibited=true;
	  break;
	}
      }
      if (anyProhibited)
	continue; // skip row
    }
/*
  We have a forcing constraint.
  Get down to the business of fixing the variables at the appropriate bound.
  We need to remember the original value of the bound we're tightening.
  Allocate a pair of arrays the size of the row. Load variables fixed at l<j>
  from the start, variables fixed at u<j> from the end. Add the column to
  the list of columns to be processed further.
*/
    double *bounds = new double[hinrow[irow]] ;
    int *rowcols = new int[hinrow[irow]] ;
    CoinBigIndex lk = krs ;
    CoinBigIndex uk = kre ;
    for (CoinBigIndex k = krs ; k < kre ; k++) {
      const int j = hcol[k] ;
      const double lj = clo[j] ;
      const double uj = cup[j] ;
      const double coeff = rowels[k] ;
      PRESOLVEASSERT(fabs(coeff) > ZTOLDP) ;
/*
  If maxup is tight at L(i), then we want to force variables x<j> to the bound
  that produced maxup: u<j> if a<ij> > 0, l<j> if a<ij> < 0. If maxdown is
  tight at U(i), it'll be just the opposite.
*/
      if (tightAtLower == (coeff > 0.0)) {
	--uk ;
	bounds[uk-krs] = lj ;
	rowcols[uk-krs] = j ;
	if (csol != 0) {
	  csol[j] = uj ;
	}
	clo[j] = uj ;
      } else {
	bounds[lk-krs] = uj ;
	rowcols[lk-krs] = j ;
	++lk ;
	if (csol != 0) {
	  csol[j] = lj ;
	}
	cup[j] = lj ;
      }
/*
  Only add a column to the list of fixed columns the first time it's fixed.
*/
      if (lj != uj) {
	fixed_cols[nfixed_cols++] = j ;
	prob->addCol(j) ;
      }
    }
    PRESOLVEASSERT(uk == lk) ;
    PRESOLVE_DETAIL_PRINT(printf("pre_forcing %dR E\n",irow)) ;
#   if PRESOLVE_DEBUG > 1
    std::cout
      << "FORCING: row(" << irow << "), " << (kre-krs) << " variables."
      << std::endl ;
#   endif
/*
  Done with this row. Remember the changes in a postsolve action.
*/
    action *f = &actions[nactions] ;
    nactions++ ;
    f->row = irow ;
    f->nlo = lk-krs ;
    f->nup = kre-uk ;
    f->rowcols = rowcols ;
    f->bounds = bounds ;
  }

/*
  Done processing the rows of interest.  No sense doing any additional work
  unless we're feasible.
*/
  if (prob->status_ == 0) {
#   if PRESOLVE_DEBUG > 0
    std::cout
      << "FORCING: " << nactions << " forcing, " << nuseless_rows << " useless."
      << std::endl ;
#   endif
/*
  Trim the actions array to size and create a postsolve object.
*/
    if (nactions) {
      next = new forcing_constraint_action(nactions, 
				 CoinCopyOfArray(actions,nactions),next) ;
    }
/*
  Hand off the job of dealing with the useless rows to a specialist.
*/
    if (nuseless_rows) {
      next = useless_constraint_action::presolve(prob,
      					useless_rows,nuseless_rows,next) ;
    }
/*
  Hand off the job of dealing with the fixed columns to a specialist.

  Note that there *cannot* be duplicates in this list or we'll get in trouble
  `unfixing' a column multiple times. The code above now adds a variable
  to fixed_cols only if it's not already fixed. If that ever changes,
  the disabled code (sort, unique) will need to be reenabled.
*/
    if (nfixed_cols) {
      if (false && nfixed_cols > 1) {
	std::sort(fixed_cols,fixed_cols+nfixed_cols) ;
	int *end = std::unique(fixed_cols,fixed_cols+nfixed_cols) ;
	nfixed_cols = static_cast<int>(end-fixed_cols) ;
      }
      next = remove_fixed_action::presolve(prob,fixed_cols,nfixed_cols,next) ;
    }
  } else {
    // delete arrays
    for (int i=0;i<nactions;i++) {
      deleteAction(actions[i].rowcols,int *) ;
      deleteAction(actions[i].bounds,double *) ;
    }
  }

  deleteAction(actions,action*) ;
  delete [] useless_rows ;
  delete [] fixed_cols ;

# if COIN_PRESOLVE_TUNING
  if (prob->tuning_) double thisTime = CoinCpuTime() ;
# endif
# if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0
  presolve_check_sol(prob) ;
  presolve_check_nbasic(prob) ;
# endif
# if PRESOLVE_DEBUG > 0 || COIN_PRESOLVE_TUNING
  int droppedRows = prob->countEmptyRows()-startEmptyRows ;
  int droppedColumns =  prob->countEmptyCols()-startEmptyColumns ;
  std::cout
    << "Leaving forcing_constraint_action::presolve: removed " << droppedRows
    << " rows, " << droppedColumns << " columns" ;
# if COIN_PRESOLVE_TUNING > 0
  if (prob->tuning_)
    std::cout << " in " << (thisTime-prob->startTime_) << "s" ;
# endif
  std::cout << "." << std::endl ;
# endif

  return (next) ;
}
Exemplo n.º 30
0
/************************************************************************

This main program reads in an integer model from an mps file.

It then tries to find SOS structure and solves using N-way variables

*************************************************************************/
int main (int argc, const char *argv[])
{
  
  // Define your favorite OsiSolver
  
  OsiClpSolverInterface solver1;
  
  // Read in model using argv[1]
  // and assert that it is a clean model
  std::string mpsFileName;
#if defined(MIPLIB3DIR)
  mpsFileName = MIPLIB3DIR "/10teams";
#else
  if (argc < 2) {
    fprintf(stderr, "Do not know where to find miplib3 MPS files.\n");
    exit(1);
  }
#endif
  if (argc>=2) mpsFileName = argv[1];
  int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),"");
  if( numMpsReadErrors != 0 )
  {
     printf("%d errors reading MPS file\n", numMpsReadErrors);
     return numMpsReadErrors;
  }
  
  int iRow, iColumn;
  int numberColumns = solver1.getNumCols();
  int numberRows = solver1.getNumRows();
  // get row copy
  const CoinPackedMatrix * matrix = solver1.getMatrixByRow();
  const double * element = matrix->getElements();
  const int * column = matrix->getIndices();
  const CoinBigIndex * rowStart = matrix->getVectorStarts();
  const int * rowLength = matrix->getVectorLengths();
  const double * rowLower = solver1.getRowLower();
  const double * rowUpper = solver1.getRowUpper();
  const double * columnLower = solver1.getColLower();
  
  // Look for possible SOS
  int numberSOS=0;
  int * mark = new int[numberColumns];
  CoinFillN(mark,numberColumns,-1);
  for (iRow=0;iRow<numberRows;iRow++) {
    if (rowLower[iRow]==1.0&&rowUpper[iRow]==1.0) {
      bool goodRow=true;
      for (int j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) {
        int iColumn = column[j];
        if (element[j]!=1.0||!solver1.isInteger(iColumn)||mark[iColumn]>=0||columnLower[iColumn]) {
          goodRow=false;
          break;
        }
      }
      if (goodRow) {
        // mark all
        for (int j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) {
          int iColumn = column[j];
          mark[iColumn]=numberSOS;
        }
        numberSOS++;
      }
    }
  }
  std::cout<<numberSOS<<" SOS"<<std::endl;
  if (!numberSOS)
    return 0;
  CbcModel model(solver1);
  // Do sets and priorities
  CbcObject ** objects = new CbcObject * [numberSOS];
  int numberIntegers = model.numberIntegers();
  /* model may not have created objects
     If none then create
  */
  if (!numberIntegers||!model.numberObjects()) {
    model.findIntegers(true);
    numberIntegers = model.numberIntegers();
  }
  int * priority = new int[numberSOS];
  // Set SOS priorities high
  CoinFillN(priority,numberSOS,1);
  // Set up SOS
  int * which = new int[numberColumns];
  for (int iSOS =0;iSOS<numberSOS;iSOS++) {
    int n=0;
    for (iColumn=0;iColumn<numberColumns;iColumn++) {
      if (mark[iColumn]==iSOS)
        which[n++]=iColumn;
    }
    // NULL uses 0,1,2 .. as weights
    objects[iSOS]= new CbcNWay(&model,n,which,iSOS);
  }
  delete [] mark;
  delete [] which;
  model.addObjects(numberSOS,objects);
  for (iColumn=0;iColumn<numberSOS;iColumn++)
    delete objects[iColumn];
  delete [] objects;
  model.passInPriorities(priority,true);
  delete [] priority;

  // If time is given then stop after that number of minutes
  if (argc>2) {
    int minutes = atoi(argv[2]);
    std::cout<<"Stopping after "<<minutes<<" minutes"<<std::endl;
    assert (minutes>=0);
    model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes);
  }
  // Switch off most output
  model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
  if (model.getNumCols()<3000) {
    model.messageHandler()->setLogLevel(1);
    //model.solver()->messageHandler()->setLogLevel(0);
  } else {
    model.messageHandler()->setLogLevel(2);
    //model.solver()->messageHandler()->setLogLevel(1);
  }
  //model.messageHandler()->setLogLevel(1);
  
  double time1 = CoinCpuTime();

  // Do complete search
  
  model.branchAndBound();

  std::cout<<mpsFileName<<" took "<<CoinCpuTime()-time1<<" seconds, "
	   <<model.getNodeCount()<<" nodes with objective "
	   <<model.getObjValue()
	   <<(!model.status() ? " Finished" : " Not finished")
	   <<std::endl;

  // Print solution - we can't get names from Osi!

  if (model.getMinimizationObjValue()<1.0e50) {
    int numberColumns = model.solver()->getNumCols();
    
    const double * solution = model.solver()->getColSolution();
    
    int iColumn;
    std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
    
    std::cout<<"--------------------------------------"<<std::endl;
    for (iColumn=0;iColumn<numberColumns;iColumn++) {
      double value=solution[iColumn];
      if (fabs(value)>1.0e-7&&model.solver()->isInteger(iColumn)) 
	std::cout<<std::setw(6)<<iColumn<<" "<<value<<std::endl;
    }
    std::cout<<"--------------------------------------"<<std::endl;
  
    std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);
  }
  return 0;
}