Пример #1
0
//-----------------------------------------------------------------------------
template <class Iter_S, class Iter_T> void
CoinSort_2(Iter_S sfirst, Iter_S slast, Iter_T tfirst)
{
  typedef typename std::iterator_traits<Iter_S>::value_type S;
  typedef typename std::iterator_traits<Iter_T>::value_type T;
  CoinSort_2(sfirst, slast, tfirst, CoinFirstLess_2<S,T>());
}
Пример #2
0
CbcBranchingObject *
CbcNWay::createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * /*info*/, int /*way*/)
{
    int numberFree = 0;
    int j;

    //OsiSolverInterface * solver = model_->solver();
    const double * solution = model_->testSolution();
    const double * lower = solver->getColLower();
    const double * upper = solver->getColUpper();
    int * list = new int[numberMembers_];
    double * sort = new double[numberMembers_];

    for (j = 0; j < numberMembers_; j++) {
        int iColumn = members_[j];
        double value = solution[iColumn];
        value = CoinMax(value, lower[iColumn]);
        value = CoinMin(value, upper[iColumn]);
        if (upper[iColumn] > lower[iColumn]) {
            double distance = upper[iColumn] - value;
            list[numberFree] = j;
            sort[numberFree++] = distance;
        }
    }
    assert (numberFree);
    // sort
    CoinSort_2(sort, sort + numberFree, list);
    // create object
    CbcBranchingObject * branch;
    branch = new CbcNWayBranchingObject(model_, this, numberFree, list);
    branch->setOriginalObject(this);
    delete [] list;
    delete [] sort;
    return branch;
}
Пример #3
0
//-------------------------------------------------------------------
// Useful Constructor
//-------------------------------------------------------------------
ClpConstraintLinear::ClpConstraintLinear (int row, int numberCoefficents ,
          int numberColumns,
          const int * column, const double * coefficient)
     : ClpConstraint()
{
     type_ = 0;
     rowNumber_ = row;
     numberColumns_ = numberColumns;
     numberCoefficients_ = numberCoefficents;
     column_ = CoinCopyOfArray(column, numberCoefficients_);
     coefficient_ = CoinCopyOfArray(coefficient, numberCoefficients_);
     CoinSort_2(column_, column_ + numberCoefficients_, coefficient_);
}
CbcBranchingObject *
CbcBranchAllDifferent::createCbcBranch(OsiSolverInterface * /*solver*/
                                       , const OsiBranchingInformation * /*info*/,
                                       int /*way*/)
{
    // by default way must be -1
    //assert (way==-1);
    const double * solution = model_->testSolution();
    double * values = new double[numberInSet_];
    int * which = new int[numberInSet_];
    int i;
    for (i = 0; i < numberInSet_; i++) {
        int iColumn = which_[i];
        values[i] = solution[iColumn];
        which[i] = iColumn;
    }
    CoinSort_2(values, values + numberInSet_, which);
    double last = -1.0;
    double closest = 1.0;
    int worst = -1;
    for (i = 0; i < numberInSet_; i++) {
        if (values[i] - last < closest) {
            closest = values[i] - last;
            worst = i - 1;
        }
        last = values[i];
    }
    assert (closest <= 0.99999);
    OsiRowCut down;
    down.setLb(-COIN_DBL_MAX);
    down.setUb(-1.0);
    int pair[2];
    double elements[] = {1.0, -1.0};
    pair[0] = which[worst];
    pair[1] = which[worst+1];
    delete [] values;
    delete [] which;
    down.setRow(2, pair, elements);
    // up is same - just with rhs changed
    OsiRowCut up = down;
    up.setLb(1.0);
    up.setUb(COIN_DBL_MAX);
    // Say is not a fix type branch
    CbcCutBranchingObject * newObject =
        new CbcCutBranchingObject(model_, down, up, false);
    if (model_->messageHandler()->logLevel() > 1)
        printf("creating cut in CbcBranchCut\n");
    return newObject;
}
Пример #5
0
/* Insert a row cut unless it is a duplicate (CoinRelFltEq)*/
void 
OsiCuts::insertIfNotDuplicate( OsiRowCut & rc , CoinRelFltEq treatAsSame)
{
  double newLb = rc.lb();
  double newUb = rc.ub();
  CoinPackedVector vector = rc.row();
  int numberElements =vector.getNumElements();
  int * newIndices = vector.getIndices();
  double * newElements = vector.getElements();
  CoinSort_2(newIndices,newIndices+numberElements,newElements);
  bool notDuplicate=true;
  int numberRowCuts = sizeRowCuts();
  for ( int i =0; i<numberRowCuts;i++) {
    const OsiRowCut * cutPtr = rowCutPtr(i);
    if (cutPtr->row().getNumElements()!=numberElements)
      continue;
    if (!treatAsSame(cutPtr->lb(),newLb))
      continue;
    if (!treatAsSame(cutPtr->ub(),newUb))
      continue;
    const CoinPackedVector * thisVector = &(cutPtr->row());
    const int * indices = thisVector->getIndices();
    const double * elements = thisVector->getElements();
    int j;
    for(j=0;j<numberElements;j++) {
      if (indices[j]!=newIndices[j])
	break;
      if (!treatAsSame(elements[j],newElements[j]))
	break;
    }
    if (j==numberElements) {
      notDuplicate=false;
      break;
    }
  }
  if (notDuplicate) {
    OsiRowCut * newCutPtr = new OsiRowCut();
    newCutPtr->setLb(newLb);
    newCutPtr->setUb(newUb);
    newCutPtr->setRow(vector);
    rowCutPtrs_.push_back(newCutPtr);
  }
}
Пример #6
0
CbcBranchingObject *
CbcBranchToFixLots::createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * /*info*/, int /*way*/)
{
    // by default way must be -1
    //assert (way==-1);
    //OsiSolverInterface * solver = model_->solver();
    const double * solution = model_->testSolution();
    const double * lower = solver->getColLower();
    const double * upper = solver->getColUpper();
    const double * dj = solver->getReducedCost();
    int i;
    int numberIntegers = model_->numberIntegers();
    const int * integerVariable = model_->integerVariable();
    double integerTolerance =
        model_->getDblParam(CbcModel::CbcIntegerTolerance);
    // make smaller ?
    double tolerance = CoinMin(1.0e-8, integerTolerance);
    // How many fixed are we aiming at
    int wantedFixed = static_cast<int> (static_cast<double>(numberIntegers) * fractionFixed_);
    int nSort = 0;
    int numberFixed = 0;
    int numberColumns = solver->getNumCols();
    int * sort = new int[numberColumns];
    double * dsort = new double[numberColumns];
    if (djTolerance_ != -1.234567) {
        int type = shallWe();
        assert (type);
        // Take clean first
        if (type == 1) {
            for (i = 0; i < numberIntegers; i++) {
                int iColumn = integerVariable[i];
                if (upper[iColumn] > lower[iColumn]) {
                    if (!mark_ || !mark_[iColumn]) {
                        if (solution[iColumn] < lower[iColumn] + tolerance) {
                            if (dj[iColumn] > djTolerance_) {
                                dsort[nSort] = -dj[iColumn];
                                sort[nSort++] = iColumn;
                            }
                        } else if (solution[iColumn] > upper[iColumn] - tolerance) {
                            if (dj[iColumn] < -djTolerance_) {
                                dsort[nSort] = dj[iColumn];
                                sort[nSort++] = iColumn;
                            }
                        }
                    }
                } else {
                    numberFixed++;
                }
            }
            // sort
            CoinSort_2(dsort, dsort + nSort, sort);
            nSort = CoinMin(nSort, wantedFixed - numberFixed);
        } else if (type < 10) {
            int i;
            //const double * rowLower = solver->getRowLower();
            const double * rowUpper = solver->getRowUpper();
            // Row copy
            const double * elementByRow = matrixByRow_.getElements();
            const int * column = matrixByRow_.getIndices();
            const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts();
            const int * rowLength = matrixByRow_.getVectorLengths();
            const double * columnLower = solver->getColLower();
            const double * columnUpper = solver->getColUpper();
            const double * solution = solver->getColSolution();
            int numberColumns = solver->getNumCols();
            int numberRows = solver->getNumRows();
            for (i = 0; i < numberColumns; i++) {
                sort[i] = i;
                if (columnLower[i] != columnUpper[i]) {
                    dsort[i] = 1.0e100;
                } else {
                    dsort[i] = 1.0e50;
                    numberFixed++;
                }
            }
            for (i = 0; i < numberRows; i++) {
                double rhsValue = rowUpper[i];
                bool oneRow = true;
                // check elements
                int numberUnsatisfied = 0;
                for (int j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) {
                    int iColumn = column[j];
                    double value = elementByRow[j];
                    double solValue = solution[iColumn];
                    if (columnLower[iColumn] != columnUpper[iColumn]) {
                        if (solValue < 1.0 - integerTolerance && solValue > integerTolerance)
                            numberUnsatisfied++;
                        if (value != 1.0) {
                            oneRow = false;
                            break;
                        }
                    } else {
                        rhsValue -= value * floor(solValue + 0.5);
                    }
                }
                if (oneRow && rhsValue <= 1.0 + tolerance) {
                    if (!numberUnsatisfied) {
                        for (int j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) {
                            int iColumn = column[j];
                            if (dsort[iColumn] > 1.0e50) {
                                dsort[iColumn] = 0;
                                nSort++;
                            }
                        }
                    }
                }
            }
            // sort
            CoinSort_2(dsort, dsort + numberColumns, sort);
        } else {
            // new way
            for (i = 0; i < numberIntegers; i++) {
                int iColumn = integerVariable[i];
                if (upper[iColumn] > lower[iColumn]) {
                    if (!mark_ || !mark_[iColumn]) {
                        double distanceDown = solution[iColumn] - lower[iColumn];
                        double distanceUp = upper[iColumn] - solution[iColumn];
                        double distance = CoinMin(distanceDown, distanceUp);
                        if (distance > 0.001 && distance < 0.5) {
                            dsort[nSort] = distance;
                            sort[nSort++] = iColumn;
                        }
                    }
                }
            }
            // sort
            CoinSort_2(dsort, dsort + nSort, sort);
            int n = 0;
            double sum = 0.0;
            for (int k = 0; k < nSort; k++) {
                sum += dsort[k];
                if (sum <= djTolerance_)
                    n = k;
                else
                    break;
            }
            nSort = CoinMin(n, numberClean_ / 1000000);
        }
    } else {
#define FIX_IF_LESS -0.1
        // 3 in same row and sum <FIX_IF_LESS?
        int numberRows = matrixByRow_.getNumRows();
        const double * solution = model_->testSolution();
        const int * column = matrixByRow_.getIndices();
        const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts();
        const int * rowLength = matrixByRow_.getVectorLengths();
        double bestSum = 1.0;
        int nBest = -1;
        int kRow = -1;
        OsiSolverInterface * solver = model_->solver();
        for (int i = 0; i < numberRows; i++) {
            int numberUnsatisfied = 0;
            double sum = 0.0;
            for (int j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) {
                int iColumn = column[j];
                if (solver->isInteger(iColumn)) {
                    double solValue = solution[iColumn];
                    if (solValue > 1.0e-5 && solValue < FIX_IF_LESS) {
                        numberUnsatisfied++;
                        sum += solValue;
                    }
                }
            }
            if (numberUnsatisfied >= 3 && sum < FIX_IF_LESS) {
                // possible
                if (numberUnsatisfied > nBest ||
                        (numberUnsatisfied == nBest && sum < bestSum)) {
                    nBest = numberUnsatisfied;
                    bestSum = sum;
                    kRow = i;
                }
            }
        }
        assert (nBest > 0);
        for (int j = rowStart[kRow]; j < rowStart[kRow] + rowLength[kRow]; j++) {
            int iColumn = column[j];
            if (solver->isInteger(iColumn)) {
                double solValue = solution[iColumn];
                if (solValue > 1.0e-5 && solValue < FIX_IF_LESS) {
                    sort[nSort++] = iColumn;
                }
            }
        }
    }
    OsiRowCut down;
    down.setLb(-COIN_DBL_MAX);
    double rhs = 0.0;
    for (i = 0; i < nSort; i++) {
        int iColumn = sort[i];
        double distanceDown = solution[iColumn] - lower[iColumn];
        double distanceUp = upper[iColumn] - solution[iColumn];
        if (distanceDown < distanceUp) {
            rhs += lower[iColumn];
            dsort[i] = 1.0;
        } else {
            rhs -= upper[iColumn];
            dsort[i] = -1.0;
        }
    }
    down.setUb(rhs);
    down.setRow(nSort, sort, dsort);
    down.setEffectiveness(COIN_DBL_MAX); // so will persist
    delete [] sort;
    delete [] dsort;
    // up is same - just with rhs changed
    OsiRowCut up = down;
    up.setLb(rhs + 1.0);
    up.setUb(COIN_DBL_MAX);
    // Say can fix one way
    CbcCutBranchingObject * newObject =
        new CbcCutBranchingObject(model_, down, up, true);
    if (model_->messageHandler()->logLevel() > 1)
        printf("creating cut in CbcBranchCut\n");
    return newObject;
}
Пример #7
0
//-----------------------------------------------------------------------------
template <class S, class T> void
CoinSort_2(S* sfirst, S* slast, T* tfirst)
{
  CoinSort_2(sfirst, slast, tfirst, CoinFirstLess_2<S,T>());
}
Пример #8
0
/** Useful constructor

  Loads actual upper & lower bounds for the specified variable.
*/
CbcLotsize::CbcLotsize (CbcModel * model,
                        int iColumn, int numberPoints,
                        const double * points, bool range)
        : CbcObject(model)
{
#if CBC_PRINT
    if (!saveModel)
        saveModel = model;
#endif
    assert (numberPoints > 0);
    columnNumber_ = iColumn ;
    // and set id so can be used for branching
    id_ = iColumn;
    // sort ranges
    int * sort = new int[numberPoints];
    double * weight = new double [numberPoints];
    int i;
    if (range) {
        rangeType_ = 2;
    } else {
        rangeType_ = 1;
    }
    for (i = 0; i < numberPoints; i++) {
        sort[i] = i;
        weight[i] = points[i*rangeType_];
    }
    CoinSort_2(weight, weight + numberPoints, sort);
    numberRanges_ = 1;
    largestGap_ = 0;
    if (rangeType_ == 1) {
        bound_ = new double[numberPoints+1];
        bound_[0] = weight[0];
        for (i = 1; i < numberPoints; i++) {
            if (weight[i] != weight[i-1])
                bound_[numberRanges_++] = weight[i];
        }
        // and for safety
        bound_[numberRanges_] = bound_[numberRanges_-1];
        for (i = 1; i < numberRanges_; i++) {
            largestGap_ = CoinMax(largestGap_, bound_[i] - bound_[i-1]);
        }
    } else {
        bound_ = new double[2*numberPoints+2];
        bound_[0] = points[sort[0] * 2];
        bound_[1] = points[sort[0] * 2 + 1];
        double hi = bound_[1];
        assert (hi >= bound_[0]);
        for (i = 1; i < numberPoints; i++) {
            double thisLo = points[sort[i] * 2];
            double thisHi = points[sort[i] * 2 + 1];
            assert (thisHi >= thisLo);
            if (thisLo > hi) {
                bound_[2*numberRanges_] = thisLo;
                bound_[2*numberRanges_+1] = thisHi;
                numberRanges_++;
                hi = thisHi;
            } else {
                //overlap
                hi = CoinMax(hi, thisHi);
                bound_[2*numberRanges_-1] = hi;
            }
        }
        // and for safety
        bound_[2*numberRanges_] = bound_[2*numberRanges_-2];
        bound_[2*numberRanges_+1] = bound_[2*numberRanges_-1];
        for (i = 1; i < numberRanges_; i++) {
            largestGap_ = CoinMax(largestGap_, bound_[2*i] - bound_[2*i-1]);
        }
    }
    delete [] sort;
    delete [] weight;
    range_ = 0;
}
Пример #9
0
void
CglClique::find_scl(OsiCuts& cs)
{
   const int nodenum = fgraph.nodenum;
   const fnode *nodes = fgraph.nodes;

   // Return at once if no nodes - otherwise we get invalid reads
   if (!nodenum)
     return;
   int *current_indices = new int[nodenum];
   int *current_degrees = new int[nodenum];
   double *current_values = new double[nodenum];

   int *star = cl_indices;
   int *star_deg = new int[nodenum];

   /** An array used in the recursive complete enumeration of maximal cliques.
       The first cl_length entries are used. */
   bool* label = new bool[nodenum];

   int i, cnt1 = 0, cnt2 = 0, cnt3 = 0;
   int clique_cnt_e = 0, clique_cnt_g = 0;
   int largest_star_size = 0;

   /* initialize global variables */
   cl_del_length = 0;

   /* initialize current_nodes, current_degrees and current_values */
   int current_nodenum = nodenum;
   for (i = 0; i < nodenum; i++) {
      current_indices[i] = i;
      current_degrees[i] = nodes[i].degree;
      current_values[i] = nodes[i].val;
   }
   
   /* find first node to be checked */
   int best_ind = scl_choose_next_node(current_nodenum, current_indices,
				       current_degrees, current_values);

   int v = current_indices[best_ind];
   int v_deg = current_degrees[best_ind];
   double v_val = current_values[best_ind];
      
   /* while there are nodes left in the graph ... (more precisely, while
      there are at least 3 nodes in the graph) */
   while (current_nodenum > 2) {

      /* if the best node is of degree < 2 then it can be deleted */
      if (v_deg < 2) {
	 cl_del_indices[cl_del_length++] = v;
	 scl_delete_node(best_ind, current_nodenum,
			 current_indices, current_degrees, current_values);
	 best_ind = scl_choose_next_node(current_nodenum, current_indices,
					 current_degrees, current_values);
	 v = current_indices[best_ind];
	 v_deg = current_degrees[best_ind];
	 v_val = current_values[best_ind];
	 largest_star_size = CoinMax(largest_star_size, v_deg);
	 continue;
      }

      /* star will contain the indices of v's neighbors (but not v's index) */
      const bool* node_node_start = node_node + nodenum * v;
      int& star_length = cl_length;
      star_length = 0;
      double star_val = v_val;
      for (i = 0; i < current_nodenum; i++) {
	 const int other_node = current_indices[i];
	 if (node_node_start[other_node]) {
	    star[star_length] = other_node;
	    star_deg[star_length++] = current_degrees[i];
	    star_val += current_values[i];
	 }
      }

      /* quick check: if sum of values for the star does not exceed 1 then
	 there won't be a violated clique in the star */
      if (star_val >= 1 + petol) {
	 /* node whose star we're evaluating is always in */
	 cl_perm_length = 1;
	 cl_perm_indices = &v;

	 /* find maximal violated cliques in star. cliques found here might not
	    be maximal wrt to entire fractional graph, only for the current
	    subset of it (some nodes might be already deleted...)
	    Note that star is the same as cl_indices and start_length is
	    cl_length... 
	 */
	 if (v_deg < scl_candidate_length_threshold) { // par
	    /* enumerate if v_deg is small enough */
	    for (i = 0; i < star_length; i++)
	       label[i] = false;
	    int pos = 0;
	    clique_cnt_e += enumerate_maximal_cliques(pos, label, cs);
	    cnt1++;
	 } else {
	    /* greedily find if v_deg is too big */
	    /* order nodes in *decreasing* order of their degrees in star */
	    CoinSort_2(star_deg, star_deg + star_length, star,
		       CoinFirstGreater_2<int,int>());
	    /* find maxl clique greedily, including v */
	    clique_cnt_g += greedy_maximal_clique(cs);
	    cnt2++;
	 }
      } else {
	 cnt3++;
      }
      /* delete v from current_indices */
      cl_del_indices[cl_del_length++] = v;
      scl_delete_node(best_ind, current_nodenum,
		      current_indices, current_degrees, current_values);
      best_ind = scl_choose_next_node(current_nodenum, current_indices,
				      current_degrees, current_values);
      v = current_indices[best_ind];
      v_deg = current_degrees[best_ind];
      v_val = current_values[best_ind];
      largest_star_size = CoinMax(largest_star_size, v_deg);
   }

   const int clique_cnt = clique_cnt_e + clique_cnt_g;

   if (scl_report_result) {
      printf("\nscl Found %i new violated cliques with the star-clique method",
	     clique_cnt);
      printf("\nscl The largest star size was %i (threshold %i)\n",
	     largest_star_size, scl_candidate_length_threshold); // par
      printf("scl Enumeration %i times, found %i maxl cliques\n",
	     cnt1, clique_cnt_e);
      printf("scl Greedy %i times, found %i maxl cliques\n",
	     cnt2, clique_cnt_g);
      printf("scl Skipped a star b/c of small solution value %i times\n",
	     cnt3);

      if (cnt2 == 0)
	 printf("scl    all cliques have been enumerated\n");
      else
	 printf("scl    not all cliques have been eliminated\n");
   }

   delete[] current_indices;
   delete[] current_degrees;
   delete[] current_values;
   delete[] star_deg;
   delete[] label;
}
Пример #10
0
/* This is the real constructor*/
ClpDynamicExampleMatrix::ClpDynamicExampleMatrix(ClpSimplex * model, int numberSets,
          int numberGubColumns, const int * starts,
          const double * lower, const double * upper,
          const CoinBigIndex * startColumn, const int * row,
          const double * element, const double * cost,
          const double * columnLower, const double * columnUpper,
          const unsigned char * status,
          const unsigned char * dynamicStatus,
          int numberIds, const int *ids)
     : ClpDynamicMatrix(model, numberSets, 0, NULL, lower, upper, NULL, NULL, NULL, NULL, NULL, NULL,
                        NULL, NULL)
{
     setType(25);
     numberColumns_ = numberGubColumns;
     // start with safe values - then experiment
     maximumGubColumns_ = numberColumns_;
     maximumElements_ = startColumn[numberColumns_];
     // delete odd stuff created by ClpDynamicMatrix constructor
     delete [] startSet_;
     startSet_ = new int [numberSets_];
     delete [] next_;
     next_ = new int [maximumGubColumns_];
     delete [] row_;
     delete [] element_;
     delete [] startColumn_;
     delete [] cost_;
     delete [] columnLower_;
     delete [] columnUpper_;
     delete [] dynamicStatus_;
     delete [] status_;
     delete [] id_;
     // and size correctly
     row_ = new int [maximumElements_];
     element_ = new double [maximumElements_];
     startColumn_ = new CoinBigIndex [maximumGubColumns_+1];
     // say no columns yet
     numberGubColumns_ = 0;
     startColumn_[0] = 0;
     cost_ = new double[maximumGubColumns_];
     dynamicStatus_ = new unsigned char [2*maximumGubColumns_];
     memset(dynamicStatus_, 0, maximumGubColumns_);
     id_ = new int[maximumGubColumns_];
     if (columnLower)
          columnLower_ = new double[maximumGubColumns_];
     else
          columnLower_ = NULL;
     if (columnUpper)
          columnUpper_ = new double[maximumGubColumns_];
     else
          columnUpper_ = NULL;
     // space for ids
     idGen_ = new int [maximumGubColumns_];
     int iSet;
     for (iSet = 0; iSet < numberSets_; iSet++)
          startSet_[iSet] = -1;
     // This starts code specific to this storage method
     CoinBigIndex i;
     fullStartGen_ = ClpCopyOfArray(starts, numberSets_ + 1);
     startColumnGen_ = ClpCopyOfArray(startColumn, numberColumns_ + 1);
     CoinBigIndex numberElements = startColumnGen_[numberColumns_];
     rowGen_ = ClpCopyOfArray(row, numberElements);
     elementGen_ = new double[numberElements];
     for (i = 0; i < numberElements; i++)
          elementGen_[i] = element[i];
     costGen_ = new double[numberColumns_];
     for (i = 0; i < numberColumns_; i++) {
          costGen_[i] = cost[i];
          // I don't think I need sorted but ...
          CoinSort_2(rowGen_ + startColumnGen_[i], rowGen_ + startColumnGen_[i+1], elementGen_ + startColumnGen_[i]);
     }
     if (columnLower) {
          columnLowerGen_ = new double[numberColumns_];
          for (i = 0; i < numberColumns_; i++) {
               columnLowerGen_[i] = columnLower[i];
               if (columnLowerGen_[i]) {
                    printf("Non-zero lower bounds not allowed - subtract from model\n");
                    abort();
               }
          }
     } else {
          columnLowerGen_ = NULL;
     }
     if (columnUpper) {
          columnUpperGen_ = new double[numberColumns_];
          for (i = 0; i < numberColumns_; i++)
               columnUpperGen_[i] = columnUpper[i];
     } else {
          columnUpperGen_ = NULL;
     }
     // end specific coding
     if (columnUpper_) {
          // set all upper bounds so we have enough space
          double * columnUpper = model->columnUpper();
          for(i = firstDynamic_; i < lastDynamic_; i++)
               columnUpper[i] = 1.0e10;
     }
     status_ = new unsigned char [2*numberSets_+4];
     if (status) {
          memcpy(status_,status, numberSets_ * sizeof(char));
          assert (dynamicStatus);
          CoinMemcpyN(dynamicStatus, numberIds, dynamicStatus_);
          assert (numberIds);
     } else {
          assert (!numberIds);
          memset(status_, 0, numberSets_);
          for (i = 0; i < numberSets_; i++) {
               // make slack key
               setStatus(i, ClpSimplex::basic);
          }
     }
     dynamicStatusGen_ = new unsigned char [numberColumns_];
     memset(dynamicStatusGen_, 0, numberColumns_); // for clarity
     for (i = 0; i < numberColumns_; i++)
          setDynamicStatusGen(i, atLowerBound);
     // Populate with enough columns
     if (!numberIds) {
          // This could be made more sophisticated
          for (iSet = 0; iSet < numberSets_; iSet++) {
               int sequence = fullStartGen_[iSet];
               CoinBigIndex start = startColumnGen_[sequence];
               addColumn(startColumnGen_[sequence+1] - start,
                         rowGen_ + start,
                         elementGen_ + start,
                         costGen_[sequence],
                         columnLowerGen_ ? columnLowerGen_[sequence] : 0,
                         columnUpperGen_ ? columnUpperGen_[sequence] : 1.0e30,
                         iSet, getDynamicStatusGen(sequence));
               idGen_[iSet] = sequence; // say which one in
               setDynamicStatusGen(sequence, inSmall);
          }
     } else {
          // put back old ones
          int * set = new int[numberColumns_];
          for (iSet = 0; iSet < numberSets_; iSet++) {
               for (CoinBigIndex j = fullStartGen_[iSet]; j < fullStartGen_[iSet+1]; j++)
                    set[j] = iSet;
          }
          for (int i = 0; i < numberIds; i++) {
               int sequence = ids[i];
               CoinBigIndex start = startColumnGen_[sequence];
               addColumn(startColumnGen_[sequence+1] - start,
                         rowGen_ + start,
                         elementGen_ + start,
                         costGen_[sequence],
                         columnLowerGen_ ? columnLowerGen_[sequence] : 0,
                         columnUpperGen_ ? columnUpperGen_[sequence] : 1.0e30,
                         set[sequence], getDynamicStatus(i));
               idGen_[iSet] = sequence; // say which one in
               setDynamicStatusGen(sequence, inSmall);
          }
          delete [] set;
     }
     if (!status) {
          gubCrash();
     } else {
          initialProblem();
     }
}
Пример #11
0
int main(int argc, const char *argv[])
{
     ClpSimplex  model;
     int status;
     // Keep names
     if (argc < 2) {
          status = model.readMps("small.mps", true);
     } else {
          status = model.readMps(argv[1], true);
     }
     if (status)
          exit(10);
     /*
       This driver implements the presolve variation of Sprint.
       This assumes we can get feasible easily
     */

     int numberRows = model.numberRows();
     int numberColumns = model.numberColumns();

     // We will need arrays to choose variables.  These are too big but ..
     double * weight = new double [numberRows+numberColumns];
     int * sort = new int [numberRows+numberColumns];

     double * columnLower = model.columnLower();
     double * columnUpper = model.columnUpper();
     double * saveLower = new double [numberColumns];
     memcpy(saveLower, columnLower, numberColumns * sizeof(double));
     double * saveUpper = new double [numberColumns];
     memcpy(saveUpper, columnUpper, numberColumns * sizeof(double));
     double * solution = model.primalColumnSolution();
     // Fix in some magical way so remaining problem is easy
#if 0
     // This is from a real-world problem
     for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
          char firstCharacter = model.columnName(iColumn)[0];
          if (firstCharacter == 'F' || firstCharacter == 'P'
                    || firstCharacter == 'L' || firstCharacter == 'T') {
               columnUpper[iColumn] = columnLower[iColumn];
          }
     }
