Example #1
0
void
CglClique::generateCuts(const OsiSolverInterface& si, OsiCuts & cs,
			const CglTreeInfo info)
{
   int i;
   bool has_petol_set = petol != -1.0;

   if (! has_petol_set)
      si.getDblParam(OsiPrimalTolerance, petol);
   int numberOriginalRows = si.getNumRows();
   if (info.inTree&&justOriginalRows_)
     numberOriginalRows = info.formulation_rows;
   int numberRowCutsBefore = cs.sizeRowCuts();
   // First select which rows/columns we are interested in.
   if (!setPacking_) {
      selectFractionalBinaries(si);
      if (!sp_orig_row_ind) {
	 selectRowCliques(si,numberOriginalRows);
      }
   } else {
      selectFractionals(si);
      delete[] sp_orig_row_ind;
      sp_numrows = numberOriginalRows;
      //sp_numcols = si.getNumCols();
      sp_orig_row_ind = new int[sp_numrows];
      for (i = 0; i < sp_numrows; ++i)
	 sp_orig_row_ind[i] = i;
   }
   // Just original rows
   if (justOriginalRows_&&info.inTree) 
     sp_numrows = CoinMin(info.formulation_rows,sp_numrows);
     

   createSetPackingSubMatrix(si);
   fgraph.edgenum = createNodeNode();
   createFractionalGraph();

   cl_indices = new int[sp_numcols];
   cl_del_indices = new int[sp_numcols];

   if (do_row_clique)
      find_rcl(cs);
   if (do_star_clique)
      find_scl(cs);
   if (!info.inTree&&((info.options&4)==4||((info.options&8)&&!info.pass))) {
     int numberRowCutsAfter = cs.sizeRowCuts();
     for (int i=numberRowCutsBefore;i<numberRowCutsAfter;i++)
       cs.rowCutPtr(i)->setGloballyValid();
   }

   delete[] cl_indices;     cl_indices = 0;
   delete[] cl_del_indices; cl_del_indices = 0;

   deleteFractionalGraph();
   delete[] node_node;      node_node = 0;
   deleteSetPackingSubMatrix();

   if (! has_petol_set)
      petol = -1;
}
Example #2
0
/*===========================================================================*
  Scan through the variables and select those that are binary and are at a
  fractional level.
 *===========================================================================*/