#else
     double * obj = model.objective();
     double * saveObj = new double [numberColumns];
     memcpy(saveObj, obj, numberColumns * sizeof(double));
     memset(obj, 0, numberColumns * sizeof(double));
     model.dual();
     memcpy(obj, saveObj, numberColumns * sizeof(double));
     delete [] saveObj;
     for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
         if (solution[iColumn]<columnLower[iColumn]+1.0e-8) {
	     columnUpper[iColumn] = columnLower[iColumn];
       }
     }
#endif

     // Just do this number of passes
     int maxPass = 100;
     int iPass;
     double lastObjective = 1.0e31;

     // Just take this number of columns in small problem
     int smallNumberColumns = 3 * numberRows;
     // And we want number of rows to be this
     int smallNumberRows = numberRows / 4;

     for (iPass = 0; iPass < maxPass; iPass++) {
          printf("Start of pass %d\n", iPass);
          ClpSimplex * model2;
          ClpPresolve pinfo;
          int numberPasses = 1; // can change this
          model2 = pinfo.presolvedModel(model, 1.0e-8, false, numberPasses, false);
          if (!model2) {
               fprintf(stdout, "ClpPresolve says %s is infeasible with tolerance of %g\n",
                       argv[1], 1.0e-8);
               // model was infeasible - maybe try again with looser tolerances
               model2 = pinfo.presolvedModel(model, 1.0e-7, false, numberPasses, false);
               if (!model2) {
                    fprintf(stdout, "ClpPresolve says %s is infeasible with tolerance of %g\n",
                            argv[1], 1.0e-7);
                    exit(2);
               }
          }
          // change factorization frequency from 200
          model2->setFactorizationFrequency(100 + model2->numberRows() / 50);
          model2->primal();
          pinfo.postsolve(true);

          // adjust smallNumberColumns if necessary
          if (iPass) {
               double ratio = ((double) smallNumberRows) / ((double) model2->numberRows());
               smallNumberColumns = (int)(smallNumberColumns * ratio);
          }
          delete model2;
          /* After this postsolve model should be optimal.
             We can use checkSolution and test feasibility */
          model.checkSolution();
          if (model.numberDualInfeasibilities() ||
                    model.numberPrimalInfeasibilities())
               printf("%g dual %g(%d) Primal %g(%d)\n",
                      model.objectiveValue(),
                      model.sumDualInfeasibilities(),
                      model.numberDualInfeasibilities(),
                      model.sumPrimalInfeasibilities(),
                      model.numberPrimalInfeasibilities());
          // Put back true bounds
          memcpy(columnLower, saveLower, numberColumns * sizeof(double));
          memcpy(columnUpper, saveUpper, numberColumns * sizeof(double));
          if ((model.objectiveValue() > lastObjective - 1.0e-7 && iPass > 5) ||
                    iPass == maxPass - 1) {
               break; // finished
          } else {
               lastObjective = model.objectiveValue();
               // now massage weight so all basic in plus good djs
	       const double * djs = model.dualColumnSolution();
               for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
                    double dj = djs[iColumn];
                    double value = solution[iColumn];
                    if (model.getStatus(iColumn) == ClpSimplex::basic)
                         dj = -1.0e50;
                    else if (dj < 0.0 && value < columnUpper[iColumn])
                         dj = dj;
                    else if (dj > 0.0 && value > columnLower[iColumn])
                         dj = -dj;
                    else if (columnUpper[iColumn] > columnLower[iColumn])
                         dj = fabs(dj);
                    else
                         dj = 1.0e50;
                    weight[iColumn] = dj;
                    sort[iColumn] = iColumn;
               }
               // sort
               CoinSort_2(weight, weight + numberColumns, sort);
               // and fix others
               for (int iColumn = smallNumberColumns; iColumn < numberColumns; iColumn++) {
                    int kColumn = sort[iColumn];
                    double value = solution[kColumn];
                    columnLower[kColumn] = value;
                    columnUpper[kColumn] = value;
               }
          }
     }
     delete [] weight;
     delete [] sort;
     delete [] saveLower;
     delete [] saveUpper;
     model.primal(1);
     return 0;
}
Пример #12
0
const CoinPresolveAction *subst_constraint_action::presolve (
    CoinPresolveMatrix *prob,
    const int *implied_free, const int *whichFree, int numberFree,
    const CoinPresolveAction *next, int maxLook)
{

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

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

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

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

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

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


  const double tol = prob->feasibilityTolerance_ ;

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

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

  int *x_to_y = new int[ncols] ;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      ntotels += rowLengths[i] ;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return (next) ;
}
Пример #13
0
// As some computation is needed in more than one place - returns row
int
CbcFollowOn::gutsOfFollowOn(int & otherRow, int & preferredWay) const
{
    int whichRow = -1;
    otherRow = -1;
    int numberRows = matrix_.getNumRows();

    int i;
    // For sorting
    int * sort = new int [numberRows];
    int * isort = new int [numberRows];
    // Column copy
    //const double * element = matrix_.getElements();
    const int * row = matrix_.getIndices();
    const CoinBigIndex * columnStart = matrix_.getVectorStarts();
    const int * columnLength = matrix_.getVectorLengths();
    // Row copy
    const double * elementByRow = matrixByRow_.getElements();
    const int * column = matrixByRow_.getIndices();
    const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts();
    const int * rowLength = matrixByRow_.getVectorLengths();
    OsiSolverInterface * solver = model_->solver();
    const double * columnLower = solver->getColLower();
    const double * columnUpper = solver->getColUpper();
    const double * solution = solver->getColSolution();
    double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance);
    int nSort = 0;
    for (i = 0; i < numberRows; i++) {
        if (rhs_[i]) {
            // check elements
            double smallest = 1.0e10;
            double largest = 0.0;
            int rhsValue = rhs_[i];
            int number1 = 0;
            int numberUnsatisfied = 0;
            for (int j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) {
                int iColumn = column[j];
                double value = elementByRow[j];
                double solValue = solution[iColumn];
                if (columnLower[iColumn] != columnUpper[iColumn]) {
                    smallest = CoinMin(smallest, value);
                    largest = CoinMax(largest, value);
                    if (value == 1.0)
                        number1++;
                    if (solValue < 1.0 - integerTolerance && solValue > integerTolerance)
                        numberUnsatisfied++;
                } else {
                    rhsValue -= static_cast<int>(value * floor(solValue + 0.5));
                }
            }
            if (numberUnsatisfied > 1) {
                if (smallest < largest) {
                    // probably no good but check a few things
                    assert (largest <= rhsValue);
                    if (number1 == 1 && largest == rhsValue)
                        printf("could fix\n");
                } else if (largest == rhsValue) {
                    sort[nSort] = i;
                    isort[nSort++] = -numberUnsatisfied;
                }
            }
        }
    }
    if (nSort > 1) {
        CoinSort_2(isort, isort + nSort, sort);
        CoinZeroN(isort, numberRows);
        double * other = new double[numberRows];
        CoinZeroN(other, numberRows);
        int * which = new int[numberRows];
        //#define COUNT
#ifndef COUNT
        bool beforeSolution = model_->getSolutionCount() == 0;
#endif
        for (int k = 0; k < nSort - 1; k++) {
            i = sort[k];
            int numberUnsatisfied = 0;
            int n = 0;
            int j;
            for (j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) {
                int iColumn = column[j];
                if (columnLower[iColumn] != columnUpper[iColumn]) {
                    double solValue = solution[iColumn] - columnLower[iColumn];
                    if (solValue < 1.0 - integerTolerance && solValue > integerTolerance) {
                        numberUnsatisfied++;
                        for (int jj = columnStart[iColumn]; jj < columnStart[iColumn] + columnLength[iColumn]; jj++) {
                            int iRow = row[jj];
                            if (rhs_[iRow]) {
                                other[iRow] += solValue;
                                if (isort[iRow]) {
                                    isort[iRow]++;
                                } else {
                                    isort[iRow] = 1;
                                    which[n++] = iRow;
                                }
                            }
                        }
                    }
                }
            }
            double total = 0.0;
            // Take out row
            double sumThis = other[i];
            other[i] = 0.0;
            assert (numberUnsatisfied == isort[i]);
            // find one nearest half if solution, one if before solution
            int iBest = -1;
            double dtarget = 0.5 * total;
#ifdef COUNT
            int target = (numberUnsatisfied + 1) >> 1;
            int best = numberUnsatisfied;
#else
            double best;
            if (beforeSolution)
                best = dtarget;
            else
                best = 1.0e30;
#endif
            for (j = 0; j < n; j++) {
                int iRow = which[j];
                double dvalue = other[iRow];
                other[iRow] = 0.0;
#ifdef COUNT
                int value = isort[iRow];
#endif
                isort[iRow] = 0;
                if (fabs(dvalue) < 1.0e-8 || fabs(sumThis - dvalue) < 1.0e-8)
                    continue;
                if (dvalue < integerTolerance || dvalue > 1.0 - integerTolerance)
                    continue;
#ifdef COUNT
                if (abs(value - target) < best && value != numberUnsatisfied) {
                    best = abs(value - target);
                    iBest = iRow;
                    if (dvalue < dtarget)
                        preferredWay = 1;
                    else
                        preferredWay = -1;
                }
#else
                if (beforeSolution) {
                    if (fabs(dvalue - dtarget) > best) {
                        best = fabs(dvalue - dtarget);
                        iBest = iRow;
                        if (dvalue < dtarget)
                            preferredWay = 1;
                        else
                            preferredWay = -1;
                    }
                } else {
                    if (fabs(dvalue - dtarget) < best) {
                        best = fabs(dvalue - dtarget);
                        iBest = iRow;
                        if (dvalue < dtarget)
                            preferredWay = 1;
                        else
                            preferredWay = -1;
                    }
                }
#endif
            }
            if (iBest >= 0) {
                whichRow = i;
                otherRow = iBest;
                break;
            }
        }
        delete [] which;
        delete [] other;
    }
Пример #14
0
int main (int argc, const char *argv[])
{
     ClpSimplex  model;
     int status;
     // Keep names
     if (argc < 2) {
          status = model.readMps("small.mps", true);
     } else {
          status = model.readMps(argv[1], true);
     }
     if (status)
          exit(10);
     /*
       This driver implements what I called Sprint.  Cplex calls it
       "sifting" which is just as silly.  When I thought of this trivial idea
       it reminded me of an LP code of the 60's called sprint which after
       every factorization took a subset of the matrix into memory (all
       64K words!) and then iterated very fast on that subset.  On the
       problems of those days it did not work very well, but it worked very
       well on aircrew scheduling problems where there were very large numbers
       of columns all with the same flavor.
     */

     /* The idea works best if you can get feasible easily.  To make it
        more general we can add in costed slacks */

     int originalNumberColumns = model.numberColumns();
     int numberRows = model.numberRows();

     // We will need arrays to choose variables.  These are too big but ..
     double * weight = new double [numberRows+originalNumberColumns];
     int * sort = new int [numberRows+originalNumberColumns];
     int numberSort = 0;
     // Say we are going to add slacks - if you can get a feasible
     // solution then do that at the comment - Add in your own coding here
     bool addSlacks = true;

     if (addSlacks) {
          // initial list will just be artificials
          // first we will set all variables as close to zero as possible
          int iColumn;
          const double * columnLower = model.columnLower();
          const double * columnUpper = model.columnUpper();
          double * columnSolution = model.primalColumnSolution();

          for (iColumn = 0; iColumn < originalNumberColumns; iColumn++) {
               double value = 0.0;
               if (columnLower[iColumn] > 0.0)
                    value = columnLower[iColumn];
               else if (columnUpper[iColumn] < 0.0)
                    value = columnUpper[iColumn];
               columnSolution[iColumn] = value;
          }
          // now see what that does to row solution
          double * rowSolution = model.primalRowSolution();
          memset (rowSolution, 0, numberRows * sizeof(double));
          model.times(1.0, columnSolution, rowSolution);

          int * addStarts = new int [numberRows+1];
          int * addRow = new int[numberRows];
          double * addElement = new double[numberRows];
          const double * lower = model.rowLower();
          const double * upper = model.rowUpper();
          addStarts[0] = 0;
          int numberArtificials = 0;
          double * addCost = new double [numberRows];
          const double penalty = 1.0e8;
          int iRow;
          for (iRow = 0; iRow < numberRows; iRow++) {
               if (lower[iRow] > rowSolution[iRow]) {
                    addRow[numberArtificials] = iRow;
                    addElement[numberArtificials] = 1.0;
                    addCost[numberArtificials] = penalty;
                    numberArtificials++;
                    addStarts[numberArtificials] = numberArtificials;
               } else if (upper[iRow] < rowSolution[iRow]) {
                    addRow[numberArtificials] = iRow;
                    addElement[numberArtificials] = -1.0;
                    addCost[numberArtificials] = penalty;
                    numberArtificials++;
                    addStarts[numberArtificials] = numberArtificials;
               }
          }
          model.addColumns(numberArtificials, NULL, NULL, addCost,
                           addStarts, addRow, addElement);
          delete [] addStarts;
          delete [] addRow;
          delete [] addElement;
          delete [] addCost;
          // Set up initial list
          numberSort = numberArtificials;
          int i;
          for (i = 0; i < numberSort; i++)
               sort[i] = i + originalNumberColumns;
     } else {
          // Get initial list in some magical way
          // Add in your own coding here
          abort();
     }

     int numberColumns = model.numberColumns();
     const double * columnLower = model.columnLower();
     const double * columnUpper = model.columnUpper();
     double * fullSolution = model.primalColumnSolution();

     // Just do this number of passes
     int maxPass = 100;
     int iPass;
     double lastObjective = 1.0e31;

     // Just take this number of columns in small problem
     int smallNumberColumns = CoinMin(3 * numberRows, numberColumns);
     smallNumberColumns = CoinMax(smallNumberColumns, 3000);
     // We will be using all rows
     int * whichRows = new int [numberRows];
     for (int iRow = 0; iRow < numberRows; iRow++)
          whichRows[iRow] = iRow;
     double originalOffset;
     model.getDblParam(ClpObjOffset, originalOffset);

     for (iPass = 0; iPass < maxPass; iPass++) {
          printf("Start of pass %d\n", iPass);
          //printf("Bug until submodel new version\n");
          CoinSort_2(sort, sort + numberSort, weight);
          // Create small problem
          ClpSimplex small(&model, numberRows, whichRows, numberSort, sort);
          // now see what variables left out do to row solution
          double * rowSolution = model.primalRowSolution();
          memset (rowSolution, 0, numberRows * sizeof(double));
          int iRow, iColumn;
          // zero out ones in small problem
          for (iColumn = 0; iColumn < numberSort; iColumn++) {
               int kColumn = sort[iColumn];
               fullSolution[kColumn] = 0.0;
          }
          // Get objective offset
          double offset = 0.0;
          const double * objective = model.objective();
          for (iColumn = 0; iColumn < originalNumberColumns; iColumn++)
               offset += fullSolution[iColumn] * objective[iColumn];
          small.setDblParam(ClpObjOffset, originalOffset - offset);
          model.times(1.0, fullSolution, rowSolution);

          double * lower = small.rowLower();
          double * upper = small.rowUpper();
          for (iRow = 0; iRow < numberRows; iRow++) {
               if (lower[iRow] > -1.0e50)
                    lower[iRow] -= rowSolution[iRow];
               if (upper[iRow] < 1.0e50)
                    upper[iRow] -= rowSolution[iRow];
          }
          /* For some problems a useful variant is to presolve problem.
             In this case you need to adjust smallNumberColumns to get
             right size problem.  Also you can dispense with creating
             small problem and fix variables in large problem and do presolve
             on that. */
          // Solve
          small.primal();
          // move solution back
          const double * solution = small.primalColumnSolution();
          for (iColumn = 0; iColumn < numberSort; iColumn++) {
               int kColumn = sort[iColumn];
               model.setColumnStatus(kColumn, small.getColumnStatus(iColumn));
               fullSolution[kColumn] = solution[iColumn];
          }
          for (iRow = 0; iRow < numberRows; iRow++)
               model.setRowStatus(iRow, small.getRowStatus(iRow));
          memcpy(model.primalRowSolution(), small.primalRowSolution(),
                 numberRows * sizeof(double));
          if ((small.objectiveValue() > lastObjective - 1.0e-7 && iPass > 5) ||
                    !small.numberIterations() ||
                    iPass == maxPass - 1) {

               break; // finished
          } else {
               lastObjective = small.objectiveValue();
               // get reduced cost for large problem
               // this assumes minimization
               memcpy(weight, model.objective(), numberColumns * sizeof(double));
               model.transposeTimes(-1.0, small.dualRowSolution(), weight);
               // now massage weight so all basic in plus good djs
               for (iColumn = 0; iColumn < numberColumns; iColumn++) {
                    double dj = weight[iColumn];
                    double value = fullSolution[iColumn];
                    if (model.getColumnStatus(iColumn) == ClpSimplex::basic)
                         dj = -1.0e50;
                    else if (dj < 0.0 && value < columnUpper[iColumn])
                         dj = dj;
                    else if (dj > 0.0 && value > columnLower[iColumn])
                         dj = -dj;
                    else if (columnUpper[iColumn] > columnLower[iColumn])
                         dj = fabs(dj);
                    else
                         dj = 1.0e50;
                    weight[iColumn] = dj;
                    sort[iColumn] = iColumn;
               }
               // sort
               CoinSort_2(weight, weight + numberColumns, sort);
               numberSort = smallNumberColumns;
          }
     }
     if (addSlacks) {
          int i;
          int numberArtificials = numberColumns - originalNumberColumns;
          for (i = 0; i < numberArtificials; i++)
               sort[i] = i + originalNumberColumns;
          model.deleteColumns(numberArtificials, sort);
     }
     delete [] weight;
     delete [] sort;
     delete [] whichRows;
     model.primal(1);
     return 0;
}
Пример #15
0
/* Does a lot of the work,
   Returns 0 if no good, 1 if dj, 2 if clean, 3 if both
   10 if branching on ones away from bound
*/
int
CbcBranchToFixLots::shallWe() const
{
    int returnCode = 0;
    OsiSolverInterface * solver = model_->solver();
    int numberRows = matrixByRow_.getNumRows();
    //if (numberRows!=solver->getNumRows())
    //return 0;
    const double * solution = model_->testSolution();
    const double * lower = solver->getColLower();
    const double * upper = solver->getColUpper();
    const double * dj = solver->getReducedCost();
    int i;
    int numberIntegers = model_->numberIntegers();
    const int * integerVariable = model_->integerVariable();
    if (numberClean_ > 1000000) {
        int wanted = numberClean_ % 1000000;
        int * sort = new int[numberIntegers];
        double * dsort = new double[numberIntegers];
        int nSort = 0;
        for (i = 0; i < numberIntegers; i++) {
            int iColumn = integerVariable[i];
            if (upper[iColumn] > lower[iColumn]) {
                if (!mark_ || !mark_[iColumn]) {
                    double distanceDown = solution[iColumn] - lower[iColumn];
                    double distanceUp = upper[iColumn] - solution[iColumn];
                    double distance = CoinMin(distanceDown, distanceUp);
                    if (distance > 0.001 && distance < 0.5) {
                        dsort[nSort] = distance;
                        sort[nSort++] = iColumn;
                    }
                }
            }
        }
        // sort
        CoinSort_2(dsort, dsort + nSort, sort);
        int n = 0;
        double sum = 0.0;
        for (int k = 0; k < nSort; k++) {
            sum += dsort[k];
            if (sum <= djTolerance_)
                n = k;
            else
                break;
        }
        delete [] sort;
        delete [] dsort;
        return (n >= wanted) ? 10 : 0;
    }
    double integerTolerance =
        model_->getDblParam(CbcModel::CbcIntegerTolerance);
    // make smaller ?
    double tolerance = CoinMin(1.0e-8, integerTolerance);
    // How many fixed are we aiming at
    int wantedFixed = static_cast<int> (static_cast<double>(numberIntegers) * fractionFixed_);
    if (djTolerance_ < 1.0e10) {
        int nSort = 0;
        int numberFixed = 0;
        for (i = 0; i < numberIntegers; i++) {
            int iColumn = integerVariable[i];
            if (upper[iColumn] > lower[iColumn]) {
                if (!mark_ || !mark_[iColumn]) {
                    if (solution[iColumn] < lower[iColumn] + tolerance) {
                        if (dj[iColumn] > djTolerance_) {
                            nSort++;
                        }
                    } else if (solution[iColumn] > upper[iColumn] - tolerance) {
                        if (dj[iColumn] < -djTolerance_) {
                            nSort++;
                        }
                    }
                }
            } else {
                numberFixed++;
            }
        }
        if (numberFixed + nSort < wantedFixed && !alwaysCreate_) {
            returnCode = 0;
        } else if (numberFixed < wantedFixed) {
            returnCode = 1;
        } else {
            returnCode = 0;
        }
    }
    if (numberClean_) {
        // see how many rows clean
        int i;
        //const double * rowLower = solver->getRowLower();
        const double * rowUpper = solver->getRowUpper();
        // Row copy
        const double * elementByRow = matrixByRow_.getElements();
        const int * column = matrixByRow_.getIndices();
        const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts();
        const int * rowLength = matrixByRow_.getVectorLengths();
        const double * columnLower = solver->getColLower();
        const double * columnUpper = solver->getColUpper();
        const double * solution = solver->getColSolution();
        int numberClean = 0;
        bool someToDoYet = false;
        int numberColumns = solver->getNumCols();
        char * mark = new char[numberColumns];
        int numberFixed = 0;
        for (i = 0; i < numberColumns; i++) {
            if (columnLower[i] != columnUpper[i]) {
                mark[i] = 0;
            } else {
                mark[i] = 1;
                numberFixed++;
            }
        }
        int numberNewFixed = 0;
        for (i = 0; i < numberRows; i++) {
            double rhsValue = rowUpper[i];
            bool oneRow = true;
            // check elements
            int numberUnsatisfied = 0;
            for (int j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) {
                int iColumn = column[j];
                double value = elementByRow[j];
                double solValue = solution[iColumn];
                if (columnLower[iColumn] != columnUpper[iColumn]) {
                    if (solValue < 1.0 - integerTolerance && solValue > integerTolerance)
                        numberUnsatisfied++;
                    if (value != 1.0) {
                        oneRow = false;
                        break;
                    }
                } else {
                    rhsValue -= value * floor(solValue + 0.5);
                }
            }
            if (oneRow && rhsValue <= 1.0 + tolerance) {
                if (numberUnsatisfied) {
                    someToDoYet = true;
                } else {
                    numberClean++;
                    for (int j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) {
                        int iColumn = column[j];
                        if (columnLower[iColumn] != columnUpper[iColumn] && !mark[iColumn]) {
                            mark[iColumn] = 1;
                            numberNewFixed++;
                        }
                    }
                }
            }
        }
        delete [] mark;
        //printf("%d clean, %d old fixed, %d new fixed\n",
        //   numberClean,numberFixed,numberNewFixed);
        if (someToDoYet && numberClean < numberClean_
                && numberNewFixed + numberFixed < wantedFixed) {
        } else if (numberFixed < wantedFixed) {
            returnCode |= 2;
        } else {
        }
    }
    return returnCode;
}
Пример #16
0
// Converts to ordered and takes out duplicates
void 
CglTreeProbingInfo::convert()
{
  if (numberEntries_>=0) {
    CoinSort_2( fixingEntry_, fixingEntry_+numberEntries_, fixEntry_);
    assert (!toZero_);
    toZero_ = new int [numberIntegers_+1];
    toOne_ = new int [numberIntegers_];
    toZero_[0]=0;
    int n=0;
    int put=0;
    for (int intVariable = 0;intVariable<numberIntegers_;intVariable++) {
      int last = n;
      for (;n<numberEntries_;n++) {
	int value = fixingEntry_[n];
	int iVar = value>>1;
	int way = value &1;
	if (intVariable!=iVar||way)
	  break;
      }
      if (n>last) {
	// sort
	assert (sizeof(int)==4);
	std::sort(reinterpret_cast<unsigned int *> (fixEntry_)+last,
		  reinterpret_cast<unsigned int *> (fixEntry_)+n);
	CliqueEntry temp2;
	temp2.fixes=0;
	setSequenceInCliqueEntry(temp2,numberVariables_+1);
	for (int i=last;i<n;i++) {
	  if (sequenceInCliqueEntry(temp2)!=sequenceInCliqueEntry(fixEntry_[i])||oneFixesInCliqueEntry(temp2)||oneFixesInCliqueEntry(fixEntry_[i])) {
	    temp2 = fixEntry_[i];
	    fixEntry_[put++]=temp2;
	  }
	}
      }
      toOne_[intVariable]=put;
      last = n;
      for (;n<numberEntries_;n++) {
	int value = fixingEntry_[n];
	int iVar = value>>1;
	if (intVariable!=iVar)
	  break;
      }
      if (n>last) {
	// sort
	assert (sizeof(int)==4);
	std::sort(reinterpret_cast<unsigned int *> (fixEntry_)+last,
		  reinterpret_cast<unsigned int *> (fixEntry_)+n);
	CliqueEntry temp2;
	temp2.fixes=0;
	setSequenceInCliqueEntry(temp2,numberVariables_+1);
	for (int i=last;i<n;i++) {
	  if (sequenceInCliqueEntry(temp2)!=sequenceInCliqueEntry(fixEntry_[i])||oneFixesInCliqueEntry(temp2)||oneFixesInCliqueEntry(fixEntry_[i])) {
	    temp2 = fixEntry_[i];
	    fixEntry_[put++]=temp2;
	  }
	}
	last=n;
      }
      toZero_[intVariable+1]=put;
    }
    delete [] fixingEntry_;
    fixingEntry_ = NULL;
    numberEntries_ = -2;
  }
Пример #17
0
const CoinPresolveAction *implied_free_action::presolve (
    CoinPresolveMatrix *prob, const CoinPresolveAction *next, int &fill_level)
{
# if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0
# if PRESOLVE_DEBUG > 0
  std::cout
    << "Entering implied_free_action::presolve, fill level " << fill_level
    << "." << std::endl ;
# endif
  presolve_consistent(prob) ;
  presolve_links_ok(prob) ;
  presolve_check_sol(prob) ;
  presolve_check_nbasic(prob) ;
# endif

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

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

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

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

/*
  Column bounds, row bounds, cost, integrality.
*/
  double *clo = prob->clo_ ;
  double *cup = prob->cup_ ;
  double *rlo = prob->rlo_ ;
  double *rup = prob->rup_ ;
  double *cost = prob->cost_ ;
  const unsigned char *integerType = prob->integerType_ ;

/*
  Documented as `inhibit x+y+z = 1 mods'.  From the code below, it's clear
  that this is intended to avoid removing SOS equalities with length >= 5
  (hardcoded). 
*/
  const bool stopSomeStuff = ((prob->presolveOptions()&0x04) != 0) ;
/*
  Ignore infeasibility. `Fix' is overly optimistic.
*/
  const bool fixInfeasibility = ((prob->presolveOptions_&0x4000) != 0) ;
/*
  Defaults to 0.0.
*/
  const double feasTol = prob->feasibilityTolerance_ ;

# if 0  
/*
  Tentatively moved to be a front-end function for useless_constraint_action,
  much as make_fixed is a front-end for make_fixed_action. This bit of code
  left for possible tuning.
  -- lh, 121127 --

  Original comment: This needs to be made faster.
*/
# ifdef COIN_LIGHTWEIGHT_PRESOLVE
  if (prob->pass_ == 1) {
#else
    if (prob->presolveOptions_&0x10) {
# endif
    next = testRedundant(prob,next) ;
    if (prob->status_&0x01 != 0) {
      if ((prob->presolveOptions_&0x4000) != 0)
        prob->status_ &= !0x01 ;
      else
	return (next) ;
    }
# if 1 //def COIN_LIGHTWEIGHT_PRESOLVE
  }
# endif
# endif

/*
  implied_free and subst take a fair bit of effort to scan for candidates.
  This is a hook to allow a presolve driver to avoid that work.
*/
  if (prob->pass_ > 15 && (prob->presolveOptions_&0x10000) != 0) { 
    fill_level = 2 ;
    return (next) ;
  }

/*
  Set up to collect implied_free actions.
*/
  action *actions = new action [n] ;
# ifdef ZEROFAULT
  CoinZeroN(reinterpret_cast<char *>(actions),n*sizeof(action)) ;
# endif
  int nactions = 0 ;

  int *implied_free = prob->usefulColumnInt_ ;
  int *whichFree = implied_free+n ;
  int numberFree = 0 ;
/*
  Arrays to hold row activity (row lhs) min and max values. Each row lhs bound
  is held as two components: a sum of finite column bounds and a count of
  infinite column bounds.
*/
  int *infiniteDown = new int[m] ;
  int *infiniteUp = new int[m] ;
  double *maxDown = new double[m] ;
  double *maxUp = new double[m] ;
/*
  Overload infiniteUp with row status codes:
  -1: L(i)/U(i) not yet computed,
  -2: do not use (empty or useless row),
  -3: give up (infeasible)
  -4: chosen as implied free row
*/
  for (int i = 0 ; i < m ; i++) {
    if (rowLengths[i] > 1)
      infiniteUp[i] = -1 ;
    else
      infiniteUp[i] = -2 ;
  }
  // Get rid of rows with prohibited columns
  if (prob->anyProhibited_) {
    for (int i = 0 ; i < m ; i++) {
      CoinBigIndex rStart = rowStarts[i];
      CoinBigIndex rEnd = rStart+rowLengths[i];
      bool badRow=false;
      for (CoinBigIndex j = rStart; j < rEnd; ++j) {
	if (prob->colProhibited(colIndices[j])) {
	  badRow=true;
	  break;
	}
      }
      if (badRow)
	infiniteUp[i] = -2 ;
    }
  }

// Can't go on without a suitable finite infinity, can we?
#ifdef USE_SMALL_LARGE
  const double large = 1.0e10 ;
#else
  const double large = 1.0e20 ;
#endif

/*
  Decide which columns we're going to look at. There are columns already queued
  in colsToDo_, but sometimes we want to look at all of them. Don't suck in
  prohibited columns. See comments at the head of the routine for fill_level.

  NOTE the overload on usefulColumnInt_. It was assigned above to whichFree
       (indices of interesting columns). We'll be ok because columns are
       consumed out of look at one per main loop iteration, but not all
       columns are interesting.

  Original comment: if gone from 2 to 3 look at all
*/
  int numberLook = prob->numberColsToDo_ ;
  int iLook ;
  int *look = prob->colsToDo_ ;
  if (fill_level < 0) {
    look = prob->usefulColumnInt_+n ;
    if (!prob->anyProhibited()) {
      CoinIotaN(look,n,0) ;
      numberLook = n ;
    } else {
      numberLook = 0 ;
      for (iLook = 0 ; iLook < n ; iLook++) 
	if (!prob->colProhibited(iLook))
	  look[numberLook++] = iLook ;
    }
  }
/*
  Step through the columns of interest looking for suitable x(tgt).

  Interesting columns are limited by number of nonzeros to minimise fill-in
  during substitution.
*/
  bool infeas = false ;
  const int maxLook = abs(fill_level) ;
  for (iLook = 0 ; iLook < numberLook ; iLook++) {
    const int tgtcol = look[iLook] ;
    const int tgtcol_len = colLengths[tgtcol] ;

    if (tgtcol_len <= 0 || tgtcol_len > maxLook) continue ;
/*
  Set up to reconnoiter the column.

  The initial value for ait_max is chosen to make sure that anything that
  satisfies the stability check is big enough to use (though we'd clearly like
  something better).
*/
    const CoinBigIndex kcs = colStarts[tgtcol] ;
    const CoinBigIndex kce = kcs+tgtcol_len ;
    const bool singletonCol = (tgtcol_len == 1) ;
    bool possibleRow = false ;
    bool singletonRow = false ;
    double ait_max = 20*ZTOLDP2 ;
/*
  If this is a singleton column, the only concern is that the row is not a
  singleton row (that has its own, simpler, transform: slack_doubleton). But
  make sure we're not dealing with some tiny a(it).

  Note that there's no point in marking a singleton row. By definition, we
  won't encounter it again.
*/
    if (singletonCol) {
      const int i = rowIndices[kcs] ;
      singletonRow = (rowLengths[i] == 1) ;
      possibleRow = (fabs(colCoeffs[kcs]) > ZTOLDP2) ;
    } else {
      
/*
  If the column is not a singleton, we'll need a numerically stable
  substitution formula. Check that this is possible.  One of the entangled
  rows must be an equality with a numerically stable coefficient, at least
  .1*MAX{i}a(it).
*/
      for (CoinBigIndex kcol = kcs ; kcol < kce ; ++kcol) {
	const int i = rowIndices[kcol] ;
	if (rowLengths[i] == 1) {
	  singletonRow = true ;
	  break ;
	}
	const double abs_ait = fabs(colCoeffs[kcol]) ;
	ait_max = CoinMax(ait_max,abs_ait) ;
	if (fabs(rlo[i]-rup[i]) < feasTol && abs_ait > .1*ait_max) {
	  possibleRow = true ;
	}
      }
    }
    if (singletonRow || !possibleRow) continue ;
/*
  The column has possibilities. Walk the column, calculate row activity
  bounds L(i) and U(i) for suitable entangled rows, then calculate the
  improvement (if any) on the column bounds for l(j) and u(j). The goal is to
  satisfy the implied free condition over all entangled rows and find at least
  one row suitable for a substitution formula (if the column is not a natural
  singleton).

  Suitable: If this is a natural singleton, we need to look at the single
  entangled constraint.  If we're attempting to create a singleton by
  substitution, only look at equalities with stable coefficients. If x(t) is
  integral, make sure the scaled rhs will be integral.
*/
#   if PRESOLVE_DEBUG > 2
    std::cout
      << "  Checking x(" << tgtcol << "), " << tgtcol_len << " nonzeros"
      << ", l(" << tgtcol << ") " << clo[tgtcol] << ", u(" << tgtcol
      << ") " << cup[tgtcol] << ", c(" << tgtcol << ") " << cost[tgtcol]
      << "." << std::endl ;
#   endif
    const double lt = clo[tgtcol] ;
    const double ut = cup[tgtcol] ;
    double impliedLow = -COIN_DBL_MAX ;
    double impliedHigh = COIN_DBL_MAX ;
    int subst_ndx = -1 ;
    int subst_len = n ;
    for (CoinBigIndex kcol = kcs ; kcol < kce ; ++kcol) {
      const int i = rowIndices[kcol] ;

      assert(infiniteUp[i] != -3) ;
      if (infiniteUp[i] <= -2) continue ;

      const double ait = colCoeffs[kcol] ;
      const int leni = rowLengths[i] ;
      const double rloi = rlo[i] ;
      const double rupi = rup[i] ;
/*
  A suitable row for substitution must
    * be an equality;
    * the entangled coefficient must be large enough to be numerically stable;
    * if x(t) is integer, the constant term in the substitution formula must be
      integer.
*/
      bool rowiOK = (fabs(rloi-rupi) < feasTol) && (fabs(ait) > .1*ait_max) ;
      rowiOK = rowiOK && ((integerType[tgtcol] == 0) ||
                          (fabs((rloi/ait)-floor((rloi/ait)+0.5)) < feasTol)) ;
/*
  If we don't already have L(i) and U(i), calculate now. Check for useless and
  infeasible constraints when that's done.
*/
      int infUi = 0 ;
      int infLi = 0 ;
      double maxUi = 0.0 ;
      double maxLi = 0.0 ;
      const CoinBigIndex krs = rowStarts[i] ;
      const CoinBigIndex kre = krs+leni ;

      if (infiniteUp[i] == -1) {
	for (CoinBigIndex krow = krs ; krow < kre ; ++krow) {
	  const double aik = rowCoeffs[krow] ;
	  const int k = colIndices[krow] ;
	  const double lk = clo[k] ;
	  const double uk = cup[k] ;
	  if (aik > 0.0) {
	    if (uk < large) 
	      maxUi += uk*aik ;
	    else
	      ++infUi ;
	    if (lk > -large) 
	      maxLi += lk*aik ;
	    else
	      ++infLi ;
	  } else if (aik < 0.0) {
	    if (uk < large) 
	      maxLi += uk*aik ;
	    else
	      ++infLi ;
	    if (lk > -large) 
	      maxUi += lk*aik ;
	    else
	      ++infUi ;
	  }
	}
	const double maxUinf = maxUi+infUi*1.0e31 ;
	const double maxLinf = maxLi-infLi*1.0e31 ;
	if (maxUinf <= rupi+feasTol && maxLinf >= rloi-feasTol) {
	  infiniteUp[i] = -2 ;
	} else if (maxUinf < rloi-feasTol && !fixInfeasibility) {
	  prob->status_|= 1 ;
	  infeas = true ;
	  prob->messageHandler()->message(COIN_PRESOLVE_ROWINFEAS,
					  prob->messages())
	    << i << rloi << rupi << CoinMessageEol ;
	  infiniteUp[i] = -3 ;
	} else if (maxLinf > rupi+feasTol && !fixInfeasibility) {
	  prob->status_|= 1 ;
	  infeas = true ;
	  prob->messageHandler()->message(COIN_PRESOLVE_ROWINFEAS,
					  prob->messages())
	    << i << rloi << rupi << CoinMessageEol ;
	  infiniteUp[i] = -3 ;
	} else {
	  infiniteUp[i] = infUi ;
	  infiniteDown[i] = infLi ;
	  maxUp[i] = maxUi ;
	  maxDown[i] = maxLi ;
	}
      } else {
        infUi = infiniteUp[i] ;
	infLi = infiniteDown[i] ;
	maxUi = maxUp[i] ;
	maxLi = maxDown[i] ;
      }
#     if PRESOLVE_DEBUG > 2
      std::cout
        << "    row(" << i << ") " << leni << " nonzeros, blow " << rloi
	<< ", L (" << infLi << "," << maxLi
	<< "), U (" << infUi << "," << maxUi
	<< "), b " << rupi ;
      if (infeas) std::cout << " infeas" ;
      if (infiniteUp[i] == -2) std::cout << " useless" ;
      std::cout << "." << std::endl ;
#     endif
/*
  If we're infeasible, no sense checking further; escape the implied bound
  loop. The other possibility is that we've just discovered the constraint
  is useless, in which case we just move on to the next one in the column.
*/
      if (infeas) break ;
      if (infiniteUp[i] == -2) continue ;
      assert(infiniteUp[i] >= 0 && infiniteUp[i] <= leni) ;
/*
  At this point we have L(i) and U(i), expressed as finite and infinite
  components, and constraint i is neither useless or infeasible. Calculate
  the implied bounds l'(t) and u'(t) on x(t). The calculation (for a(it) > 0)
  is
    u'(t) <= (b(i) - (L(i)-a(it)l(t)))/a(it) = l(t)+(b(i)-L(i))/a(it)
    l'(t) >= (blow(i) - (U(i)-a(it)u(t)))/a(it) = u(t)+(blow(i)-U(i))/a(it)
  Insert the appropriate flips for a(it) < 0. Notice that if there's exactly
  one infinite contribution to L(i) or U(i) and x(t) is responsible, then the
  finite portion of L(i) or U(i) is already correct.

  Cut some slack for possible numerical inaccuracy if the finite portion of
  L(i) or U(i) is very large. If the new bound is very large, force it to
  infinity.
*/
      double ltprime = -COIN_DBL_MAX ;
      double utprime = COIN_DBL_MAX ;
      if (ait > 0.0) {
	if (rloi > -large) {
	  if (!infUi) {
	    assert(ut < large) ;
	    ltprime = ut+(rloi-maxUi)/ait ;
	    if (fabs(maxUi) > 1.0e8 && !singletonCol)
	      ltprime -= 1.0e-12*fabs(maxUi) ;
	  } else if (infUi == 1 && ut > large) {
	    ltprime = (rloi-maxUi)/ait ;
	    if (fabs(maxUi) > 1.0e8 && !singletonCol)
	      ltprime -= 1.0e-12*fabs(maxUi) ;
	  } else {
	    ltprime = -COIN_DBL_MAX ;
	  }
	  impliedLow = CoinMax(impliedLow,ltprime) ;
	}
	if (rupi < large) {
	  if (!infLi) {
	    assert(lt > -large) ;
	    utprime = lt+(rupi-maxLi)/ait ;
	    if (fabs(maxLi) > 1.0e8 && !singletonCol)
	      utprime += 1.0e-12*fabs(maxLi) ;
	  } else if (infLi == 1 && lt < -large) {
	    utprime = (rupi-maxLi)/ait ;
	    if (fabs(maxLi) > 1.0e8 && !singletonCol)
	      utprime += 1.0e-12*fabs(maxLi) ;
	  } else {
	    utprime = COIN_DBL_MAX ;
	  }
	  impliedHigh = CoinMin(impliedHigh,utprime) ;
	}
      } else {
	if (rloi > -large) {
	  if (!infUi) {
	    assert(lt > -large) ;
	    utprime = lt+(rloi-maxUi)/ait ;
	    if (fabs(maxUi) > 1.0e8 && !singletonCol)
	      utprime += 1.0e-12*fabs(maxUi) ;
	  } else if (infUi == 1 && lt < -large) {
	    utprime = (rloi-maxUi)/ait ;
	    if (fabs(maxUi) > 1.0e8 && !singletonCol)
	      utprime += 1.0e-12*fabs(maxUi) ;
	  } else {
	    utprime = COIN_DBL_MAX ;
	  }
	  impliedHigh = CoinMin(impliedHigh,utprime) ;
	}
	if (rupi < large) {
	  if (!infLi) {
	    assert(ut < large) ;
	    ltprime = ut+(rupi-maxLi)/ait ;
	    if (fabs(maxLi) > 1.0e8 && !singletonCol)
	      ltprime -= 1.0e-12*fabs(maxLi) ;
	  } else if (infLi == 1 && ut > large) {
	    ltprime = (rupi-maxLi)/ait ;
	    if (fabs(maxLi) > 1.0e8 && !singletonCol)
	      ltprime -= 1.0e-12*fabs(maxLi) ;
	  } else {
	    ltprime = -COIN_DBL_MAX ;
	  }
	  impliedLow = CoinMax(impliedLow,ltprime) ;
	}
      }
#     if PRESOLVE_DEBUG > 2
      std::cout
        << "    row(" << i << ") l'(" << tgtcol << ") " << ltprime
	<< ", u'(" << tgtcol << ") " << utprime ;
      if (lt <= impliedLow && impliedHigh <= ut)
	std::cout << "; implied free satisfied" ;
      std::cout << "." << std::endl ;
#     endif
/*
  For x(t) integral, see if a substitution formula based on row i will
  preserve integrality.  The final check in this clause aims to preserve
  SOS equalities (i.e., don't eliminate a non-trivial SOS equality from
  the system using this transform).

  Note that this can't be folded into the L(i)/U(i) loop because the answer
  changes with x(t).

  Original comment: can only accept if good looking row
*/
      if (integerType[tgtcol]) {
	possibleRow = true ;
	bool allOnes = true ;
	for (CoinBigIndex krow = krs ; krow < kre ; ++krow) {
	  const int j = colIndices[krow] ;
	  const double scaled_aij = rowCoeffs[krow]/ait ;
	  if (fabs(scaled_aij) != 1.0)
	    allOnes = false ;
	  if (!integerType[j] ||
	      fabs(scaled_aij-floor(scaled_aij+0.5)) > feasTol) {
	    possibleRow = false ;
	    break ;
	  }
	}
	if (rloi == 1.0 && leni >= 5 && stopSomeStuff && allOnes)
	  possibleRow = false ;
	rowiOK = rowiOK && possibleRow ;
      }
/*
  Do we have a winner? If we have an incumbent, prefer the one with fewer
  coefficients.
*/
      if (rowiOK) {
	if (subst_ndx < 0 || (leni < subst_len)) {
#         if PRESOLVE_DEBUG > 2
          std::cout
	    << "    row(" << i << ") now candidate for x(" << tgtcol << ")."
	    << std::endl ;
#         endif
	  subst_ndx = i ;
	  subst_len = leni ;
	}
      }
    }

    if (infeas) break ;
/*
  Can we do the transform? If so, subst_ndx will have a valid row.
  Record the implied free variable and the equality we'll use to substitute
  it out. Take the row out of the running --- we can't use the same row
  for two substitutions.
*/
    if (lt <= impliedLow && impliedHigh <= ut &&
        (subst_ndx >= 0 || singletonRow)) {
      implied_free[numberFree] = subst_ndx ;
      infiniteUp[subst_ndx] = -4 ;
      whichFree[numberFree++] = tgtcol ;
#     if PRESOLVE_DEBUG > 1
      std::cout
        << "  x(" << tgtcol << ") implied free by row " << subst_ndx
	<< std::endl ;
#     endif
    }
  }

  delete[] infiniteDown ;
  delete[] infiniteUp ;
  delete[] maxDown ;
  delete[] maxUp ;

/*
  If we're infeasible, there's nothing more to be done.
*/
  if (infeas) {
#   if PRESOLVE_SUMMARY > 0 || PRESOLVE_DEBUG > 0
    std::cout << "  IMPLIED_FREE: infeasible." << std::endl ;
#   endif
    return (next) ;
  }

/*
  We have a list of implied free variables, each with a row that can be used
  to substitute the variable to singleton status if the variable is not a
  natural singleton. The loop here will only process natural singletons.
  We'll hand the remainder to subst_constraint_action below, if there is
  a remainder.

  The natural singletons processed here are compressed out of whichFree and
  implied_free.
*/
  int unprocessed = 0 ;
  for (iLook = 0 ; iLook < numberFree ; iLook++) {
    const int tgtcol = whichFree[iLook] ;
    
    if (colLengths[tgtcol] != 1) {
      whichFree[unprocessed] = whichFree[iLook] ;
      implied_free[unprocessed] = implied_free[iLook] ;
      unprocessed++ ;
      continue ;
    }
    
    const int tgtrow = implied_free[iLook] ;
    const int tgtrow_len = rowLengths[tgtrow] ;

    const CoinBigIndex kcs = colStarts[tgtcol] ;
    const double tgtcol_coeff = colCoeffs[kcs] ;
    const double tgtcol_cost = cost[tgtcol] ;

    const CoinBigIndex krs = rowStarts[tgtrow] ;
    const CoinBigIndex kre = krs+tgtrow_len ;
    if (tgtcol_cost != 0.0) {
      // Check costs don't make unstable
      //double minOldCost=COIN_DBL_MAX;
      double maxOldCost=0.0;
      //double minNewCost=COIN_DBL_MAX;
      double maxNewCost=0.0;
      for (CoinBigIndex krow = krs ; krow < kre ; krow++) {
	const int j = colIndices[krow] ;
	if (j != tgtcol) {
	  double oldCost = cost[j] ;
	  double newCost = oldCost - (tgtcol_cost*rowCoeffs[krow])/tgtcol_coeff ;
	  oldCost = fabs(oldCost);
	  newCost = fabs(newCost);
	  //minOldCost=CoinMin(minOldCost,oldCost);
	  maxOldCost=CoinMax(maxOldCost,oldCost);
	  //minNewCost=CoinMin(minNewCost,newCost);
	  maxNewCost=CoinMax(maxNewCost,newCost);
	}
      }
      if (maxNewCost>1000.0*(maxOldCost+1.0) && maxOldCost) {
	//printf("too big %d tgtcost %g maxOld %g maxNew %g\n",
	//   tgtcol,tgtcol_cost,maxOldCost,maxNewCost);
	continue;
      }
    }
/*
  Initialise the postsolve action. We need to remember the row and column.
*/
    action *s = &actions[nactions++] ;
    s->row = tgtrow ;
    s->col = tgtcol ;
    s->clo = clo[tgtcol] ;
    s->cup = cup[tgtcol] ;
    s->rlo = rlo[tgtrow] ;
    s->rup = rup[tgtrow] ;
    s->ninrow = tgtrow_len ;
    s->rowels = presolve_dupmajor(rowCoeffs,colIndices,tgtrow_len,krs) ;
    s->costs = NULL ;
/*
  We're processing a singleton, hence no substitutions in the matrix, but we
  do need to fix up the cost vector. The substitution formula is
    x(t) = (rhs(i) - SUM{j\t}a(ik)x(k))/a(it)
  hence
    c'(k) = c(k)-c(t)a(ik)/a(it)
  and there's a constant offset
    c(t)rhs(i)/a(it).
  where rhs(i) is one of blow(i) or b(i).

  For general constraints where blow(i) != b(i), we need to take a bit
  of care. If only one of blow(i) or b(i) is finite, that's the one to
  use. Where we have two finite but unequal bounds, choose the bound that
  will result in the most favourable value for x(t). For minimisation, if
  c(t) < 0 we want to maximise x(t), so choose b(i) if a(it) > 0, blow(i)
  if a(it) < 0.  A bit of case analysis says choose b(i) when c(t)a(it) <
  0, blow(i) when c(t)a(it) > 0. We shouldn't be here if both row bounds
  are infinite.

  Fortunately, the objective coefficients are not affected by this.
*/
    if (tgtcol_cost != 0.0) {
      double tgtrow_rhs = rup[tgtrow] ;
      if (fabs(rlo[tgtrow]-rup[tgtrow]) > feasTol) {
	const double rlot = rlo[tgtrow] ;
	const double rupt = rup[tgtrow] ;
        if (rlot > -COIN_DBL_MAX && rupt < COIN_DBL_MAX) {
	  if ((tgtcol_cost*tgtcol_coeff) > 0)
	    tgtrow_rhs = rlot ;
	  else
	    tgtrow_rhs = rupt ;
	} else if (rupt >= COIN_DBL_MAX) {
	  tgtrow_rhs = rlot ;
	}
      }
      assert(fabs(tgtrow_rhs) <= large) ;
      double *save_costs = new double[tgtrow_len] ;

      for (CoinBigIndex krow = krs ; krow < kre ; krow++) {
	const int j = colIndices[krow] ;
	save_costs[krow-krs] = cost[j] ;
	cost[j] -= (tgtcol_cost*rowCoeffs[krow])/tgtcol_coeff ;
      }
      prob->change_bias((tgtcol_cost*tgtrow_rhs)/tgtcol_coeff) ;
      cost[tgtcol] = 0.0 ;
      s->costs = save_costs ;
    }
/*
  Remove the row from the column-major representation, queuing up each column
  for reconsideration. Then remove the row from the row-major representation.
*/
    for (CoinBigIndex krow = krs ; krow < kre ; krow++) {
      const int j = colIndices[krow] ;
      presolve_delete_from_col(tgtrow,j,colStarts,colLengths,rowIndices,
      			       colCoeffs) ;
      if (colLengths[j] == 0) {
        PRESOLVE_REMOVE_LINK(prob->clink_,j) ;
      } else {
	prob->addCol(j) ;
      }
    }
    PRESOLVE_REMOVE_LINK(clink,tgtcol) ;
    colLengths[tgtcol] = 0 ;

    PRESOLVE_REMOVE_LINK(rlink,tgtrow) ;
    rowLengths[tgtrow] = 0 ;
    rlo[tgtrow] = 0.0 ;
    rup[tgtrow] = 0.0 ;
  }
/*
  We're done with the natural singletons. Trim actions to length and create
  the postsolve object.
*/
  if (nactions) {
#   if PRESOLVE_SUMMARY > 0 || PRESOLVE_DEBUG > 0
    printf("NIMPLIED FREE:  %d\n", nactions) ;
#   endif
    action *actions1 = new action[nactions] ;
    CoinMemcpyN(actions, nactions, actions1) ;
    next = new implied_free_action(nactions,actions1,next) ;
  } 
  delete [] actions ;
# if PRESOLVE_DEBUG > 0
  std::cout
    << "  IMPLIED_FREE: identified " << numberFree
    << " implied free transforms, processed " << numberFree-unprocessed
    << " natural singletons." << std::endl ;
# endif

/*
  Now take a stab at the columns that aren't natural singletons, if there are
  any left.
*/
  if (unprocessed != 0) {
    // if not integer - don't allow much fill
    if (!prob->anyInteger())
    {
      int numberFree=unprocessed;
      int nBad=0;
      unprocessed=0;
      // Take out ones that make much denser or might lead to instability
      /*
	Unpack the row- and column-major representations.
      */
      CoinBigIndex *rowStarts = prob->mrstrt_ ;
      int *rowLengths = prob->hinrow_ ;
      double *rowCoeffs = prob->rowels_ ;
      int *colIndices = prob->hcol_ ;
      
      CoinBigIndex *colStarts = prob->mcstrt_ ;
      int *colLengths = prob->hincol_ ;
      double *colCoeffs = prob->colels_ ;
      int *rowIndices = prob->hrow_ ;
      
      /*
	This array is used to hold the indices of columns involved in substitutions,
	where we have the potential for cancellation. At the end they'll be
	checked to eliminate any actual zeros that may result.
	
	NOTE that usefulColumnInt_ is already in use for parameters implied_free and
	whichFree when this routine is called from implied_free.
      */
      
      int *rowsUsed = &prob->usefulRowInt_[0] ;
      int nRowsUsed = 0 ;
      /*
	Open a loop to process the (equality r, implied free variable t) pairs
	in whichFree and implied_free.
	
	It can happen that removal of (row, natural singleton) pairs back in
	implied_free will reduce the length of column t. It can also happen
	that previous processing here has resulted in fillin or cancellation. So
	check again for column length and exclude natural singletons and overly
	dense columns.
      */
      for (int iLook = 0 ; iLook < numberFree ; iLook++) {
	const int tgtcol = whichFree[iLook] ;
	const int tgtrow = implied_free[iLook] ;
	
	if (colLengths[tgtcol] < 2 || colLengths[tgtcol] > maxLook) {
#     if PRESOLVE_DEBUG > 3
	  std::cout
	    << "    skipping eqn " << tgtrow << " x(" << tgtcol
	    << "); length now " << colLengths[tgtcol] << "." << std::endl ;
#     endif
	  continue ;
	}
	
	CoinBigIndex tgtcs = colStarts[tgtcol] ;
	CoinBigIndex tgtce = tgtcs+colLengths[tgtcol] ;
	/*
	  A few checks to make sure that the candidate pair is still suitable.
	  Processing candidates earlier in the list can eliminate coefficients.
	  * Don't use this pair if any involved row i has become a row singleton
	  or empty.
	  * Don't use this pair if any involved row has been modified as part of
	  the processing for a previous candidate pair on this call.
	  * Don't use this pair if a(i,tgtcol) has become zero.
	  
	  The checks on a(i,tgtcol) seem superfluous but it's possible that
	  implied_free identified two candidate pairs to eliminate the same column. If
	  we've already processed one of them, we could be in trouble.
	*/
	double tgtcoeff = 0.0 ;
	bool dealBreaker = false ;
	for (CoinBigIndex kcol = tgtcs ; kcol < tgtce ; ++kcol) {
	  const int i = rowIndices[kcol] ;
	  if (rowLengths[i] < 2 || prob->rowUsed(i)) {
	    dealBreaker = true ;
	    break ;
	  }
	  const double aij = colCoeffs[kcol] ;
	  if (fabs(aij) <= ZTOLDP2) {
	    dealBreaker = true ;
	    break ;
	  }
	  if (i == tgtrow) tgtcoeff = aij ;
	}
	
	if (dealBreaker == true) {
#     if PRESOLVE_DEBUG > 3
	  std::cout
	    << "    skipping eqn " << tgtrow << " x(" << tgtcol
	    << "); deal breaker (1)." << std::endl ;
#     endif
	  continue ;
	}
	/*
	  Check for numerical stability.A large coeff_factor will inflate the
	  coefficients in the substitution formula.
	*/
	dealBreaker = false ;
	for (CoinBigIndex kcol = tgtcs ; kcol < tgtce ; ++kcol) {
	  const double coeff_factor = fabs(colCoeffs[kcol]/tgtcoeff) ;
	  if (coeff_factor > 10.0)
	    dealBreaker = true ;
	}
	if (dealBreaker == true) {
#     if PRESOLVE_DEBUG > 3
	  std::cout
	    << "    skipping eqn " << tgtrow << " x(" << tgtcol
	    << "); deal breaker (2)." << std::endl ;
#     endif
	  continue ;
	}
	/*
	  Count up the total number of coefficients in entangled rows and mark them as
	  contaminated.
	*/
	int ntotels = 0 ;
	for (CoinBigIndex kcol = tgtcs ; kcol < tgtce ; ++kcol) {
	  const int i = rowIndices[kcol] ;
	  ntotels += rowLengths[i] ;
	  PRESOLVEASSERT(!prob->rowUsed(i)) ;
	  prob->setRowUsed(i) ;
	  rowsUsed[nRowsUsed++] = i ;
	}
	
	CoinBigIndex tgtrs = rowStarts[tgtrow] ;
	CoinBigIndex tgtre = tgtrs+rowLengths[tgtrow] ;
	
	// kill small if wanted
	int relax= (prob->presolveOptions()&0x60000)>>17;
	double tolerance = 1.0e-12;
	for (int i=0;i<relax;i++)
	  tolerance *= 10.0;
	
	/*
	  Sort the target row for efficiency
	*/
	CoinSort_2(colIndices+tgtrs,colIndices+tgtre,rowCoeffs+tgtrs) ;
	CoinBigIndex start=colStarts[tgtcol];
	CoinBigIndex end = start+colLengths[tgtcol];
	numberBadElements=0;
	int numberFill=-rowLengths[tgtrow];
	for (int colndx = start ; colndx < end ; ++colndx) {
	  int i = rowIndices[colndx] ;
	  if (i == tgtrow) continue ;
	  
	  double ait = colCoeffs[colndx] ;
	  double coeff_factor = -ait/tgtcoeff ;
	  
	  CoinBigIndex krs = rowStarts[i] ;
	  CoinBigIndex kre = krs+rowLengths[i] ;
	  /*
	    Sort the row for efficiency and call add_row to do the actual business of
	    changing coefficients due to substitution. This has the potential to trigger
	    compaction of the row-major bulk store, so update bulk store indices.
	  */
	  CoinSort_2(colIndices+krs,colIndices+kre,rowCoeffs+krs) ;
	  
	  numberFill += check_row(rowStarts,rowCoeffs,colIndices,
				  rowLengths,coeff_factor,tolerance,i,tgtrow);
	}
	if (numberBadElements||3*numberFill>2*(colLengths[tgtcol]+rowLengths[tgtrow])) {
	  //printf("Bad subst col %d row %d - %d small elements, fill %d\n",
	  //	 tgtcol,tgtrow,numberBadElements,numberFill);
	  if (numberBadElements)
	    nBad++;
	} else {
	  whichFree[unprocessed]=tgtcol;
	  implied_free[unprocessed++]=tgtrow;
	  //printf("Good subst col %d row %d - fill %d\n",
	  //	 tgtcol,tgtrow,numberFill);
	}
      }
      /*
	That's it, we've processed all the candidate pairs.
	
	Clear the row used flags.
      */
      for (int i = 0 ; i < nRowsUsed ; i++) prob->unsetRowUsed(rowsUsed[i]) ;
#if CLP_USEFUL_PRINTOUT
      printf("%d allowed through out of %d - %d on coefficient\n",
	     unprocessed,numberFree,nBad);
#endif      
    }
    next = subst_constraint_action::presolve(prob,implied_free,whichFree,
    					     unprocessed,next,maxLook) ;
  }
/*
  Give some feedback to the presolve driver. If we aren't finding enough
  candidates and haven't reached the limit, bump fill_level and return a
  negated value. The presolve driver can tweak this value or simply return
  it on the next call. See the top of the routine for a full explanation.
*/
  if (numberFree < 30 && maxLook < prob->maxSubstLevel_) {
    fill_level = -(maxLook+1) ;
  } else {
    fill_level = maxLook ;
  }

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

  return (next) ;
}
Пример #18
0
static int outDupsEtc(int numberIntegers, int & numberCliques, int & numberMatrixCliques,
		      int * & cliqueStart, char * & cliqueType, CliqueEntry *& entry, 
		      int numberLastTime, int printit)
{
  bool allNew=false;
  int * whichP = new int [numberIntegers];
  int iClique;
  assert (sizeof(int)==4);
  assert (sizeof(CliqueEntry)==4);
  // If lots then get rid of short ones
#define KEEP_CLIQUES 10000
  if (numberCliques-numberMatrixCliques>KEEP_CLIQUES) {
    int * sort = new int [numberCliques];
    for (iClique=numberMatrixCliques;iClique<numberCliques;iClique++) {
      int j = cliqueStart[iClique];
      int n = cliqueStart[iClique+1]-j;
      sort[iClique]=n;
    }
    std::sort(sort+numberMatrixCliques,sort+numberCliques);
    int allow = sort[numberCliques-KEEP_CLIQUES];
    int nEqual=0;
    for (iClique=numberCliques-KEEP_CLIQUES;iClique<numberCliques;iClique++) {
      if (sort[iClique]>allow)
	break;
      else
	nEqual++;
    }
    delete [] sort;
    int j=cliqueStart[numberMatrixCliques];
    int put=j;
    int nClique=numberMatrixCliques;
    for (iClique=numberMatrixCliques;iClique<numberCliques;iClique++) {
      int end = cliqueStart[iClique+1];
      int n = end-j;
      bool copy=false;
      if (n>allow) {
	copy=true;
      } else if (n==allow&&nEqual) {
	copy=true;
	nEqual--;
      }
      if (copy) {
	cliqueType[nClique++]=cliqueType[iClique];
	for (;j<end;j++)
	  entry[put++]=entry[j];
      }
      j = cliqueStart[iClique+1];
      cliqueStart[nClique]=put;
    }
    numberCliques = nClique;
  }
  // sort
  for (iClique=0;iClique<numberCliques;iClique++) {
    int j = cliqueStart[iClique];
    int n = cliqueStart[iClique+1]-j;
    for (int i=0;i<n;i++) 
      whichP[i]=sequenceInCliqueEntry(entry[i+j]);
    CoinSort_2(whichP,whichP+n,(reinterpret_cast<int *>(entry))+j);
  }
  // lexicographic sort
  int * which = new int [numberCliques];
  int * position = new int [numberCliques];
  int * sort = new int [numberCliques];
  int * value = new int [numberCliques];
  for (iClique=0;iClique<numberCliques;iClique++) {
    which[iClique]=iClique;
    sort[iClique]=sequenceInCliqueEntry(entry[cliqueStart[iClique]]);
    value[iClique]=sort[iClique];
    position[iClique]=0;
  }
  CoinSort_2(sort,sort+numberCliques,which);
  int lastDone=-1;
  int nDup=0;
  int nSave=0;
  while (lastDone<numberCliques-1) {
    int jClique=lastDone+1;
    int jFirst = jClique;
    int iFirst = which[jFirst];
    int iValue = value[iFirst];
    int iPos = position[iFirst];
    jClique++;
    for (;jClique<numberCliques;jClique++) {
      int kClique = which[jClique];
      int jValue = value[kClique];
      if (jValue>iValue||position[kClique]<iPos)
	break;
    }
    if (jClique==jFirst+1) {
      // done that bit
      lastDone++;
    } else {
      // use next bit to sort and then repeat
      int jLast=jClique;
      for (jClique=jFirst;jClique<jLast;jClique++) {
	int kClique = which[jClique];
	int iValue = value[kClique];
	// put at end if finished
	if (iValue<numberIntegers) {
	  int kPos=position[kClique]+1;
	  position[kClique]=kPos;
	  kPos += cliqueStart[kClique];
	  if (kPos==cliqueStart[kClique+1]) {
	    iValue = numberIntegers;
	  } else {
	    iValue = sequenceInCliqueEntry(entry[kPos]);
	  }
	  value[kClique]=iValue;
	}
	sort[jClique]=iValue;
      }
      CoinSort_2(sort+jFirst,sort+jLast,which+jFirst);
      // if duplicate mark and move on
      int iLowest=numberCliques;
      for (jClique=jFirst;jClique<jLast;jClique++) {
	int kClique = which [jClique];
	int iValue = value[kClique];
	if (iValue<numberIntegers) 
	  break;
	iLowest = CoinMin(iLowest,kClique);
      }
      if (jClique>jFirst) {
	// mark all apart from lowest number as duplicate and move on
	lastDone =jClique-1;
	for (jClique=jFirst;jClique<=lastDone;jClique++) {
	  int kClique = which [jClique];
	  if (kClique!=iLowest) {
	    value[kClique]=-2;
	    nDup++;
	    nSave += cliqueStart[kClique+1]-cliqueStart[kClique];
	  }
	}
      }
    }
  }
  if (printit)
    printf("%d duplicates\n",nDup);
  // Now see if any subset
  int nOut=0;
  for (int jClique=0;jClique<numberCliques;jClique++) {
    if (value[jClique]!=-2) {
      position[jClique]=cliqueStart[jClique];
      value[jClique]=sequenceInCliqueEntry(entry[cliqueStart[jClique]]);
    }
  }
  nSave=0;
  int startLooking=0;
  for (int jClique=0;jClique<numberCliques;jClique++) {
    int kClique = which[jClique];
    if (value[kClique]==-2) {
      nOut++;
      nSave += cliqueStart[kClique+1]-cliqueStart[kClique];
      if (jClique==startLooking)
	startLooking++;
      continue;
    }
    int kValue =value[kClique];
    for (int iiClique=startLooking;iiClique<jClique;iiClique++) {
      int iClique = which[iiClique];
      int iValue = value[iClique];
      if (iValue==-2||iValue==numberIntegers) {
	if (iiClique==startLooking)
	  startLooking++;
	continue;
      } else {
	if (kValue>static_cast<int> (sequenceInCliqueEntry(entry[cliqueStart[iClique+1]-1]))) {
	  value[iClique]=numberIntegers;
	  continue;
	}
      }
      if (iValue<kValue) {
	while (iValue<kValue) {
	  int iPos=position[iClique]+1;
	  position[iClique]=iPos;
	  if (iPos==cliqueStart[iClique+1]) {
	    iValue = numberIntegers;
	  } else {
	    iValue = sequenceInCliqueEntry(entry[iPos]);
	  }
	  value[iClique]=iValue;
	}
      } 
      if (iValue>kValue) 
	continue; // not a candidate
      // See if subset (remember duplicates have gone)
      if (cliqueStart[iClique+1]-position[iClique]>
	  cliqueStart[kClique+1]-cliqueStart[kClique]) {
	// could be subset ?
	int offset = cliqueStart[iClique]-position[kClique];
	int j;
	bool subset=true;
	// what about different fixes bool odd=false;
	for (j=cliqueStart[kClique]+1;j<cliqueStart[kClique+1];j++) {
	  int kColumn = sequenceInCliqueEntry(entry[j]);
	  int iColumn = sequenceInCliqueEntry(entry[j+offset]);
	  if (iColumn>kColumn) {
	    subset=false;
	  } else {
	    while (iColumn<kColumn) {
	      offset++;
	      if (j+offset<cliqueStart[iClique+1]) {
		iColumn = sequenceInCliqueEntry(entry[j+offset]);
	      } else {
		subset=false;
		break;
	      }
	    }
	  }
	  if (!subset)
	    break;
	}
	if (subset) {
	  value[kClique]=-2;
	  if (printit>1)
	    printf("clique %d is subset of %d\n",kClique,iClique);
	  nOut++;
	  break;
	}
      }
    }
  }
  if (nOut) {
    if(printit) 
      printf("Can get rid of %d cliques\n",nOut);
    // make new copy
    int nNewC=numberCliques-nOut;
    int size = cliqueStart[numberCliques]-nSave;
    int n=0;
    int * start = new int [nNewC+1];
    char * type = new char [nNewC];
    start[0]=0;
    CliqueEntry * entryC = new CliqueEntry [size];
    int nel=0;
    allNew = true;
    for (int jClique=0;jClique<numberCliques;jClique++) {
      int kClique = which[jClique];
      if (value[kClique]!=-2&&kClique<numberMatrixCliques) {
	if (kClique>=numberLastTime)
	  allNew=false;
	int nn=cliqueStart[kClique+1]-cliqueStart[kClique];
	memcpy(entryC+nel,entry+cliqueStart[kClique],nn*sizeof(CliqueEntry));
	nel += nn;
	type[n++]=cliqueType[kClique];
	start[n]=nel;
      }
    }
    int nM=n;
    for (int jClique=0;jClique<numberCliques;jClique++) {
      int kClique = which[jClique];
      if (value[kClique]!=-2&&kClique>=numberMatrixCliques) {
	if (kClique>=numberLastTime)
	  allNew=false;
	int nn=cliqueStart[kClique+1]-cliqueStart[kClique];
	memcpy(entryC+nel,entry+cliqueStart[kClique],nn*sizeof(CliqueEntry));
	nel += nn;
	type[n++]=cliqueType[kClique];
	start[n]=nel;
      }
    }
    // move
    numberCliques=n;
    numberMatrixCliques=nM;
    delete [] cliqueStart;
    cliqueStart=start;
    delete [] entry;
    entry = entryC;
    delete [] cliqueType;
    cliqueType = type;
    if (printit>1) {
      for (int jClique=0;jClique<numberCliques;jClique++) {
	printf("%d [ ",jClique);
	for (int i=cliqueStart[jClique];i<cliqueStart[jClique+1];i++)
	  printf("%d(%d) ",sequenceInCliqueEntry(entry[i]),oneFixesInCliqueEntry(entry[i]));
	printf("]\n");
      }
    }
    if (printit)
      printf("%d matrix cliques and %d found by probing\n",numberMatrixCliques,numberCliques-numberMatrixCliques);
  }
  delete [] value;
  delete [] sort;
  delete [] which;
  delete [] position;
  delete [] whichP;
  if (!allNew)
    return nOut;
  else
    return -1;
}
Пример #19
0
void
CglClique::find_rcl(OsiCuts& cs)
{
   const int nodenum = fgraph.nodenum;
   const fnode *nodes = fgraph.nodes;

   /* A flag for each column that might be used to extend the current row
      clique */
   bool *cand = new bool[nodenum];
   /* In cl_indices we'll list the indices of the 'true' entries in cand */
   /* The degree of each candidate (those listed in cl_indices) */
   int *degrees = new int[nodenum];

   /** An array used in the recursive complete enumeration of maximal cliques.
       The first cl_length entries are used. */
   bool* label = new bool[nodenum];

   int i, j, k;

   /* initialize global variables */
   cl_del_length = 0;
   cl_length = 0;

   int clique_count = 0;
   int largest_length = 0;

   /* for each row of the matrix */
   for (j = 0; j < sp_numrows; j++) {

      /* if the row is of zero length, take the next row */
      const int len = sp_row_start[j+1] - sp_row_start[j];
      if (!len)
	 continue;

      /* the beginning of the row to be considered */
      const int *row = sp_row_ind + sp_row_start[j];

      /* copy the row of node_node corresponding to the first column in 'row'
	 into cand, and take the AND of this vector with every row of
	 node_node corresponding to the rest of the columns in 'row' to
	 determine those columns that are non-orthog to every column in row */
      std::copy(node_node + row[0]*nodenum, node_node + (row[0]+1)*nodenum,
		cand);
      for (i = 1; i < len; i++) {
	 const bool* node_node_col = node_node + row[i] * nodenum;
	 for (k = 0; k < nodenum; k++)
	    cand[k] &= node_node_col[k];
      }
      cl_length = 0;
      for (k = 0; k < nodenum; k++)
	 if (cand[k])
	    cl_indices[cl_length++] = k;
      largest_length = CoinMax(cl_length, largest_length);

      /* if there is anything in indices, enumerate (or greedily find)
	 maximal cliques */
      if (cl_length > 0) {
	 cl_perm_length = len;
	 cl_perm_indices = row;
	 if (cl_length <= rcl_candidate_length_threshold) {
	    for (i = 0; i < cl_length; i++)
	       label[i] = false;
	    int pos = 0;
	    clique_count += enumerate_maximal_cliques(pos, label, cs);
	 } else {
	    /* order cl_indices into decreasing order of their degrees */
	    for (i = 0; i < cl_length; i++)
	       degrees[i] = nodes[cl_indices[i]].degree;
	    CoinSort_2(degrees, degrees + cl_length, cl_indices,
		       CoinFirstGreater_2<int,int>());
	    clique_count += greedy_maximal_clique(cs);
	 }
      }
   }

   if (rcl_report_result) {
      printf("\nrcl Found %i new violated cliques with the row-clique method",
	     clique_count);
      printf("\nrcl The largest admissible number was %i (threshold %i)\n",
	     largest_length, rcl_candidate_length_threshold);
      if (largest_length < rcl_candidate_length_threshold)
	 printf("rcl    all row cliques have been enumerated\n");
      else
	 printf("rcl    not all row cliques have been eliminated\n");
   }

   delete[] degrees;
   delete[] cand;
   delete[] label;
}
Пример #20
0
OsiSolverInterface *
CglTreeProbingInfo::analyze(const OsiSolverInterface & si,int createSolver,
			    int numberExtraCliques,const int * starts,
			    const CliqueEntry * entries,const char * type)
{
  if (!createSolver)
    return NULL;
  convert();
  if (!numberIntegers_)
    return NULL;
  bool alwaysDo=false;
  if (numberExtraCliques<0) {
    alwaysDo=true;
    numberExtraCliques=0;
  }
  bool printit=false;
  int numberCliques=0;
  int numberEntries=0;
  int * cliqueStart = NULL;
  CliqueEntry * entry = NULL;
  char * cliqueType=NULL;
  int * whichP = new int [numberIntegers_];
  int * whichM = new int [numberIntegers_];
  int *whichClique=NULL;
  int numberRows=si.getNumRows(); 
  int numberMatrixCliques=0;
  const CoinPackedMatrix * rowCopy = si.getMatrixByRow();
  assert(numberRows&&si.getNumCols());
  int iRow;
  const int * column = rowCopy->getIndices();
  const double * elementByRow = rowCopy->getElements();
  const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
  const int * rowLength = rowCopy->getVectorLengths(); 
  const double * lower = si.getColLower();
  const double * upper = si.getColUpper();
  const double * rowLower = si.getRowLower();
  const double * rowUpper = si.getRowUpper();
  for (int iPass=0;iPass<2;iPass++) {
    if (iPass) {
      int numberExtraEntries=0;
      if (numberExtraCliques) 
	numberExtraEntries = starts[numberExtraCliques];
      cliqueStart = new int [numberCliques+1+numberExtraCliques];
      cliqueStart[0]=0;
      entry = new CliqueEntry [numberEntries+numberExtraEntries];
      cliqueType = new char [numberCliques+numberExtraCliques];
      whichClique = new int [numberEntries+numberExtraEntries];
      numberCliques=0;
      numberEntries=0;
    }
#if 1
    for (iRow=0;iRow<numberRows;iRow++) {
      int numberP1=0, numberM1=0;
      int numberTotal=0;
      CoinBigIndex j;
      double upperValue=rowUpper[iRow];
      double lowerValue=rowLower[iRow];
      bool good=true;
      for (j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) {
	int iColumn = column[j];
	double value = elementByRow[j];
	if (upper[iColumn]-lower[iColumn]<1.0e-8) {
	  // fixed
	  upperValue -= lower[iColumn]*value;
	  lowerValue -= lower[iColumn]*value;
	  continue;
	} else if (backward_[iColumn]<0) {
	  good = false;
	  break;
	} else {
	  iColumn = backward_[iColumn];
	  numberTotal++;
	}
	if (fabs(value)!=1.0) {
	  good=false;
	} else if (value>0.0) {
	  assert (numberP1<numberIntegers_);
	  whichP[numberP1++]=iColumn;;
	} else {
	  assert (numberM1<numberIntegers_);
	  whichM[numberM1++]=iColumn;
	}
      }
      int iUpper = static_cast<int> (floor(upperValue+1.0e-5));
      int iLower = static_cast<int> (ceil(lowerValue-1.0e-5));
      int state=0;
      if (upperValue<1.0e6) {
	if (iUpper==1-numberM1)
	  state=1;
	else if (iUpper==-numberM1)
	  state=2;
	else if (iUpper<-numberM1)
	  state=3;
	if (fabs(static_cast<double> (iUpper)-upperValue)>1.0e-9)
	  state =-1;
      }
      if (!state&&lowerValue>-1.0e6) {
	if (-iLower==1-numberP1)
	  state=-1;
	else if (-iLower==-numberP1)
	  state=-2;
	else if (-iLower<-numberP1)
	  state=-3;
	if (fabs(static_cast<double> (iLower)-lowerValue)>1.0e-9)
	  state =-1;
      }
      if (numberP1+numberM1<2)
	state=-1;
      if (good&&state>0) {
	if (abs(state)==3) {
	  // infeasible
	  printf("FFF Infeasible\n");;
	  //feasible=false;
	  break;
	} else if (abs(state)==2) {
	  // we can fix all
	  //numberFixed += numberP1+numberM1;
	  printf("FFF can fix %d\n",numberP1+numberM1);
	} else {
	  for (j=0;j<numberP1;j++) {
	    int iColumn = whichP[j];
	    if (iPass) {
	      CliqueEntry temp;
	      setOneFixesInCliqueEntry(temp,true);
	      setSequenceInCliqueEntry(temp,iColumn);
	      entry[numberEntries]=temp;
	    }
	    numberEntries++;
	  }
	  for (j=0;j<numberM1;j++) {
	    int iColumn = whichM[j];
	    if (iPass) {
	      CliqueEntry temp;
	      setOneFixesInCliqueEntry(temp,false);
	      setSequenceInCliqueEntry(temp,iColumn);
	      entry[numberEntries]=temp;
	    }
	    numberEntries++;
	  }
	  if (iPass) {
	    if (iLower!=iUpper) {
	      // slack
	      cliqueType[numberCliques]='S';
	    } else {
	      cliqueType[numberCliques]='E';
	    }
	    cliqueStart[numberCliques+1]=numberEntries;
	  }
	  numberCliques++;
	}
      }
    }
#endif
    if (numberExtraCliques) {
      int numberExtraEntries = starts[numberExtraCliques];
      memcpy(entry+numberEntries,entries,numberExtraEntries*sizeof(CliqueEntry));
      for (int iClique=0;iClique<numberExtraCliques;iClique++) {
	cliqueType[numberCliques] = type[iClique];
	numberCliques++;
	cliqueStart[numberCliques]=starts[iClique]+numberEntries;
      }
      numberEntries += numberExtraEntries;
    }
    numberMatrixCliques=numberCliques;
    //int size = toZero_[numberIntegers_];
    //char * used = new char [size];
    //memset(used,0,size);
    // find two cliques
    int nFix=0;
    for (int iColumn=0;iColumn<static_cast<int> (numberIntegers_);iColumn++) {
      int j;
      for ( j=toZero_[iColumn];j<toOne_[iColumn];j++) {
	int jColumn=sequenceInCliqueEntry(fixEntry_[j]);
	// just look at ones beore (this also skips non 0-1)
	if (jColumn<iColumn) {
	  int k;
	  for ( k=toZero_[jColumn];k<toOne_[jColumn];k++) {
	    if (sequenceInCliqueEntry(fixEntry_[k])== (iColumn)) {
	      if (oneFixesInCliqueEntry(fixEntry_[j])) {
		if (oneFixesInCliqueEntry(fixEntry_[k])) {
		  if (printit&&!iPass)
		    printf("%d to zero implies %d to one and %d to zero implies %d to one\n",
			   iColumn,jColumn,jColumn,iColumn);
		  //0-0 illegal
		  if (iPass) {
		    CliqueEntry temp;
		    setOneFixesInCliqueEntry(temp,false);
		    setSequenceInCliqueEntry(temp,iColumn);
		    entry[numberEntries]=temp;
		  }
		  numberEntries++;
		  if (iPass) {
		    CliqueEntry temp;
		    setOneFixesInCliqueEntry(temp,false);
		    setSequenceInCliqueEntry(temp,jColumn);
		    entry[numberEntries]=temp;
		  }
		  numberEntries++;
		  if (iPass) {
		    // slack
		    cliqueType[numberCliques]='S';
		    cliqueStart[numberCliques+1]=numberEntries;
		  }
		  numberCliques++;
		} else {
		  if (printit&&!iPass)
		    printf("%d to zero implies %d to one and %d to zero implies %d to zero\n",
			   iColumn,jColumn,jColumn,iColumn);
		  nFix++; // jColumn is 1
		}
	      } else {
		if (oneFixesInCliqueEntry(fixEntry_[k])) {
		  if (printit&&!iPass)
		    printf("%d to zero implies %d to zero and %d to zero implies %d to one\n",
			   iColumn,jColumn,jColumn,iColumn);
		  nFix++; // iColumn is 1
		} else {
		  if (printit&&!iPass)
		    printf("%d to zero implies %d to zero and %d to zero implies %d to zero\n",
			   iColumn,jColumn,jColumn,iColumn);
		  nFix++; // jColumn=iColumn
		}
	      }
	    }
	  }
	  for ( k=toOne_[jColumn];k<toZero_[jColumn+1];k++) {
	    if (sequenceInCliqueEntry(fixEntry_[k])== (iColumn)) {
	      if (oneFixesInCliqueEntry(fixEntry_[j])) {
		if (oneFixesInCliqueEntry(fixEntry_[k])) {
		  if (printit&&!iPass)
		    printf("%d to zero implies %d to one and %d to one implies %d to one\n",
			   iColumn,jColumn,jColumn,iColumn);
		  nFix++; //iColumn is 1
		} else {
		  if (printit&&!iPass)
		    printf("%d to zero implies %d to one and %d to one implies %d to zero\n",
			   iColumn,jColumn,jColumn,iColumn);
		  nFix++; // iColumn+jcolumn=1
		}
	      } else {
		if (oneFixesInCliqueEntry(fixEntry_[k])) {
		  if (printit&&!iPass)
		    printf("%d to zero implies %d to zero and %d to one implies %d to one\n",
			   iColumn,jColumn,jColumn,iColumn);
		  // 0-1 illegal
		  if (iPass) {
		    CliqueEntry temp;
		    setOneFixesInCliqueEntry(temp,false);
		    setSequenceInCliqueEntry(temp,iColumn);
		    entry[numberEntries]=temp;
		  }
		  numberEntries++;
		  if (iPass) {
		    CliqueEntry temp;
		    setOneFixesInCliqueEntry(temp,true);
		    setSequenceInCliqueEntry(temp,jColumn);
		    entry[numberEntries]=temp;
		  }
		  numberEntries++;
		  if (iPass) {
		    // slack
		    cliqueType[numberCliques]='S';
		    cliqueStart[numberCliques+1]=numberEntries;
		  }
		  numberCliques++;
		} else {
		  if (printit&&!iPass)
		    printf("%d to zero implies %d to zero and %d to one implies %d to zero\n",
			   iColumn,jColumn,jColumn,iColumn);
		  nFix++; // jColumn is 0
		}
	      }
	    }
	  }
	}
      }
      for ( j=toOne_[iColumn];j<toZero_[iColumn+1];j++) {
	int jColumn=sequenceInCliqueEntry(fixEntry_[j]);
	if (jColumn<iColumn) {
	  int k;
	  for ( k=toZero_[jColumn];k<toOne_[jColumn];k++) {
	    if (sequenceInCliqueEntry(fixEntry_[k])== (iColumn)) {
	      if (oneFixesInCliqueEntry(fixEntry_[j])) {
		if (oneFixesInCliqueEntry(fixEntry_[k])) {
		  if (printit&&!iPass)
		    printf("%d to one implies %d to one and %d to zero implies %d to one\n",
			   iColumn,jColumn,jColumn,iColumn);
		  nFix++; // jColumn is 1
		} else {
		  if (printit&&!iPass)
		    printf("%d to one implies %d to one and %d to zero implies %d to zero\n",
			   iColumn,jColumn,jColumn,iColumn);
		  // 1-0 illegal
		  if (iPass) {
		    CliqueEntry temp;
		    setOneFixesInCliqueEntry(temp,true);
		    setSequenceInCliqueEntry(temp,iColumn);
		    entry[numberEntries]=temp;
		  }
		  numberEntries++;
		  if (iPass) {
		    CliqueEntry temp;
		    setOneFixesInCliqueEntry(temp,false);
		    setSequenceInCliqueEntry(temp,jColumn);
		    entry[numberEntries]=temp;
		  }
		  numberEntries++;
		  if (iPass) {
		    // slack
		    cliqueType[numberCliques]='S';
		    cliqueStart[numberCliques+1]=numberEntries;
		  }
		  numberCliques++;
		}
	      } else {
		if (oneFixesInCliqueEntry(fixEntry_[k])) {
		  if (printit&&!iPass)
		    printf("%d to one implies %d to zero and %d to zero implies %d to one\n",
			   iColumn,jColumn,jColumn,iColumn);
		  nFix++; // iColumn+jColumn=1
		} else {
		  if (printit&&!iPass)
		    printf("%d to one implies %d to zero and %d to zero implies %d to zero\n",
			   iColumn,jColumn,jColumn,iColumn);
		  nFix++; // iColumn is 0
		}
	      }
	    }
	  }
	  for ( k=toOne_[jColumn];k<toZero_[jColumn+1];k++) {
	    if (sequenceInCliqueEntry(fixEntry_[k])== (iColumn)) {
	      if (oneFixesInCliqueEntry(fixEntry_[j])) {
		if (oneFixesInCliqueEntry(fixEntry_[k])) {
		  if (printit&&!iPass)
		    printf("%d to one implies %d to one and %d to one implies %d to one\n",
			   iColumn,jColumn,jColumn,iColumn);
		  nFix++; // iColumn == jColumn
		} else {
		  if (printit&&!iPass)
		    printf("%d to one implies %d to one and %d to one implies %d to zero\n",
			   iColumn,jColumn,jColumn,iColumn);
		  nFix++; // iColumn is 0
		}
	      } else {
		if (oneFixesInCliqueEntry(fixEntry_[k])) {
		  if (printit&&!iPass)
		    printf("%d to one implies %d to zero and %d to one implies %d to one\n",
			   iColumn,jColumn,jColumn,iColumn);
		  nFix++; // jColumn is 0
		} else {
		  if (printit&&!iPass)
		    printf("%d to one implies %d to zero and %d to one implies %d to zero\n",
			   iColumn,jColumn,jColumn,iColumn);
		  // 1-1 illegal
		  if (iPass) {
		    CliqueEntry temp;
		    setOneFixesInCliqueEntry(temp,true);
		    setSequenceInCliqueEntry(temp,iColumn);
		    entry[numberEntries]=temp;
		  }
		  numberEntries++;
		  if (iPass) {
		    CliqueEntry temp;
		    setOneFixesInCliqueEntry(temp,true);
		    setSequenceInCliqueEntry(temp,jColumn);
		    entry[numberEntries]=temp;
		  }
		  numberEntries++;
		  if (iPass) {
		    // slack
		    cliqueType[numberCliques]='S';
		    cliqueStart[numberCliques+1]=numberEntries;
		  }
		  numberCliques++;
		}
	      }
	    }
	  }
	}
      }
    }
    if (!iPass)
      printf("%d cliques and %d fixed (%d already from matrix))\n",
	     numberCliques-numberMatrixCliques,nFix,numberMatrixCliques);
  }
  int iClique;
  outDupsEtc(numberIntegers_, numberCliques, numberMatrixCliques,
	     cliqueStart, cliqueType, entry, -1, printit ? 2 : 1);
  printf("%d matrix cliques and %d found by probing\n",numberMatrixCliques,numberCliques-numberMatrixCliques);
  int * zeroStart = new int [numberIntegers_+1];
  int * oneStart = new int [numberIntegers_];
  int * zeroCount = new int [numberIntegers_];
  int * oneCount = new int [numberIntegers_];
  char * mark = new char [numberIntegers_];
  memset(mark,0,numberIntegers_);
  int nStrengthen=-1;
  int iPass=0;
  while (nStrengthen&&iPass<20) {
    iPass++;
    int numberLastTime = numberCliques;
    int * count = new int [numberCliques];
    int i,iColumn;
    for (i=0;i<numberCliques;i++) {
      count[i]=0;
    }
    int * whichCount = new int [numberCliques];
    CoinZeroN(zeroCount,numberIntegers_);
    CoinZeroN(oneCount,numberIntegers_);
    for (iClique=0;iClique<numberCliques;iClique++) {
      for (int j=cliqueStart[iClique];j<cliqueStart[iClique+1];j++) {
	int iColumn = static_cast<int> (sequenceInCliqueEntry(entry[j]));
	if (oneFixesInCliqueEntry(entry[j])) {
	  oneCount[iColumn]++;
	} else {
	  zeroCount[iColumn]++;
	}
      }
    }
    int j;
    zeroStart[0]=0;
    cliqueStart[0]=0;
    for (j=0;j<numberIntegers_;j++) {
      int n;
      n=zeroCount[j];
      zeroCount[j]=0;
      oneStart[j] = zeroStart[j]+n;
      n=oneCount[j];
      oneCount[j]=0;
      zeroStart[j+1] = oneStart[j]+n;
    }
    for (iClique=0;iClique<numberCliques;iClique++) {
      for (int j=cliqueStart[iClique];j<cliqueStart[iClique+1];j++) {
	int iColumn = static_cast<int> (sequenceInCliqueEntry(entry[j]));
	if (oneFixesInCliqueEntry(entry[j])) {
	  int k=oneCount[iColumn];
	  oneCount[iColumn]++;
	  int put = oneStart[iColumn]+k;
	  whichClique[put]=iClique;
	} else {
	  int k=zeroCount[iColumn];
	  zeroCount[iColumn]++;
	  int put = zeroStart[iColumn]+k;
	  whichClique[put]=iClique;
	}
      }
    }
    nStrengthen=0;
    int numberEntries=cliqueStart[numberCliques];
    int maximumEntries=numberEntries;
    int maximumCliques=numberCliques;
    for (iColumn=0;iColumn<numberIntegers_;iColumn++) {
      int i;
      int n;
      int nCount=0;
      n=0;
      for (i=zeroStart[iColumn];i<oneStart[iColumn];i++) {
	int jClique = whichClique[i];
	//if (jClique<numberMatrixCliques) 
	//continue;
	int j = cliqueStart[jClique];
	//assert (cliqueStart[jClique+1]==j+2);
	for (;j<cliqueStart[jClique+1];j++) {
	  CliqueEntry eJ = entry[j];
	  int jColumn = sequenceInCliqueEntry(eJ);
	  if (jColumn>iColumn&&!mark[jColumn]) {
	    mark[jColumn]=1;
	    whichP[n++]=jColumn;
	    assert (n<numberIntegers_);
	    if (oneFixesInCliqueEntry(eJ)) {
	      for (int k=oneStart[jColumn];k<zeroStart[jColumn+1];k++) {
		int jClique = whichClique[k];
		if (!count[jClique]) 
		  whichCount[nCount++]=jClique;
		count[jClique]++;
	      }
	    } else {
	      for (int k=zeroStart[jColumn];k<oneStart[jColumn];k++) {
		int jClique = whichClique[k];
		if (!count[jClique]) 
		  whichCount[nCount++]=jClique;
		count[jClique]++;
	      }
	    }
	  }
	}
      }
      std::sort(whichP,whichP+n);
      for (i=0;i<nCount;i++) {
	int jClique = whichCount[i];
	int jCount = count[jClique];
	count[jClique]=0;
	if (jCount==cliqueStart[jClique+1]-cliqueStart[jClique]) {
	  printf("Zero can extend %d [ ",jClique);
	  for (int i=cliqueStart[jClique];i<cliqueStart[jClique+1];i++)
	    printf("%d(%d) ",sequenceInCliqueEntry(entry[i]),oneFixesInCliqueEntry(entry[i]));
	  printf("] by %d(0)\n",iColumn);
	  nStrengthen++;
	  if (numberEntries+jCount+1>maximumEntries) {
	    maximumEntries = CoinMax(numberEntries+jCount+1,(maximumEntries*12)/10+100);
	    CliqueEntry * temp = new CliqueEntry [maximumEntries];
	    memcpy(temp,entry,numberEntries*sizeof(CliqueEntry));
	    delete [] entry;
	    entry=temp;
	    int * tempI = new int [maximumEntries];
	    memcpy(tempI,whichClique,numberEntries*sizeof(int));
	    delete [] whichClique;
	    whichClique=tempI;
	  }
	  if (numberCliques==maximumCliques) {
	    maximumCliques = (maximumCliques*12)/10+100;
	    int * temp = new int [maximumCliques+1];
	    memcpy(temp,cliqueStart,(numberCliques+1)*sizeof(int));
	    delete [] cliqueStart;
	    cliqueStart=temp;
	    char * tempT = new char [maximumCliques];
	    memcpy(tempT,cliqueType,numberCliques);
	    delete [] cliqueType;
	    cliqueType=tempT;
	  }
	  CliqueEntry eI;
	  eI.fixes=0;
	  setSequenceInCliqueEntry(eI,iColumn);
	  setOneFixesInCliqueEntry(eI,false);
	  entry[numberEntries++]=eI;
	  whichM[0]=iColumn;
	  int n=1;
	  for (int i=cliqueStart[jClique];i<cliqueStart[jClique+1];i++) {
	    entry[numberEntries++]=entry[i];
	    whichM[n++]=sequenceInCliqueEntry(entry[i]);
	  }
	  CoinSort_2(whichM,whichM+n,(reinterpret_cast<int *>(entry))+numberEntries-n);
	  cliqueType[numberCliques]='S';
	  numberCliques++;
	  cliqueStart[numberCliques]=numberEntries;
	}
      }
      for (i=0;i<n;i++)
	mark[whichP[i]]=0;
      nCount=0;
      n=0;
      for (i=oneStart[iColumn];i<zeroStart[iColumn+1];i++) {
	int jClique = whichClique[i];
	//if (jClique<numberMatrixCliques) 
	//continue;
	int j = cliqueStart[jClique];
	//assert (cliqueStart[jClique+1]==j+2);
	for (;j<cliqueStart[jClique+1];j++) {
	  CliqueEntry eJ = entry[j];
	  int jColumn = sequenceInCliqueEntry(eJ);
	  if (jColumn>iColumn&&!mark[jColumn]) {
	    mark[jColumn]=1;
	    whichP[n++]=jColumn;
	    assert (n<numberIntegers_);
	    if (oneFixesInCliqueEntry(eJ)) {
	      for (int k=oneStart[jColumn];k<zeroStart[jColumn+1];k++) {
		int jClique = whichClique[k];
		if (!count[jClique]) 
		  whichCount[nCount++]=jClique;
		count[jClique]++;
	      }
	    } else {
	      for (int k=zeroStart[jColumn];k<oneStart[jColumn];k++) {
		int jClique = whichClique[k];
		if (!count[jClique]) 
		  whichCount[nCount++]=jClique;
		count[jClique]++;
	      }
	    }
	  }
	}
      }
      std::sort(whichP,whichP+n);
      for (i=0;i<nCount;i++) {
	int jClique = whichCount[i];
	int jCount = count[jClique];
	count[jClique]=0;
	if (jCount==cliqueStart[jClique+1]-cliqueStart[jClique]) {
#if 1
		if (printit) {
	    printf("One can extend %d [ ",jClique);
	    for (int i=cliqueStart[jClique];i<cliqueStart[jClique+1];i++)
	      printf("%d(%d) ",sequenceInCliqueEntry(entry[i]),oneFixesInCliqueEntry(entry[i]));
	    printf("] by %d(1)\n",iColumn);
	  }
#endif
	  nStrengthen++;
	  if (numberEntries+jCount+1>maximumEntries) {
	    maximumEntries = CoinMax(numberEntries+jCount+1,(maximumEntries*12)/10+100);
	    CliqueEntry * temp = new CliqueEntry [maximumEntries];
	    memcpy(temp,entry,numberEntries*sizeof(CliqueEntry));
	    delete [] entry;
	    entry=temp;
	    int * tempI = new int [maximumEntries];
	    memcpy(tempI,whichClique,numberEntries*sizeof(int));
	    delete [] whichClique;
	    whichClique=tempI;
	  }
	  if (numberCliques==maximumCliques) {
	    maximumCliques = (maximumCliques*12)/10+100;
	    int * temp = new int [maximumCliques+1];
	    memcpy(temp,cliqueStart,(numberCliques+1)*sizeof(int));
	    delete [] cliqueStart;
	    cliqueStart=temp;
	    char * tempT = new char [maximumCliques];
	    memcpy(tempT,cliqueType,numberCliques);
	    delete [] cliqueType;
	    cliqueType=tempT;
	  }
	  CliqueEntry eI;
	  eI.fixes=0;
	  setSequenceInCliqueEntry(eI,iColumn);
	  setOneFixesInCliqueEntry(eI,true);
	  entry[numberEntries++]=eI;
	  whichM[0]=iColumn;
	  int n=1;
	  for (int i=cliqueStart[jClique];i<cliqueStart[jClique+1];i++) {
	    entry[numberEntries++]=entry[i];
	    whichM[n++]=sequenceInCliqueEntry(entry[i]);
	  }
	  CoinSort_2(whichM,whichM+n,(reinterpret_cast<int *>(entry))+numberEntries-n);
	  cliqueType[numberCliques]='S';
	  numberCliques++;
	  cliqueStart[numberCliques]=numberEntries;
	}
      }
      for (i=0;i<n;i++)
	mark[whichP[i]]=0;
    }
    if (nStrengthen) {
      int numberDeleted = outDupsEtc(numberIntegers_, numberCliques, numberMatrixCliques,
		 cliqueStart, cliqueType, entry, numberLastTime,printit ? 2 : 1);
      if (numberDeleted<0||(iPass>1&&numberCliques-numberDeleted>5000))
	nStrengthen=0;
    }
    delete [] count;
    delete [] whichCount;
  }
#if 0
  if (numberCliques>numberMatrixCliques) {
    // should keep as cliques and also use in branching ??
    double * element = new double [numberIntegers_];
    for (iClique=numberMatrixCliques;iClique<numberCliques;iClique++) {
      int n=0;
      double rhs=1.0;
      for (int i=cliqueStart[iClique];i<cliqueStart[iClique+1];i++) {
	CliqueEntry eI=entry[i];
	int iColumn = integerVariable_[sequenceInCliqueEntry(eI)];
	whichP[n]=iColumn;
	if (oneFixesInCliqueEntry(eI)) {
	  element[n++]=1.0;
	} else {
	  element[n++]=-1.0;
	  rhs -= 1.0;
	}
      }
      stored->addCut(-COIN_DBL_MAX,rhs,n,whichP,element);
    } 
    delete [] element;
  }
#endif
  OsiSolverInterface * newSolver=NULL; 
  if (numberCliques>numberMatrixCliques||alwaysDo) {
    newSolver = si.clone();
    // Delete all rows
    int * start = new int [ CoinMax(numberRows,numberCliques+1)];
    int i;
    for (i=0;i<numberRows;i++)
      start[i]=i;
    newSolver->deleteRows(numberRows,start);
    start[0]=0;
    int numberElements = cliqueStart[numberCliques];
    int * column = new int [numberElements];
    double * element = new double [numberElements];
    double * lower = new double [numberCliques];
    double * upper = new double [numberCliques];
    numberElements=0;
    for (iClique=0;iClique<numberCliques;iClique++) {
      double rhs=1.0;
      for (int i=cliqueStart[iClique];i<cliqueStart[iClique+1];i++) {
	CliqueEntry eI=entry[i];
	int iColumn = integerVariable_[sequenceInCliqueEntry(eI)];
	column[numberElements]=iColumn;
	if (oneFixesInCliqueEntry(eI)) {
	  element[numberElements++]=1.0;
	} else {
	  element[numberElements++]=-1.0;
	  rhs -= 1.0;
	}
      }
      start[iClique+1]=numberElements;
      assert (cliqueType[iClique]=='S'||
	      cliqueType[iClique]=='E');
      if (cliqueType[iClique]=='S')
	lower[iClique]=-COIN_DBL_MAX;
      else
	lower[iClique] = rhs;
      upper[iClique]=rhs;
    }
    newSolver->addRows(numberCliques,start,column,element,lower,upper);
    delete [] start;
    delete [] column;
    delete [] element;
    delete [] lower;
    delete [] upper;
  }
  delete [] mark;
  delete [] whichP;
  delete [] whichM;
  delete [] cliqueStart;
  delete [] entry;
  delete [] cliqueType;
  delete [] zeroStart;
  delete [] oneStart;
  delete [] zeroCount;
  delete [] oneCount;
  delete [] whichClique;
  return newSolver;
}
Пример #21
0
CbcBranchingObject *
CbcGeneralDepth::createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int /*way*/)
{
    int numberDo = numberNodes_;
    if (whichSolution_ >= 0 && (model_->moreSpecialOptions()&33554432)==0) 
        numberDo--;
    assert (numberDo > 0);
    // create object
    CbcGeneralBranchingObject * branch = new CbcGeneralBranchingObject(model_);
    // skip solution
    branch->numberSubProblems_ = numberDo;
    // If parentBranch_ back in then will have to be 2*
    branch->numberSubLeft_ = numberDo;
    branch->setNumberBranches(numberDo);
    CbcSubProblem * sub = new CbcSubProblem[numberDo];
    int iProb = 0;
    branch->subProblems_ = sub;
    branch->numberRows_ = model_->solver()->getNumRows();
    int iNode;
    //OsiSolverInterface * solver = model_->solver();
    OsiClpSolverInterface * clpSolver
    = dynamic_cast<OsiClpSolverInterface *> (solver);
    assert (clpSolver);
    ClpSimplex * simplex = clpSolver->getModelPtr();
    int numberColumns = simplex->numberColumns();
    if ((model_->moreSpecialOptions()&33554432)==0) {
      double * lowerBefore = CoinCopyOfArray(simplex->getColLower(),
					     numberColumns);
      double * upperBefore = CoinCopyOfArray(simplex->getColUpper(),
					     numberColumns);
      ClpNodeStuff * info = nodeInfo_;
      double * weight = new double[numberNodes_];
      int * whichNode = new int [numberNodes_];
      // Sort
      for (iNode = 0; iNode < numberNodes_; iNode++) {
        if (iNode != whichSolution_) {
	  double objectiveValue = info->nodeInfo_[iNode]->objectiveValue();
	  double sumInfeasibilities = info->nodeInfo_[iNode]->sumInfeasibilities();
	  int numberInfeasibilities = info->nodeInfo_[iNode]->numberInfeasibilities();
	  double thisWeight = 0.0;
#if 1
	  // just closest
	  thisWeight = 1.0e9 * numberInfeasibilities;
	  thisWeight += sumInfeasibilities;
	  thisWeight += 1.0e-7 * objectiveValue;
	  // Try estimate
	  thisWeight = info->nodeInfo_[iNode]->estimatedSolution();
#else
	  thisWeight = 1.0e-3 * numberInfeasibilities;
	  thisWeight += 1.0e-5 * sumInfeasibilities;
	  thisWeight += objectiveValue;
#endif
	  whichNode[iProb] = iNode;
	  weight[iProb++] = thisWeight;
        }
      }
      assert (iProb == numberDo);
      CoinSort_2(weight, weight + numberDo, whichNode);
      for (iProb = 0; iProb < numberDo; iProb++) {
        iNode = whichNode[iProb];
        ClpNode * node = info->nodeInfo_[iNode];
        // move bounds
        node->applyNode(simplex, 3);
        // create subproblem
        sub[iProb] = CbcSubProblem(clpSolver, lowerBefore, upperBefore,
                                   node->statusArray(), node->depth());
        sub[iProb].objectiveValue_ = node->objectiveValue();
        sub[iProb].sumInfeasibilities_ = node->sumInfeasibilities();
        sub[iProb].numberInfeasibilities_ = node->numberInfeasibilities();
#ifdef CHECK_PATH
        if (simplex->numberColumns() == numberColumns_Z) {
	  bool onOptimal = true;
	  const double * columnLower = simplex->columnLower();
	  const double * columnUpper = simplex->columnUpper();
	  for (int i = 0; i < numberColumns_Z; i++) {
	    if (iNode == gotGoodNode_Z)
	      printf("good %d %d %g %g\n", iNode, i, columnLower[i], columnUpper[i]);
	    if (columnUpper[i] < debuggerSolution_Z[i] || columnLower[i] > debuggerSolution_Z[i] && simplex->isInteger(i)) {
	      onOptimal = false;
	      break;
	    }
	  }
	  if (onOptimal) {
	    printf("adding to node %x as %d - objs\n", this, iProb);
	    for (int j = 0; j <= iProb; j++)
	      printf("%d %g\n", j, sub[j].objectiveValue_);
	  }
        }
#endif
      }
      delete [] weight;
      delete [] whichNode;
      const double * lower = solver->getColLower();
      const double * upper = solver->getColUpper();
      // restore bounds
      for ( int j = 0; j < numberColumns; j++) {
        if (lowerBefore[j] != lower[j])
	  solver->setColLower(j, lowerBefore[j]);
        if (upperBefore[j] != upper[j])
	  solver->setColUpper(j, upperBefore[j]);
      }
      delete [] upperBefore;
      delete [] lowerBefore;
    } else {
      // from diving
      CbcSubProblem ** nodes = reinterpret_cast<CbcSubProblem **>
	(model_->temporaryPointer());
      assert (nodes);
      int adjustDepth=info->depth_;
      assert (numberDo);
      numberNodes_=0;
      for (iProb = 0; iProb < numberDo; iProb++) {
	if ((nodes[iProb]->problemStatus_&2)==0) {
	  // create subproblem (and swap way and/or make inactive)
	  sub[numberNodes_].takeOver(*nodes[iProb],true);
	  // but adjust depth
	  sub[numberNodes_].depth_+=adjustDepth;
	  numberNodes_++;
	}
	delete nodes[iProb];
      }
      branch->numberSubProblems_ = numberNodes_;
      branch->numberSubLeft_ = numberNodes_;
      branch->setNumberBranches(numberNodes_);
      if (!numberNodes_) {
	// infeasible
	delete branch;
	branch=NULL;
      }
      delete [] nodes;
    }
    return branch;
}
Пример #22
0
int main (int argc, const char *argv[])
{
     ClpSimplex  model;
     int status;
     int maxFactor = 100;
     if (argc < 2) {
          status = model.readMps("../../Data/Netlib/czprob.mps");
          if (status) {
               printf("Unable to read matrix - trying gzipped version\n");
               status = model.readMps("../../Data/Netlib/czprob.mps.gz");
          }
     } else {
          status = model.readMps(argv[1]);
     }
     if (status) {
          printf("errors on input\n");
          exit(77);
     }
     if (argc > 2) {
          maxFactor = atoi(argv[2]);
          printf("max factor %d\n", maxFactor);
     }
     if (argc > 3) {
          printf("Using ClpDynamicMatrix\n");
     } else {
          printf("Using ClpDynamicExampleMatrix\n");
     }
     // find gub
     int numberRows = model.numberRows();
     int * gubStart = new int[numberRows+1];
     int * gubEnd = new int[numberRows];
     int * which = new int[numberRows];
     int * whichGub = new int[numberRows];
     int numberColumns = model.numberColumns();
     int * mark = new int[numberColumns];
     int iRow, iColumn;
     // delete variables fixed to zero
     const double * columnLower = model.columnLower();
     const double * columnUpper = model.columnUpper();
     int numberDelete = 0;
     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
          if (columnUpper[iColumn] == 0.0 && columnLower[iColumn] == 0.0)
               mark[numberDelete++] = iColumn;
     }
     if (numberDelete) {
          model.deleteColumns(numberDelete, mark);
          numberColumns -= numberDelete;
          columnLower = model.columnLower();
          columnUpper = model.columnUpper();
     }
     double * lower = new double[numberRows];
     double * upper = new double[numberRows];
     const double * rowLower = model.rowLower();
     const double * rowUpper = model.rowUpper();
     for (iColumn = 0; iColumn < numberColumns; iColumn++)
          mark[iColumn] = -1;
     CoinPackedMatrix * matrix = model.matrix();
     // get row copy
     CoinPackedMatrix rowCopy = *matrix;
     rowCopy.reverseOrdering();
     const int * column = rowCopy.getIndices();
     const int * rowLength = rowCopy.getVectorLengths();
     const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
     const double * element = rowCopy.getElements();
     int putGub = numberRows;
     int putNonGub = numberRows;
     int * rowIsGub = new int [numberRows];
     for (iRow = numberRows - 1; iRow >= 0; iRow--) {
          bool gubRow = true;
          int first = numberColumns + 1;
          int last = -1;
          for (int j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
               if (element[j] != 1.0) {
                    gubRow = false;
                    break;
               } else {
                    int iColumn = column[j];
                    if (mark[iColumn] >= 0) {
                         gubRow = false;
                         break;
                    } else {
                         last = CoinMax(last, iColumn);
                         first = CoinMin(first, iColumn);
                    }
               }
          }
          if (last - first + 1 != rowLength[iRow] || !gubRow) {
               which[--putNonGub] = iRow;
               rowIsGub[iRow] = 0;
          } else {
               for (int j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
                    int iColumn = column[j];
                    mark[iColumn] = iRow;
               }
               rowIsGub[iRow] = -1;
               putGub--;
               gubStart[putGub] = first;
               gubEnd[putGub] = last + 1;
               lower[putGub] = rowLower[iRow];
               upper[putGub] = rowUpper[iRow];
               whichGub[putGub] = iRow;
          }
     }
     int numberNonGub = numberRows - putNonGub;
     int numberGub = numberRows - putGub;
     if (numberGub > 0) {
          printf("** %d gub rows\n", numberGub);
          int numberNormal = 0;
          const int * row = matrix->getIndices();
          const int * columnLength = matrix->getVectorLengths();
          const CoinBigIndex * columnStart = matrix->getVectorStarts();
          const double * elementByColumn = matrix->getElements();
          int numberElements = 0;
          bool doLower = false;
          bool doUpper = false;
          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
               if (mark[iColumn] < 0) {
                    mark[numberNormal++] = iColumn;
               } else {
                    numberElements += columnLength[iColumn];
                    if (columnLower[iColumn] != 0.0)
                         doLower = true;
                    if (columnUpper[iColumn] < 1.0e20)
                         doUpper = true;
               }
          }
          if (!numberNormal) {
               printf("Putting back one gub row to make non-empty\n");
               for (iColumn = gubStart[putGub]; iColumn < gubEnd[putGub]; iColumn++)
                    mark[numberNormal++] = iColumn;
               putGub++;
               numberGub--;
          }
          ClpSimplex model2(&model, numberNonGub, which + putNonGub, numberNormal, mark);
          // and copy for restart test
          ClpSimplex model3 = model2;
          int numberGubColumns = numberColumns - numberNormal;
          // sort gubs so monotonic
          int * which = new int[numberGub];
          int i;
          for (i = 0; i < numberGub; i++)
               which[i] = i;
          CoinSort_2(gubStart + putGub, gubStart + putGub + numberGub, which);
          // move to bottom if we want to use later
          memmove(gubStart, gubStart + putGub, numberGub * sizeof(int));
          int * temp1 = new int [numberGub];
          for (i = 0; i < numberGub; i++) {
               int k = which[i];
               temp1[i] = gubEnd[putGub+k];
          }
          memcpy(gubEnd, temp1, numberGub * sizeof(int));
          delete [] temp1;
          double * temp2 = new double [numberGub];
          for (i = 0; i < numberGub; i++) {
               int k = which[i];
               temp2[i] = lower[putGub+k];
          }
          memcpy(lower, temp2, numberGub * sizeof(double));
          for (i = 0; i < numberGub; i++) {
               int k = which[i];
               temp2[i] = upper[putGub+k];
          }
          memcpy(upper, temp2, numberGub * sizeof(double));
          delete [] temp2;
          delete [] which;
          numberElements -= numberGubColumns;
          int * start2 = new int[numberGubColumns+1];
          int * row2 = new int[numberElements];
          double * element2 = new double[numberElements];
          double * cost2 = new double [numberGubColumns];
          double * lowerColumn2 = NULL;
          if (doLower) {
               lowerColumn2 = new double [numberGubColumns];
               CoinFillN(lowerColumn2, numberGubColumns, 0.0);
          }
          double * upperColumn2 = NULL;
          if (doUpper) {
               upperColumn2 = new double [numberGubColumns];
               CoinFillN(upperColumn2, numberGubColumns, COIN_DBL_MAX);
          }
          numberElements = 0;
          int numberNonGubRows = 0;
          for (iRow = 0; iRow < numberRows; iRow++) {
               if (!rowIsGub[iRow])
                    rowIsGub[iRow] = numberNonGubRows++;
          }
          numberColumns = 0;
          int iStart = gubStart[0];
          gubStart[0] = 0;
          start2[0] = 0;
          const double * cost = model.objective();
          for (int iSet = 0; iSet < numberGub; iSet++) {
               int iEnd = gubEnd[iSet];
               for (int k = iStart; k < iEnd; k++) {
                    cost2[numberColumns] = cost[k];
                    if (columnLower[k])
                         lowerColumn2[numberColumns] = columnLower[k];
                    if (columnUpper[k] < 1.0e20)
                         upperColumn2[numberColumns] = columnUpper[k];
                    for (int j = columnStart[k]; j < columnStart[k] + columnLength[k]; j++) {
                         int iRow = rowIsGub[row[j]];
                         if (iRow >= 0) {
                              row2[numberElements] = iRow;
                              element2[numberElements++] = elementByColumn[j];
                         }
                    }
                    start2[++numberColumns] = numberElements;
               }
               if (iSet < numberGub - 1)
                    iStart = gubStart[iSet+1];
               gubStart[iSet+1] = numberColumns;
          }
          printf("** Before adding matrix there are %d rows and %d columns\n",
                 model2.numberRows(), model2.numberColumns());
          if (argc > 3) {
               ClpDynamicMatrix * newMatrix = new ClpDynamicMatrix(&model2, numberGub,
                         numberColumns, gubStart,
                         lower, upper,
                         start2, row2, element2, cost2,
                         lowerColumn2, upperColumn2);
               model2.replaceMatrix(newMatrix);
               newMatrix->switchOffCheck();
               newMatrix->setRefreshFrequency(1000);
          } else {
               ClpDynamicExampleMatrix * newMatrix = new ClpDynamicExampleMatrix(&model2, numberGub,
                         numberColumns, gubStart,
                         lower, upper,
                         start2, row2, element2, cost2,
                         lowerColumn2, upperColumn2);
               model2.replaceMatrix(newMatrix);
               newMatrix->switchOffCheck();
               newMatrix->setRefreshFrequency(1000);
          }
          printf("** While after adding matrix there are %d rows and %d columns\n",
                 model2.numberRows(), model2.numberColumns());
          model2.setSpecialOptions(4); // exactly to bound
          // For now scaling off
          model2.scaling(0);
          ClpPrimalColumnSteepest steepest(5);
          model2.setPrimalColumnPivotAlgorithm(steepest);
          //model2.messageHandler()->setLogLevel(63);
          model2.setFactorizationFrequency(maxFactor);
          model2.setMaximumIterations(4000000);
          double time1 = CoinCpuTime();
          model2.primal();
          // can't use values pass
          model2.primal(0);
          // test proper restart
          if (argc > 3) {
               ClpDynamicMatrix * oldMatrix =
                    dynamic_cast< ClpDynamicMatrix*>(model2.clpMatrix());
               assert (oldMatrix);
               ClpDynamicMatrix * newMatrix = new
               ClpDynamicMatrix(&model3, numberGub,
                                numberColumns, gubStart,
                                lower, upper,
                                start2, row2, element2, cost2,
                                lowerColumn2, upperColumn2,
                                oldMatrix->gubRowStatus(), oldMatrix->dynamicStatus());
               model3.replaceMatrix(newMatrix);
               // and ordinary status (but only NON gub rows)
               memcpy(model3.statusArray(), model2.statusArray(),
                      (newMatrix->numberStaticRows() + model3.numberColumns())*sizeof(unsigned char));
               newMatrix->switchOffCheck();
               newMatrix->setRefreshFrequency(1000);
          } else {
               ClpDynamicExampleMatrix * oldMatrix =
                    dynamic_cast< ClpDynamicExampleMatrix*>(model2.clpMatrix());
               assert (oldMatrix);
               ClpDynamicExampleMatrix * newMatrix = new
               ClpDynamicExampleMatrix(&model3, numberGub,
                                       numberColumns, gubStart,
                                       lower, upper,
                                       start2, row2, element2, cost2,
                                       lowerColumn2, upperColumn2,
                                       oldMatrix->gubRowStatus(), oldMatrix->dynamicStatus(),
                                       oldMatrix->numberGubColumns(), oldMatrix->idGen());
               model3.replaceMatrix(newMatrix);
               // and ordinary status (but only NON gub rows)
               memcpy(model3.statusArray(), model2.statusArray(),
                      (newMatrix->numberStaticRows() + model3.numberColumns())*sizeof(unsigned char));
               newMatrix->switchOffCheck();
               newMatrix->setRefreshFrequency(1000);
          }
          model3.setSpecialOptions(4); // exactly to bound
          // For now scaling off
          model3.scaling(0);
          model3.setPrimalColumnPivotAlgorithm(steepest);
          model3.messageHandler()->setLogLevel(63);
          model3.setFactorizationFrequency(maxFactor);
          model3.setMaximumIterations(4000000);
          delete [] rowIsGub;
          delete [] start2;
          delete [] row2;
          delete [] element2;
          delete [] cost2;
          delete [] lowerColumn2;
          delete [] upperColumn2;
          model3.primal();
          // this code expects non gub first in original matrix
          // and only works at present for ClpDynamicMatrix
          ClpDynamicMatrix * gubMatrix =
               dynamic_cast< ClpDynamicMatrix*>(model2.clpMatrix());
          assert (gubMatrix);
          ClpDynamicExampleMatrix * gubMatrix2 =
               dynamic_cast< ClpDynamicExampleMatrix*>(model2.clpMatrix());
          if (!gubMatrix2) {
               const double * solution = model2.primalColumnSolution();
               const double * cost = model.objective();
               int numberGubColumns = gubMatrix->numberGubColumns();
               int firstOdd = gubMatrix->firstDynamic();
               int lastOdd = gubMatrix->firstAvailable();
               int numberTotalColumns = firstOdd + numberGubColumns;
               int originalNumberRows = model.numberRows();
               int numberStaticRows = gubMatrix->numberStaticRows();
               char * status = new char [numberTotalColumns];
               double * gubSolution = new double [numberTotalColumns];
               int numberSets = gubMatrix->numberSets();
               const int * id = gubMatrix->id();
               int i;
               const float * columnLower = gubMatrix->columnLower();
               const float * columnUpper = gubMatrix->columnUpper();
               for (i = 0; i < numberGubColumns; i++) {
                    if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::atUpperBound) {
                         gubSolution[i+firstOdd] = columnUpper[i];
                         status[i+firstOdd] = 2;
                    } else if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::atLowerBound && columnLower) {
                         gubSolution[i+firstOdd] = columnLower[i];
                         status[i+firstOdd] = 1;
                    } else if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::soloKey) {
                         int iSet = gubMatrix->whichSet(i);
                         gubSolution[i+firstOdd] = gubMatrix->keyValue(iSet);
                         status[i+firstOdd] = 0;
                    } else {
                         gubSolution[i+firstOdd] = 0.0;
                         status[i+firstOdd] = 1;
                    }
               }
               for (i = 0; i < firstOdd; i++) {
                    ClpSimplex::Status thisStatus = model2.getStatus(i);
                    if (thisStatus == ClpSimplex::basic)
                         status[i] = 0;
                    else if (thisStatus == ClpSimplex::atLowerBound)
                         status[i] = 1;
                    else if (thisStatus == ClpSimplex::atUpperBound)
                         status[i] = 2;
                    else if (thisStatus == ClpSimplex::isFixed)
                         status[i] = 3;
                    else
                         abort();
                    gubSolution[i] = solution[i];
               }
               for (i = firstOdd; i < lastOdd; i++) {
                    int iBig = id[i-firstOdd] + firstOdd;
                    ClpSimplex::Status thisStatus = model2.getStatus(i);
                    if (thisStatus == ClpSimplex::basic)
                         status[iBig] = 0;
                    else if (thisStatus == ClpSimplex::atLowerBound)
                         status[iBig] = 1;
                    else if (thisStatus == ClpSimplex::atUpperBound)
                         status[iBig] = 2;
                    else if (thisStatus == ClpSimplex::isFixed)
                         status[iBig] = 3;
                    else
                         abort();
                    gubSolution[iBig] = solution[i];
               }
               char * rowStatus = new char[originalNumberRows];
               for (i = 0; i < numberStaticRows; i++) {
                    ClpSimplex::Status thisStatus = model2.getRowStatus(i);
                    if (thisStatus == ClpSimplex::basic)
                         rowStatus[i] = 0;
                    else if (thisStatus == ClpSimplex::atLowerBound)
                         rowStatus[i] = 1;
                    else if (thisStatus == ClpSimplex::atUpperBound)
                         rowStatus[i] = 2;
                    else if (thisStatus == ClpSimplex::isFixed)
                         rowStatus[i] = 3;
                    else
                         abort();
               }
               double objValue = 0.0;
               for (i = 0; i < numberTotalColumns; i++)
                    objValue += cost[i] * gubSolution[i];
               printf("objective value is %g\n", objValue);
               for (i = 0; i < numberSets; i++) {
                    ClpSimplex::Status thisStatus = gubMatrix->getStatus(i);
                    if (thisStatus == ClpSimplex::basic)
                         rowStatus[numberStaticRows+i] = 0;
                    else if (thisStatus == ClpSimplex::atLowerBound)
                         rowStatus[numberStaticRows+i] = 1;
                    else if (thisStatus == ClpSimplex::atUpperBound)
                         rowStatus[numberStaticRows+i] = 2;
                    else if (thisStatus == ClpSimplex::isFixed)
                         rowStatus[numberStaticRows+i] = 3;
                    else
                         abort();
               }
               // Coding below may not work if gub rows not at end
               FILE * fp = fopen ("xx.sol", "w");
               fwrite(gubSolution, sizeof(double), numberTotalColumns, fp);
               fwrite(status, sizeof(char), numberTotalColumns, fp);
               const double * rowsol = model2.primalRowSolution();
               double * rowsol2 = new double[originalNumberRows];
               memset(rowsol2, 0, originalNumberRows * sizeof(double));
               model.times(1.0, gubSolution, rowsol2);
               for (i = 0; i < numberStaticRows; i++)
                    assert (fabs(rowsol[i] - rowsol2[i]) < 1.0e-3);
               for (; i < originalNumberRows; i++)
                    assert (rowsol2[i] > lower[i-numberStaticRows] - 1.0e-3 &&
                            rowsol2[i] < upper[i-numberStaticRows] + 1.0e-3);
               //for (;i<originalNumberRows;i++)
               //printf("%d %g\n",i,rowsol2[i]);
               fwrite(rowsol2, sizeof(double), originalNumberRows, fp);
               delete [] rowsol2;
               fwrite(rowStatus, sizeof(char), originalNumberRows, fp);
               fclose(fp);
               delete [] status;
               delete [] gubSolution;
               // ** if going to rstart as dynamic need id_
               // also copy coding in useEf.. from ClpGubMatrix (i.e. test for basis)
          }
          printf("obj offset is %g\n", model2.objectiveOffset());
          printf("Primal took %g seconds\n", CoinCpuTime() - time1);
     }
     delete [] mark;
     delete [] gubStart;
     delete [] gubEnd;
     delete [] which;
     delete [] whichGub;
     delete [] lower;
     delete [] upper;
     return 0;
}
Пример #23
0
int main (int argc, const char *argv[])
{
     ClpSimplex  model;
     int status;
     // Keep names
     if (argc < 2) {
          status = model.readMps("small.mps", true);
     } else {
          status = model.readMps(argv[1], false);
     }
     if (status)
          exit(10);
     /*
       This driver implements a method of treating a problem as all cuts.
       So it adds in all E rows, solves and then adds in violated rows.
     */

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

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

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

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

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

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

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

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

     numberIterations += model.numberIterations();;
     printf("Solve took %g seconds\n", CoinCpuTime() - time1);
     return 0;
}
Пример #24
0
void
CbcTreeArray::cleanTree(CbcModel * model, double cutoff, double & bestPossibleObjective)
{
    int j;
    int nNodes = size();
    int lastNode = nNodes + 1;
    CbcNode ** nodeArray = new CbcNode * [lastNode];
    int * depth = new int [lastNode];
    int k = 0;
    int kDelete = lastNode;
    bestPossibleObjective = 1.0e100 ;
    /*
        Destructively scan the heap. Nodes to be retained go into the front of
        nodeArray, nodes to be deleted into the back. Store the depth in a
        correlated array for nodes to be deleted.
    */
    for (j = 0; j < nNodes; j++) {
        CbcNode * node = nodes_.front();
        nodes_.front()->setOnTree(false);
        std::pop_heap(nodes_.begin(), nodes_.end(), comparison_);
        nodes_.pop_back();
        double value = node ? node->objectiveValue() : COIN_DBL_MAX;
        if (node && value >= cutoff) {
            // double check in case node can change its mind!
            value = node->checkIsCutoff(cutoff);
        }
        if (value >= cutoff || !node->active()) {
            if (node) {
                nodeArray[--kDelete] = node;
                depth[kDelete] = node->depth();
            }
        } else {
            bestPossibleObjective = CoinMin(bestPossibleObjective, value);
            nodeArray[k++] = node;
        }
    }
    if (lastNode_) {
        double value = lastNode_->objectiveValue();
        bestPossibleObjective = CoinMin(bestPossibleObjective, value);
        if (value >= cutoff || !lastNode_->active()) {
            nodeArray[--kDelete] = lastNode_;
            depth[kDelete] = lastNode_->depth();
            lastNode_ = NULL;
        }
    }
    CbcCompareDefault * compareDefault
    = dynamic_cast<CbcCompareDefault *> (comparison_.test_);
    assert (compareDefault);
    compareDefault->setBestPossible(bestPossibleObjective);
    compareDefault->setCutoff(cutoff);
    /*
      Rebuild the heap using the retained nodes.
    */
    for (j = 0; j < k; j++) {
        CbcNode * node = nodeArray[j];
        node->setOnTree(true);
        nodes_.push_back(node);
        std::push_heap(nodes_.begin(), nodes_.end(), comparison_);
    }
    /*
      Sort the list of nodes to be deleted, nondecreasing.
    */
    CoinSort_2(depth + kDelete, depth + lastNode, nodeArray + kDelete);
    /*
      Work back from deepest to shallowest. In spite of the name, addCuts1 is
      just a preparatory step. When it returns, the following will be true:
        * all cuts are removed from the solver's copy of the constraint system;
        * lastws will be a basis appropriate for the specified node;
        * variable bounds will be adjusted to be appropriate for the specified
          node;
        * addedCuts_ (returned via addedCuts()) will contain a list of cuts that
          should be added to the constraint system at this node (but they have
          not actually been added).
      Then we scan the cut list for the node. Decrement the reference count
      for the cut, and if it's gone to 0, really delete it.

      I don't yet see why the checks for status != basic and addedCuts_[i] != 0
      are necessary. When reconstructing a node, these checks are used to skip
      over loose cuts, excluding them from the reconstituted basis. But here
      we're just interested in correcting the reference count. Tight/loose
      should make no difference.

      Arguably a separate routine should be used in place of addCuts1. It's
      doing more work than needed, modifying the model to match a subproblem
      at a node that will be discarded.  Then again, we seem to need the basis.
    */
    for (j = lastNode - 1; j >= kDelete; j--) {
        CbcNode * node = nodeArray[j];
        CoinWarmStartBasis *lastws = model->getEmptyBasis() ;

        model->addCuts1(node, lastws);
        // Decrement cut counts
        assert (node);
        //assert (node->nodeInfo());
        int numberLeft = (node->nodeInfo()) ? node->nodeInfo()->numberBranchesLeft() : 0;
        int i;
        for (i = 0; i < model->currentNumberCuts(); i++) {
            // take off node
            CoinWarmStartBasis::Status status =
                lastws->getArtifStatus(i + model->numberRowsAtContinuous());
            if (status != CoinWarmStartBasis::basic &&
                    model->addedCuts()[i]) {
                if (!model->addedCuts()[i]->decrement(numberLeft))
                    delete model->addedCuts()[i];
            }
        }
        // node should not have anything pointing to it
        if (node->nodeInfo())
            node->nodeInfo()->throwAway();
        delete node ;
        delete lastws ;
    }
    delete [] nodeArray;
    delete [] depth;
}
Пример #25
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 */
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;
}
Пример #26
0
  int
  BonNWayChoose::setupList ( OsiBranchingInformation *info, bool initialize)
  {
    assert(initialize);
    if (initialize) {
      status_=-2;
      delete [] goodSolution_;
      bestObjectIndex_=-1;
      goodSolution_ = NULL;
      goodObjectiveValue_ = COIN_DBL_MAX;
    }


    numberOnList_=0;
    numberUnsatisfied_=0;
    int numberObjects = info->solver_->numberObjects() - start_nway_;
    double cutoff = info->cutoff_;
    if(info->depth_ == 0){
      bounds_.resize(0);
      unit_changes_.resize(0);
      bounds_.resize(numberObjects, std::vector<double>(numberObjects,cutoff));
      unit_changes_.resize(numberObjects, std::vector<double>(numberObjects,0));
      num_eval_.resize(numberObjects, 0);
      num_ps_costs_.resize(numberObjects, std::vector<int>(numberObjects,0));
    }
    else {
      assert(unit_changes_.size() == numberObjects);
      assert(bounds_.size() == unit_changes_.size());
    }
    //Always allow all objects on the list  
    int maximumStrong = numberObjects;

    double check = -COIN_DBL_MAX;
    int checkIndex=0;
    int bestPriority=COIN_INT_MAX;
    int putOther = numberObjects;
    int i;
    for (i=0;i<numberObjects;i++) {
      list_[i]=-1;
      useful_[i]=0.0;
    }

    OsiObject ** object = info->solver_->objects();
    object += start_nway_;

    // Say feasible
    bool feasible = true;
    for ( i=0;i<numberObjects;i++) {
      int way;
      double value = object[i]->infeasibility(info,way);
      if (value>0.0) {
        numberUnsatisfied_++;
        int priorityLevel = object[i]->priority();
        // Better priority? Flush choices.
        if (priorityLevel<bestPriority) {
          for (int j=maximumStrong-1;j>=0;j--) {
            if (list_[j]>=0) {
              int iObject = list_[j];
              list_[j]=-1;
              useful_[j]=0.0;
              list_[--putOther]=iObject;
            }
          }
          bestPriority = priorityLevel;
          check=-COIN_DBL_MAX;
          checkIndex=0;
        }
        if (priorityLevel==bestPriority) {
          // Modify value
          //Compute usefullness
          if(info->depth_ != 0){
            value = compute_usefulness(i + start_nway_, info); 
          }

          if (value>check) {
            //add to list
            int iObject = list_[checkIndex];
            if (iObject>=0) {
              assert (list_[putOther-1]<0);
              list_[--putOther]=iObject;  // to end
            }
            list_[checkIndex]= i + start_nway_;
            assert (checkIndex<putOther);
            useful_[checkIndex]=value;
            // find worst
            check=COIN_DBL_MAX;
            maximumStrong = CoinMin(maximumStrong,putOther);
            for (int j=0;j<maximumStrong;j++) {
              if (list_[j]>=0) {
                if (useful_[j]<check) {
                  check=useful_[j];
                  checkIndex=j;
                }
               }
               else {
                 check=0.0;
                 checkIndex = j;
                 break;
               }
             }
          }
          else {
            // to end
            assert (list_[putOther-1]<0);
            list_[--putOther]=i + start_nway_;
            maximumStrong = CoinMin(maximumStrong,putOther);
          }
        }
        else {
          // worse priority
          // to end
          assert (list_[putOther-1]<0);
          list_[--putOther]=i + start_nway_;
          maximumStrong = CoinMin(maximumStrong,putOther);
        }
      }
    }

    // Get list
    numberOnList_=0;
    if (feasible) {
      maximumStrong = CoinMin(maximumStrong,putOther);
      for (i=0;i<maximumStrong;i++) {
      if (list_[i]>=0) {
          list_[numberOnList_]=list_[i];
          useful_[numberOnList_++]=-useful_[i];
        }
      }
      if (numberOnList_) {
        // Sort
        CoinSort_2(useful_,useful_+numberOnList_,list_);
        // move others
        i = numberOnList_;
        for (;putOther<numberObjects;putOther++)
          list_[i++]=list_[putOther];
        assert (i==numberUnsatisfied_);
        if (!numberStrong_)
          numberOnList_=0;
      }
    }
    else {
      // not feasible
      numberUnsatisfied_=-1;
    }
    // Get rid of any shadow prices info
    info->defaultDual_ = -1.0; // switch off
    delete [] info->usefulRegion_;
    delete [] info->indexRegion_;

    return numberUnsatisfied_;
  }