void
CglClique::selectFractionalBinaries(const OsiSolverInterface& si)
{
   // extract the primal tolerance from the solver
   double lclPetol = 0.0;
   si.getDblParam(OsiPrimalTolerance, lclPetol);

   const int numcols = si.getNumCols();
   if (petol<0.0) {
     // do all if not too many
     int n=0;
     for (int i = 0; i < numcols; ++i) {
       if (si.isBinary(i))
	 n++;
     }
     if (n<5000)
       lclPetol=-1.0e-5;
   }
   const double* x = si.getColSolution();
   std::vector<int> fracind;
   int i;
   for (i = 0; i < numcols; ++i) {
      if (si.isBinary(i) && x[i] > lclPetol && x[i] < 1-petol)
	 fracind.push_back(i);
   }
   sp_numcols = static_cast<int>(fracind.size());
   sp_orig_col_ind = new int[sp_numcols];
   sp_colsol = new double[sp_numcols];
   for (i = 0; i < sp_numcols; ++i) {
      sp_orig_col_ind[i] = fracind[i];
      sp_colsol[i] = x[fracind[i]];
   }
}
Example #3
0
// Returns true if current solution satsifies one side of branch
bool 
OsiSolverBranch::feasibleOneWay(const OsiSolverInterface & solver) const
{
  bool feasible = false;
  int numberColumns = solver.getNumCols();
  const double * columnLower = solver.getColLower();
  const double * columnUpper = solver.getColUpper();
  const double * columnSolution = solver.getColSolution();
  double primalTolerance;
  solver.getDblParam(OsiPrimalTolerance,primalTolerance);
  for (int base = 0; base<4; base +=2) {
    feasible=true;
    int i;
    for (i=start_[base];i<start_[base+1];i++) {
      int iColumn = indices_[i];
      if (iColumn<numberColumns) {
        double value = CoinMax(bound_[i],columnLower[iColumn]);
        if (columnSolution[iColumn]<value-primalTolerance) {
          feasible=false;
          break;
        }
      } else {
        abort(); // do later (other stuff messed up anyway - e.g. CBC)
      }
    }
    if (!feasible)
      break;
    for (i=start_[base+1];i<start_[base+2];i++) {
      int iColumn = indices_[i];
      if (iColumn<numberColumns) {
        double value = CoinMin(bound_[i],columnUpper[iColumn]);
        if (columnSolution[iColumn]>value+primalTolerance) {
          feasible=false;
          break;
        }
      } else {
        abort(); // do later (other stuff messed up anyway - e.g. CBC)
      }
    }
    if (feasible)
      break; // OK this way
  }
  return feasible;
}
Example #4
0
// Generate cuts
void
CglFakeClique::generateCuts(const OsiSolverInterface& si, OsiCuts & cs,
			const CglTreeInfo info) const
{
  if (fakeSolver_) {
    assert (si.getNumCols()==fakeSolver_->getNumCols());
    fakeSolver_->setColLower(si.getColLower());
    fakeSolver_->setColSolution(si.getColSolution());
    fakeSolver_->setColUpper(si.getColUpper());
    CglClique::generateCuts(*fakeSolver_,cs,info);
    if (probing_) {
      // get and set branch and bound cutoff
      double cutoff;
      si.getDblParam(OsiDualObjectiveLimit,cutoff);
      fakeSolver_->setDblParam(OsiDualObjectiveLimit,cutoff);
      probing_->generateCuts(*fakeSolver_,cs,info);
    }
  } else {
    // just use real solver
    CglClique::generateCuts(si,cs,info);
  }
}
Example #5
0
void
CglClique::selectFractionals(const OsiSolverInterface& si)
{
   // extract the primal tolerance from the solver
   double lclPetol = 0.0;
   si.getDblParam(OsiPrimalTolerance, lclPetol);

   const int numcols = si.getNumCols();
   const double* x = si.getColSolution();
   std::vector<int> fracind;
   int i;
   for (i = 0; i < numcols; ++i) {
      if (x[i] > lclPetol && x[i] < 1-lclPetol)
	 fracind.push_back(i);
   }
   sp_numcols = static_cast<int>(fracind.size());
   sp_orig_col_ind = new int[sp_numcols];
   sp_colsol = new double[sp_numcols];
   for (i = 0; i < sp_numcols; ++i) {
      sp_orig_col_ind[i] = fracind[i];
      sp_colsol[i] = x[fracind[i]];
   }
}
Example #6
0
// inner part of dive
int 
CbcHeuristicDive::solution(double & solutionValue, int & numberNodes,
			   int & numberCuts, OsiRowCut ** cuts,
			   CbcSubProblem ** & nodes,
			   double * newSolution)
{
#ifdef DIVE_DEBUG
    int nRoundInfeasible = 0;
    int nRoundFeasible = 0;
#endif
    int reasonToStop = 0;
    double time1 = CoinCpuTime();
    int numberSimplexIterations = 0;
    int maxSimplexIterations = (model_->getNodeCount()) ? maxSimplexIterations_
                               : maxSimplexIterationsAtRoot_;
    // but can't be exactly coin_int_max
    maxSimplexIterations = CoinMin(maxSimplexIterations,COIN_INT_MAX>>3);
    OsiSolverInterface * solver = cloneBut(6); // was model_->solver()->clone();
# ifdef COIN_HAS_CLP
    OsiClpSolverInterface * clpSolver
    = dynamic_cast<OsiClpSolverInterface *> (solver);
    if (clpSolver) {
      ClpSimplex * clpSimplex = clpSolver->getModelPtr();
      int oneSolveIts = clpSimplex->maximumIterations();
      oneSolveIts = CoinMin(1000+2*(clpSimplex->numberRows()+clpSimplex->numberColumns()),oneSolveIts);
      clpSimplex->setMaximumIterations(oneSolveIts);
      if (!nodes) {
        // say give up easily
        clpSimplex->setMoreSpecialOptions(clpSimplex->moreSpecialOptions() | 64);
      } else {
	// get ray
	int specialOptions = clpSimplex->specialOptions();
	specialOptions &= ~0x3100000;
	specialOptions |= 32;
        clpSimplex->setSpecialOptions(specialOptions);
        clpSolver->setSpecialOptions(clpSolver->specialOptions() | 1048576);
	if ((model_->moreSpecialOptions()&16777216)!=0) {
	  // cutoff is constraint
	  clpSolver->setDblParam(OsiDualObjectiveLimit, COIN_DBL_MAX);
	}
      }
    }
# endif
    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 = model_->getDblParam(CbcModel::CbcIntegerTolerance);
    double primalTolerance;
    solver->getDblParam(OsiPrimalTolerance, primalTolerance);

    int numberRows = matrix_.getNumRows();
    assert (numberRows <= solver->getNumRows());
    int numberIntegers = model_->numberIntegers();
    const int * integerVariable = model_->integerVariable();
    double direction = solver->getObjSense(); // 1 for min, -1 for max
    double newSolutionValue = direction * solver->getObjValue();
    int returnCode = 0;
    // Column copy
    const double * element = matrix_.getElements();
    const int * row = matrix_.getIndices();
    const CoinBigIndex * columnStart = matrix_.getVectorStarts();
    const int * columnLength = matrix_.getVectorLengths();
#ifdef DIVE_FIX_BINARY_VARIABLES
    // Row copy
    const double * elementByRow = matrixByRow_.getElements();
    const int * column = matrixByRow_.getIndices();
    const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts();
    const int * rowLength = matrixByRow_.getVectorLengths();
#endif

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

    // vectors to store the latest variables fixed at their bounds
    int* columnFixed = new int [numberIntegers];
    double* originalBound = new double [numberIntegers+2*numberColumns];
    double * lowerBefore = originalBound+numberIntegers;
    double * upperBefore = lowerBefore+numberColumns;
    memcpy(lowerBefore,lower,numberColumns*sizeof(double));
    memcpy(upperBefore,upper,numberColumns*sizeof(double));
    double * lastDjs=newSolution+numberColumns;
    bool * fixedAtLowerBound = new bool [numberIntegers];
    PseudoReducedCost * candidate = new PseudoReducedCost [numberIntegers];
    double * random = new double [numberIntegers];

    int maxNumberAtBoundToFix = static_cast<int> (floor(percentageToFix_ * numberIntegers));
    assert (!maxNumberAtBoundToFix||!nodes);

    // count how many fractional variables
    int numberFractionalVariables = 0;
    for (int i = 0; i < numberIntegers; i++) {
        random[i] = randomNumberGenerator_.randomDouble() + 0.3;
        int iColumn = integerVariable[i];
        double value = newSolution[iColumn];
        if (fabs(floor(value + 0.5) - value) > integerTolerance) {
            numberFractionalVariables++;
        }
    }

    const double* reducedCost = NULL;
    // See if not NLP
    if (model_->solverCharacteristics()->reducedCostsAccurate())
        reducedCost = solver->getReducedCost();

    int iteration = 0;
    while (numberFractionalVariables) {
        iteration++;

        // initialize any data
        initializeData();

        // select a fractional variable to bound
        int bestColumn = -1;
        int bestRound; // -1 rounds down, +1 rounds up
        bool canRound = selectVariableToBranch(solver, newSolution,
                                               bestColumn, bestRound);
        // if the solution is not trivially roundable, we don't try to round;
        // if the solution is trivially roundable, we try to round. However,
        // if the rounded solution is worse than the current incumbent,
        // then we don't round and proceed normally. In this case, the
        // bestColumn will be a trivially roundable variable
        if (canRound) {
            // check if by rounding all fractional variables
            // we get a solution with an objective value
            // better than the current best integer solution
            double delta = 0.0;
            for (int i = 0; i < numberIntegers; i++) {
                int iColumn = integerVariable[i];
                double value = newSolution[iColumn];
                if (fabs(floor(value + 0.5) - value) > integerTolerance) {
                    assert(downLocks_[i] == 0 || upLocks_[i] == 0);
                    double obj = objective[iColumn];
                    if (downLocks_[i] == 0 && upLocks_[i] == 0) {
                        if (direction * obj >= 0.0)
                            delta += (floor(value) - value) * obj;
                        else
                            delta += (ceil(value) - value) * obj;
                    } else if (downLocks_[i] == 0)
                        delta += (floor(value) - value) * obj;
                    else
                        delta += (ceil(value) - value) * obj;
                }
            }
            if (direction*(solver->getObjValue() + delta) < solutionValue) {
#ifdef DIVE_DEBUG
                nRoundFeasible++;
#endif
		if (!nodes||bestColumn<0) {
		  // Round all the fractional variables
		  for (int i = 0; i < numberIntegers; i++) {
                    int iColumn = integerVariable[i];
                    double value = newSolution[iColumn];
                    if (fabs(floor(value + 0.5) - value) > integerTolerance) {
		      assert(downLocks_[i] == 0 || upLocks_[i] == 0);
		      if (downLocks_[i] == 0 && upLocks_[i] == 0) {
			if (direction * objective[iColumn] >= 0.0)
			  newSolution[iColumn] = floor(value);
			else
			  newSolution[iColumn] = ceil(value);
		      } else if (downLocks_[i] == 0)
			newSolution[iColumn] = floor(value);
		      else
			newSolution[iColumn] = ceil(value);
                    }
		  }
		  break;
		} else {
		  // can't round if going to use in branching
		  int i;
		  for (i = 0; i < numberIntegers; i++) {
		    int iColumn = integerVariable[i];
		    double value = newSolution[bestColumn];
		    if (fabs(floor(value + 0.5) - value) > integerTolerance) {
		      if (iColumn==bestColumn) {
			assert(downLocks_[i] == 0 || upLocks_[i] == 0);
			double obj = objective[bestColumn];
			if (downLocks_[i] == 0 && upLocks_[i] == 0) {
			  if (direction * obj >= 0.0)
                            bestRound=-1;
			  else
                            bestRound=1;
			} else if (downLocks_[i] == 0)
			  bestRound=-1;
			else
			  bestRound=1;
			break;
		      }
		    }
		  }
		}
	    }
#ifdef DIVE_DEBUG
            else
                nRoundInfeasible++;
#endif
        }

        // do reduced cost fixing
#ifdef DIVE_DEBUG
        int numberFixed = reducedCostFix(solver);
        std::cout << "numberReducedCostFixed = " << numberFixed << std::endl;
#else
        reducedCostFix(solver);
#endif

        int numberAtBoundFixed = 0;
#ifdef DIVE_FIX_BINARY_VARIABLES
        // fix binary variables based on pseudo reduced cost
        if (binVarIndex_.size()) {
            int cnt = 0;
            int n = static_cast<int>(binVarIndex_.size());
            for (int j = 0; j < n; j++) {
                int iColumn1 = binVarIndex_[j];
                double value = newSolution[iColumn1];
                if (fabs(value) <= integerTolerance &&
                        lower[iColumn1] != upper[iColumn1]) {
                    double maxPseudoReducedCost = 0.0;
#ifdef DIVE_DEBUG
                    std::cout << "iColumn1 = " << iColumn1 << ", value = " << value << std::endl;
#endif
                    int iRow = vbRowIndex_[j];
                    double chosenValue = 0.0;
                    for (int k = rowStart[iRow]; k < rowStart[iRow] + rowLength[iRow]; k++) {
                        int iColumn2 = column[k];
#ifdef DIVE_DEBUG
                        std::cout << "iColumn2 = " << iColumn2 << std::endl;
#endif
                        if (iColumn1 != iColumn2) {
                            double pseudoReducedCost = fabs(reducedCost[iColumn2] *
                                                            elementByRow[k]);
#ifdef DIVE_DEBUG
                            int k2;
                            for (k2 = rowStart[iRow]; k2 < rowStart[iRow] + rowLength[iRow]; k2++) {
                                if (column[k2] == iColumn1)
                                    break;
                            }
                            std::cout << "reducedCost[" << iColumn2 << "] = "
                                      << reducedCost[iColumn2]
                                      << ", elementByRow[" << iColumn2 << "] = " << elementByRow[k]
                                      << ", elementByRow[" << iColumn1 << "] = " << elementByRow[k2]
                                      << ", pseudoRedCost = " << pseudoReducedCost
                                      << std::endl;
#endif
                            if (pseudoReducedCost > maxPseudoReducedCost)
                                maxPseudoReducedCost = pseudoReducedCost;
                        } else {
                            // save value
                            chosenValue = fabs(elementByRow[k]);
                        }
                    }
                    assert (chosenValue);
                    maxPseudoReducedCost /= chosenValue;
#ifdef DIVE_DEBUG
                    std::cout << ", maxPseudoRedCost = " << maxPseudoReducedCost << std::endl;
#endif
                    candidate[cnt].var = iColumn1;
                    candidate[cnt++].pseudoRedCost = maxPseudoReducedCost;
                }
            }
#ifdef DIVE_DEBUG
            std::cout << "candidates for rounding = " << cnt << std::endl;
#endif
            std::sort(candidate, candidate + cnt, compareBinaryVars);
            for (int i = 0; i < cnt; i++) {
                int iColumn = candidate[i].var;
                if (numberAtBoundFixed < maxNumberAtBoundToFix) {
                    columnFixed[numberAtBoundFixed] = iColumn;
                    originalBound[numberAtBoundFixed] = upper[iColumn];
                    fixedAtLowerBound[numberAtBoundFixed] = true;
                    solver->setColUpper(iColumn, lower[iColumn]);
                    numberAtBoundFixed++;
                    if (numberAtBoundFixed == maxNumberAtBoundToFix)
                        break;
                }
            }
        }
#endif

        // fix other integer variables that are at their bounds
        int cnt = 0;
#ifdef GAP
        double gap = 1.0e30;
#endif
        if (reducedCost && true) {
#ifndef JJF_ONE
            cnt = fixOtherVariables(solver, solution, candidate, random);
#else
#ifdef GAP
            double cutoff = model_->getCutoff() ;
            if (cutoff < 1.0e20 && false) {
                double direction = solver->getObjSense() ;
                gap = cutoff - solver->getObjValue() * direction ;
                gap *= 0.1; // Fix more if plausible
                double tolerance;
                solver->getDblParam(OsiDualTolerance, tolerance) ;
                if (gap <= 0.0)
                    gap = tolerance;
                gap += 100.0 * tolerance;
            }
            int nOverGap = 0;
#endif
            int numberFree = 0;
            int numberFixed = 0;
            for (int i = 0; i < numberIntegers; i++) {
                int iColumn = integerVariable[i];
                if (upper[iColumn] > lower[iColumn]) {
                    numberFree++;
                    double value = newSolution[iColumn];
                    if (fabs(floor(value + 0.5) - value) <= integerTolerance) {
                        candidate[cnt].var = iColumn;
                        candidate[cnt++].pseudoRedCost =
                            fabs(reducedCost[iColumn] * random[i]);
#ifdef GAP
                        if (fabs(reducedCost[iColumn]) > gap)
                            nOverGap++;
#endif
                    }
                } else {
                    numberFixed++;
                }
            }
#ifdef GAP
            int nLeft = maxNumberAtBoundToFix - numberAtBoundFixed;
#ifdef CLP_INVESTIGATE4
            printf("cutoff %g obj %g nover %d - %d free, %d fixed\n",
                   cutoff, solver->getObjValue(), nOverGap, numberFree, numberFixed);
#endif
            if (nOverGap > nLeft && true) {
                nOverGap = CoinMin(nOverGap, nLeft + maxNumberAtBoundToFix / 2);
                maxNumberAtBoundToFix += nOverGap - nLeft;
            }
#else
#ifdef CLP_INVESTIGATE4
            printf("cutoff %g obj %g - %d free, %d fixed\n",
                   model_->getCutoff(), solver->getObjValue(), numberFree, numberFixed);
#endif
#endif
#endif
        } else {
            for (int i = 0; i < numberIntegers; i++) {
                int iColumn = integerVariable[i];
                if (upper[iColumn] > lower[iColumn]) {
                    double value = newSolution[iColumn];
                    if (fabs(floor(value + 0.5) - value) <= integerTolerance) {
                        candidate[cnt].var = iColumn;
                        candidate[cnt++].pseudoRedCost = numberIntegers - i;
                    }
                }
            }
        }
        std::sort(candidate, candidate + cnt, compareBinaryVars);
        for (int i = 0; i < cnt; i++) {
            int iColumn = candidate[i].var;
            if (upper[iColumn] > lower[iColumn]) {
                double value = newSolution[iColumn];
                if (fabs(floor(value + 0.5) - value) <= integerTolerance &&
                        numberAtBoundFixed < maxNumberAtBoundToFix) {
                    // fix the variable at one of its bounds
                    if (fabs(lower[iColumn] - value) <= integerTolerance) {
                        columnFixed[numberAtBoundFixed] = iColumn;
                        originalBound[numberAtBoundFixed] = upper[iColumn];
                        fixedAtLowerBound[numberAtBoundFixed] = true;
                        solver->setColUpper(iColumn, lower[iColumn]);
                        numberAtBoundFixed++;
                    } else if (fabs(upper[iColumn] - value) <= integerTolerance) {
                        columnFixed[numberAtBoundFixed] = iColumn;
                        originalBound[numberAtBoundFixed] = lower[iColumn];
                        fixedAtLowerBound[numberAtBoundFixed] = false;
                        solver->setColLower(iColumn, upper[iColumn]);
                        numberAtBoundFixed++;
                    }
                    if (numberAtBoundFixed == maxNumberAtBoundToFix)
                        break;
                }
            }
        }
#ifdef DIVE_DEBUG
        std::cout << "numberAtBoundFixed = " << numberAtBoundFixed << std::endl;
#endif

        double originalBoundBestColumn;
        double bestColumnValue;
	int whichWay;
        if (bestColumn >= 0) {
	    bestColumnValue = newSolution[bestColumn];
            if (bestRound < 0) {
                originalBoundBestColumn = upper[bestColumn];
                solver->setColUpper(bestColumn, floor(bestColumnValue));
		whichWay=0;
            } else {
                originalBoundBestColumn = lower[bestColumn];
                solver->setColLower(bestColumn, ceil(bestColumnValue));
		whichWay=1;
            }
        } else {
            break;
        }
        int originalBestRound = bestRound;
        int saveModelOptions = model_->specialOptions();
	
        while (1) {

            model_->setSpecialOptions(saveModelOptions | 2048);
            solver->resolve();
            model_->setSpecialOptions(saveModelOptions);
            if (!solver->isAbandoned()&&!solver->isIterationLimitReached()) {
                numberSimplexIterations += solver->getIterationCount();
            } else {
                numberSimplexIterations = maxSimplexIterations + 1;
		reasonToStop += 100;
                break;
            }

            if (!solver->isProvenOptimal()) {
	        if (nodes) {
		  if (solver->isProvenPrimalInfeasible()) {
		    if (maxSimplexIterationsAtRoot_!=COIN_INT_MAX) {
		      // stop now
		      printf("stopping on first infeasibility\n");
		      break;
		    } else if (cuts) {
		      // can do conflict cut
		      printf("could do intermediate conflict cut\n");
		      bool localCut;
		      OsiRowCut * cut = model_->conflictCut(solver,localCut);
		      if (cut) {
			if (!localCut) {
			  model_->makePartialCut(cut,solver);
			  cuts[numberCuts++]=cut;
			} else {
			  delete cut;
			}
		      }
		    }
		  } else {
		    reasonToStop += 10;
		    break;
		  }
		}
                if (numberAtBoundFixed > 0) {
                    // Remove the bound fix for variables that were at bounds
                    for (int i = 0; i < numberAtBoundFixed; i++) {
                        int iColFixed = columnFixed[i];
                        if (fixedAtLowerBound[i])
                            solver->setColUpper(iColFixed, originalBound[i]);
                        else
                            solver->setColLower(iColFixed, originalBound[i]);
                    }
                    numberAtBoundFixed = 0;
                } else if (bestRound == originalBestRound) {
                    bestRound *= (-1);
		    whichWay |=2;
                    if (bestRound < 0) {
                        solver->setColLower(bestColumn, originalBoundBestColumn);
                        solver->setColUpper(bestColumn, floor(bestColumnValue));
                    } else {
                        solver->setColLower(bestColumn, ceil(bestColumnValue));
                        solver->setColUpper(bestColumn, originalBoundBestColumn);
                    }
                } else
                    break;
            } else
                break;
        }

        if (!solver->isProvenOptimal() ||
                direction*solver->getObjValue() >= solutionValue) {
            reasonToStop += 1;
        } else if (iteration > maxIterations_) {
            reasonToStop += 2;
        } else if (CoinCpuTime() - time1 > maxTime_) {
            reasonToStop += 3;
        } else if (numberSimplexIterations > maxSimplexIterations) {
            reasonToStop += 4;
            // also switch off
#ifdef CLP_INVESTIGATE
            printf("switching off diving as too many iterations %d, %d allowed\n",
                   numberSimplexIterations, maxSimplexIterations);
#endif
            when_ = 0;
        } else if (solver->getIterationCount() > 1000 && iteration > 3 && !nodes) {
            reasonToStop += 5;
            // also switch off
#ifdef CLP_INVESTIGATE
            printf("switching off diving one iteration took %d iterations (total %d)\n",
                   solver->getIterationCount(), numberSimplexIterations);
#endif
            when_ = 0;
        }

        memcpy(newSolution, solution, numberColumns*sizeof(double));
        numberFractionalVariables = 0;
	double sumFractionalVariables=0.0;
        for (int i = 0; i < numberIntegers; i++) {
            int iColumn = integerVariable[i];
            double value = newSolution[iColumn];
	    double away = fabs(floor(value + 0.5) - value);
            if (away > integerTolerance) {
                numberFractionalVariables++;
		sumFractionalVariables += away;
            }
        }
	if (nodes) {
	  // save information
	  //branchValues[numberNodes]=bestColumnValue;
	  //statuses[numberNodes]=whichWay+(bestColumn<<2);
	  //bases[numberNodes]=solver->getWarmStart();
	  ClpSimplex * simplex = clpSolver->getModelPtr();
	  CbcSubProblem * sub =
	    new CbcSubProblem(clpSolver,lowerBefore,upperBefore,
			  simplex->statusArray(),numberNodes);
	  nodes[numberNodes]=sub;
	  // other stuff
	  sub->branchValue_=bestColumnValue;
	  sub->problemStatus_=whichWay;
	  sub->branchVariable_=bestColumn;
	  sub->objectiveValue_ = simplex->objectiveValue();
	  sub->sumInfeasibilities_ = sumFractionalVariables;
	  sub->numberInfeasibilities_ = numberFractionalVariables;
	  printf("DiveNode %d column %d way %d bvalue %g obj %g\n",
		 numberNodes,sub->branchVariable_,sub->problemStatus_,
		 sub->branchValue_,sub->objectiveValue_);
	  numberNodes++;
	  if (solver->isProvenOptimal()) {
	    memcpy(lastDjs,solver->getReducedCost(),numberColumns*sizeof(double));
	    memcpy(lowerBefore,lower,numberColumns*sizeof(double));
	    memcpy(upperBefore,upper,numberColumns*sizeof(double));
	  }
	}
	if (!numberFractionalVariables||reasonToStop)
	  break;
    }
    if (nodes) {
      printf("Exiting dive for reason %d\n",reasonToStop);
      if (reasonToStop>1) {
	printf("problems in diving\n");
	int whichWay=nodes[numberNodes-1]->problemStatus_;
	CbcSubProblem * sub;
	if ((whichWay&2)==0) {
	  // leave both ways
	  sub = new CbcSubProblem(*nodes[numberNodes-1]);
	  nodes[numberNodes++]=sub;
	} else {
	  sub = nodes[numberNodes-1];
	}
	if ((whichWay&1)==0)
	  sub->problemStatus_=whichWay|1;
	else
	  sub->problemStatus_=whichWay&~1;
      }
      if (!numberNodes) {
	// was good at start! - create fake
	clpSolver->resolve();
	ClpSimplex * simplex = clpSolver->getModelPtr();
	CbcSubProblem * sub =
	  new CbcSubProblem(clpSolver,lowerBefore,upperBefore,
			    simplex->statusArray(),numberNodes);
	nodes[numberNodes]=sub;
	// other stuff
	sub->branchValue_=0.0;
	sub->problemStatus_=0;
	sub->branchVariable_=-1;
	sub->objectiveValue_ = simplex->objectiveValue();
	sub->sumInfeasibilities_ = 0.0;
	sub->numberInfeasibilities_ = 0;
	printf("DiveNode %d column %d way %d bvalue %g obj %g\n",
	       numberNodes,sub->branchVariable_,sub->problemStatus_,
	       sub->branchValue_,sub->objectiveValue_);
	numberNodes++;
	assert (solver->isProvenOptimal());
      }
      nodes[numberNodes-1]->problemStatus_ |= 256*reasonToStop;
      // use djs as well
      if (solver->isProvenPrimalInfeasible()&&cuts) {
	// can do conflict cut and re-order
	printf("could do final conflict cut\n");
	bool localCut;
	OsiRowCut * cut = model_->conflictCut(solver,localCut);
	if (cut) {
	  printf("cut - need to use conflict and previous djs\n");
	  if (!localCut) {
	    model_->makePartialCut(cut,solver);
	    cuts[numberCuts++]=cut;
	  } else {
	    delete cut;
	  }
	} else {
	  printf("bad conflict - just use previous djs\n");
	}
      }
    }
    
    // re-compute new solution value
    double objOffset = 0.0;
    solver->getDblParam(OsiObjOffset, objOffset);
    newSolutionValue = -objOffset;
    for (int i = 0 ; i < numberColumns ; i++ )
      newSolutionValue += objective[i] * newSolution[i];
    newSolutionValue *= direction;
    //printf("new solution value %g %g\n",newSolutionValue,solutionValue);
    if (newSolutionValue < solutionValue && !reasonToStop) {
      double * rowActivity = new double[numberRows];
      memset(rowActivity, 0, numberRows*sizeof(double));
      // paranoid check
      memset(rowActivity, 0, numberRows*sizeof(double));
      for (int 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 (int 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;
	}
      }
      for (int i = 0; i < numberIntegers; i++) {
	int iColumn = integerVariable[i];
	double value = newSolution[iColumn];
	if (fabs(floor(value + 0.5) - value) > integerTolerance) {
	  feasible = false;
	  break;
	}
      }
      if (feasible) {
	// new solution
	solutionValue = newSolutionValue;
	//printf("** Solution of %g found by CbcHeuristicDive\n",newSolutionValue);
	//if (cuts)
	//clpSolver->getModelPtr()->writeMps("good8.mps", 2);
	returnCode = 1;
      } else {
	// Can easily happen
	//printf("Debug CbcHeuristicDive giving bad solution\n");
      }
      delete [] rowActivity;
    }

#ifdef DIVE_DEBUG
    std::cout << "nRoundInfeasible = " << nRoundInfeasible
              << ", nRoundFeasible = " << nRoundFeasible
              << ", returnCode = " << returnCode
              << ", reasonToStop = " << reasonToStop
              << ", simplexIts = " << numberSimplexIterations
              << ", iterations = " << iteration << std::endl;
#endif

    delete [] columnFixed;
    delete [] originalBound;
    delete [] fixedAtLowerBound;
    delete [] candidate;
    delete [] random;
    delete [] downArray_;
    downArray_ = NULL;
    delete [] upArray_;
    upArray_ = NULL;
    delete solver;
    return returnCode;
}
Example #7
0
/** Standard cut generation methods. */
void
OaDecompositionBase::generateCuts(const OsiSolverInterface &si,  OsiCuts & cs,
    const CglTreeInfo info) {
  if (nlp_ == NULL) {
    throw CoinError("Error in cut generator for outer approximation no NLP ipopt assigned", "generateCuts", "OaDecompositionBase");
  }

  // babInfo is used to communicate with the b-and-b solver (Cbc or Bcp).
  BabInfo * babInfo = dynamic_cast<BabInfo *> (si.getAuxiliaryInfo());
  assert(babInfo);
  assert(babInfo->babPtr());
  numSols_ = babInfo->babPtr()->model().getSolutionCount ();
  CglTreeInfo info_copy = info;
  const CbcNode * node = babInfo->babPtr()->model().currentNode();
  info_copy.level = (node == NULL) ? 0 : babInfo->babPtr()->model().currentNode()->depth();
  if(babInfo->hasSolution()) numSols_ ++;
  if (babInfo)
    if (!babInfo->mipFeasible())
      return;

  //Get the continuous solution
  const double *colsol = si.getColSolution();


  vector<double> savedColLower(nlp_->getNumCols());
  CoinCopyN(nlp_->getColLower(), nlp_->getNumCols(), savedColLower());
  vector<double> savedColUpper(nlp_->getNumCols());
  CoinCopyN(nlp_->getColUpper(), nlp_->getNumCols(), savedColUpper());


  OsiBranchingInformation brInfo(nlp_, false);
  brInfo.solution_ = colsol;
  //Check integer infeasibility
  bool isInteger = integerFeasible(*nlp_, brInfo, parameters_.cbcIntegerTolerance_,
                              objects_, nObjects_);


  //Check nodeNumber if it did not change scan savedCuts_ if one is violated force it and exit
  int nodeNumber = babInfo->babPtr()->model().getNodeCount();
  if(nodeNumber == currentNodeNumber_){
#ifdef OA_DEBUG
    printf("OA decomposition recalled from the same node!\n");
#endif
    int numCuts = savedCuts_.sizeRowCuts();
    for(int i = 0 ; i < numCuts ; i++){
       //Check if cuts off solution
       if(savedCuts_.rowCut(i).violated(colsol) > 0.){
#ifdef OA_DEBUG
         printf("A violated saved cut has been found\n");
#endif
         savedCuts_.rowCut(i).setEffectiveness(9.99e99);
         cs.insert(savedCuts_.rowCut(i));
         savedCuts_.eraseRowCut(i);
         return;
         i--; numCuts--;
       }
    }
  }
  else {
    currentNodeNumber_ = nodeNumber;
    savedCuts_.dumpCuts();
  } 
         
  if (!isInteger) {
    if (!doLocalSearch(babInfo))//create sub mip solver.
      return;
  }

  //get the current cutoff
  double cutoff;
  si.getDblParam(OsiDualObjectiveLimit, cutoff);

  // Save solvers state if needed

  solverManip * lpManip = NULL;
  if (lp_ != NULL) {
      assert(lp_ == &si);
      lpManip = new solverManip(lp_, true, leaveSiUnchanged_, true, true);
  }
  else {
    lpManip = new solverManip(si);
  }
  lpManip->setObjects(objects_, nObjects_);

  double milpBound = performOa(cs, *lpManip, babInfo, cutoff, info_copy);

  if(babInfo->hasSolution()){
     babInfo->babPtr()->model().setSolutionCount (numSols_ - 1);
  }

  //Transmit the bound found by the milp
  {
    if (milpBound>-1e100)
    {
      // Also store into solver
      if (babInfo)
        babInfo->setMipBound(milpBound);
    }
  }  //Clean everything :

  //  Reset the two solvers
  if (leaveSiUnchanged_)
    lpManip->restore();
  delete lpManip;

  nlp_->setColLower(savedColLower());
  nlp_->setColUpper(savedColUpper());

  return;
}
/*
  First tries setting a variable to better value.  If feasible then
  tries setting others.  If not feasible then tries swaps
  Returns 1 if solution, 0 if not */