Пример #27
0
template <class S, class T> void
// This Always uses std::sort
CoinSort_2Std(S* sfirst, S* slast, T* tfirst)
{
  CoinSort_2(sfirst, slast, tfirst, CoinFirstLess_2<S,T>());
}
Пример #28
0
//-------------------------------------------------------------------
//  Given the model data, a row of the model, and a LP solution,
//  this function tries to generate a violated lifted simple generalized
//  flow cover.
//-------------------------------------------------------------------
bool
CglFlowCover::generateOneFlowCut( const OsiSolverInterface & si,
				  const int rowLen,
				  int* ind,
				  double* coef,
				  char sense,
				  double rhs,
				  OsiRowCut& flowCut,
				  double& violation ) const
{
  bool generated       = false;
  const double* xlp    = si.getColSolution();
  const int numCols    = si.getNumCols();

  double* up           = new double [rowLen];
  double* x            = new double [rowLen];
  double* y            = new double [rowLen];
  CglFlowColType* sign = new CglFlowColType [rowLen];

  int i, j;
  double value, LB, UB;

  CglFlowVLB VLB;
  CglFlowVUB VUB;
  static int count=0;
  ++count;
  CGLFLOW_DEBUG=false;
  doLift=true;
  // Get integer types
  const char * columnType = si.getColType ();
  for (i = 0; i < rowLen; ++i) {
    if ( xlp[ind[i]] - floor(xlp[ind[i]]) > EPSILON_ && ceil(xlp[ind[i]]) - xlp[ind[i]] > EPSILON_ )
      break;
  }

  if (i == rowLen)  {
    delete [] sign;
    delete [] up;
    delete [] x;
    delete [] y;
    return generated;
  }

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

  if (sense == 'G') flipRow(rowLen, coef, rhs); // flips everything,
  // but the sense


  if(CGLFLOW_DEBUG) {
    std::cout << "***************************" << std::endl;
    std::cout << "Generate Flow cover -- initial constraint, converted to L sense..." << std::endl;
    std::cout << "Rhs = " << rhs << std::endl;
    std::cout << "coef [var_index]" << " -- " <<  "xlp[var_index]" << '\t' << "vub_coef[vub_index] vub_lp_value OR var_index_col_ub" << std::endl;

    for(int iD = 0; iD < rowLen; ++iD) {
      VUB = getVubs(ind[iD]);

      std::cout << std::setw(5) << coef[iD] << "["  << std::setw(5)  << ind[iD] << "] -- "
		<< std::setw(20) << xlp[ind[iD]] << '\t';
      if (VUB.getVar() != UNDEFINED_) {
	std::cout << std::setw(20) << VUB.getVal() << "[" << std::setw(5) << VUB.getVar() << "]"
		  << std::setw(20) << xlp[VUB.getVar()] << std::endl;
      }
      else
	std::cout << std::setw(20) << si.getColUpper()[ind[iD]] << "       " << std::setw(20) << 1.0 << std::endl;

    }
  }

  //-------------------------------------------------------------------------
  // Generate conservation inequality and capacity equalities from
  // the given row.

  for (i = 0; i < rowLen; ++i) {

    VLB = getVlbs(ind[i]);
    LB = ( VLB.getVar() != UNDEFINED_ ) ?
      VLB.getVal() : si.getColLower()[ind[i]];

    VUB = getVubs(ind[i]);
    UB = ( VUB.getVar() != UNDEFINED_ ) ?
      VUB.getVal() : si.getColUpper()[ind[i]];

    if (LB < -EPSILON_) {   // Only consider rows whose variables are all
      delete [] sign;       // non-negative (LB>= 0).
      delete [] up;
      delete [] x;
      delete [] y;
      return generated;
    }

    if ( columnType[ind[i]]==1 ) {   // Binary variable
      value = coef[i];
      if (value > EPSILON_)
	sign[i] = CGLFLOW_COL_BINPOS;
      else {
	sign[i] = CGLFLOW_COL_BINNEG;
	value = -value;
      }
      up[i] = value;
      x[i] =  xlp[ind[i]];
      y[i] = value * x[i];
    }
    else {
      value = coef[i];
      if (value > EPSILON_)
	sign[i] = CGLFLOW_COL_CONTPOS;
      else {
	sign[i] = CGLFLOW_COL_CONTNEG;
	value = -value;
      }
      up[i] = value* UB;
      x[i] = (VUB.getVar() != UNDEFINED_) ? xlp[VUB.getVar()] : 1.0;
      y[i] = value * xlp[ind[i]];
    }
  }

  //-------------------------------------------------------------------------
  // Find a initial cover (C+, C-) in (N+, N-)
  double  knapRHS   = rhs;
  double  tempSum   = 0.0;
  double  tempMin   = INFTY_;
  CglFlowColCut *    candidate = new CglFlowColCut [rowLen];
  CglFlowColCut *    label     = new CglFlowColCut [rowLen];
  double* ratio     = new double [rowLen];
  int t = -1;
  for (i = 0; i < rowLen; ++i) {
    candidate[i] = label[i] = CGLFLOW_COL_OUTCUT;
    ratio[i] = INFTY_;

    switch(sign[i]) {
    case CGLFLOW_COL_CONTPOS:
    case CGLFLOW_COL_BINPOS:
      if( y[i] > EPSILON_ ) {
	ratio[i] = (1.0 - x[i]) / up[i];
	if( y[i] > up[i] * x[i] - EPSILON_ ) {       // Violated
	  candidate[i] = CGLFLOW_COL_PRIME;
	  tempSum += up[i];
	}
	else {
	  candidate[i] = CGLFLOW_COL_SECONDARY;
	}
      }
      break;
    case CGLFLOW_COL_CONTNEG:
    case CGLFLOW_COL_BINNEG:
      if( up[i] > ( (1.0 - EPSILON_) * INFTY_ ) ) {  // UB is infty
	label[i] = CGLFLOW_COL_INCUT;
      }
      else {
	knapRHS += up[i];
	if( y[i] < up[i] ) {
	  candidate[i] = CGLFLOW_COL_PRIME;
	  ratio[i] = x[i] / up[i];
	  tempSum += up[i];
	}
      }
      break;
    }
  }

  double diff, tempD, lambda;
  int xID = -1;
  if (knapRHS >1.0e10) {
    if(CGLFLOW_DEBUG) {
      std::cout << "knapsack RHS too large. RETURN." << std::endl;
    }
    delete [] sign;
    delete [] up;
    delete [] x;
    delete [] y;
    delete [] candidate;
    delete [] label;
    delete [] ratio;
    return generated;
  }

  while (tempSum < knapRHS + EPSILON_) { // Not a cover yet
    diff = INFTY_;
    for (i = 0; i < rowLen; ++i) {
      if (candidate[i] == CGLFLOW_COL_SECONDARY) {
	tempD = up[i] * x[i] - y[i];
	if (tempD < diff - EPSILON_) {
	  diff = tempD;
	  xID = i;
	}
      }
    }

    if( diff > (1.0 - EPSILON_) * INFTY_  ) {   // NO cover exits.
      delete [] sign;
      delete [] up;
      delete [] x;
      delete [] y;
      delete [] candidate;
      delete [] label;
      delete [] ratio;
      return generated;
    }
    else {
      tempSum += up[xID];
      candidate[xID] = CGLFLOW_COL_PRIME;
    }
  }

  // Solve the knapsack problem to get an initial cover
  tempSum = 0.0;
  for (i = 0; i < rowLen; ++i) {
    if (candidate[i] == CGLFLOW_COL_PRIME && ratio[i] < EPSILON_) {
      //Zero ratio
      label[i] = CGLFLOW_COL_INCUT;
      tempSum += up[i];
    }
  }

  while (tempSum < knapRHS + EPSILON_) {
    tempMin = INFTY_;
    xID=-1;
    for (i = 0; i < rowLen; i++) {   // Search the col with  minimum ratio
      if (candidate[i] == CGLFLOW_COL_PRIME && label[i] == 0 &&
	  ratio[i] < tempMin) {
	tempMin = ratio[i];
	xID = i;
      }
    }
    if (xID>=0) {
      label[xID] = CGLFLOW_COL_INCUT;
      tempSum += up[xID];
    } else {
      if(CGLFLOW_DEBUG) {
	std::cout << "knapsack RHS too large B. RETURN." << std::endl;
      }
      delete [] sign;
      delete [] up;
      delete [] x;
      delete [] y;
      delete [] candidate;
      delete [] label;
      delete [] ratio;
      return generated;
    }
  }

  // Reduce to a minimal cover
  for (i = 0; i < rowLen; ++i) {
    if (label[i] == CGLFLOW_COL_INCUT && ratio[i] > EPSILON_) {
      if (tempSum - up[i] > knapRHS + EPSILON_) {
	label[i] = CGLFLOW_COL_OUTCUT;
	tempSum -= up[i];
      }
    }
  }
  for (i = 0; i < rowLen; ++i) {
    if (label[i] == CGLFLOW_COL_INCUT && ratio[i] < EPSILON_) {
      if (tempSum - up[i] > knapRHS + EPSILON_) {
	label[i] = CGLFLOW_COL_OUTCUT;
	tempSum -= up[i];
      }
    }
  }

  // Due to the way to handle N-
  for(i = 0; i < rowLen; ++i) {
    if( sign[i] < 0 )
      label[i] = label[i]==CGLFLOW_COL_OUTCUT?CGLFLOW_COL_INCUT:CGLFLOW_COL_OUTCUT;
  }

  // No cover, no cut.
  bool emptyCover = true;
  for (i = 0; i < rowLen; ++i) {
    if (label[i] == CGLFLOW_COL_INCUT) {
      emptyCover = false;
      break;
    }
  }
  if (emptyCover) {
    if(CGLFLOW_DEBUG) {
      std::cout << "No cover. RETURN." << std::endl;
    }
    delete [] sign;
    delete [] up;
    delete [] x;
    delete [] y;
    delete [] candidate;
    delete [] label;
    delete [] ratio;
    return generated;
  }

  lambda = tempSum - knapRHS;

  if(CGLFLOW_DEBUG) {
    double sum_mj_Cplus = 0.0;
    double sum_mj_Cminus= 0.0;
    // double checkLambda; // variable not used anywhere (LL)
    // print out the knapsack variables
    std::cout << "Knapsack Cover: C+" << std::endl;
    for (i = 0; i < rowLen; ++i) {
      if ( label[i] == CGLFLOW_COL_INCUT && sign[i] > 0 ) {
	std::cout << ind[i] << '\t' << up[i] << std::endl;
	sum_mj_Cplus += up[i];
      }
    }
    std::cout << "Knapsack Cover: C-" << std::endl;
    for (i = 0; i < rowLen; ++i) {
      if ( label[i] == CGLFLOW_COL_INCUT && sign[i] < 0 ) {
	std::cout << ind[i] << '\t' << up[i] << std::endl;
	sum_mj_Cminus += up[i];
      }
    }

    // rlh: verified "lambda" is lambda in the paper.
    // lambda = (sum coefficients in C+) - (sum of VUB
    // coefficients in C-) - rhs-orig-constraint
    std::cout << "lambda = " << lambda << std::endl;
  }

  //-------------------------------------------------------------------------
  // Generate a violated SGFC

  int numCMinus = 0;
  int numPlusPlus = 0;
  double* rho     = new double [rowLen];
  double* xCoef   = new double [rowLen];
  double* yCoef   = new double [rowLen];
  double cutRHS   = rhs;
  double temp     = 0.0;
  double sum      = 0.0;
  double minPlsM  = INFTY_;
  double minNegM  = INFTY_;

  for(i = 0; i < rowLen; ++i) {
    rho[i]   = 0.0;
    xCoef[i] = 0.0;
    yCoef[i] = 0.0;
  }

  // Project out variables in C-
  // d^' = d + sum_{i in C^-} m_i. Now cutRHS = d^'
  for (i = 0; i < rowLen; ++i) {
    if ( label[i] == CGLFLOW_COL_INCUT && sign[i] < 0 ) {
      cutRHS += up[i];
      ++numCMinus;
    }
  }

  // (1) Compute the coefficients of the simple generalized flow cover
  // (2) Compute minPlsM, minNegM and sum
  //
  // sum = sum_{i in C+\C++} m_i + sum_{i in L--} m_i = m. Page 15.
  // minPlsM = min_{i in C++} m_i
  // minNegM = min_{i in L-} m_i

  temp = cutRHS;

  for (i = 0; i < rowLen; ++i) {
    if (label[i] == CGLFLOW_COL_INCUT  && sign[i] > 0) { // C+
      yCoef[i] = 1.0;
      if ( up[i] > lambda + EPSILON_ ) { // C++
	++numPlusPlus;
	xCoef[i] = lambda - up[i];
	cutRHS += xCoef[i];
	if( up[i] < minPlsM ) {
	  minPlsM = up[i];
	}
      }
      else {  // C+\C++
	xCoef[i] = 0.0;  // rlh: is this necesarry? (xCoef initialized to zero)
	sum += up[i];
      }
    }

    if (label[i] != CGLFLOW_COL_INCUT && sign[i] < 0) { // N-\C-
      temp += up[i];
      if ( up[i] > lambda) {      // L-
	if(CGLFLOW_DEBUG) {
	  std::cout << "Variable " << ind[i] << " is in L-" << std::endl;
	}
	yCoef[i] = 0.0;
	xCoef[i] = -lambda;
	label[i] = CGLFLOW_COL_INLMIN;
	if ( up[i] < minNegM ) {
	  minNegM = up[i];
	}
      }
      else  {        // L--
	if(CGLFLOW_DEBUG) {
	  std::cout << "Variable " << ind[i] << " is in L-- " << std::endl;
	}
	yCoef[i] = -1.0;
	xCoef[i] = 0.0; // rlh: is this necesarry? (xCoef initialized to zero)
	label[i] = CGLFLOW_COL_INLMINMIN;
	sum += up[i];
      }
    }
  }

  // Sort the upper bounds (m_i) of variables in C++ and L-.

  int     ix;
  int     index  = 0;
  double  temp1  = 0.0;
  double* mt     = new double [rowLen];
  double* M      = new double [rowLen + 1];
  // order to look at variables
  int * order = new int [rowLen];
  int nLook=0;
  for (int i = 0; i < rowLen; ++i) {
    if ( (label[i] == CGLFLOW_COL_INCUT && sign[i] > 0) ||
	 label[i] == CGLFLOW_COL_INLMIN ) {     //  C+ || L-
      // possible
      M[nLook]=-up[i];
      order[nLook++]=i;
    }
  }
  CoinSort_2(M,M+nLook,order);
  int kLook=0;

  while (kLook<nLook) {
    ix = UNDEFINED_;
    i = order[kLook];
    kLook++;
    if ( (label[i] == CGLFLOW_COL_INCUT && sign[i] > 0) ||
	 label[i] == CGLFLOW_COL_INLMIN ) {     //  C+ || L-
      if ( up[i] > lambda ) {       // C++ || L-(up[i] > lambda)
	ix = i;
      }
    }

    if( ix == UNDEFINED_ )  break;

    mt[index++] = up[ix];  // Record m_i in C++ and L-(not all) in descending order.

    if( label[ix] == CGLFLOW_COL_INLMIN )
      label[ix] = CGLFLOW_COL_INLMINDONE;
    else
      label[ix] = CGLFLOW_COL_INCUTDONE;
  }
  //printf("mins %g %g\n",minNegM,minPlsM);
  if( index == 0 || numPlusPlus == 0) {
    // No column in C++ and L-(not all). RETURN.
    if(CGLFLOW_DEBUG) {
      std::cout << "index = 0. RETURN." << std::endl;
    }
    delete [] sign;
    delete [] up;
    delete [] x;
    delete [] y;
    delete [] candidate;
    delete [] label;
    delete [] ratio;
    delete [] rho;
    delete [] xCoef;
    delete [] yCoef;
    delete [] mt;
    delete [] M;
    delete [] order;
    return generated;
  }

  for ( i = 0; i < rowLen; i++ ) {
    switch( label[i] ) {
    case  CGLFLOW_COL_INCUTDONE:
      label[i] = CGLFLOW_COL_INCUT;
      break;
    case  CGLFLOW_COL_INLMIN:
    case  CGLFLOW_COL_INLMINDONE:
    case  CGLFLOW_COL_INLMINMIN:
      label[i] = CGLFLOW_COL_OUTCUT;
      break;
    case CGLFLOW_COL_INCUT:
    case CGLFLOW_COL_OUTCUT:
    case CGLFLOW_COL_PRIME:
    case CGLFLOW_COL_SECONDARY:
      break;
    }
  }

  temp1 = temp;

  /* Get t */
  t = 0;
  for ( i = 0; i < index; ++i ) {
    if ( mt[i] < minPlsM ) {
      t = i;
      break;
    }
  }

  if (i == index) {
    t = index;
  }

  /* Compute M_i */
  M[0] = 0.0;
  for ( i = 1; i <= index; ++i ) {
    M[i] = M[(i-1)] + mt[(i-1)];
    if(CGLFLOW_DEBUG) {
      std::cout << "t = " << t << std::endl;
      std::cout << "mt[" << std::setw(5) << (i-1) << "]=" << std::setw(2) << ", M[" << std::setw(5) << i << "]=" << std::setw(20) << M[i] << std::endl;
    }
  }
  // Exit if very big M
  if (M[index]>1.0e30) { // rlh: should test for huge col UB earler
    // no sense doing all this work in that case.
    if(CGLFLOW_DEBUG) {
      std::cout << "M[index]>1.0e30. RETURN." << std::endl;
      delete [] sign;
      delete [] up;
      delete [] x;
      delete [] y;
      delete [] candidate;
      delete [] label;
      delete [] ratio;
      delete [] rho;
      delete [] xCoef;
      delete [] yCoef;
      delete [] mt;
      delete [] M;
      delete [] order;
      return generated;
    }
  }

  /* Get ml */
  double ml = CoinMin(sum, lambda);
  if(CGLFLOW_DEBUG) {
    // sum = sum_{i in C+\C++} m_i + sum_{i in L--} m_i = m. Page 15.
    std::cout << "ml = CoinMin(m, lambda) = CoinMin(" << sum << ", " << lambda << ") =" << ml << std::endl;
  }
  /* rho_i = max[0, m_i - (minPlsM - lamda) - ml */
  if (t < index ) { /* rho exits only for t <= index-1 */
    value = (minPlsM - lambda) + ml;
    for (i = t; i < index; ++i) {
      rho[i] =  CoinMax(0.0, mt[i] - value);
      if(CGLFLOW_DEBUG) {
	std::cout << "rho[" << std::setw(5) << i << "]=" << std::setw(20) << rho[i] << std::endl;
      }
    }
  }
  // Calculate the violation
  violation = -cutRHS;
  for ( i = 0; i < rowLen; ++i ) {
#ifdef CGLFLOW_DEBUG2
    if(CGLFLOW_DEBUG) {
      std::cout << "i = " << i << " ind = " << ind[i] << " sign = "
		<< sign[i]
		<< " coef = " << coef[i] << " x = " << x[i] << " xCoef = "
		<< xCoef[i] << " y = " << y[i] << " yCoef = " << yCoef[i]
		<< " up = " << up[i] << " label = " << label[i] << std::endl;
    }
#endif
    violation += y[i] * yCoef[i] + x[i] * xCoef[i];
  }

  if(CGLFLOW_DEBUG) {
    std::cout << "violation = " << violation << std::endl;
  }
  //  double violationBeforeLift=violation; // variable not used anywhere (LL)
  if(doLift && fabs(violation) > TOLERANCE_ ) {  // LIFTING
    double estY, estX;
    double movement = 0.0;
    double dPrimePrime = temp + cutRHS;
    bool lifted = false;
    for( i = 0; i < rowLen; ++i ) {
      if ( (label[i] != CGLFLOW_COL_INCUT) && (sign[i] > 0) ) {/* N+\C+*/
	lifted = liftPlus(estY, estX,
			  index, up[i],
			  lambda,
			  y[i], x[i],
			  dPrimePrime, M);

	xCoef[i] = -estX;
	yCoef[i] = estY;
	if(CGLFLOW_DEBUG) {
	  if (lifted) {
	    printf("Success: Lifted col %i (up_i=%f,yCoef[i]=%f,xCoef[i]=%f) in N+\\C+\n",
		   ind[i], up[i], yCoef[i], xCoef[i]);
	  }
	  else {
	    printf("Failed to Lift col %i (m_i=%f) in N+\\C+\n",
		   ind[i], up[i]);
	  }
	}
      }
      if (label[i] == CGLFLOW_COL_INCUT && sign[i] < 0) {
	/* C- */
	liftMinus(movement, t,
		  index, up[i],
		  dPrimePrime,
		  lambda, ml,
		  M, rho);

	if(movement > EPSILON_) {
	  if(CGLFLOW_DEBUG) {
	    printf("Success: Lifted col %i in C-, movement=%f\n",
		   ind[i], movement);
	  }
	  lifted = true;
	  xCoef[i] = -movement;
	  cutRHS -= movement;
	}
	else {
	  if(CGLFLOW_DEBUG) {
	    printf("Failed to Lift col %i in C-, g=%f\n",
		   ind[i], movement);
	  }
	}
      }
    }
  }
  //-------------------------------------------------------------------


  // Calculate the violation
  violation = -cutRHS;
  for ( i = 0; i < rowLen; ++i ) {
#ifdef CGLFLOW_DEBUG2
    if(CGLFLOW_DEBUG) {
      std::cout << "i = " << i << " ind = " << ind[i] << " sign = "
		<< sign[i]
		<< " coef = " << coef[i] << " x = " << x[i] << " xCoef = "
		<< xCoef[i] << " y = " << y[i] << " yCoef = " << yCoef[i]
		<< " up = " << up[i] << " label = " << label[i] << std::endl;
    }
#endif
    violation += y[i] * yCoef[i] + x[i] * xCoef[i];
  }

  if(CGLFLOW_DEBUG) {
    std::cout << "violation = " << violation << std::endl;
  }

  int     cutLen     = 0;
  char    cutSense   = 'L';
  int*    cutInd     = 0;
  double* cutCoef    = 0;

  // If violated, transform the inequality back to original system
  if ( violation > TOLERANCE_ ) {
    cutLen = 0;
    cutSense = 'L';
    cutInd  = new int [numCols];
    cutCoef = new double [numCols];

    for ( i = 0; i < rowLen; ++i )  {
      VUB = getVubs(ind[i]);

      if ( ( sign[i] == CGLFLOW_COL_CONTPOS ) ||
	   ( sign[i] == CGLFLOW_COL_CONTNEG ) ) {

	if ( fabs( yCoef[i] ) > EPSILON_ ) {

	  if ( sign[i] == CGLFLOW_COL_CONTPOS )
	    cutCoef[cutLen] = coef[i] * yCoef[i];
	  else
	    cutCoef[cutLen] = -coef[i] * yCoef[i];

	  cutInd[cutLen++] = ind[i];
	}

	if ( fabs( xCoef[i] ) > EPSILON_ ) {
	  if ( VUB.getVar() != UNDEFINED_ ) {
	    cutCoef[cutLen] = xCoef[i];
	    cutInd[cutLen++] = VUB.getVar();
	  }
	  else
	    cutRHS -= xCoef[i];
	}
      }

      if ( ( sign[i] == CGLFLOW_COL_BINPOS ) ||
	   ( sign[i] == CGLFLOW_COL_BINNEG ) ) {
	if (fabs(yCoef[i]) > EPSILON_ || fabs(xCoef[i]) > EPSILON_) {
	  if (sign[i] == CGLFLOW_COL_BINPOS)
	    cutCoef[cutLen] = coef[i] * yCoef[i] + xCoef[i];
	  else
	    cutCoef[cutLen] = -coef[i] * yCoef[i] + xCoef[i];
	  cutInd[cutLen++] = ind[i];
	}
      }
    }

    for ( i = 0; i < cutLen; ++i ) {
      for ( j = 0; j < i; j++ ) {
	if ( cutInd[j] == cutInd[i] ) { /* Duplicate*/
	  cutCoef[j] += cutCoef[i];
	  cutInd[i] = -1;
	}
      }
    }

    for ( j = 0, i = 0; i < cutLen; ++i ) {
      if ( ( cutInd[i] == -1 ) || ( fabs( cutCoef[i]) < EPSILON_ ) ){
	/* Small coeff*/
      }
      else {
	cutCoef[j] = cutCoef[i];
	cutInd[j] = cutInd[i];
	j++;
      }
    }

    cutLen = j;
    // Skip if no elements ? - bug somewhere
    assert (cutLen);

    // Recheck the violation.
    violation = 0.0;
    for (i = 0; i < cutLen; ++i)
      violation += cutCoef[i] * xlp[cutInd[i]];

    violation -= cutRHS;

    if ( violation > TOLERANCE_ ) {
      flowCut.setRow(cutLen, cutInd, cutCoef);
      flowCut.setLb(-1.0 * si.getInfinity());
      flowCut.setUb(cutRHS);
      flowCut.setEffectiveness(violation);
      generated = true;

      if(CGLFLOW_DEBUG) {
	std::cout << "generateOneFlowCover(): Found a cut" << std::endl;
      }
    }
    else {
      if(CGLFLOW_DEBUG) {
	std::cout << "generateOneFlowCover(): Lost a cut" << std::endl;
      }
    }
  }

  //-------------------------------------------------------------------------
  delete [] sign;
  delete [] up;
  delete [] x;
  delete [] y;
  delete [] candidate;
  delete [] label;
  delete [] ratio;
  delete [] rho;
  delete [] xCoef;
  delete [] yCoef;
  delete [] mt;
  delete [] M;
  delete [] order;
  delete [] cutInd;
  delete [] cutCoef;

  return generated;
}
Пример #29
0
int main(int argc, const char *argv[])
{
#if COIN_BIG_INDEX<2
     ClpSimplex  model;
     int status;
     int maxIts = 0;
     int maxFactor = 100;
     if (argc < 2) {
#if defined(SAMPLEDIR)
          status = model.readMps(SAMPLEDIR "/p0033.mps", true);
#else
          fprintf(stderr, "Do not know where to find sample MPS files.\n");
          exit(1);
#endif
     } else
          status = model.readMps(argv[1]);
     if (status) {
          printf("errors on input\n");
          exit(77);
     }
     if (argc > 2) {
          maxFactor = atoi(argv[2]);
          printf("max factor %d\n", maxFactor);
     }
     if (argc > 3) {
          maxIts = atoi(argv[3]);
          printf("max its %d\n", maxIts);
     }
     // For now scaling off
     model.scaling(0);
     if (maxIts) {
          // Do partial dantzig
          ClpPrimalColumnSteepest dantzig(5);
          model.setPrimalColumnPivotAlgorithm(dantzig);
          //model.messageHandler()->setLogLevel(63);
          model.setFactorizationFrequency(maxFactor);
          model.setMaximumIterations(maxIts);
          model.primal();
          if (!model.status())
               exit(1);
     }
     // find gub
     int numberRows = model.numberRows();
     int * gubStart = new int[numberRows+1];
     int * gubEnd = new int[numberRows];
     int * which = new int[numberRows];
     int * whichGub = new int[numberRows];
     int numberColumns = model.numberColumns();
     int * mark = new int[numberColumns];
     int iRow, iColumn;
     // delete variables fixed to zero
     const double * columnLower = model.columnLower();
     const double * columnUpper = model.columnUpper();
     int numberDelete = 0;
     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
          if (columnUpper[iColumn] == 0.0 && columnLower[iColumn] == 0.0)
               mark[numberDelete++] = iColumn;
     }
     if (numberDelete) {
          model.deleteColumns(numberDelete, mark);
          numberColumns -= numberDelete;
          columnLower = model.columnLower();
          columnUpper = model.columnUpper();
#if 0
          CoinMpsIO writer;
          writer.setMpsData(*model.matrix(), COIN_DBL_MAX,
                            model.getColLower(), model.getColUpper(),
                            model.getObjCoefficients(),
                            (const char*) 0 /*integrality*/,
                            model.getRowLower(), model.getRowUpper(),
                            NULL, NULL);
          writer.writeMps("cza.mps", 0, 0, 1);
#endif
     }
     double * lower = new double[numberRows];
     double * upper = new double[numberRows];
     const double * rowLower = model.rowLower();
     const double * rowUpper = model.rowUpper();
     for (iColumn = 0; iColumn < numberColumns; iColumn++)
          mark[iColumn] = -1;
     CoinPackedMatrix * matrix = model.matrix();
     // get row copy
     CoinPackedMatrix rowCopy = *matrix;
     rowCopy.reverseOrdering();
     const int * column = rowCopy.getIndices();
     const int * rowLength = rowCopy.getVectorLengths();
     const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
     const double * element = rowCopy.getElements();
     int putGub = numberRows;
     int putNonGub = numberRows;
     int * rowIsGub = new int [numberRows];
     for (iRow = numberRows - 1; iRow >= 0; iRow--) {
          bool gubRow = true;
          int first = numberColumns + 1;
          int last = -1;
          for (int j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
               if (element[j] != 1.0) {
                    gubRow = false;
                    break;
               } else {
                    int iColumn = column[j];
                    if (mark[iColumn] >= 0) {
                         gubRow = false;
                         break;
                    } else {
                         last = CoinMax(last, iColumn);
                         first = CoinMin(first, iColumn);
                    }
               }
          }
          if (last - first + 1 != rowLength[iRow] || !gubRow) {
               which[--putNonGub] = iRow;
               rowIsGub[iRow] = 0;
          } else {
               for (int j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
                    int iColumn = column[j];
                    mark[iColumn] = iRow;
               }
               rowIsGub[iRow] = -1;
               putGub--;
               gubStart[putGub] = first;
               gubEnd[putGub] = last + 1;
               lower[putGub] = rowLower[iRow];
               upper[putGub] = rowUpper[iRow];
               whichGub[putGub] = iRow;
          }
     }
     int numberNonGub = numberRows - putNonGub;
     int numberGub = numberRows - putGub;
     if (numberGub > 0) {
          printf("** %d gub rows\n", numberGub);
          int numberNormal = 0;
          const int * row = matrix->getIndices();
          const int * columnLength = matrix->getVectorLengths();
          const CoinBigIndex * columnStart = matrix->getVectorStarts();
          const double * elementByColumn = matrix->getElements();
          int numberElements = 0;
          bool doLower = false;
          bool doUpper = false;
          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
               if (mark[iColumn] < 0) {
                    mark[numberNormal++] = iColumn;
               } else {
                    numberElements += columnLength[iColumn];
                    if (columnLower[iColumn] != 0.0)
                         doLower = true;
                    if (columnUpper[iColumn] < 1.0e20)
                         doUpper = true;
               }
          }
          if (!numberNormal) {
               printf("Putting back one gub row to make non-empty\n");
               for (iColumn = gubStart[putGub]; iColumn < gubEnd[putGub]; iColumn++)
                    mark[numberNormal++] = iColumn;
               putGub++;
               numberGub--;
          }
          ClpSimplex model2(&model, numberNonGub, which + putNonGub, numberNormal, mark);
          int numberGubColumns = numberColumns - numberNormal;
          // sort gubs so monotonic
          int * which = new int[numberGub];
          int i;
          for (i = 0; i < numberGub; i++)
               which[i] = i;
          CoinSort_2(gubStart + putGub, gubStart + putGub + numberGub, which);
          int * temp1 = new int [numberGub];
          for (i = 0; i < numberGub; i++) {
               int k = which[i];
               temp1[i] = gubEnd[putGub+k];
          }
          memcpy(gubEnd + putGub, temp1, numberGub * sizeof(int));
          delete [] temp1;
          double * temp2 = new double [numberGub];
          for (i = 0; i < numberGub; i++) {
               int k = which[i];
               temp2[i] = lower[putGub+k];
          }
          memcpy(lower + putGub, temp2, numberGub * sizeof(double));
          for (i = 0; i < numberGub; i++) {
               int k = which[i];
               temp2[i] = upper[putGub+k];
          }
          memcpy(upper + putGub, temp2, numberGub * sizeof(double));
          delete [] temp2;
          delete [] which;
          numberElements -= numberGubColumns;
          int * start2 = new int[numberGubColumns+1];
          int * row2 = new int[numberElements];
          double * element2 = new double[numberElements];
          double * cost2 = new double [numberGubColumns];
          double * lowerColumn2 = NULL;
          if (doLower) {
               lowerColumn2 = new double [numberGubColumns];
               CoinFillN(lowerColumn2, numberGubColumns, 0.0);
          }
          double * upperColumn2 = NULL;
          if (doUpper) {
               upperColumn2 = new double [numberGubColumns];
               CoinFillN(upperColumn2, numberGubColumns, COIN_DBL_MAX);
          }
          numberElements = 0;
          int numberNonGubRows = 0;
          for (iRow = 0; iRow < numberRows; iRow++) {
               if (!rowIsGub[iRow])
                    rowIsGub[iRow] = numberNonGubRows++;
          }
          numberColumns = 0;
          gubStart[0] = 0;
          start2[0] = 0;
          const double * cost = model.objective();
          for (int iSet = 0; iSet < numberGub; iSet++) {
               int iStart = gubStart[iSet+putGub];
               int iEnd = gubEnd[iSet+putGub];
               for (int k = iStart; k < iEnd; k++) {
                    cost2[numberColumns] = cost[k];
                    if (columnLower[k])
                         lowerColumn2[numberColumns] = columnLower[k];
                    if (columnUpper[k] < 1.0e20)
                         upperColumn2[numberColumns] = columnUpper[k];
                    for (int j = columnStart[k]; j < columnStart[k] + columnLength[k]; j++) {
                         int iRow = rowIsGub[row[j]];
                         if (iRow >= 0) {
                              row2[numberElements] = iRow;
                              element2[numberElements++] = elementByColumn[j];
                         }
                    }
                    start2[++numberColumns] = numberElements;
               }
               gubStart[iSet+1] = numberColumns;
          }
          model2.replaceMatrix(new ClpGubDynamicMatrix(&model2, numberGub,
                               numberColumns, gubStart,
                               lower + putGub, upper + putGub,
                               start2, row2, element2, cost2,
                               lowerColumn2, upperColumn2));
          delete [] rowIsGub;
          delete [] start2;
          delete [] row2;
          delete [] element2;
          delete [] cost2;
          delete [] lowerColumn2;
          delete [] upperColumn2;
          // For now scaling off
          model2.scaling(0);
          // Do partial dantzig
          ClpPrimalColumnSteepest dantzig(5);
          model2.setPrimalColumnPivotAlgorithm(dantzig);
          //model2.messageHandler()->setLogLevel(63);
          model2.setFactorizationFrequency(maxFactor);
          model2.setMaximumIterations(4000000);
          double time1 = CoinCpuTime();
          model2.primal();
          {
               ClpGubDynamicMatrix * gubMatrix =
                    dynamic_cast< ClpGubDynamicMatrix*>(model2.clpMatrix());
               assert(gubMatrix);
               const double * solution = model2.primalColumnSolution();
               int numberGubColumns = gubMatrix->numberGubColumns();
               int firstOdd = gubMatrix->firstDynamic();
               int lastOdd = gubMatrix->firstAvailable();
               int numberTotalColumns = firstOdd + numberGubColumns;
               int numberRows = model2.numberRows();
               char * status = new char [numberTotalColumns];
               double * gubSolution = new double [numberTotalColumns];
               int numberSets = gubMatrix->numberSets();
               const int * id = gubMatrix->id();
               int i;
               const double * lowerColumn = gubMatrix->lowerColumn();
               const double * upperColumn = gubMatrix->upperColumn();
               for (i = 0; i < numberGubColumns; i++) {
                    if (gubMatrix->getDynamicStatus(i) == ClpGubDynamicMatrix::atUpperBound) {
                         gubSolution[i+firstOdd] = upperColumn[i];
                         status[i+firstOdd] = 2;
                    } else if (gubMatrix->getDynamicStatus(i) == ClpGubDynamicMatrix::atLowerBound && lowerColumn) {
                         gubSolution[i+firstOdd] = lowerColumn[i];
                         status[i+firstOdd] = 1;
                    } else {
                         gubSolution[i+firstOdd] = 0.0;
                         status[i+firstOdd] = 1;
                    }
               }
               for (i = 0; i < firstOdd; i++) {
                    ClpSimplex::Status thisStatus = model2.getStatus(i);
                    if (thisStatus == ClpSimplex::basic)
                         status[i] = 0;
                    else if (thisStatus == ClpSimplex::atLowerBound)
                         status[i] = 1;
                    else if (thisStatus == ClpSimplex::atUpperBound)
                         status[i] = 2;
                    else if (thisStatus == ClpSimplex::isFixed)
                         status[i] = 3;
                    else
                         abort();
                    gubSolution[i] = solution[i];
               }
               for (i = firstOdd; i < lastOdd; i++) {
                    int iBig = id[i-firstOdd] + firstOdd;
                    ClpSimplex::Status thisStatus = model2.getStatus(i);
                    if (thisStatus == ClpSimplex::basic)
                         status[iBig] = 0;
                    else if (thisStatus == ClpSimplex::atLowerBound)
                         status[iBig] = 1;
                    else if (thisStatus == ClpSimplex::atUpperBound)
                         status[iBig] = 2;
                    else if (thisStatus == ClpSimplex::isFixed)
                         status[iBig] = 3;
                    else
                         abort();
                    gubSolution[iBig] = solution[i];
               }
               char * rowStatus = new char[numberRows];
               for (i = 0; i < numberRows; i++) {
                    ClpSimplex::Status thisStatus = model2.getRowStatus(i);
                    if (thisStatus == ClpSimplex::basic)
                         rowStatus[i] = 0;
                    else if (thisStatus == ClpSimplex::atLowerBound)
                         rowStatus[i] = 1;
                    else if (thisStatus == ClpSimplex::atUpperBound)
                         rowStatus[i] = 2;
                    else if (thisStatus == ClpSimplex::isFixed)
                         rowStatus[i] = 3;
                    else
                         abort();
               }
               char * setStatus = new char[numberSets];
               int * keyVariable = new int[numberSets];
               memcpy(keyVariable, gubMatrix->keyVariable(), numberSets * sizeof(int));
               for (i = 0; i < numberSets; i++) {
                    int iKey = keyVariable[i];
                    if (iKey > lastOdd)
                         iKey = numberTotalColumns + i;
                    else
                         iKey = id[iKey-firstOdd] + firstOdd;
                    keyVariable[i] = iKey;
                    ClpSimplex::Status thisStatus = gubMatrix->getStatus(i);
                    if (thisStatus == ClpSimplex::basic)
                         setStatus[i] = 0;
                    else if (thisStatus == ClpSimplex::atLowerBound)
                         setStatus[i] = 1;
                    else if (thisStatus == ClpSimplex::atUpperBound)
                         setStatus[i] = 2;
                    else if (thisStatus == ClpSimplex::isFixed)
                         setStatus[i] = 3;
                    else
                         abort();
               }
               FILE * fp = fopen("xx.sol", "w");
               fwrite(gubSolution, sizeof(double), numberTotalColumns, fp);
               fwrite(status, sizeof(char), numberTotalColumns, fp);
               const double * rowsol = model2.primalRowSolution();
               int originalNumberRows = model.numberRows();
               double * rowsol2 = new double[originalNumberRows];
               memset(rowsol2, 0, originalNumberRows * sizeof(double));
               model.times(1.0, gubSolution, rowsol2);
               for (i = 0; i < numberRows; i++)
                    assert(fabs(rowsol[i] - rowsol2[i]) < 1.0e-3);
               //for (;i<originalNumberRows;i++)
               //printf("%d %g\n",i,rowsol2[i]);
               delete [] rowsol2;
               fwrite(rowsol, sizeof(double), numberRows, fp);
               fwrite(rowStatus, sizeof(char), numberRows, fp);
               fwrite(setStatus, sizeof(char), numberSets, fp);
               fwrite(keyVariable, sizeof(int), numberSets, fp);
               fclose(fp);
               delete [] status;
               delete [] gubSolution;
               delete [] setStatus;
               delete [] keyVariable;
               // ** if going to rstart as dynamic need id_
               // also copy coding in useEf.. from ClpGubMatrix (i.e. test for basis)
          }
          printf("obj offset is %g\n", model2.objectiveOffset());
          printf("Primal took %g seconds\n", CoinCpuTime() - time1);
          //model2.primal(1);
     }
     delete [] mark;
     delete [] gubStart;
     delete [] gubEnd;
     delete [] which;
     delete [] whichGub;
     delete [] lower;
     delete [] upper;