int
CbcHeuristicVND::solution(double & solutionValue,
                          double * betterSolution)
{
    numCouldRun_++;
    int returnCode = 0;
    const double * bestSolution = model_->bestSolution();
    if (!bestSolution)
        return 0; // No solution found yet
#ifdef HEURISTIC_INFORM
    printf("Entering heuristic %s - nRuns %d numCould %d when %d\n",
	   heuristicName(),numRuns_,numCouldRun_,when_);
#endif
    if (numberSolutions_ < model_->getSolutionCount()) {
        // new solution - add info
        numberSolutions_ = model_->getSolutionCount();

        int numberIntegers = model_->numberIntegers();
        const int * integerVariable = model_->integerVariable();

        int i;
        for (i = 0; i < numberIntegers; i++) {
            int iColumn = integerVariable[i];
            const OsiObject * object = model_->object(i);
            // get original bounds
            double originalLower;
            double originalUpper;
            getIntegerInformation( object, originalLower, originalUpper);
            double value = bestSolution[iColumn];
            if (value < originalLower) {
                value = originalLower;
            } else if (value > originalUpper) {
                value = originalUpper;
            }
        }
    }
    int numberNodes = model_->getNodeCount();
    if (howOften_ == 100) {
        if (numberNodes < lastNode_ + 12)
            return 0;
        // Do at 50 and 100
        if ((numberNodes > 40 && numberNodes <= 50) || (numberNodes > 90 && numberNodes < 100))
            numberNodes = howOften_;
    }
    if ((numberNodes % howOften_) == 0 && (model_->getCurrentPassNumber() <= 1 ||
                                           model_->getCurrentPassNumber() == 999999)) {
        lastNode_ = model_->getNodeCount();
        OsiSolverInterface * solver = model_->solver();

        int numberIntegers = model_->numberIntegers();
        const int * integerVariable = model_->integerVariable();

        const double * currentSolution = solver->getColSolution();
        OsiSolverInterface * newSolver = cloneBut(3); // was model_->continuousSolver()->clone();
        //const double * colLower = newSolver->getColLower();
        //const double * colUpper = newSolver->getColUpper();

        double primalTolerance;
        solver->getDblParam(OsiPrimalTolerance, primalTolerance);

        // Sort on distance
        double * distance = new double [numberIntegers];
        int * which = new int [numberIntegers];

        int i;
        int nFix = 0;
        double tolerance = 10.0 * primalTolerance;
        for (i = 0; i < numberIntegers; i++) {
            int iColumn = integerVariable[i];
            const OsiObject * object = model_->object(i);
            // get original bounds
            double originalLower;
            double originalUpper;
            getIntegerInformation( object, originalLower, originalUpper);
            double valueInt = bestSolution[iColumn];
            if (valueInt < originalLower) {
                valueInt = originalLower;
            } else if (valueInt > originalUpper) {
                valueInt = originalUpper;
            }
            baseSolution_[iColumn] = currentSolution[iColumn];
            distance[i] = fabs(currentSolution[iColumn] - valueInt);
            which[i] = i;
            if (fabs(currentSolution[iColumn] - valueInt) < tolerance)
                nFix++;
        }
        CoinSort_2(distance, distance + numberIntegers, which);
        nDifferent_ = numberIntegers - nFix;
        stepSize_ = nDifferent_ / 10;
        k_ = stepSize_;
        //nFix = numberIntegers-stepSize_;
        for (i = 0; i < nFix; i++) {
            int j = which[i];
            int iColumn = integerVariable[j];
            const OsiObject * object = model_->object(i);
            // get original bounds
            double originalLower;
            double originalUpper;
            getIntegerInformation( object, originalLower, originalUpper);
            double valueInt = bestSolution[iColumn];
            if (valueInt < originalLower) {
                valueInt = originalLower;
            } else if (valueInt > originalUpper) {
                valueInt = originalUpper;
            }
            double nearest = floor(valueInt + 0.5);
            newSolver->setColLower(iColumn, nearest);
            newSolver->setColUpper(iColumn, nearest);
        }
        delete [] distance;
        delete [] which;
        if (nFix > numberIntegers / 5) {
            //printf("%d integers have samish value\n",nFix);
            returnCode = smallBranchAndBound(newSolver, numberNodes_, betterSolution, solutionValue,
                                             model_->getCutoff(), "CbcHeuristicVND");
            if (returnCode < 0)
                returnCode = 0; // returned on size
            else
                numRuns_++;
            if ((returnCode&1) != 0)
                numberSuccesses_++;
            //printf("return code %d",returnCode);
            if ((returnCode&2) != 0) {
                // could add cut
                returnCode &= ~2;
                //printf("could add cut with %d elements (if all 0-1)\n",nFix);
            } else {
                //printf("\n");
            }
            numberTries_++;
            if ((numberTries_ % 10) == 0 && numberSuccesses_*3 < numberTries_)
                howOften_ += static_cast<int> (howOften_ * decayFactor_);
        }

        delete newSolver;
    }
    return returnCode;
}
Example #9
0
// Generate cuts
void
CglFakeClique::generateCuts(const OsiSolverInterface& si, OsiCuts & cs,
			const CglTreeInfo info)
{
  if (fakeSolver_) {
    assert (si.getNumCols()==fakeSolver_->getNumCols());
    fakeSolver_->setColLower(si.getColLower());
    const double * solution = si.getColSolution();
    fakeSolver_->setColSolution(solution);
    fakeSolver_->setColUpper(si.getColUpper());
    // get and set branch and bound cutoff
    double cutoff;
    si.getDblParam(OsiDualObjectiveLimit,cutoff);
    fakeSolver_->setDblParam(OsiDualObjectiveLimit,COIN_DBL_MAX);
#ifdef COIN_HAS_CLP
    OsiClpSolverInterface * clpSolver
      = dynamic_cast<OsiClpSolverInterface *> (fakeSolver_);
    if (clpSolver) {
      // fix up fake solver
      const ClpSimplex * siSimplex = clpSolver->getModelPtr();
      // need to set djs
      memcpy(siSimplex->primalColumnSolution(),
	     si.getReducedCost(),si.getNumCols()*sizeof(double));
      fakeSolver_->setDblParam(OsiDualObjectiveLimit,cutoff);
    }
#endif
    const CoinPackedMatrix * matrixByRow = si.getMatrixByRow();
    const double * elementByRow = matrixByRow->getElements();
    const int * column = matrixByRow->getIndices();
    const CoinBigIndex * rowStart = matrixByRow->getVectorStarts();
    const int * rowLength = matrixByRow->getVectorLengths();
    const double * rowUpper = si.getRowUpper();
    const double * rowLower = si.getRowLower();
    
    // Scan all rows looking for possibles
    int numberRows = si.getNumRows();
    double tolerance = 1.0e-3;
    for (int iRow=0;iRow<numberRows;iRow++) {
      CoinBigIndex start = rowStart[iRow];
      CoinBigIndex end = start + rowLength[iRow];
      double upRhs = rowUpper[iRow]; 
      double loRhs = rowLower[iRow]; 
      double sum = 0.0;
      for (CoinBigIndex j=start;j<end;j++) {
	int iColumn=column[j];
	double value = elementByRow[j];
	sum += solution[iColumn]*value;
      }
      if (sum<loRhs-tolerance||sum>upRhs+tolerance) {
	// add as cut
	OsiRowCut rc;
	rc.setLb(loRhs);
	rc.setUb(upRhs);
	rc.setRow(end-start,column+start,elementByRow+start,false);
	CoinAbsFltEq equal(1.0e-12);
	cs.insertIfNotDuplicate(rc,equal);
      }
    }
    CglClique::generateCuts(*fakeSolver_,cs,info);
    if (probing_) {
      probing_->generateCuts(*fakeSolver_,cs,info);
    }
  } else {
    // just use real solver
    CglClique::generateCuts(si,cs,info);
  }
}
Example #10
0
/*
  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;

}
Example #11
0
// See if rounding will give solution
// Sets value of solution
// Assumes rhs for original matrix still okay
// At present only works with integers 
// Fix values if asked for
// Returns 1 if solution, 0 if not
int
AbcRounding::solution(double & solutionValue,
		      double * betterSolution)
{
    // 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(AbcModel::AbcIntegerTolerance);
    double primalTolerance;
    solver->getDblParam(OsiPrimalTolerance, primalTolerance);

    int numberRows = matrix_.getNumRows();

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

    // 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) {
	// See if we can do better
	//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];
		double value = newSolution[iColumn];
		assert(fabs(floor(value + 0.5) - value) < integerTolerance);
		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);
		returnCode=1;
	    } else {
		// Can easily happen
		//printf("Debug AbcRounding giving bad solution\n");
	    }
	}
    }
    delete [] newSolution;
    delete [] rowActivity;
    return returnCode;
}
Example #12
0
/*
  First tries setting a variable to better value.  If feasible then
  tries setting others.  If not feasible then tries swaps
  Returns 1 if solution, 0 if not 
  The main body of this routine implements an O((q^2)/2) brute force search
  around the current solution, for q = number of integer variables. Call this
  the inc/dec heuristic.  For each integer variable x<i>, first decrement the
  value. Then, for integer variables x<i+1>, ..., x<q-1>, try increment and
  decrement. If one of these permutations produces a better solution,
  remember it.  Then repeat, with x<i> incremented. If we find a better
  solution, update our notion of current solution and continue.

  The net effect is a greedy walk: As each improving pair is found, the
  current solution is updated and the search continues from this updated
  solution.

  Way down at the end, we call solutionFix, which will create a drastically
  restricted problem based on variables marked as used, then do mini-BaC on
  the restricted problem. This can occur even if we don't try the inc/dec
  heuristic. This would be more obvious if the inc/dec heuristic were broken
  out as a separate routine and solutionFix had a name that reflected where
  it was headed.

  The return code of 0 is grossly overloaded, because it maps to a return
  code of 0 from solutionFix, which is itself grossly overloaded. See
  comments in solutionFix and in CbcHeuristic::smallBranchAndBound.
  */
int
CbcHeuristicLocal::solution(double & solutionValue,
                            double * betterSolution)
{
/*
  Execute only if a new solution has been discovered since the last time we
  were called.
*/

    numCouldRun_++;
    // See if frequency kills off idea
    int swap = swap_%100;
    int skip = swap_/100;
    int nodeCount = model_->getNodeCount();
    if (nodeCount<lastRunDeep_+skip && nodeCount != lastRunDeep_+1) 
      return 0;
    if (numberSolutions_ == model_->getSolutionCount() &&
	(numberSolutions_ == howOftenShallow_ ||
	 nodeCount < lastRunDeep_+2*skip))
        return 0;
    howOftenShallow_ = numberSolutions_;
    numberSolutions_ = model_->getSolutionCount();
    if (nodeCount<lastRunDeep_+skip ) 
      return 0;
    lastRunDeep_ = nodeCount;
    howOftenShallow_ = numberSolutions_;

    if ((swap%10) == 2) {
        // try merge
        return solutionFix( solutionValue, betterSolution, NULL);
    }
/*
  Exclude long (column), thin (row) systems.

  Given the n^2 nature of the search, more than 100,000 columns could get
  expensive. But I don't yet see the rationale for the second part of the
  condition (cols > 10*rows). And cost is proportional to number of integer
  variables --- shouldn't we use that?

  Why wait until we have more than one solution?
*/
    if ((model_->getNumCols() > 100000 && model_->getNumCols() >
            10*model_->getNumRows()) || numberSolutions_ <= 1)
        return 0; // probably not worth it
    // worth trying

    OsiSolverInterface * solver = model_->solver();
    const double * rowLower = solver->getRowLower();
    const double * rowUpper = solver->getRowUpper();
    const double * solution = model_->bestSolution();
/*
  Shouldn't this test be redundant if we've already checked that
  numberSolutions_ > 1? Stronger: shouldn't this be an assertion?
*/
    if (!solution)
        return 0; // No solution found yet
    const double * objective = solver->getObjCoefficients();
    double primalTolerance;
    solver->getDblParam(OsiPrimalTolerance, primalTolerance);

    int numberRows = matrix_.getNumRows();

    int numberIntegers = model_->numberIntegers();
    const int * integerVariable = model_->integerVariable();

    int i;
    double direction = solver->getObjSense();
    double newSolutionValue = model_->getObjValue() * direction;
    int returnCode = 0;
    numRuns_++;
    // Column copy
    const double * element = matrix_.getElements();
    const int * row = matrix_.getIndices();
    const CoinBigIndex * columnStart = matrix_.getVectorStarts();
    const int * columnLength = matrix_.getVectorLengths();

    // Get solution array for heuristic solution
    int numberColumns = solver->getNumCols();
    double * newSolution = new double [numberColumns];
    memcpy(newSolution, solution, numberColumns*sizeof(double));
#ifdef LOCAL_FIX_CONTINUOUS
    // mark continuous used
    const double * columnLower = solver->getColLower();
    for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
        if (!solver->isInteger(iColumn)) {
            if (solution[iColumn] > columnLower[iColumn] + 1.0e-8)
                used_[iColumn] = numberSolutions_;
        }
    }