#else
     printf("testGub2 not available with COIN_BIG_INDEX=2\n");
#endif
     return 0;
}
Пример #30
0
// This version fixes stuff and does IP
int
CbcHeuristicLocal::solutionFix(double & objectiveValue,
                               double * newSolution,
                               const int * /*keep*/)
{
/*
  If when is set to off (0), or set to root (1) and we're not at the root,
  return. If this heuristic discovered the current solution, don't continue.
*/

    numCouldRun_++;
    // See if to do
    if (!when() || (when() == 1 && model_->phase() != 1))
        return 0; // switched off
    // Don't do if it was this heuristic which found solution!
    if (this == model_->lastHeuristic())
        return 0;
/*
  Load up a new solver with the solution.

  Why continuousSolver(), as opposed to solver()?
*/
    OsiSolverInterface * newSolver = model_->continuousSolver()->clone();
    const double * colLower = newSolver->getColLower();
    //const double * colUpper = newSolver->getColUpper();

    int numberIntegers = model_->numberIntegers();
    const int * integerVariable = model_->integerVariable();
/*
  The net effect here is that anything that hasn't moved from its lower bound
  will be fixed at lower bound.

  See comments in solution() w.r.t. asymmetric treatment of upper and lower
  bounds.
*/

    int i;
    int nFix = 0;
    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);
        newSolver->setColLower(iColumn, CoinMax(colLower[iColumn], originalLower));
        if (!used_[iColumn]) {
            newSolver->setColUpper(iColumn, colLower[iColumn]);
            nFix++;
        }
    }