#endif

    // way is 1 if down possible, 2 if up possible, 3 if both possible
    char * way = new char[numberIntegers];
    // corrected costs
    double * cost = new double[numberIntegers];
    // for array to mark infeasible rows after iColumn branch
    char * mark = new char[numberRows];
    memset(mark, 0, numberRows);
    // space to save values so we don't introduce rounding errors
    double * save = new double[numberRows];
/*
  Force variables within their original bounds, then to the nearest integer.
  Overall, we seem to be prepared to cope with noninteger bounds. Is this
  necessary? Seems like we'd be better off to force the bounds to integrality
  as part of preprocessing.  More generally, why do we need to do this? This
  solution should have been cleaned and checked when it was accepted as a
  solution!

  Once the value is set, decide whether we can move up or down.

  The only place that used_ is used is in solutionFix; if a variable is not
  flagged as used, it will be fixed (at lower bound). Why the asymmetric
  treatment? This makes some sense for binary variables (for which there are
  only two options). But for general integer variables, why not make a similar
  test against the original upper bound?
*/

    // clean solution
    for (i = 0; i < numberIntegers; i++) {
        int iColumn = integerVariable[i];
        const OsiObject * object = model_->object(i);
        // get original bounds
        double originalLower;
        double originalUpper;
        getIntegerInformation( object, originalLower, originalUpper);
        double value = newSolution[iColumn];
        if (value < originalLower) {
            value = originalLower;
            newSolution[iColumn] = value;
        } else if (value > originalUpper) {
            value = originalUpper;
            newSolution[iColumn] = value;
        }
        double nearest = floor(value + 0.5);
        //assert(fabs(value-nearest)<10.0*primalTolerance);
        value = nearest;
        newSolution[iColumn] = nearest;
        // if away from lower bound mark that fact
        if (nearest > originalLower) {
            used_[iColumn] = numberSolutions_;
        }
        cost[i] = direction * objective[iColumn];
/*
  Given previous computation we're checking that value is at least 1 away
  from the original bounds.
*/
        int iway = 0;

        if (value > originalLower + 0.5)
            iway = 1;
        if (value < originalUpper - 0.5)
            iway |= 2;
        way[i] = static_cast<char>(iway);
    }