/*
  Try a `small' branch-and-bound search. The notion here is that we've fixed a
  lot of variables and reduced the amount of `free' problem to a point where a
  small BaB search will suffice to fully explore the remaining problem. This
  routine will execute integer presolve, then call branchAndBound to do the
  actual search.
*/
    int returnCode = 0;
#ifdef CLP_INVESTIGATE2
    printf("Fixing %d out of %d (%d continuous)\n",
           nFix, numberIntegers, newSolver->getNumCols() - numberIntegers);
#endif
    if (nFix*10 <= numberIntegers) {
        // see if we can fix more
        int * which = new int [2*(numberIntegers-nFix)];
        int * sort = which + (numberIntegers - nFix);
        int n = 0;
        for (i = 0; i < numberIntegers; i++) {
            int iColumn = integerVariable[i];
            if (used_[iColumn]) {
                which[n] = iColumn;
                sort[n++] = used_[iColumn];
            }
        }
        CoinSort_2(sort, sort + n, which);
        // only half fixed in total
        n = CoinMin(n, numberIntegers / 2 - nFix);
        int allow = CoinMax(numberSolutions_ - 2, sort[0]);
        int nFix2 = 0;
        for (i = 0; i < n; i++) {
            int iColumn = integerVariable[i];
            if (used_[iColumn] <= allow) {
                newSolver->setColUpper(iColumn, colLower[iColumn]);
                nFix2++;
            } else {
                break;
            }
        }
        delete [] which;
        nFix += nFix2;
#ifdef CLP_INVESTIGATE2
        printf("Number fixed increased from %d to %d\n",
               nFix - nFix2, nFix);
#endif
    }
    if (nFix*10 > numberIntegers) {
        returnCode = smallBranchAndBound(newSolver, numberNodes_, newSolution, objectiveValue,
                                         objectiveValue, "CbcHeuristicLocal");
 /*
  -2 is return due to user event, and -1 is overloaded with what look to be
  two contradictory meanings.
*/
       if (returnCode < 0) {
            returnCode = 0; // returned on size
            int numberColumns = newSolver->getNumCols();
            int numberContinuous = numberColumns - numberIntegers;
            if (numberContinuous > 2*numberIntegers &&
                    nFix*10 < numberColumns) {
#define LOCAL_FIX_CONTINUOUS
#ifdef LOCAL_FIX_CONTINUOUS
                //const double * colUpper = newSolver->getColUpper();
                const double * colLower = newSolver->getColLower();
                int nAtLb = 0;
                //double sumDj=0.0;
                const double * dj = newSolver->getReducedCost();
                double direction = newSolver->getObjSense();
                for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
                    if (!newSolver->isInteger(iColumn)) {
                        if (!used_[iColumn]) {
                            //double djValue = dj[iColumn]*direction;
                            nAtLb++;
                            //sumDj += djValue;
                        }
                    }
                }
                if (nAtLb) {
                    // fix some continuous
                    double * sort = new double[nAtLb];
                    int * which = new int [nAtLb];
                    //double threshold = CoinMax((0.01*sumDj)/static_cast<double>(nAtLb),1.0e-6);
                    int nFix2 = 0;
                    for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
                        if (!newSolver->isInteger(iColumn)) {
                            if (!used_[iColumn]) {
                                double djValue = dj[iColumn] * direction;
                                if (djValue > 1.0e-6) {
                                    sort[nFix2] = -djValue;
                                    which[nFix2++] = iColumn;
                                }
                            }
                        }
                    }
                    CoinSort_2(sort, sort + nFix2, which);
                    int divisor = 2;
                    nFix2 = CoinMin(nFix2, (numberColumns - nFix) / divisor);
                    for (int i = 0; i < nFix2; i++) {
                        int iColumn = which[i];
                        newSolver->setColUpper(iColumn, colLower[iColumn]);
                    }
                    delete [] sort;
                    delete [] which;
#ifdef CLP_INVESTIGATE2
                    printf("%d integers have zero value, and %d continuous fixed at lb\n",
                           nFix, nFix2);
#endif
                    returnCode = smallBranchAndBound(newSolver,
                                                     numberNodes_, newSolution,
                                                     objectiveValue,
                                                     objectiveValue, "CbcHeuristicLocal");
                    if (returnCode < 0)
                        returnCode = 0; // returned on size
                }
#endif
            }
        }
    }
/*
  If the result is complete exploration with a solution (3) or proven
  infeasibility (2), we could generate a cut (the AI folks would call it a
  nogood) to prevent us from going down this route in the future.
*/
    if ((returnCode&2) != 0) {
        // could add cut
        returnCode &= ~2;
    }

    delete newSolver;
    return returnCode;
}