/*
  Calculate lhs of each constraint for groomed solution.
*/
    // get row activities
    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 that constraints are satisfied. For small infeasibility, force the
  activity within bound. Again, why is this necessary if the current solution
  was accepted as a valid solution?

  Why are we scanning past the first unacceptable constraint?
*/
    // check was feasible - if not adjust (cleaning may move)
    // if very infeasible then give up
    bool tryHeuristic = true;
    for (i = 0; i < numberRows; i++) {
        if (rowActivity[i] < rowLower[i]) {
            if (rowActivity[i] < rowLower[i] - 10.0*primalTolerance)
                tryHeuristic = false;
            rowActivity[i] = rowLower[i];
        } else if (rowActivity[i] > rowUpper[i]) {
            if (rowActivity[i] < rowUpper[i] + 10.0*primalTolerance)
                tryHeuristic = false;
            rowActivity[i] = rowUpper[i];
        }
    }
/*
  This bit of code is not quite totally redundant: it'll bail at 10,000
  instead of 100,000. Potentially we can do a lot of work to get here, only
  to abandon it.
*/
    // Switch off if may take too long
    if (model_->getNumCols() > 10000 && model_->getNumCols() >
            10*model_->getNumRows())
        tryHeuristic = false;
/*
  Try the inc/dec heuristic?
*/
    if (tryHeuristic) {

        // total change in objective
        double totalChange = 0.0;
        // local best change in objective
        double bestChange = 0.0;
	// maybe just do 1000
	int maxIntegers = numberIntegers;
	if (((swap/10) &1) != 0) {
	  maxIntegers = CoinMin(1000,numberIntegers);
	}
/*
  Outer loop to walk integer variables. Call the current variable x<i>. At the
  end of this loop, bestChange will contain the best (negative) change in the
  objective for any single pair.

  The trouble is, we're limited to monotonically increasing improvement.
  Suppose we discover an improvement of 10 for some pair. If, later in the
  search, we discover an improvement of 9 for some other pair, we will not use
  it. That seems wasteful.
*/

        for (i = 0; i < numberIntegers; i++) {
            int iColumn = integerVariable[i];
	    bestChange = 0.0;
	    int endInner = CoinMin(numberIntegers,i+maxIntegers);

            double objectiveCoefficient = cost[i];
            int k;
            int j;
            int goodK = -1;
            int wayK = -1, wayI = -1;
/*
  Try decrementing x<i>.
*/
            if ((way[i]&1) != 0) {
                int numberInfeasible = 0;
/*
  Adjust row activities where x<i> has a nonzero coefficient. Save the old
  values for restoration. Mark any rows that become infeasible as a result
  of the decrement.
*/
                // save row activities and adjust
                for (j = columnStart[iColumn];
                        j < columnStart[iColumn] + columnLength[iColumn]; j++) {
                    int iRow = row[j];
                    save[iRow] = rowActivity[iRow];
                    rowActivity[iRow] -= element[j];
                    if (rowActivity[iRow] < rowLower[iRow] - primalTolerance ||
                            rowActivity[iRow] > rowUpper[iRow] + primalTolerance) {
                        // mark row
                        mark[iRow] = 1;
                        numberInfeasible++;
                    }
                }
  /*
  Run through the remaining integer variables. Try increment and decrement on
  each one. If the potential objective change is better than anything we've
  seen so far, do a full evaluation of x<k> in that direction.  If we can
  repair all infeasibilities introduced by pushing x<i> down, we have a
  winner. Remember the best variable, and the direction for x<i> and x<k>.
*/
              // try down
                for (k = i + 1; k < endInner; k++) {
                    if ((way[k]&1) != 0) {
                        // try down
                        if (-objectiveCoefficient - cost[k] < bestChange) {
                            // see if feasible down
                            bool good = true;
                            int numberMarked = 0;
                            int kColumn = integerVariable[k];
                            for (j = columnStart[kColumn];
                                    j < columnStart[kColumn] + columnLength[kColumn]; j++) {
                                int iRow = row[j];
                                double newValue = rowActivity[iRow] - element[j];
                                if (newValue < rowLower[iRow] - primalTolerance ||
                                        newValue > rowUpper[iRow] + primalTolerance) {
                                    good = false;
                                    break;
                                } else if (mark[iRow]) {
                                    // made feasible
                                    numberMarked++;
                                }
                            }
                            if (good && numberMarked == numberInfeasible) {
                                // better solution
                                goodK = k;
                                wayK = -1;
                                wayI = -1;
                                bestChange = -objectiveCoefficient - cost[k];
                            }
                        }
                    }
                    if ((way[k]&2) != 0) {
                        // try up
                        if (-objectiveCoefficient + cost[k] < bestChange) {
                            // see if feasible up
                            bool good = true;
                            int numberMarked = 0;
                            int kColumn = integerVariable[k];
                            for (j = columnStart[kColumn];
                                    j < columnStart[kColumn] + columnLength[kColumn]; j++) {
                                int iRow = row[j];
                                double newValue = rowActivity[iRow] + element[j];
                                if (newValue < rowLower[iRow] - primalTolerance ||
                                        newValue > rowUpper[iRow] + primalTolerance) {
                                    good = false;
                                    break;
                                } else if (mark[iRow]) {
                                    // made feasible
                                    numberMarked++;
                                }
                            }
                            if (good && numberMarked == numberInfeasible) {
                                // better solution
                                goodK = k;
                                wayK = 1;
                                wayI = -1;
                                bestChange = -objectiveCoefficient + cost[k];
                            }
                        }
                    }
                }
/*
  Remove effect of decrementing x<i> by restoring original lhs values.
*/
                // restore row activities
                for (j = columnStart[iColumn];
                        j < columnStart[iColumn] + columnLength[iColumn]; j++) {
                    int iRow = row[j];
                    rowActivity[iRow] = save[iRow];
                    mark[iRow] = 0;
                }
            }
/*
  Try to increment x<i>. Actions as for decrement.
*/
            if ((way[i]&2) != 0) {
                int numberInfeasible = 0;
                // save row activities and adjust
                for (j = columnStart[iColumn];
                        j < columnStart[iColumn] + columnLength[iColumn]; j++) {
                    int iRow = row[j];
                    save[iRow] = rowActivity[iRow];
                    rowActivity[iRow] += element[j];
                    if (rowActivity[iRow] < rowLower[iRow] - primalTolerance ||
                            rowActivity[iRow] > rowUpper[iRow] + primalTolerance) {
                        // mark row
                        mark[iRow] = 1;
                        numberInfeasible++;
                    }
                }
                // try up
                for (k = i + 1; k < endInner; k++) {
                    if ((way[k]&1) != 0) {
                        // try down
                        if (objectiveCoefficient - cost[k] < bestChange) {
                            // see if feasible down
                            bool good = true;
                            int numberMarked = 0;
                            int kColumn = integerVariable[k];
                            for (j = columnStart[kColumn];
                                    j < columnStart[kColumn] + columnLength[kColumn]; j++) {
                                int iRow = row[j];
                                double newValue = rowActivity[iRow] - element[j];
                                if (newValue < rowLower[iRow] - primalTolerance ||
                                        newValue > rowUpper[iRow] + primalTolerance) {
                                    good = false;
                                    break;
                                } else if (mark[iRow]) {
                                    // made feasible
                                    numberMarked++;
                                }
                            }
                            if (good && numberMarked == numberInfeasible) {
                                // better solution
                                goodK = k;
                                wayK = -1;
                                wayI = 1;
                                bestChange = objectiveCoefficient - cost[k];
                            }
                        }
                    }
                    if ((way[k]&2) != 0) {
                        // try up
                        if (objectiveCoefficient + cost[k] < bestChange) {
                            // see if feasible up
                            bool good = true;
                            int numberMarked = 0;
                            int kColumn = integerVariable[k];
                            for (j = columnStart[kColumn];
                                    j < columnStart[kColumn] + columnLength[kColumn]; j++) {
                                int iRow = row[j];
                                double newValue = rowActivity[iRow] + element[j];
                                if (newValue < rowLower[iRow] - primalTolerance ||
                                        newValue > rowUpper[iRow] + primalTolerance) {
                                    good = false;
                                    break;
                                } else if (mark[iRow]) {
                                    // made feasible
                                    numberMarked++;
                                }
                            }
                            if (good && numberMarked == numberInfeasible) {
                                // better solution
                                goodK = k;
                                wayK = 1;
                                wayI = 1;
                                bestChange = objectiveCoefficient + cost[k];
                            }
                        }
                    }
                }
                // restore row activities
                for (j = columnStart[iColumn];
                        j < columnStart[iColumn] + columnLength[iColumn]; j++) {
                    int iRow = row[j];
                    rowActivity[iRow] = save[iRow];
                    mark[iRow] = 0;
                }
            }
/*
  We've found a pair x<i> and x<k> which produce a better solution. Update our
  notion of current solution to match.

  Why does this not update newSolutionValue?
*/
            if (goodK >= 0) {
                // we found something - update solution
                for (j = columnStart[iColumn];
                        j < columnStart[iColumn] + columnLength[iColumn]; j++) {
                    int iRow = row[j];
                    rowActivity[iRow]  += wayI * element[j];
                }
                newSolution[iColumn] += wayI;
                int kColumn = integerVariable[goodK];
                for (j = columnStart[kColumn];
                        j < columnStart[kColumn] + columnLength[kColumn]; j++) {
                    int iRow = row[j];
                    rowActivity[iRow]  += wayK * element[j];
                }
                newSolution[kColumn] += wayK;
/*
  Adjust motion range for x<k>. We may have banged up against a bound with that
  last move.
*/
               // See if k can go further ?
                const OsiObject * object = model_->object(goodK);
                // get original bounds
                double originalLower;
                double originalUpper;
                getIntegerInformation( object, originalLower, originalUpper);

                double value = newSolution[kColumn];
                int iway = 0;

                if (value > originalLower + 0.5)
                    iway = 1;
                if (value < originalUpper - 0.5)
                    iway |= 2;
                way[goodK] = static_cast<char>(iway);
		totalChange += bestChange;
            }
        }
/*
  End of loop to try increment/decrement of integer variables.

  newSolutionValue does not necessarily match the current newSolution, and
  bestChange simply reflects the best single change. Still, that's sufficient
  to indicate that there's been at least one change. Check that we really do
  have a valid solution.
*/
        if (totalChange + 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];
                    }
                }
            }
            int numberBad = 0;
            double sumBad = 0.0;
            // check was approximately feasible
            for (i = 0; i < numberRows; i++) {
                if (rowActivity[i] < rowLower[i]) {
                    sumBad += rowLower[i] - rowActivity[i];
                    if (rowActivity[i] < rowLower[i] - 10.0*primalTolerance)
                        numberBad++;
                } else if (rowActivity[i] > rowUpper[i]) {
                    sumBad += rowUpper[i] - rowActivity[i];
                    if (rowActivity[i] > rowUpper[i] + 10.0*primalTolerance)
                        numberBad++;
                }
            }
            if (!numberBad) {
                for (i = 0; i < numberIntegers; i++) {
                    int iColumn = integerVariable[i];
                    const OsiObject * object = model_->object(i);
                    // get original bounds
                    double originalLower;
                    double originalUpper;
                    getIntegerInformation( object, originalLower, originalUpper);

                    double value = newSolution[iColumn];
                    // if away from lower bound mark that fact
                    if (value > originalLower) {
                        used_[iColumn] = numberSolutions_;
                    }
                }
/*
  Copy the solution to the array returned to the client. Grab a basis from
  the solver (which, if it exists, is almost certainly infeasible, but it
  should be ok for a dual start). The value returned as solutionValue is
  conservative because of handling of newSolutionValue and bestChange, as
  described above.
*/
                // new solution
                memcpy(betterSolution, newSolution, numberColumns*sizeof(double));
                CoinWarmStartBasis * basis =
                    dynamic_cast<CoinWarmStartBasis *>(solver->getWarmStart()) ;
                if (basis) {
                    model_->setBestSolutionBasis(* basis);
                    delete basis;
                }
                returnCode = 1;
                solutionValue = newSolutionValue + bestChange;
            } else {
                // bad solution - should not happen so debug if see message
                COIN_DETAIL_PRINT(printf("Local search got bad solution with %d infeasibilities summing to %g\n",
					 numberBad, sumBad));
            }
        }
    }
/*
  We're done. Clean up.
*/
    delete [] newSolution;
    delete [] rowActivity;
    delete [] way;
    delete [] cost;
    delete [] save;
    delete [] mark;
/*
  Do we want to try swapping values between solutions?
  swap_ is set elsewhere; it's not adjusted during heuristic execution.

  Again, redundant test. We shouldn't be here if numberSolutions_ = 1.
*/
    if (numberSolutions_ > 1 && (swap%10) == 1) {
        // try merge
        int returnCode2 = solutionFix( solutionValue, betterSolution, NULL);
        if (returnCode2)
            returnCode = 1;
    }
    return returnCode;
}