Пример #1
0
//-------------------------------------------------------------------
// Copy constructor
//-------------------------------------------------------------------
ClpQuadraticObjective::ClpQuadraticObjective(const ClpQuadraticObjective &rhs,
  int type)
  : ClpObjective(rhs)
{
  numberColumns_ = rhs.numberColumns_;
  numberExtendedColumns_ = rhs.numberExtendedColumns_;
  fullMatrix_ = rhs.fullMatrix_;
  if (rhs.objective_) {
    objective_ = new double[numberExtendedColumns_];
    CoinMemcpyN(rhs.objective_, numberExtendedColumns_, objective_);
  } else {
    objective_ = NULL;
  }
  if (rhs.gradient_) {
    gradient_ = new double[numberExtendedColumns_];
    CoinMemcpyN(rhs.gradient_, numberExtendedColumns_, gradient_);
  } else {
    gradient_ = NULL;
  }
  if (rhs.quadraticObjective_) {
    // see what type of matrix wanted
    if (type == 0) {
      // just copy
      quadraticObjective_ = new CoinPackedMatrix(*rhs.quadraticObjective_);
    } else if (type == 1) {
      // expand to full symmetric
      fullMatrix_ = true;
      const int *columnQuadratic1 = rhs.quadraticObjective_->getIndices();
      const CoinBigIndex *columnQuadraticStart1 = rhs.quadraticObjective_->getVectorStarts();
      const int *columnQuadraticLength1 = rhs.quadraticObjective_->getVectorLengths();
      const double *quadraticElement1 = rhs.quadraticObjective_->getElements();
      CoinBigIndex *columnQuadraticStart2 = new CoinBigIndex[numberExtendedColumns_ + 1];
      int *columnQuadraticLength2 = new int[numberExtendedColumns_];
      int iColumn;
      int numberColumns = rhs.quadraticObjective_->getNumCols();
      int numberBelow = 0;
      int numberAbove = 0;
      int numberDiagonal = 0;
      CoinZeroN(columnQuadraticLength2, numberExtendedColumns_);
      for (iColumn = 0; iColumn < numberColumns; iColumn++) {
        for (CoinBigIndex j = columnQuadraticStart1[iColumn];
             j < columnQuadraticStart1[iColumn] + columnQuadraticLength1[iColumn]; j++) {
          int jColumn = columnQuadratic1[j];
          if (jColumn > iColumn) {
            numberBelow++;
            columnQuadraticLength2[jColumn]++;
            columnQuadraticLength2[iColumn]++;
          } else if (jColumn == iColumn) {
            numberDiagonal++;
            columnQuadraticLength2[iColumn]++;
          } else {
            numberAbove++;
          }
        }
      }
      if (numberAbove > 0) {
        if (numberAbove == numberBelow) {
          // already done
          quadraticObjective_ = new CoinPackedMatrix(*rhs.quadraticObjective_);
          delete[] columnQuadraticStart2;
          delete[] columnQuadraticLength2;
        } else {
          printf("number above = %d, number below = %d, error\n",
            numberAbove, numberBelow);
          abort();
        }
      } else {
        int numberElements = numberDiagonal + 2 * numberBelow;
        int *columnQuadratic2 = new int[numberElements];
        double *quadraticElement2 = new double[numberElements];
        columnQuadraticStart2[0] = 0;
        numberElements = 0;
        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
          int n = columnQuadraticLength2[iColumn];
          columnQuadraticLength2[iColumn] = 0;
          numberElements += n;
          columnQuadraticStart2[iColumn + 1] = numberElements;
        }
        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
          for (CoinBigIndex j = columnQuadraticStart1[iColumn];
               j < columnQuadraticStart1[iColumn] + columnQuadraticLength1[iColumn]; j++) {
            int jColumn = columnQuadratic1[j];
            if (jColumn > iColumn) {
              // put in two places
              CoinBigIndex put = columnQuadraticLength2[jColumn] + columnQuadraticStart2[jColumn];
              columnQuadraticLength2[jColumn]++;
              quadraticElement2[put] = quadraticElement1[j];
              columnQuadratic2[put] = iColumn;
              put = columnQuadraticLength2[iColumn] + columnQuadraticStart2[iColumn];
              columnQuadraticLength2[iColumn]++;
              quadraticElement2[put] = quadraticElement1[j];
              columnQuadratic2[put] = jColumn;
            } else if (jColumn == iColumn) {
              CoinBigIndex put = columnQuadraticLength2[iColumn] + columnQuadraticStart2[iColumn];
              columnQuadraticLength2[iColumn]++;
              quadraticElement2[put] = quadraticElement1[j];
              columnQuadratic2[put] = iColumn;
            } else {
              abort();
            }
          }
        }
        // Now create
        quadraticObjective_ = new CoinPackedMatrix(true,
          rhs.numberExtendedColumns_,
          rhs.numberExtendedColumns_,
          numberElements,
          quadraticElement2,
          columnQuadratic2,
          columnQuadraticStart2,
          columnQuadraticLength2, 0.0, 0.0);
        delete[] columnQuadraticStart2;
        delete[] columnQuadraticLength2;
        delete[] columnQuadratic2;
        delete[] quadraticElement2;
      }
    } else {
      fullMatrix_ = false;
      abort(); // code when needed
    }

  } else {
    quadraticObjective_ = NULL;
  }
}
Пример #2
0
void CoinPresolveMatrix::setMatrix (const CoinPackedMatrix *mtx)

{
/*
  Check to make sure the matrix will fit and is column ordered.
*/
  if (mtx->isColOrdered() == false)
  { throw CoinError("source matrix must be column ordered",
		    "setMatrix","CoinPrePostsolveMatrix") ; }

  int numCols = mtx->getNumCols() ;
  if (numCols > ncols0_)
  { throw CoinError("source matrix exceeds allocated capacity",
		    "setMatrix","CoinPrePostsolveMatrix") ; }
/*
  Acquire the actual size, but allocate the matrix storage to the
  requested capacity. The column-major rep is part of the PrePostsolve
  object, the row-major rep belongs to the Presolve object.
*/
  ncols_ = numCols ;
  nrows_ = mtx->getNumRows() ;
  nelems_ = mtx->getNumElements() ;
  bulk0_ = static_cast<CoinBigIndex> (bulkRatio_*nelems0_) ;

  if (mcstrt_ == 0) mcstrt_ = new CoinBigIndex [ncols0_+1] ;
  if (hincol_ == 0) hincol_ = new int [ncols0_+1] ;
  if (hrow_ == 0) hrow_ = new int [bulk0_] ;
  if (colels_ == 0) colels_ = new double [bulk0_] ;

  if (mrstrt_ == 0) mrstrt_ = new CoinBigIndex [nrows0_+1] ;
  if (hinrow_ == 0) hinrow_ = new int [nrows0_+1] ;
  if (hcol_ == 0) hcol_ = new int [bulk0_] ;
  if (rowels_ == 0) rowels_ = new double [bulk0_] ;
/*
  Grab the corresponding vectors from the source matrix.
*/
  const CoinBigIndex *src_mcstrt = mtx->getVectorStarts() ;
  const int *src_hincol = mtx->getVectorLengths() ;
  const double *src_colels = mtx->getElements() ;
  const int *src_hrow = mtx->getIndices() ;
/*
  Bulk copy the column starts and lengths.
*/
  CoinMemcpyN(src_mcstrt,mtx->getSizeVectorStarts(),mcstrt_) ;
  CoinMemcpyN(src_hincol,mtx->getSizeVectorLengths(),hincol_) ;
/*
  Copy the coefficients column by column in case there are gaps between
  the columns in the bulk storage area. The assert is just in case the
  gaps are *really* big.
*/
  assert(src_mcstrt[ncols_] <= bulk0_) ;
  int j;
  for ( j = 0 ; j < numCols ; j++)
  { int lenj = src_hincol[j] ;
    CoinBigIndex offset = mcstrt_[j] ;
    CoinMemcpyN(src_colels+offset,lenj,colels_+offset) ;
    CoinMemcpyN(src_hrow+offset,lenj,hrow_+offset) ; }
/*
  Now make a row-major copy. Start by counting the number of coefficients in
  each row; we can do this directly in hinrow. Given the number of
  coefficients in a row, we know how to lay out the bulk storage area.
*/
  CoinZeroN(hinrow_,nrows0_+1) ;
  for ( j = 0 ; j < ncols_ ; j++)
  { int *rowIndices = hrow_+mcstrt_[j] ;
    int lenj = hincol_[j] ;
    for (int k = 0 ; k < lenj ; k++)
    { int i = rowIndices[k] ;
      hinrow_[i]++ ; } }
/*
  Initialize mrstrt[i] to the start of row i+1. As we drop each coefficient
  and column index into the bulk storage arrays, we'll decrement and store.
  When we're done, mrstrt[i] will point to the start of row i, as it should.
*/
  int totalCoeffs = 0 ;
  int i;
  for ( i = 0 ; i < nrows_ ; i++)
  { totalCoeffs += hinrow_[i] ;
    mrstrt_[i] = totalCoeffs ; }
  mrstrt_[nrows_] = totalCoeffs ;
  for ( j = ncols_-1 ; j >= 0 ; j--)
  { int lenj = hincol_[j] ;
    double *colCoeffs = colels_+mcstrt_[j] ;
    int *rowIndices = hrow_+mcstrt_[j] ;
    for (int k = 0 ; k < lenj ; k++)
    { int ri;
      ri = rowIndices[k] ;
      double aij = colCoeffs[k] ;
      CoinBigIndex l = --mrstrt_[ri] ;
      rowels_[l] = aij ;
      hcol_[l] = j ; } }
/*
  Now the support structures. The entry for original column j should start
  out as j; similarly for row i. originalColumn_ and originalRow_ belong to
  the PrePostsolve object.
*/
  if (originalColumn_ == 0) originalColumn_ = new int [ncols0_] ;
  if (originalRow_ == 0) originalRow_ = new int [nrows0_] ;

  for ( j = 0 ; j < ncols0_ ; j++) 
    originalColumn_[j] = j ;
  for ( i = 0 ; i < nrows0_ ; i++) 
    originalRow_[i] = i ;
/*
  We have help to set up the clink_ and rlink_ vectors (aids for matrix bulk
  storage management). clink_ and rlink_ belong to the Presolve object.  Once
  this is done, it's safe to set mrstrt_[nrows_] and mcstrt_[ncols_] to the
  full size of the bulk storage area.
*/
  if (clink_ == 0) clink_ = new presolvehlink [ncols0_+1] ;
  if (rlink_ == 0) rlink_ = new presolvehlink [nrows0_+1] ;
  presolve_make_memlists(/*mcstrt_,*/hincol_,clink_,ncols_) ;
  presolve_make_memlists(/*mrstrt_,*/hinrow_,rlink_,nrows_) ;
  mcstrt_[ncols_] = bulk0_ ;
  mrstrt_[nrows_] = bulk0_ ;
/*
  No rows or columns have been changed just yet. colChanged_ and rowChanged_
  belong to the Presolve object.
*/
  if (colChanged_ == 0) colChanged_ = new unsigned char [ncols0_] ;
  CoinZeroN(colChanged_,ncols0_) ;
  if (rowChanged_ == 0) rowChanged_ = new unsigned char [nrows0_] ;
  CoinZeroN(rowChanged_,nrows0_) ;
/*
  Finally, allocate the various *ToDo arrays. These are used to track the rows
  and columns which should be processed in a given round of presolve
  transforms. These belong to the Presolve object. Setting number*ToDo to 0
  is all the initialization that's required here.
*/
  rowsToDo_ = new int [nrows0_] ;
  numberRowsToDo_ = 0 ;
  nextRowsToDo_ = new int [nrows0_] ;
  numberNextRowsToDo_ = 0 ;
  colsToDo_ = new int [ncols0_] ;
  numberColsToDo_ = 0 ;
  nextColsToDo_ = new int [ncols0_] ;
  numberNextColsToDo_ = 0 ;
  initializeStuff();
  return ; }
Пример #3
0
// fix variables interior says should be
void
ClpInterior::fixFixed(bool reallyFix)
{
     // Arrays for change in columns and rhs
     CoinWorkDouble * columnChange = new CoinWorkDouble[numberColumns_];
     CoinWorkDouble * rowChange = new CoinWorkDouble[numberRows_];
     CoinZeroN(columnChange, numberColumns_);
     CoinZeroN(rowChange, numberRows_);
     matrix_->times(1.0, columnChange, rowChange);
     int i;
     CoinWorkDouble tolerance = primalTolerance();
     for (i = 0; i < numberColumns_; i++) {
          if (columnUpper_[i] < 1.0e20 || columnLower_[i] > -1.0e20) {
               if (columnUpper_[i] > columnLower_[i]) {
                    if (fixedOrFree(i)) {
                         if (columnActivity_[i] - columnLower_[i] < columnUpper_[i] - columnActivity_[i]) {
                              CoinWorkDouble change = columnLower_[i] - columnActivity_[i];
                              if (CoinAbs(change) < tolerance) {
                                   if (reallyFix)
                                        columnUpper_[i] = columnLower_[i];
                                   columnChange[i] = change;
                                   columnActivity_[i] = columnLower_[i];
                              }
                         } else {
                              CoinWorkDouble change = columnUpper_[i] - columnActivity_[i];
                              if (CoinAbs(change) < tolerance) {
                                   if (reallyFix)
                                        columnLower_[i] = columnUpper_[i];
                                   columnChange[i] = change;
                                   columnActivity_[i] = columnUpper_[i];
                              }
                         }
                    }
               }
          }
     }
     CoinZeroN(rowChange, numberRows_);
     matrix_->times(1.0, columnChange, rowChange);
     // If makes mess of things then don't do
     CoinWorkDouble newSum = 0.0;
     for (i = 0; i < numberRows_; i++) {
          CoinWorkDouble value = rowActivity_[i] + rowChange[i];
          if (value > rowUpper_[i] + tolerance)
               newSum += value - rowUpper_[i] - tolerance;
          else if (value < rowLower_[i] - tolerance)
               newSum -= value - rowLower_[i] + tolerance;
     }
     if (newSum > 1.0e-5 + 1.5 * sumPrimalInfeasibilities_) {
          // put back and skip changes
          for (i = 0; i < numberColumns_; i++)
               columnActivity_[i] -= columnChange[i];
     } else {
          CoinZeroN(rowActivity_, numberRows_);
          matrix_->times(1.0, columnActivity_, rowActivity_);
          if (reallyFix) {
               for (i = 0; i < numberRows_; i++) {
                    if (rowUpper_[i] < 1.0e20 || rowLower_[i] > -1.0e20) {
                         if (rowUpper_[i] > rowLower_[i]) {
                              if (fixedOrFree(i + numberColumns_)) {
                                   if (rowActivity_[i] - rowLower_[i] < rowUpper_[i] - rowActivity_[i]) {
                                        CoinWorkDouble change = rowLower_[i] - rowActivity_[i];
                                        if (CoinAbs(change) < tolerance) {
                                             if (reallyFix)
                                                  rowUpper_[i] = rowLower_[i];
                                             rowActivity_[i] = rowLower_[i];
                                        }
                                   } else {
                                        CoinWorkDouble change = rowLower_[i] - rowActivity_[i];
                                        if (CoinAbs(change) < tolerance) {
                                             if (reallyFix)
                                                  rowLower_[i] = rowUpper_[i];
                                             rowActivity_[i] = rowUpper_[i];
                                        }
                                   }
                              }
                         }
                    }
               }
          }
     }
     delete [] rowChange;
     delete [] columnChange;
}
Пример #4
0
/*
  This routine empties the columns for the list of fixed variables passed in
  (fcols, nfcols). As each coefficient a<ij> is set to 0, rlo<i> and rup<i>
  are adjusted accordingly. Note, however, that c<j> is not considered to be
  removed from the objective until column j is physically removed from the
  matrix (drop_empty_cols_action), so the correction to the objective is
  adjusted there.

  If a column solution is available, row activity (acts_) is adjusted.
  remove_fixed_action implicitly assumes that the value of the variable has
  already been forced within bounds. If this isn't true, the correction to
  acts_ will be wrong. See make_fixed_action if you need to force the value
  within bounds first.
*/
const remove_fixed_action*
remove_fixed_action::presolve (CoinPresolveMatrix *prob,
                               int *fcols, int nfcols,
                               const CoinPresolveAction *next)
{
    double *colels	= prob->colels_;
    int *hrow		= prob->hrow_;
    CoinBigIndex *mcstrt	= prob->mcstrt_;
    int *hincol		= prob->hincol_;

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

    double *clo	= prob->clo_;
    double *rlo	= prob->rlo_;
    double *rup	= prob->rup_;
    double *sol	= prob->sol_;
    double *acts	= prob->acts_;

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

    action *actions 	= new  action[nfcols+1];

# if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0
# if PRESOLVE_DEBUG > 0
    std::cout
            << "Entering remove_fixed_action::presolve; processing " << nfcols
            << " fixed columns." << std::endl ;
# endif
    presolve_check_sol(prob) ;
    presolve_check_nbasic(prob) ;
# endif

    /*
      Scan columns to be removed and total up the number of coefficients.
    */
    int estsize=0;
    int ckc;
    for (ckc = 0 ; ckc < nfcols ; ckc++) {
        int j = fcols[ckc];
        estsize += hincol[j];
    }
// Allocate arrays to hold coefficients and associated row indices
    double * els_action = new double[estsize];
    int * rows_action = new int[estsize];
    int actsize=0;
    // faster to do all deletes in row copy at once
    int nrows		= prob->nrows_;
    CoinBigIndex * rstrt = new int[nrows+1];
    CoinZeroN(rstrt,nrows);

    /*
      Open a loop to excise each column a<j>. The first thing to do is load the
      action entry with the index j, the value of x<j>, and the number of
      entries in a<j>. After we walk the column and tweak the row-major
      representation, we'll simply claim this column is empty by setting
      hincol[j] = 0.
    */
    for (ckc = 0 ; ckc < nfcols ; ckc++) {
        int j = fcols[ckc];
        double solj = clo[j];
        CoinBigIndex kcs = mcstrt[j];
        CoinBigIndex kce = kcs + hincol[j];
        CoinBigIndex k;

        {   action &f = actions[ckc];
            f.col = j;
            f.sol = solj;
            f.start = actsize;
        }
        /*
          Now walk a<j>. For each row i with a coefficient a<ij> != 0:
            * save the coefficient and row index,
            * substitute the value of x<j>, adjusting the row bounds and lhs value
              accordingly, then
            * delete a<ij> from the row-major representation.
            * Finally: mark the row as changed and add it to the list of rows to be
        	processed next. Then, for each remaining column in the row, put it on
        	the list of columns to be processed.
        */
        for (k = kcs ; k < kce ; k++) {
            int row = hrow[k];
            double coeff = colels[k];

            els_action[actsize]=coeff;
            rstrt[row]++; // increase counts
            rows_action[actsize++]=row;

            // Avoid reducing finite infinity.
            if (-PRESOLVE_INF < rlo[row])
                rlo[row] -= solj*coeff;
            if (rup[row] < PRESOLVE_INF)
                rup[row] -= solj*coeff;
            if (sol) {
                acts[row] -= solj*coeff;
            }
#define TRY2
#ifndef TRY2
            presolve_delete_from_row(row,j,mrstrt,hinrow,hcol,rowels);
            if (hinrow[row] == 0)
            {
                PRESOLVE_REMOVE_LINK(rlink,row) ;
            }

            // mark unless already marked
            if (!prob->rowChanged(row)) {
                prob->addRow(row);
                CoinBigIndex krs = mrstrt[row];
                CoinBigIndex kre = krs + hinrow[row];
                for (CoinBigIndex k=krs; k<kre; k++) {
                    int jcol = hcol[k];
                    prob->addCol(jcol);
                }
            }
#endif
        }
        /*
          Remove the column's link from the linked list of columns, and declare
          it empty in the column-major representation. Link removal must execute
          even if the column is already of length 0 when it arrives.
        */
        PRESOLVE_REMOVE_LINK(clink, j);
        hincol[j] = 0;
    }
    /*
      Set the actual end of the coefficient and row index arrays.
    */
    actions[nfcols].start=actsize;
# if PRESOLVE_SUMMARY
    printf("NFIXED:  %d", nfcols);
    if (estsize-actsize > 0)
    {
        printf(", overalloc %d",estsize-actsize) ;
    }
    printf("\n") ;
# endif
    // Now get columns by row
    int * column = new int[actsize];
    int nel=0;
    int iRow;
    for (iRow=0; iRow<nrows; iRow++) {
        int n=rstrt[iRow];
        rstrt[iRow]=nel;
        nel += n;
    }
    rstrt[nrows]=nel;
    for (ckc = 0 ; ckc < nfcols ; ckc++) {
        int kcs = actions[ckc].start;
        int j=actions[ckc].col;
        int kce;
        if (ckc<nfcols-1)
            kce = actions[ckc+1].start;
        else
            kce = actsize;
        for (int k=kcs; k<kce; k++) {
            int iRow = rows_action[k];
            CoinBigIndex put = rstrt[iRow];
            rstrt[iRow]++;
            column[put]=j;
        }
    }
    // Now do rows
    int ncols		= prob->ncols_;
    char * mark = new char[ncols];
    memset(mark,0,ncols);
    // rstrts are now one out i.e. rstrt[0] is end of row 0
    nel=0;
#ifdef TRY2
    for (iRow=0; iRow<nrows; iRow++) {
        int k;
        for (k=nel; k<rstrt[iRow]; k++) {
            mark[column[k]]=1;
        }
        presolve_delete_many_from_major(iRow,mark,mrstrt,hinrow,hcol,rowels);
#if PRESOLVE_DEBUG > 0
        for (k = nel ; k < rstrt[iRow] ; k++) {
            assert(mark[column[k]] == 0) ;
        }
#endif
        if (hinrow[iRow] == 0)
        {
            PRESOLVE_REMOVE_LINK(rlink,iRow) ;
        }
        // mark unless already marked
        if (!prob->rowChanged(iRow)) {
            prob->addRow(iRow);
            CoinBigIndex krs = mrstrt[iRow];
            CoinBigIndex kre = krs + hinrow[iRow];
            for (CoinBigIndex k=krs; k<kre; k++) {
                int jcol = hcol[k];
                prob->addCol(jcol);
            }
        }
        nel=rstrt[iRow];
    }
#endif
    delete [] mark;
    delete [] column;
    delete [] rstrt;

    /*
      Create the postsolve object, link it at the head of the list of postsolve
      objects, and return a pointer.
    */
    const remove_fixed_action *fixedActions =
        new remove_fixed_action(nfcols,actions,els_action,rows_action,next) ;

# if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0
    presolve_check_sol(prob) ;
# if PRESOLVE_DEBUG > 0
    std::cout << "Leaving remove_fixed_action::presolve." << std::endl ;
# endif
# endif

    return (fixedActions) ;
}
Пример #5
0
/*
  Reintroduce the column (y) and doubleton row (irow) removed in presolve.
  Correct the other column (x) involved in the doubleton, update the solution,
  etc.

  A fair amount of complication arises because the presolve transform saves the
  shorter of x or y. Postsolve thus includes portions to restore either.
*/
void doubleton_action::postsolve(CoinPostsolveMatrix *prob) const
{
  const action *const actions = actions_ ;
  const int nactions = nactions_ ;

  double *colels	= prob->colels_ ;
  int *hrow		= prob->hrow_ ;
  CoinBigIndex *mcstrt	= prob->mcstrt_ ;
  int *hincol		= prob->hincol_ ;
  int *link		= prob->link_ ;

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

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

  double *dcost	= prob->cost_ ;

  double *sol	= prob->sol_ ;
  double *acts	= prob->acts_ ;
  double *rowduals = prob->rowduals_ ;
  double *rcosts = prob->rcosts_ ;

  unsigned char *colstat = prob->colstat_ ;
  unsigned char *rowstat = prob->rowstat_ ;

  const double maxmin	= prob->maxmin_ ;

  CoinBigIndex &free_list = prob->free_list_ ;

  const double ztolzb	= prob->ztolzb_ ;
  const double ztoldj	= prob->ztoldj_ ;
  const double ztolzero = 1.0e-12 ;

  int nrows = prob->nrows_ ;

  // Arrays to rebuild the unsaved column.
  int *index1 = new int[nrows] ;
  double *element1 = new double[nrows] ;
  CoinZeroN(element1,nrows) ;

# if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0
  char *cdone	= prob->cdone_ ;
  char *rdone	= prob->rdone_ ;

  presolve_check_threads(prob) ;
  presolve_check_sol(prob,2,2,2) ;
  presolve_check_nbasic(prob) ;
  presolve_check_reduced_costs(prob) ;

# if PRESOLVE_DEBUG > 0
  std::cout
    << "Entering doubleton_action::postsolve, " << nactions
    << " transforms to undo." << std::endl ;
# endif
# endif
/*
  The outer loop: step through the doubletons in this array of actions.
  The first activity is to unpack the doubleton.
*/
  for (const action *f = &actions[nactions-1] ; actions <= f ; f--) {

    const int irow = f->row ;
    const double lo0 = f->clox ;
    const double up0 = f->cupx ;


    const double coeffx = f->coeffx ;
    const double coeffy = f->coeffy ;
    const int jcolx = f->icolx ;
    const int jcoly = f->icoly ;

    const double rhs = f->rlo ;

#   if PRESOLVE_DEBUG > 2
    std::cout
      << std::endl
      << "  restoring doubleton " << irow << ", elim x(" << jcoly
      << "), kept x(" << jcolx << "); stored col " ;
    if (f->ncoly)
      std::cout << jcoly ;
    else 
      std::cout << jcolx ;
    std::cout << "." << std::endl ;
    std::cout
      << "  x(" << jcolx << ") " << prob->columnStatusString(jcolx) << " "
      << clo[jcolx] << " <= " << sol[jcolx] << " <= " << cup[jcolx]
      << "; cj " << f->costx << " dj " << rcosts[jcolx] << "." << std::endl ;
#   endif
/*
  jcolx is in the problem (for whatever reason), and the doubleton row (irow)
  and column (jcoly) have only been processed by empty row/column postsolve
  (i.e., reintroduced with length 0).
*/
    PRESOLVEASSERT(cdone[jcolx] && rdone[irow] == DROP_ROW) ;
    PRESOLVEASSERT(cdone[jcoly] == DROP_COL) ;

/*
  Restore bounds for doubleton row, bounds and objective coefficient for x,
  objective for y.

  Original comment: restoration of rlo and rup likely isn't necessary.
*/
    rlo[irow] = f->rlo ;
    rup[irow] = f->rlo ;

    clo[jcolx] = lo0 ;
    cup[jcolx] = up0 ;

    dcost[jcolx] = f->costx ;
    dcost[jcoly] = f->costy ;

/*
  Set primal solution for y (including status) and row activity for the
  doubleton row. The motivation (up in presolve) for wanting coeffx < coeffy
  is to avoid inflation into sol[y]. Since this is a (satisfied) equality,
  activity is the rhs value and the logical is nonbasic.
*/
    const double diffy = rhs-coeffx*sol[jcolx] ;
    if (fabs(diffy) < ztolzero)
      sol[jcoly] = 0 ;
    else
      sol[jcoly] = diffy/coeffy ;
    acts[irow] = rhs ;
    if (rowstat)
      prob->setRowStatus(irow,CoinPrePostsolveMatrix::atLowerBound) ;

#   if PRESOLVE_DEBUG > 2
/*
  Original comment: I've forgotten what this is about

  We have sol[y] = (rhs - coeffx*sol[x])/coeffy. As best I can figure,
  the original check here tested for the possibility of loss of significant
  digits through cancellation, followed by inflation if coeffy is small.
  The hazard is clear enough, but the test was puzzling. Overly complicated
  and it generated false warnings for the common case of sol[y] a clean zero.
  Replaced with something that I hope is more useful. The tolerances are, sad
  to say, completely arbitrary.    -- lh, 121106 --
*/
    if ((fabs(diffy) < 1.0e-6) && (fabs(diffy) >= ztolzero) &&
        (fabs(coeffy) < 1.0e-3))
      std::cout
        << "  loss of significance? rhs " << rhs
	<< " (coeffx*sol[jcolx])" << (coeffx*sol[jcolx])
	<< " diff " << diffy << "." << std::endl ;
#   endif

/*
  Time to get into the correction/restoration of coefficients for columns x
  and y, with attendant correction of row bounds and activities. Accumulate
  partial reduced costs (missing the contribution from the doubleton row) so
  that we can eventually calculate a dual for the doubleton row.
*/
    double djy = maxmin*dcost[jcoly] ;
    double djx = maxmin*dcost[jcolx] ;
/*
  We saved column y in the action, so we'll use it to reconstruct column x.
  There are two aspects: correction of existing x coefficients, and fill in.
  Given
    coeffx'[k] = coeffx[k]+coeffy[k]*coeff_factor
  we have
    coeffx[k] = coeffx'[k]-coeffy[k]*coeff_factor
  where
    coeff_factor = -coeffx[dblton]/coeffy[dblton].

  Keep in mind that the major vector stored in the action does not include
  the coefficient from the doubleton row --- the doubleton coefficients are
  held in coeffx and coeffy.
*/
    if (f->ncoly) {
      int ncoly = f->ncoly-1 ;
      int *indy = reinterpret_cast<int *>(f->colel+ncoly) ;
/*
  Rebuild a threaded column y, starting with the end of the thread and working
  back to the beginning. In the process, accumulate corrections to column x
  in element1 and index1. Fix row bounds and activity as we go (add back the
  constant correction removed in presolve), and accumulate contributions to
  the reduced cost for y. Don't tweak finite infinity.

  The PRESOLVEASSERT says this row should already be present. 
*/
      int ystart = NO_LINK ;
      int nX = 0 ;
      for (int kcol = 0 ; kcol < ncoly ; ++kcol) {
	const int i = indy[kcol] ;
	PRESOLVEASSERT(rdone[i]) ;

	double yValue = f->colel[kcol] ;

	if (-PRESOLVE_INF < rlo[i])
	  rlo[i] += (yValue*rhs)/coeffy ;
	if (rup[i] < PRESOLVE_INF)
	  rup[i] += (yValue*rhs)/coeffy ;

	acts[i] += (yValue*rhs)/coeffy ;

	djy -= rowduals[i]*yValue ;
/*
  Link the coefficient into column y: Acquire the first free slot in the
  bulk arrays and store the row index and coefficient. Then link the slot
  in front of coefficients we've already processed.
*/
	const CoinBigIndex kfree = free_list ;
	assert(kfree >= 0 && kfree < prob->bulk0_) ;
	free_list = link[free_list] ;
	hrow[kfree] = i ;
	colels[kfree] = yValue ;
	link[kfree] = ystart ;
	ystart = kfree ;

#       if PRESOLVE_DEBUG > 4
	std::cout
	  << "  link y " << kfree << " row " << i << " coeff " << yValue
	  << " dual " << rowduals[i] << std::endl ;
#       endif
/*
  Calculate and store the correction to the x coefficient.
*/
	yValue = (yValue*coeffx)/coeffy ;
	element1[i] = yValue ;
	index1[nX++] = i ;
      }
#     if PRESOLVE_CONSISTENCY > 0
      presolve_check_free_list(prob) ;
#     endif
/*
  Handle the coefficients of the doubleton row. Insert coeffy, coeffx.
*/
      const CoinBigIndex kfree = free_list ;
      assert(kfree >= 0 && kfree < prob->bulk0_) ;
      free_list = link[free_list] ;
      hrow[kfree] = irow ;
      colels[kfree] = coeffy ;
      link[kfree] = ystart ;
      ystart = kfree ;

#     if PRESOLVE_DEBUG > 4
      std::cout
	<< "  link y " << kfree << " row " << irow << " coeff " << coeffy
	<< " dual n/a" << std::endl ;
#     endif

      element1[irow] = coeffx ;
      index1[nX++] = irow ;
/*
  Attach the threaded column y to mcstrt and record the length.
*/
      mcstrt[jcoly] = ystart ;
      hincol[jcoly] = f->ncoly ;
/*
  Now integrate the corrections to column x. Scan the column and correct the
  existing entries.  The correction could cancel the existing coefficient and
  we don't want to leave an explicit zero. In this case, relink the column
  around it.  The freed slot is linked at the beginning of the free list.
*/
      CoinBigIndex kcs = mcstrt[jcolx] ;
      CoinBigIndex last_nonzero = NO_LINK ;
      int numberInColumn = hincol[jcolx] ;
      const int numberToDo = numberInColumn ;
      for (int kcol = 0 ; kcol < numberToDo ; ++kcol) {
	const int i = hrow[kcs] ;
	assert(i >= 0 && i < nrows && i != irow) ;
	double value = colels[kcs]+element1[i] ;
	element1[i] = 0.0 ;
	if (fabs(value) >= 1.0e-15) {
	  colels[kcs] = value ;
	  last_nonzero = kcs ;
	  kcs = link[kcs] ;
	  djx -= rowduals[i]*value ;

#         if PRESOLVE_DEBUG > 4
	  std::cout
	    << "  link x " << last_nonzero << " row " << i << " coeff "
	    << value << " dual " << rowduals[i] << std::endl ;
#         endif

	} else {

#         if PRESOLVE_DEBUG > 4
	  std::cout
	    << "  link x skipped row  " << i << " dual "
	    << rowduals[i] << std::endl ;
#         endif

	  numberInColumn-- ;
	  // add to free list
	  int nextk = link[kcs] ;
	  assert(free_list >= 0) ;
	  link[kcs] = free_list ;
	  free_list = kcs ;
	  assert(kcs >= 0) ;
	  kcs = nextk ;
	  if (last_nonzero != NO_LINK)
	    link[last_nonzero] = kcs ;
	  else
	    mcstrt[jcolx] = kcs ;
	}
      }
      if (last_nonzero != NO_LINK)
	link[last_nonzero] = NO_LINK ;
/*
  We've dealt with the existing nonzeros in column x. Any remaining
  nonzeros in element1 will be fill in, which we insert at the beginning of
  the column.
*/
      for (int kcol = 0 ; kcol < nX ; kcol++) {
	const int i = index1[kcol] ;
	double xValue = element1[i] ;
	element1[i] = 0.0 ;
	if (fabs(xValue) >= 1.0e-15) {
	  if (i != irow)
	    djx -= rowduals[i]*xValue ;
	  numberInColumn++ ;
	  CoinBigIndex kfree = free_list ;
	  assert(kfree >= 0 && kfree < prob->bulk0_) ;
	  free_list = link[free_list] ;
	  hrow[kfree] = i ;
	  PRESOLVEASSERT(rdone[hrow[kfree]] || (hrow[kfree] == irow)) ;
	  colels[kfree] = xValue ;
	  link[kfree] = mcstrt[jcolx] ;
	  mcstrt[jcolx] = kfree ;
#         if PRESOLVE_DEBUG > 4
	  std::cout
	    << "  link x " << kfree << " row " << i << " coeff " << xValue
	    << " dual " ;
	  if (i != irow)
	    std::cout << rowduals[i] ;
	  else
	    std::cout << "n/a" ;
	  std::cout << std::endl ;
#         endif
	}
      }
	  
#     if PRESOLVE_CONSISTENCY > 0
      presolve_check_free_list(prob) ;
#     endif
	  
/*
  Whew! Set the column length and we're done.
*/
      assert(numberInColumn) ;
      hincol[jcolx] = numberInColumn ;
    } else {
/*
  Of course, we could have saved column x in the action. Now we need to
  regenerate coefficients of column y.
  Given
    coeffx'[k] = coeffx[k]+coeffy[k]*coeff_factor
  we have
    coeffy[k] = (coeffx'[k]-coeffx[k])*(1/coeff_factor)
  where
    coeff_factor = -coeffx[dblton]/coeffy[dblton].
*/
      const int ncolx = f->ncolx-1 ;
      int *indx = reinterpret_cast<int *> (f->colel+ncolx) ;
/*
  Scan existing column x to find the end. While we're at it, accumulate part
  of the new y coefficients in index1 and element1.
*/
      CoinBigIndex kcs = mcstrt[jcolx] ;
      int nX = 0 ;
      for (int kcol = 0 ; kcol < hincol[jcolx]-1 ; ++kcol) {
	if (colels[kcs]) {
	  const int i = hrow[kcs] ;
	  index1[nX++] = i ;
	  element1[i] = -(colels[kcs]*coeffy)/coeffx ;
	}
	kcs = link[kcs] ;
      }
      if (colels[kcs]) {
        const int i = hrow[kcs] ;
        index1[nX++] = i ;
        element1[i] = -(colels[kcs]*coeffy)/coeffx ;
      }
/*
  Replace column x with the the original column x held in the doubleton action
  (recall that this column does not include coeffx). We first move column
  x to the free list, then thread a column with the original coefficients,
  back to front.  While we're at it, add the second part of the y coefficients
  to index1 and element1.
*/
      link[kcs] = free_list ;
      free_list = mcstrt[jcolx] ;
      int xstart = NO_LINK ;
      for (int kcol = 0 ; kcol < ncolx ; ++kcol) {
	const int i = indx[kcol] ;
	PRESOLVEASSERT(rdone[i] && i != irow) ;

	double xValue = f->colel[kcol] ;
	CoinBigIndex k = free_list ;
	assert(k >= 0 && k < prob->bulk0_) ;
	free_list = link[free_list] ;
	hrow[k] = i ;
	colels[k] = xValue ;
	link[k] = xstart ;
	xstart = k ;

	djx -= rowduals[i]*xValue ;

	xValue = (xValue*coeffy)/coeffx ;
	if (!element1[i]) {
	  element1[i] = xValue ;
	  index1[nX++] = i ;
	} else {
	  element1[i] += xValue ;
	}
      }
#     if PRESOLVE_CONSISTENCY > 0
      presolve_check_free_list(prob) ;
#     endif
/*
  The same, for the doubleton row.
*/
      {
	double xValue = coeffx ;
	CoinBigIndex k = free_list ;
	assert(k >= 0 && k < prob->bulk0_) ;
	free_list = link[free_list] ;
	hrow[k] = irow ;
	colels[k] = xValue ;
	link[k] = xstart ;
	xstart = k ;
	element1[irow] = coeffy ;
	index1[nX++] = irow ;
      }
/*
  Link the new column x to mcstrt and set the length.
*/
      mcstrt[jcolx] = xstart ;
      hincol[jcolx] = f->ncolx ;
/*
  Now get to work building a threaded column y from the nonzeros in element1.
  As before, build the thread in reverse.
*/
      int ystart = NO_LINK ;
      int leny = 0 ;
      for (int kcol = 0 ; kcol < nX ; kcol++) {
	const int i = index1[kcol] ;
	PRESOLVEASSERT(rdone[i] || i == irow) ;
	double yValue = element1[i] ;
	element1[i] = 0.0 ;
	if (fabs(yValue) >= ztolzero) {
	  leny++ ;
	  CoinBigIndex k = free_list ;
	  assert(k >= 0 && k < prob->bulk0_) ;
	  free_list = link[free_list] ;
	  hrow[k] = i ;
	  colels[k] = yValue ;
	  link[k] = ystart ;
	  ystart = k ;
	}
      }
#     if PRESOLVE_CONSISTENCY > 0
      presolve_check_free_list(prob) ;
#     endif
/*
  Tidy up --- link the new column into mcstrt and set the length.
*/
      mcstrt[jcoly] = ystart ;
      assert(leny) ;
      hincol[jcoly] = leny ;
/*
  Now that we have the original y, we can scan it and do the corrections to
  the row bounds and activity, and get a start on a reduced cost for y.
*/
      kcs = mcstrt[jcoly] ;
      const int ny = hincol[jcoly] ;
      for (int kcol = 0 ; kcol < ny ; ++kcol) {
	const int row = hrow[kcs] ;
	const double coeff = colels[kcs] ;
	kcs = link[kcs] ;

	if (row != irow) {
	  
	  // undo elim_doubleton(1)
	  if (-PRESOLVE_INF < rlo[row])
	    rlo[row] += (coeff*rhs)/coeffy ;
	  
	  // undo elim_doubleton(2)
	  if (rup[row] < PRESOLVE_INF)
	    rup[row] += (coeff*rhs)/coeffy ;
	  
	  acts[row] += (coeff*rhs)/coeffy ;
	  
	  djy -= rowduals[row]*coeff ;
	}
      }
    }
#   if PRESOLVE_DEBUG > 2
/*
  Sanity checks. The doubleton coefficients should be linked in the first
  position of the each column (for no good reason except that it makes it much
  easier to write these checks).
*/
#   if PRESOLVE_DEBUG > 4
    std::cout
      << "  kept: saved " << jcolx << " " << coeffx << ", reconstructed "
      << hrow[mcstrt[jcolx]] << " " << colels[mcstrt[jcolx]]
      << "." << std::endl ;
    std::cout
      << "  elim: saved " << jcoly << " " << coeffy << ", reconstructed "
      << hrow[mcstrt[jcoly]] << " " << colels[mcstrt[jcoly]]
      << "." << std::endl ;
#   endif
    assert((coeffx == colels[mcstrt[jcolx]]) &&
	   (coeffy == colels[mcstrt[jcoly]])) ;
#   endif
/*
  Time to calculate a dual for the doubleton row, and settle the status of x
  and y. Ideally, we'll leave x at whatever nonbasic status it currently has
  and make y basic. There's a potential problem, however: Remember that we
  transferred bounds from y to x when we eliminated y. If those bounds were
  tighter than x's original bounds, we may not be able to maintain x at its
  present status, or even as nonbasic.

  We'll make two claims here:

    * If the dual value for the doubleton row is chosen to keep the reduced
      cost djx of col x at its prior value, then the reduced cost djy of col
      y will be 0. (Crank through the linear algebra to convince yourself.)

    * If the bounds on x have loosened, then it must be possible to make y
      nonbasic, because we've transferred the tight bound back to y. (Yeah,
      I'm waving my hands. But it sounds good.  -- lh, 040907 --)

  So ... if we can maintain x nonbasic, then we need to set y basic, which
  means we should calculate rowduals[dblton] so that rcost[jcoly] == 0. We
  may need to change the status of x (an artifact of loosening a bound when
  x was previously a fixed variable).
  
  If we need to push x into the basis, then we calculate rowduals[dblton] so
  that rcost[jcolx] == 0 and make y nonbasic.
*/
#   if PRESOLVE_DEBUG > 2
    std::cout
      << "  pre status: x(" << jcolx << ") " << prob->columnStatusString(jcolx)
      << " " << clo[jcolx] << " <= " << sol[jcolx] << " <= " << cup[jcolx]
      << ", cj " << dcost[jcolx]
      << ", dj " << djx << "." << std::endl ;
    std::cout
      << "  pre status: x(" << jcoly << ") "
      << clo[jcoly] << " <= " << sol[jcoly] << " <= " << cup[jcoly]
      << ", cj " << dcost[jcoly]
      << ", dj " << djy << "." << std::endl ;
#   endif
    if (colstat) {
      bool basicx = prob->columnIsBasic(jcolx) ;
      bool nblbxok = (fabs(lo0 - sol[jcolx]) < ztolzb) &&
		     (rcosts[jcolx] >= -ztoldj) ;
      bool nbubxok = (fabs(up0 - sol[jcolx]) < ztolzb) &&
		     (rcosts[jcolx] <= ztoldj) ;
      if (basicx || nblbxok || nbubxok) {
        if (!basicx) {
	  if (nblbxok) {
	    prob->setColumnStatus(jcolx,
				  CoinPrePostsolveMatrix::atLowerBound) ;
	  } else if (nbubxok) {
	    prob->setColumnStatus(jcolx,
				  CoinPrePostsolveMatrix::atUpperBound) ;
	  }
	}
	prob->setColumnStatus(jcoly,CoinPrePostsolveMatrix::basic) ;
	rowduals[irow] = djy/coeffy ;
	rcosts[jcolx] = djx-rowduals[irow]*coeffx ;
	rcosts[jcoly] = 0.0 ;
      } else {
	prob->setColumnStatus(jcolx,CoinPrePostsolveMatrix::basic) ;
	prob->setColumnStatusUsingValue(jcoly) ;
	rowduals[irow] = djx/coeffx ;
	rcosts[jcoly] = djy-rowduals[irow]*coeffy ;
	rcosts[jcolx] = 0.0 ;
      }
#     if PRESOLVE_DEBUG > 2
      std::cout
        << "  post status: " << irow << " dual " << rowduals[irow]
	<< " rhs " << rlo[irow]
	<< std::endl ;
      std::cout
	<< "  post status: x(" << jcolx << ") "
	<< prob->columnStatusString(jcolx) << " "
	<< clo[jcolx] << " <= " << sol[jcolx] << " <= " << cup[jcolx]
	<< ", cj " << dcost[jcolx]
	<< ", dj = " << rcosts[jcolx] << "." << std::endl ;
      std::cout
	<< "  post status: x(" << jcoly << ") "
	<< prob->columnStatusString(jcoly) << " "
	<< clo[jcoly] << " <= " << sol[jcoly] << " <= " << cup[jcoly]
	<< ", cj " << dcost[jcoly]
	<< ", dj " << rcosts[jcoly] << "." << std::endl ;
/*
  These asserts are valid but need a scaled tolerance to work well over
  a range of problems. Occasionally useful for a hard stop while debugging.

      assert(!prob->columnIsBasic(jcolx) || (fabs(rcosts[jcolx]) < 1.0e-5)) ;
      assert(!prob->columnIsBasic(jcoly) || (fabs(rcosts[jcoly]) < 1.0e-5)) ;
*/
#     endif
    } else {
      // No status array
      // this is the coefficient we need to force col y's reduced cost to 0.0 ;
      // for example, this is obviously true if y is a singleton column
      rowduals[irow] = djy/coeffy ;
      rcosts[jcoly] = 0.0 ;
    }
    
#   if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0
/*
  Mark the column and row as processed by doubleton action. Then check
  integrity of the threaded matrix.
*/
    cdone[jcoly] = DOUBLETON ;
    rdone[irow] = DOUBLETON ;
    presolve_check_threads(prob) ;
#   endif
#   if PRESOLVE_DEBUG > 0
/*
  Confirm accuracy of reduced cost for columns x and y.
*/
    {
      CoinBigIndex k = mcstrt[jcolx] ;
      const int nx = hincol[jcolx] ;
      double dj = maxmin*dcost[jcolx] ;
      
      for (int kcol = 0 ; kcol < nx ; ++kcol) {
	const int row = hrow[k] ;
	const double coeff = colels[k] ;
	k = link[k] ;
	dj -= rowduals[row]*coeff ;
      }
      if (!(fabs(rcosts[jcolx]-dj) < 100*ZTOLDP))
	printf("BAD DOUBLE X DJ:  %d %d %g %g\n",
	       irow,jcolx,rcosts[jcolx],dj) ;
      rcosts[jcolx] = dj ;
    }
    {
      CoinBigIndex k = mcstrt[jcoly] ;
      const int ny = hincol[jcoly] ;
      double dj = maxmin*dcost[jcoly] ;
      
      for (int kcol = 0 ; kcol < ny ; ++kcol) {
	const int row = hrow[k] ;
	const double coeff = colels[k] ;
	k = link[k] ;
	dj -= rowduals[row]*coeff ;
      }
      if (!(fabs(rcosts[jcoly]-dj) < 100*ZTOLDP))
	printf("BAD DOUBLE Y DJ:  %d %d %g %g\n",
	       irow,jcoly,rcosts[jcoly],dj) ;
      rcosts[jcoly] = dj ;
    }
#   endif
  }
/*
  Done at last. Delete the scratch arrays.
*/
  delete [] index1 ;
  delete [] element1 ;

# if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0
  presolve_check_sol(prob,2,2,2) ;
  presolve_check_nbasic(prob) ;
  presolve_check_reduced_costs(prob) ;
# if PRESOLVE_DEBUG > 0
  std::cout << "Leaving doubleton_action::postsolve." << std::endl ;
# endif
# endif
}
Пример #6
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;
}
Пример #7
0
/* Orders rows and saves pointer to matrix.and model */
int
ClpCholeskyMumps::order(ClpInterior * model)
{
     numberRows_ = model->numberRows();
     if (doKKT_) {
          numberRows_ += numberRows_ + model->numberColumns();
          printf("finish coding MUMPS KKT!\n");
          abort();
     }
     rowsDropped_ = new char [numberRows_];
     memset(rowsDropped_, 0, numberRows_);
     numberRowsDropped_ = 0;
     model_ = model;
     rowCopy_ = model->clpMatrix()->reverseOrderedCopy();
     const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts();
     const int * columnLength = model_->clpMatrix()->getVectorLengths();
     const int * row = model_->clpMatrix()->getIndices();
     const CoinBigIndex * rowStart = rowCopy_->getVectorStarts();
     const int * rowLength = rowCopy_->getVectorLengths();
     const int * column = rowCopy_->getIndices();
     // We need two arrays for counts
     int * which = new int [numberRows_];
     int * used = new int[numberRows_+1];
     CoinZeroN(used, numberRows_);
     int iRow;
     sizeFactor_ = 0;
     for (iRow = 0; iRow < numberRows_; iRow++) {
          int number = 1;
          // make sure diagonal exists
          which[0] = iRow;
          used[iRow] = 1;
          if (!rowsDropped_[iRow]) {
               CoinBigIndex startRow = rowStart[iRow];
               CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow];
               for (CoinBigIndex k = startRow; k < endRow; k++) {
                    int iColumn = column[k];
                    CoinBigIndex start = columnStart[iColumn];
                    CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn];
                    for (CoinBigIndex j = start; j < end; j++) {
                         int jRow = row[j];
                         if (jRow >= iRow && !rowsDropped_[jRow]) {
                              if (!used[jRow]) {
                                   used[jRow] = 1;
                                   which[number++] = jRow;
                              }
                         }
                    }
               }
               sizeFactor_ += number;
               int j;
               for (j = 0; j < number; j++)
                    used[which[j]] = 0;
          }
     }
     delete [] which;
     // NOT COMPRESSED FOR NOW ??? - Space for starts
     mumps_->ICNTL(5) = 0; // say NOT compressed format
     try {
          choleskyStart_ = new CoinBigIndex[numberRows_+1+sizeFactor_];
     } catch (...) {
          // no memory
          return -1;
     }
     // Now we have size - create arrays and fill in
     try {
          choleskyRow_ = new int [sizeFactor_];
     } catch (...) {
          // no memory
          delete [] choleskyStart_;
          choleskyStart_ = NULL;
          return -1;
     }
     try {
          sparseFactor_ = new double[sizeFactor_];
     } catch (...) {
          // no memory
          delete [] choleskyRow_;
          choleskyRow_ = NULL;
          delete [] choleskyStart_;
          choleskyStart_ = NULL;
          return -1;
     }

     sizeFactor_ = 0;
     which = choleskyRow_;
     for (iRow = 0; iRow < numberRows_; iRow++) {
          int number = 1;
          // make sure diagonal exists
          which[0] = iRow;
          used[iRow] = 1;
          choleskyStart_[iRow] = sizeFactor_;
          if (!rowsDropped_[iRow]) {
               CoinBigIndex startRow = rowStart[iRow];
               CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow];
               for (CoinBigIndex k = startRow; k < endRow; k++) {
                    int iColumn = column[k];
                    CoinBigIndex start = columnStart[iColumn];
                    CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn];
                    for (CoinBigIndex j = start; j < end; j++) {
                         int jRow = row[j];
                         if (jRow >= iRow && !rowsDropped_[jRow]) {
                              if (!used[jRow]) {
                                   used[jRow] = 1;
                                   which[number++] = jRow;
                              }
                         }
                    }
               }
               sizeFactor_ += number;
               int j;
               for (j = 0; j < number; j++)
                    used[which[j]] = 0;
               // Sort
               std::sort(which, which + number);
               // move which on
               which += number;
          }
     }
     choleskyStart_[numberRows_] = sizeFactor_;
     delete [] used;
     permuteInverse_ = new int [numberRows_];
     permute_ = new int[numberRows_];
     // To Fortran and fake
     for (iRow = 0; iRow < numberRows_ + 1; iRow++) {
          int k = choleskyStart_[iRow];
          int kEnd = choleskyStart_[iRow+1];
          k += numberRows_ + 1;
          kEnd += numberRows_ + 1;
          for (; k < kEnd; k++)
               choleskyStart_[k] = iRow + 1;
          choleskyStart_[iRow]++;
     }
     mumps_->nz = sizeFactor_;
     mumps_->irn = choleskyStart_ + numberRows_ + 1;
     mumps_->jcn = choleskyRow_;
     mumps_->a = NULL;
     for (CoinBigIndex i = 0; i < sizeFactor_; i++) {
          choleskyRow_[i]++;
#ifndef NDEBUG
          assert (mumps_->irn[i] >= 1 && mumps_->irn[i] <= numberRows_);
          assert (mumps_->jcn[i] >= 1 && mumps_->jcn[i] <= numberRows_);
#endif
     }
     // validate
     //mumps code here
     mumps_->n = numberRows_;
     mumps_->nelt = numberRows_;
     mumps_->eltptr = choleskyStart_;
     mumps_->eltvar = choleskyRow_;
     mumps_->a_elt = NULL;
     mumps_->rhs = NULL;
     mumps_->job = 1; // order
     dmumps_c(mumps_);
     mumps_->a = sparseFactor_;
     if (mumps_->infog[0]) {
          COIN_DETAIL_PRINT(printf("MUMPS ordering failed -error %d %d\n",
				   mumps_->infog[0], mumps_->infog[1]));
          return 1;
     } else {
          double size = mumps_->infog[19];
          if (size < 0)
               size *= -1000000;
          COIN_DETAIL_PRINT(printf("%g nonzeros, flop count %g\n", size, mumps_->rinfog[0]));
     }
     for (iRow = 0; iRow < numberRows_; iRow++) {
          permuteInverse_[iRow] = iRow;
          permute_[iRow] = iRow;
     }
     return 0;
}
Пример #8
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;
    }
Пример #9
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) ;
}
Пример #10
0
// Infeasibility - large is 0.5
double 
CbcLink::infeasibility(int & preferredWay) const
{
  int j;
  int firstNonZero=-1;
  int lastNonZero = -1;
  OsiSolverInterface * solver = model_->solver();
  const double * solution = model_->testSolution();
  //const double * lower = solver->getColLower();
  const double * upper = solver->getColUpper();
  double integerTolerance = 
    model_->getDblParam(CbcModel::CbcIntegerTolerance);
  double weight = 0.0;
  double sum =0.0;

  // check bounds etc
  double lastWeight=-1.0e100;
  int base=0;
  for (j=0;j<numberMembers_;j++) {
    for (int k=0;k<numberLinks_;k++) {
      int iColumn = which_[base+k];
      //if (lower[iColumn])
      //throw CoinError("Non zero lower bound in CBCLink","infeasibility","CbcLink");
      if (lastWeight>=weights_[j]-1.0e-7)
        throw CoinError("Weights too close together in CBCLink","infeasibility","CbcLink");
      double value = CoinMax(0.0,solution[iColumn]);
      sum += value;
      if (value>integerTolerance&&upper[iColumn]) {
        // Possibly due to scaling a fixed variable might slip through
        if (value>upper[iColumn]+1.0e-8) {
          // Could change to #ifdef CBC_DEBUG
#ifndef NDEBUG
          if (model_->messageHandler()->logLevel()>1)
            printf("** Variable %d (%d) has value %g and upper bound of %g\n",
                   iColumn,j,value,upper[iColumn]);
#endif
        } 
	value = CoinMin(value,upper[iColumn]);
        weight += weights_[j]*value;
        if (firstNonZero<0)
          firstNonZero=j;
        lastNonZero=j;
      }
    }
    base += numberLinks_;
  }
  double valueInfeasibility;
  preferredWay=1;
  if (lastNonZero-firstNonZero>=sosType_) {
    // find where to branch
    assert (sum>0.0);
    weight /= sum;
    valueInfeasibility = lastNonZero-firstNonZero+1;
    valueInfeasibility *= 0.5/((double) numberMembers_);
    //#define DISTANCE
#ifdef DISTANCE
    assert (sosType_==1); // code up
    /* may still be satisfied.
       For LOS type 2 we might wish to move coding around
       and keep initial info in model_ for speed
    */
    int iWhere;
    bool possible=false;
    for (iWhere=firstNonZero;iWhere<=lastNonZero;iWhere++) {
      if (fabs(weight-weights_[iWhere])<1.0e-8) {
	possible=true;
	break;
      }
    }
    if (possible) {
      // One could move some of this (+ arrays) into model_
      const CoinPackedMatrix * matrix = solver->getMatrixByCol();
      const double * element = matrix->getMutableElements();
      const int * row = matrix->getIndices();
      const CoinBigIndex * columnStart = matrix->getVectorStarts();
      const int * columnLength = matrix->getVectorLengths();
      const double * rowSolution = solver->getRowActivity();
      const double * rowLower = solver->getRowLower();
      const double * rowUpper = solver->getRowUpper();
      int numberRows = matrix->getNumRows();
      double * array = new double [numberRows];
      CoinZeroN(array,numberRows);
      int * which = new int [numberRows];
      int n=0;
      int base=numberLinks_*firstNonZero;
      for (j=firstNonZero;j<=lastNonZero;j++) {
	for (int k=0;k<numberLinks_;k++) {
	  int iColumn = which_[base+k];
	  double value = CoinMax(0.0,solution[iColumn]);
	  if (value>integerTolerance&&upper[iColumn]) {
	    value = CoinMin(value,upper[iColumn]);
	    for (int j=columnStart[iColumn];j<columnStart[iColumn]+columnLength[iColumn];j++) {
	      int iRow = row[j];
	      double a = array[iRow];
	      if (a) {
		a += value*element[j];
		if (!a)
		  a = 1.0e-100;
	      } else {
		which[n++]=iRow;
		a=value*element[j];
		assert (a);
	      }
	      array[iRow]=a;
	    }
	  }
	}
	base += numberLinks_;
      }
      base=numberLinks_*iWhere;
      for (int k=0;k<numberLinks_;k++) {
	int iColumn = which_[base+k];
	const double value = 1.0;
	for (int j=columnStart[iColumn];j<columnStart[iColumn]+columnLength[iColumn];j++) {
	  int iRow = row[j];
	  double a = array[iRow];
	  if (a) {
	    a -= value*element[j];
	    if (!a)
	      a = 1.0e-100;
	  } else {
	    which[n++]=iRow;
	    a=-value*element[j];
	    assert (a);
	  }
	  array[iRow]=a;
	}
      }
      for (j=0;j<n;j++) {
	int iRow = which[j];
	// moving to point will increase row solution by this
	double distance = array[iRow];
	if (distance>1.0e-8) {
	  if (distance+rowSolution[iRow]>rowUpper[iRow]+1.0e-8) {
	    possible=false;
	    break;
	  }
	} else if (distance<-1.0e-8) {
	  if (distance+rowSolution[iRow]<rowLower[iRow]-1.0e-8) {
	    possible=false;
	    break;
	  } 
	}
      }
      for (j=0;j<n;j++)
	array[which[j]]=0.0;
      delete [] array;
      delete [] which;
      if (possible) {
	valueInfeasibility=0.0;
	printf("possible %d %d %d\n",firstNonZero,lastNonZero,iWhere);
      }
    }
#endif
  } else {
    valueInfeasibility = 0.0; // satisfied
  }
  return valueInfeasibility;
}
Пример #11
0
// This looks at solution and sets bounds to contain solution
void 
CbcLink::feasibleRegion()
{
  int j;
  int firstNonZero=-1;
  int lastNonZero = -1;
  OsiSolverInterface * solver = model_->solver();
  const double * solution = model_->testSolution();
  const double * upper = solver->getColUpper();
  double integerTolerance = 
    model_->getDblParam(CbcModel::CbcIntegerTolerance);
  double weight = 0.0;
  double sum =0.0;

  int base=0;
  for (j=0;j<numberMembers_;j++) {
    for (int k=0;k<numberLinks_;k++) {
      int iColumn = which_[base+k];
      double value = CoinMax(0.0,solution[iColumn]);
      sum += value;
      if (value>integerTolerance&&upper[iColumn]) {
        weight += weights_[j]*value;
        if (firstNonZero<0)
          firstNonZero=j;
        lastNonZero=j;
      }
    }
    base += numberLinks_;
  }
#ifdef DISTANCE
  if (lastNonZero-firstNonZero>sosType_-1) {
    /* may still be satisfied.
       For LOS type 2 we might wish to move coding around
       and keep initial info in model_ for speed
    */
    int iWhere;
    bool possible=false;
    for (iWhere=firstNonZero;iWhere<=lastNonZero;iWhere++) {
      if (fabs(weight-weights_[iWhere])<1.0e-8) {
	possible=true;
	break;
      }
    }
    if (possible) {
      // One could move some of this (+ arrays) into model_
      const CoinPackedMatrix * matrix = solver->getMatrixByCol();
      const double * element = matrix->getMutableElements();
      const int * row = matrix->getIndices();
      const CoinBigIndex * columnStart = matrix->getVectorStarts();
      const int * columnLength = matrix->getVectorLengths();
      const double * rowSolution = solver->getRowActivity();
      const double * rowLower = solver->getRowLower();
      const double * rowUpper = solver->getRowUpper();
      int numberRows = matrix->getNumRows();
      double * array = new double [numberRows];
      CoinZeroN(array,numberRows);
      int * which = new int [numberRows];
      int n=0;
      int base=numberLinks_*firstNonZero;
      for (j=firstNonZero;j<=lastNonZero;j++) {
	for (int k=0;k<numberLinks_;k++) {
	  int iColumn = which_[base+k];
	  double value = CoinMax(0.0,solution[iColumn]);
	  if (value>integerTolerance&&upper[iColumn]) {
	    value = CoinMin(value,upper[iColumn]);
	    for (int j=columnStart[iColumn];j<columnStart[iColumn]+columnLength[iColumn];j++) {
	      int iRow = row[j];
	      double a = array[iRow];
	      if (a) {
		a += value*element[j];
		if (!a)
		  a = 1.0e-100;
	      } else {
		which[n++]=iRow;
		a=value*element[j];
		assert (a);
	      }
	      array[iRow]=a;
	    }
	  }
	}
	base += numberLinks_;
      }
      base=numberLinks_*iWhere;
      for (int k=0;k<numberLinks_;k++) {
	int iColumn = which_[base+k];
	const double value = 1.0;
	for (int j=columnStart[iColumn];j<columnStart[iColumn]+columnLength[iColumn];j++) {
	  int iRow = row[j];
	  double a = array[iRow];
	  if (a) {
	    a -= value*element[j];
	    if (!a)
	      a = 1.0e-100;
	  } else {
	    which[n++]=iRow;
	    a=-value*element[j];
	    assert (a);
	  }
	  array[iRow]=a;
	}
      }
      for (j=0;j<n;j++) {
	int iRow = which[j];
	// moving to point will increase row solution by this
	double distance = array[iRow];
	if (distance>1.0e-8) {
	  if (distance+rowSolution[iRow]>rowUpper[iRow]+1.0e-8) {
	    possible=false;
	    break;
	  }
	} else if (distance<-1.0e-8) {
	  if (distance+rowSolution[iRow]<rowLower[iRow]-1.0e-8) {
	    possible=false;
	    break;
	  } 
	}
      }
      for (j=0;j<n;j++)
	array[which[j]]=0.0;
      delete [] array;
      delete [] which;
      if (possible) {
	printf("possible feas region %d %d %d\n",firstNonZero,lastNonZero,iWhere);
	firstNonZero=iWhere;
	lastNonZero=iWhere;
      }
    }
  }
#else
  assert (lastNonZero-firstNonZero<sosType_) ;
#endif
  base=0;
  for (j=0;j<firstNonZero;j++) {
    for (int k=0;k<numberLinks_;k++) {
      int iColumn = which_[base+k];
      solver->setColUpper(iColumn,0.0);
    }
    base += numberLinks_;
  }
  // skip
  base += numberLinks_;
  for (j=lastNonZero+1;j<numberMembers_;j++) {
    for (int k=0;k<numberLinks_;k++) {
      int iColumn = which_[base+k];
      solver->setColUpper(iColumn,0.0);
    }
    base += numberLinks_;
  }
}
Пример #12
0
void drop_empty_rows_action::postsolve(CoinPostsolveMatrix *prob) const
{
  const int nactions	= nactions_;
  const action *const actions = actions_;

  int ncols	= prob->ncols_;
  CoinBigIndex *mcstrt	= prob->mcstrt_;
  int *hincol	= prob->hincol_;

  int *hrow	= prob->hrow_;

  double *rlo	= prob->rlo_;
  double *rup	= prob->rup_;
  unsigned char *rowstat	= prob->rowstat_;
  double *rowduals = prob->rowduals_;
  double *acts	= prob->acts_;
# if PRESOLVE_DEBUG
  char *rdone	= prob->rdone_;
# endif

  int nrows0	= prob->nrows0_;
  int nrows	= prob->nrows_;

  int * rowmapping = new int [nrows0];
  CoinZeroN(rowmapping,nrows0) ;

  int i, action_i;
  for (action_i = 0; action_i<nactions; action_i++) {
    const action *e = &actions[action_i];
    int hole = e->row;
    rowmapping[hole]=-1;
  }

  // move data
  for (i=nrows0-1; i>=0; i--) {
    if (!rowmapping[i]) {
      // not a hole
      nrows--;
      rlo[i]=rlo[nrows];
      rup[i]=rup[nrows];
      acts[i]=acts[nrows];
      rowduals[i]=rowduals[nrows];
      if (rowstat)
	rowstat[i] = rowstat[nrows];
#     if PRESOLVE_DEBUG
      rdone[i] = rdone[nrows] ;
#     endif
    }
  }
  assert (!nrows);
  // set up mapping for matrix
  for (i=0;i<nrows0;i++) {
    if (!rowmapping[i])
      rowmapping[nrows++]=i;
  }

  for (int j=0; j<ncols; j++) {
    CoinBigIndex start = mcstrt[j];
    CoinBigIndex end   = start + hincol[j];

    for (CoinBigIndex k=start; k<end; ++k) {
      hrow[k] = rowmapping[hrow[k]];
    }
  }


  delete [] rowmapping;

  for (action_i = 0; action_i < nactions; action_i++) {
    const action *e = &actions[action_i];
    int irow = e->row;

    // Now recreate irow
    rlo[irow] = e->rlo;
    rup[irow] = e->rup;

    if (rowstat)
      prob->setRowStatus(irow,CoinPrePostsolveMatrix::basic);
    rowduals[irow] = 0.0;	// ???
    acts[irow] = 0.0;

#   if PRESOLVE_DEBUG
    rdone[irow] = DROP_ROW;
#   endif
  }

  prob->nrows_ = prob->nrows_+nactions;

# if PRESOLVE_DEBUG
  presolve_check_threads(prob) ;
# endif

}
Пример #13
0
/*
  Physically remove empty columns, compressing mcstrt and hincol. The major
  side effect is that columns are renumbered, thus clink_ is no longer valid
  and must be rebuilt.

  It's necessary to rebuild clink_ in order to do direct conversion of a
  CoinPresolveMatrix to a CoinPostsolveMatrix by transferring the data arrays.
  Without clink_, it's impractical to build link_ to match the transferred bulk
  storage.
*/
const CoinPresolveAction
  *drop_empty_cols_action::presolve (CoinPresolveMatrix *prob,
				     int *ecols,
				     int necols,
				     const CoinPresolveAction *next)
{
  int ncols		= prob->ncols_;
  CoinBigIndex *mcstrt	= prob->mcstrt_;
  int *hincol		= prob->hincol_;

  presolvehlink *clink	= prob->clink_;

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

  const double ztoldj	= prob->ztoldj_;

  unsigned char * integerType     = prob->integerType_;
  int * originalColumn  = prob->originalColumn_;

  const double maxmin	= prob->maxmin_;

  double * sol = prob->sol_;
  unsigned char * colstat = prob->colstat_;

  action *actions 	= new action[necols];
  int * colmapping = new int [ncols+1];
  bool fixInfeasibility = (prob->presolveOptions_&16384)!=0;

  CoinZeroN(colmapping,ncols);
  int i;
  for (i=necols-1; i>=0; i--) {
    int jcol = ecols[i];
    colmapping[jcol]=-1;
    action &e = actions[i];

    e.jcol	= jcol;
    e.clo	= clo[jcol];
    e.cup	= cup[jcol];
    // adjust if integer
    if (integerType[jcol]) {
      e.clo = ceil(e.clo-1.0e-9);
      e.cup = floor(e.cup+1.0e-9);
      if (e.clo>e.cup&&!fixInfeasibility) {
        // infeasible
	prob->status_|= 1;
	prob->messageHandler()->message(COIN_PRESOLVE_COLINFEAS,
					     prob->messages())
				 	       <<jcol
					       <<e.clo
					       <<e.cup
					       <<CoinMessageEol;
      }
    }
    e.cost	= dcost[jcol];

    // there are no more constraints on this variable,
    // so we had better be able to compute the answer now
    if (fabs(dcost[jcol])<ztoldj)
      dcost[jcol]=0.0;
    if (dcost[jcol] * maxmin == 0.0) {
      // hopefully, we can make this non-basic
      // what does OSL currently do in this case???
      e.sol = (-PRESOLVE_INF < e.clo
	       ? e.clo
	       : e.cup < PRESOLVE_INF
	       ? e.cup
	       : 0.0);
    } else if (dcost[jcol] * maxmin > 0.0) {
      if (-PRESOLVE_INF < e.clo)
	e.sol = e.clo;
      else {
	  prob->messageHandler()->message(COIN_PRESOLVE_COLUMNBOUNDB,
					     prob->messages())
					       <<jcol
					       <<CoinMessageEol;
	prob->status_ |= 2;
	break;
      }
    } else {
      if (e.cup < PRESOLVE_INF)
	e.sol = e.cup;
      else {
	  prob->messageHandler()->message(COIN_PRESOLVE_COLUMNBOUNDA,
					     prob->messages())
					       <<jcol
					       <<CoinMessageEol;
	prob->status_ |= 2;
	break;
      }
    }

#if	PRESOLVE_DEBUG
    if (e.sol * dcost[jcol]) {
      //printf("\a>>>NON-ZERO COST FOR EMPTY COL %d:  %g\n", jcol, dcost[jcol]);
    }
#endif
    prob->change_bias(e.sol * dcost[jcol]);


  }
  int ncols2=0;

  // now move remaining ones down
  for (i=0;i<ncols;i++) {
    if (!colmapping[i]) {
      mcstrt[ncols2] = mcstrt[i];
      hincol[ncols2] = hincol[i];

      clo[ncols2]   = clo[i];
      cup[ncols2]   = cup[i];

      dcost[ncols2] = dcost[i];
      if (sol) {
	sol[ncols2] = sol[i];
	colstat[ncols2] = colstat[i];
      }

      integerType[ncols2] = integerType[i];
      originalColumn[ncols2] = originalColumn[i];
      colmapping[i] = ncols2++;
    }
  }
  mcstrt[ncols2] = mcstrt[ncols] ;
  colmapping[ncols] = ncols2 ;
/*
  Rebuild clink_. At this point, all empty columns are linked out, so the
  only columns left are columns that are to be saved, hence available in
  colmapping.  All we need to do is walk clink_ and write the new entries
  into a new array.
*/

  { presolvehlink *newclink = new presolvehlink [ncols2+1] ;
    for (int oldj = ncols ; oldj >= 0 ; oldj = clink[oldj].pre)
    { presolvehlink &oldlnk = clink[oldj] ;
      int newj = colmapping[oldj] ;
      assert(newj >= 0 && newj <= ncols2) ;
      presolvehlink &newlnk = newclink[newj] ;
      if (oldlnk.suc >= 0)
      { newlnk.suc = colmapping[oldlnk.suc] ; }
      else
      { newlnk.suc = NO_LINK ; }
      if (oldlnk.pre >= 0)
      { newlnk.pre = colmapping[oldlnk.pre] ; }
      else
      { newlnk.pre = NO_LINK ; } }
    delete [] clink ;
    prob->clink_ = newclink ; }

  delete [] colmapping;
  prob->ncols_ = ncols2;

  return (new drop_empty_cols_action(necols, actions, next));
}
Пример #14
0
void drop_empty_cols_action::postsolve(CoinPostsolveMatrix *prob) const
{
  const int nactions	= nactions_;
  const action *const actions = actions_;

  int ncols		= prob->ncols_;

  CoinBigIndex *mcstrt	= prob->mcstrt_;
  int *hincol	= prob->hincol_;
  //  int *hrow	= prob->hrow_;

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

  double *sol	= prob->sol_;
  double *cost	= prob->cost_;
  double *rcosts	= prob->rcosts_;
  unsigned char *colstat	= prob->colstat_;
  const double maxmin = prob->maxmin_;

  int ncols2 = ncols+nactions;
  int * colmapping = new int [ncols2];

  CoinZeroN(colmapping,ncols2);
# if PRESOLVE_DEBUG
  char *cdone	= prob->cdone_;
# endif
  int action_i;
  for (action_i = 0; action_i < nactions; action_i++) {
    const action *e = &actions[action_i];
    int jcol = e->jcol;
    colmapping[jcol]=-1;
  }

  int i;

  // now move remaining ones up
  for (i=ncols2-1;i>=0;i--) {
    if (!colmapping[i]) {
      ncols--;
      mcstrt[i] = mcstrt[ncols];
      hincol[i] = hincol[ncols];

      clo[i]   = clo[ncols];
      cup[i]   = cup[ncols];

      cost[i] = cost[ncols];

      if (sol)
	sol[i] = sol[ncols];

      if (rcosts)
        rcosts[i] = rcosts[ncols];

      if (colstat)
	colstat[i] = colstat[ncols];
#     if PRESOLVE_DEBUG
      cdone[i] = cdone[ncols];
#     endif
    }
  }
  assert (!ncols);

  delete [] colmapping;

  for (action_i = 0; action_i < nactions; action_i++) {
    const action *e = &actions[action_i];
    int jcol = e->jcol;

    // now recreate jcol
    clo[jcol] = e->clo;
    cup[jcol] = e->cup;
    if (sol)
      sol[jcol] = e->sol;
    cost[jcol] = e->cost;

    if (rcosts)
      rcosts[jcol] = maxmin*cost[jcol];

    hincol[jcol] = 0;
    mcstrt[jcol] = NO_LINK ;
# if PRESOLVE_DEBUG
    cdone[jcol] = DROP_COL;
# endif
    if (colstat)
      prob->setColumnStatusUsingValue(jcol);
  }

  prob->ncols_ += nactions;

# if PRESOLVE_CONSISTENCY
  presolve_check_threads(prob) ;
# endif

}
Пример #15
0
//#############################################################################
void 
MibSBilevel::checkBilevelFeasiblity(bool isRoot)
{
  
  int cutStrategy =
    model_->MibSPar_->entry(MibSParams::cutStrategy);

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

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

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

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

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

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

  OsiSolverInterface *lSolver = solver_;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

  //delete lSolver;
  
}
Пример #16
0
/* Orders rows and saves pointer to matrix.and model */
int
ClpCholeskyUfl::order(ClpInterior * model)
{
     numberRows_ = model->numberRows();
     if (doKKT_) {
          numberRows_ += numberRows_ + model->numberColumns();
          printf("finish coding UFL KKT!\n");
          abort();
     }
     rowsDropped_ = new char [numberRows_];
     memset(rowsDropped_, 0, numberRows_);
     numberRowsDropped_ = 0;
     model_ = model;
     rowCopy_ = model->clpMatrix()->reverseOrderedCopy();
     // Space for starts
     choleskyStart_ = new CoinBigIndex[numberRows_+1];
     const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts();
     const int * columnLength = model_->clpMatrix()->getVectorLengths();
     const int * row = model_->clpMatrix()->getIndices();
     const CoinBigIndex * rowStart = rowCopy_->getVectorStarts();
     const int * rowLength = rowCopy_->getVectorLengths();
     const int * column = rowCopy_->getIndices();
     // We need two arrays for counts
     int * which = new int [numberRows_];
     int * used = new int[numberRows_+1];
     CoinZeroN(used, numberRows_);
     int iRow;
     sizeFactor_ = 0;
     for (iRow = 0; iRow < numberRows_; iRow++) {
          int number = 1;
          // make sure diagonal exists
          which[0] = iRow;
          used[iRow] = 1;
          if (!rowsDropped_[iRow]) {
               CoinBigIndex startRow = rowStart[iRow];
               CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow];
               for (CoinBigIndex k = startRow; k < endRow; k++) {
                    int iColumn = column[k];
                    CoinBigIndex start = columnStart[iColumn];
                    CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn];
                    for (CoinBigIndex j = start; j < end; j++) {
                         int jRow = row[j];
                         if (jRow >= iRow && !rowsDropped_[jRow]) {
                              if (!used[jRow]) {
                                   used[jRow] = 1;
                                   which[number++] = jRow;
                              }
                         }
                    }
               }
               sizeFactor_ += number;
               int j;
               for (j = 0; j < number; j++)
                    used[which[j]] = 0;
          }
     }
     delete [] which;
     // Now we have size - create arrays and fill in
     try {
          choleskyRow_ = new int [sizeFactor_];
     } catch (...) {
          // no memory
          delete [] choleskyStart_;
          choleskyStart_ = NULL;
          return -1;
     }
     try {
          sparseFactor_ = new double[sizeFactor_];
     } catch (...) {
          // no memory
          delete [] choleskyRow_;
          choleskyRow_ = NULL;
          delete [] choleskyStart_;
          choleskyStart_ = NULL;
          return -1;
     }

     sizeFactor_ = 0;
     which = choleskyRow_;
     for (iRow = 0; iRow < numberRows_; iRow++) {
          int number = 1;
          // make sure diagonal exists
          which[0] = iRow;
          used[iRow] = 1;
          choleskyStart_[iRow] = sizeFactor_;
          if (!rowsDropped_[iRow]) {
               CoinBigIndex startRow = rowStart[iRow];
               CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow];
               for (CoinBigIndex k = startRow; k < endRow; k++) {
                    int iColumn = column[k];
                    CoinBigIndex start = columnStart[iColumn];
                    CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn];
                    for (CoinBigIndex j = start; j < end; j++) {
                         int jRow = row[j];
                         if (jRow >= iRow && !rowsDropped_[jRow]) {
                              if (!used[jRow]) {
                                   used[jRow] = 1;
                                   which[number++] = jRow;
                              }
                         }
                    }
               }
               sizeFactor_ += number;
               int j;
               for (j = 0; j < number; j++)
                    used[which[j]] = 0;
               // Sort
               std::sort(which, which + number);
               // move which on
               which += number;
          }
     }
     choleskyStart_[numberRows_] = sizeFactor_;
     delete [] used;
     permuteInverse_ = new int [numberRows_];
     permute_ = new int[numberRows_];
     cholmod_sparse A ;
     A.nrow = numberRows_;
     A.ncol = numberRows_;
     A.nzmax = choleskyStart_[numberRows_];
     A.p = choleskyStart_;
     A.i = choleskyRow_;
     A.x = NULL;
     A.stype = -1;
     A.itype = CHOLMOD_INT;
     A.xtype = CHOLMOD_PATTERN;
     A.dtype = CHOLMOD_DOUBLE;
     A.sorted = 1;
     A.packed = 1;
     c_->nmethods = 9;
     c_->postorder = true;
     //c_->dbound=1.0e-20;
     L_ = cholmod_analyze (&A, c_) ;
     if (c_->status) {
       COIN_DETAIL_PRINT(std::cout << "CHOLMOD ordering failed" << std::endl);
          return 1;
     } else {
       COIN_DETAIL_PRINT(printf("%g nonzeros, flop count %g\n", c_->lnz, c_->fl));
     }
     for (iRow = 0; iRow < numberRows_; iRow++) {
          permuteInverse_[iRow] = iRow;
          permute_[iRow] = iRow;
     }
     return 0;
}
Пример #17
0
//#############################################################################
void 
MibSBilevel::createBilevel(CoinPackedVector* sol, 
			   MibSModel *mibs)
{
  
  /** Splits sol into two parts, upper- and lower-level components **/

  if(!mibs) return;
  
  model_ = mibs;

  heuristic_ = new MibSHeuristic(mibs);
  
  int i(0);
  int N(model_->numVars_);
  int lN(model_->lowerDim_); // lower-level dimension
  //int uN(N - lN); // upper-level dimension
  int uN(model_->upperDim_); // upper-level dimension
  double etol(model_->BlisPar()->entry(BlisParams::integerTol));
  //double etol(model_->etol_); 
  
  assert(N == model_->solver()->getNumCols());
  
  int *indices = sol->getIndices();
  double *values = sol->getElements();
  int numElements(sol->getNumElements()); // number of nonzero elements
  
  //FIXME: These don't seem to be used anymore. 
  if(!lowerSolution_)
    lowerSolution_ = new double[lN];
  if(!upperSolution_)
    upperSolution_ = new double[uN];
  CoinZeroN(lowerSolution_, lN);
  CoinZeroN(upperSolution_, uN);

  if(!lowerSolutionOrd_)
    lowerSolutionOrd_ = new double[lN];
  if(!upperSolutionOrd_)
    upperSolutionOrd_ = new double[uN];
  CoinZeroN(lowerSolutionOrd_, lN);
  CoinZeroN(upperSolutionOrd_, uN);
  
  isIntegral_ = true;
  isUpperIntegral_ = true;
  isBilevelFeasible_ = true;
  
  int * lowerColInd = mibs->getLowerColInd();
  int * upperColInd = mibs->getUpperColInd();
  int index(0), uCount(0), lCount(0);
  
  /*
  for(i = 0; i < numElements; i ++){
    index = indices[i];
    if(binarySearch(0, lN - 1, index, lowerColInd) < 0){
      if(fabs(floor(values[i] + 0.5) - values[i]) > etol){
	isIntegral_ = false;
	isBilevelFeasible_ = false;
	upperSolution_[uCount++] = values[i];
      }
      else{
	upperSolution_[uCount++] = floor(values[i] + 0.5);
      }
    }
    else{
      if(fabs(floor(values[i] + 0.5) - values[i]) > etol){
	isIntegral_ = false;
	isBilevelFeasible_ = false;
	lowerSolution_[lCount++] = values[i];
      }    
      else{
	lowerSolution_[lCount++] = floor(values[i] + 0.5);
      }
    }
  }
  */

  //changed this 5/12 to allow for continuous variables

  //FIXME: THIS IS WRONG.  
  //VALUES SHOULD EITHER BE PLACED DIFFERENTLY OR VECTORS MADE SMALLER
  //PROBABLY PLACE THEM DIFFERENTLY AS BELOW, KEEPING NONZERO PLACES
  /*
  for(i = 0; i < numElements; i ++){
    index = indices[i];
    if(binarySearch(0, lN - 1, index, lowerColInd) < 0){
       if(fabs(floor(values[i] + 0.5) - values[i]) > etol){
	  if(mibs->solver()->isInteger(i)){
	     isIntegral_ = false;
	     isBilevelFeasible_ = false;
	  }
	  upperSolution_[uCount++] = values[i];	     
       }
       else{
	  if(mibs->solver()->isInteger(i))
	     upperSolution_[uCount++] = floor(values[i] + 0.5);
	  else
	     upperSolution_[uCount++] = values[i];
       }
    }
    else{
       if(fabs(floor(values[i] + 0.5) - values[i]) > etol){
	  if(mibs->solver()->isInteger(i)){
	     isIntegral_ = false;
	     isBilevelFeasible_ = false;
	  }
	  lowerSolution_[lCount++] = values[i];
       }    
       else{
	  if(mibs->solver()->isInteger(i))
	     lowerSolution_[lCount++] = floor(values[i] + 0.5);
	  else
	     lowerSolution_[lCount++] = values[i];
       }
    }
  }
  */

  const double *lower = model_->solver()->getColLower();
  const double *upper = model_->solver()->getColUpper();
  double value;
  for(i = 0; i < numElements; i ++){
    index = indices[i];
    value = CoinMax(values[i], lower[index]);
    value = CoinMin(value, upper[index]);
    if(binarySearch(0, uN - 1, index, upperColInd) >= 0){
       if(fabs(floor(value + 0.5) - value) > etol){
#if 1
	  //This check is failing when Blis has already declared the solution integral
	  //It's not really needed
	  if(mibs->solver()->isInteger(index)){
	     isUpperIntegral_ = false;
	     isIntegral_ = false;
	     isBilevelFeasible_ = false;
	  }
#endif
       }
    }
    else{
       if(fabs(floor(value + 0.5) - value) > etol){
#if 1
	  //This check is failing when Blis has already declared the solution integral
	  //It's not really needed
	  if(mibs->solver()->isInteger(index)){
	     isIntegral_ = false;
	     isBilevelFeasible_ = false;
	  }
#endif
       }    
    }
  }
 

  /* put the solution in order by integers first */

  int pos(0);

  for(i = 0; i < numElements; i ++){
    index = indices[i];
    pos = binarySearch(0, lN - 1, index, lowerColInd);
    if(pos < 0){
      pos = binarySearch(0, uN - 1, index, upperColInd);
      upperSolutionOrd_[pos] = values[i];
    }
    else
      lowerSolutionOrd_[pos] = values[i];
  }

  if(isUpperIntegral_)
     checkBilevelFeasiblity(mibs->isRoot_);

}
Пример #18
0
void presolve_check_reduced_costs (const CoinPostsolveMatrix *postObj)
{

  static bool warned = false ;
  static double *warned_rcosts = 0 ;
  static int allocSize = 0 ;
  static const CoinPostsolveMatrix *lastObj = 0 ;

/*
  Is the client asking for reinitialisation only?
*/
  if (postObj == 0)
  { warned = false ;
    if (warned_rcosts != 0)
    { delete[] warned_rcosts ;
      warned_rcosts = 0 ; }
    allocSize = 0 ;
    lastObj = 0 ;
    return ; }
/*
  *Should* the client have asked for reinitialisation?
*/
  int ncols0 = postObj->ncols0_ ;
  if (allocSize < ncols0 || postObj != lastObj)
  { warned = false ;
    delete[] warned_rcosts ;
    warned_rcosts = 0 ;
    allocSize = 0 ;
    lastObj = postObj ; }


  double *rcosts = postObj->rcosts_ ;

/*
  By tracking values in warned_rcosts, we can produce a single message the
  first time a value is determined to be incorrect.
*/
  if (!warned)
  { warned = true ;
    std::cout
      << "reduced cost" << std::endl ;
    warned_rcosts = new double[ncols0] ;
    CoinZeroN(warned_rcosts,ncols0) ; }

  double *colels = postObj->colels_ ;
  int *hrow = postObj->hrow_ ;
  int *mcstrt = postObj->mcstrt_ ;
  int *hincol = postObj->hincol_ ;
  CoinBigIndex *link = postObj->link_ ;

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

  double *dcost	= postObj->cost_ ;

  double *sol = postObj->sol_ ;

  char *cdone = postObj->cdone_ ;
  char *rdone = postObj->rdone_ ;

  const double ztoldj = postObj->ztoldj_ ;
  const double ztolzb = postObj->ztolzb_ ;

  double *rowduals = postObj->rowduals_ ;

  double maxmin = postObj->maxmin_ ;
  std::string strMaxmin((maxmin < 0)?"max":"min") ;
  int checkCol=-1;
/*
  Scan all columns, but only check the ones that are marked as having been
  postprocessed.
*/
  for (int j = 0 ; j < ncols0 ; j++)
  { if (cdone[j] == 0) continue ;
    const char *statjstr = postObj->columnStatusString(j) ;
/*
  Check the stored reduced cost for accuracy. See note above w.r.t. maxmin.
*/
    double dj = rcosts[j] ;
    double wrndj = warned_rcosts[j] ;

    { int ndx ;
      CoinBigIndex k = mcstrt[j] ;
      int len = hincol[j] ;
      double chkdj = maxmin*dcost[j] ;
      if (j==checkCol)
        printf("dj for %d is %g - cost is %g\n",
               j,dj,chkdj);
      for (ndx = 0 ; ndx < len ; ndx++)
      { int row = hrow[k] ;
	PRESOLVEASSERT(rdone[row] != 0) ;
	chkdj -= rowduals[row]*colels[k] ;
        if (j==checkCol)
          printf("row %d coeff %g dual %g => dj %g\n",
                 row,colels[k],rowduals[row],chkdj);

	k = link[k] ; }
      if (fabs(dj-chkdj) > ztoldj && wrndj != dj)
      { std::cout
          << "Inacc rcost: " << j << " " << statjstr << " "
	  << strMaxmin << " have " << dj
	  << " should be " << chkdj << " err " << fabs(dj-chkdj)
	  << std::endl ; } }
/*
  Check the stored reduced cost for consistency with the variable's status.
  The cases are
    * basic: (reduced cost) == 0
    * at upper bound and not at lower bound: (reduced cost)*(maxmin) <= 0
    * at lower bound and not at upper bound: (reduced cost)*(maxmin) >= 0
    * not at either bound: any sign is correct (the variable can move either
      way) but superbasic status is sufficiently exotic that it always
      deserves a message. (There should be no superbasic variables at the
      completion of postsolve.)
  As a courtesy, show the reduced cost with the proper sign.
*/
    { double xj = sol[j] ;
      double lj = clo[j] ;
      double uj = cup[j] ;

      if (postObj->columnIsBasic(j))
      { if (fabs(dj) > ztoldj && wrndj != dj)
	{ std::cout
	    << "Bad rcost: " << j << " " << maxmin*dj
	    << " " << statjstr << " " << strMaxmin << std::endl ; } }
      else
      if (fabs(xj-uj) < ztolzb && fabs(xj-lj) > ztolzb)
      { if (dj >= ztoldj && wrndj != dj)
	{ std::cout
	    << "Bad rcost: " << j << " " << maxmin*dj
	    << " " << statjstr << " " << strMaxmin << std::endl ; } }
      else
      if (fabs(xj-lj) < ztolzb && fabs(xj-uj) > ztolzb)
      { if (dj <= -ztoldj && wrndj != dj)
	{ std::cout
	    << "Bad rcost: " << j << " " << maxmin*dj
	    << " " << statjstr << " " << strMaxmin << std::endl ; } }
      else
      if (fabs(xj-lj) > ztolzb && fabs(xj-uj) > ztolzb)
      { if (fabs(dj) > ztoldj && wrndj != dj)
        { std::cout
	    << "Superbasic rcost: " << j << " " << maxmin*dj
	    << " " << statjstr << " " << strMaxmin
	    << " lb "<< lj << " val " << xj << " ub "<< uj << std::endl ; } }
    }

    warned_rcosts[j] = rcosts[j] ; }

}
Пример #19
0
void
CoinPostsolveMatrix::assignPresolveToPostsolve (CoinPresolveMatrix *&preObj)

{
/*
  Start with simple data --- allocated and current size.
*/
  ncols0_ = preObj->ncols0_ ;
  nrows0_ = preObj->nrows0_ ;
  nelems0_ = preObj->nelems0_ ;
  bulk0_ = preObj->bulk0_ ;

  ncols_ = preObj->ncols_ ;
  nrows_ = preObj->nrows_ ;
  nelems_ = preObj->nelems_ ;
/*
  Now bring over the column-major matrix and other problem data.
*/
  mcstrt_ = preObj->mcstrt_ ;
  preObj->mcstrt_ = 0 ;
  hincol_ = preObj->hincol_ ;
  preObj->hincol_ = 0 ;
  hrow_ = preObj->hrow_ ;
  preObj->hrow_ = 0 ;
  colels_ = preObj->colels_ ;
  preObj->colels_ = 0 ;

  cost_ = preObj->cost_ ;
  preObj->cost_ = 0 ;
  originalOffset_ = preObj->originalOffset_ ;
  clo_ = preObj->clo_ ;
  preObj->clo_ = 0 ;
  cup_ = preObj->cup_ ;
  preObj->cup_ = 0 ;
  rlo_ = preObj->rlo_ ;
  preObj->rlo_ = 0 ;
  rup_ = preObj->rup_ ;
  preObj->rup_ = 0 ;

  originalColumn_ = preObj->originalColumn_ ;
  preObj->originalColumn_ = 0 ;
  originalRow_ = preObj->originalRow_ ;
  preObj->originalRow_ = 0 ;

  ztolzb_ = preObj->ztolzb_ ;
  ztoldj_ = preObj->ztoldj_ ;
  maxmin_ = preObj->maxmin_ ;
/*
  Now the problem solution. Often this will be empty, but that's not a problem.
*/
  sol_ = preObj->sol_ ;
  preObj->sol_ = 0 ;
  rowduals_ = preObj->rowduals_ ;
  preObj->rowduals_ = 0 ;
  acts_ = preObj->acts_ ;
  preObj->acts_ = 0 ;
  rcosts_ = preObj->rcosts_ ;
  preObj->rcosts_ = 0 ;
  colstat_ = preObj->colstat_ ;
  preObj->colstat_ = 0 ;
  rowstat_ = preObj->rowstat_ ;
  preObj->rowstat_ = 0 ;
/*
  The CoinPostsolveMatrix comes with messages and a handler, but replace them
  with the versions from the CoinPresolveObject, in case they've been
  customized. Let preObj believe it's no longer responsible for the handler.
*/
  if (defaultHandler_ == true)
    delete handler_ ;
  handler_ = preObj->handler_ ;
  preObj->defaultHandler_ = false ;
  messages_ = preObj->messages_ ;
/*
  Initialise the postsolve portions of this object. Which amounts to setting
  up the thread links to match the column-major matrix representation. This
  would be trivial except that the presolve matrix is loosely packed. We can
  either compress the matrix, or record the existing free space pattern. Bet
  that the latter is more efficient. Remember that mcstrt_[ncols_] actually
  points to the end of the bulk storage area, so when we process the last
  column in the bulk storage area, we'll add the free space block at the end
  of bulk storage to the free list.

  We need to allow for a 0x0 matrix here --- a pathological case, but it slips
  in when (for example) confirming a solution in an ILP code.
*/
  free_list_ = NO_LINK ;
  maxlink_ = bulk0_ ;
  link_ = new CoinBigIndex [maxlink_] ;

  if (ncols_ > 0)
  { CoinBigIndex minkcs = -1 ;
    for (int j = 0 ; j < ncols_ ; j++)
    { CoinBigIndex kcs = mcstrt_[j] ;
      int lenj = hincol_[j] ;
      assert(lenj > 0) ;
      CoinBigIndex kce = kcs+lenj-1 ;
      CoinBigIndex k ;

      for (k = kcs ; k < kce ; k++)
      { link_[k] = k+1 ; }
      link_[k++] = NO_LINK ;

      if (preObj->clink_[j].pre == NO_LINK)
      { minkcs = kcs ; }
      int nxtj = preObj->clink_[j].suc ;
      assert(nxtj >= 0 && nxtj <= ncols_) ;
      CoinBigIndex nxtcs = mcstrt_[nxtj] ;
      for ( ; k < nxtcs ; k++)
      { link_[k] = free_list_ ;
	free_list_ = k ; } }

    assert(minkcs >= 0) ;
    if (minkcs > 0)
    { for (CoinBigIndex k = 0 ; k < minkcs ; k++)
      { link_[k] = free_list_ ;
	free_list_ = k ; } } }
  else
  { for (CoinBigIndex k = 0 ; k < maxlink_ ; k++)
    { link_[k] = free_list_ ;
      free_list_ = k ; } }
/*
  That's it, preObj can die now.
*/
  delete preObj ;
  preObj = 0 ;

# if PRESOLVE_DEBUG || PRESOLVE_CONSISTENCY
/*
  These are used to track the action of postsolve transforms during debugging.
*/
  cdone_ = new char [ncols0_] ;
  CoinFillN(cdone_,ncols_,PRESENT_IN_REDUCED) ;
  CoinZeroN(cdone_+ncols_,ncols0_-ncols_) ;
  rdone_ = new char [nrows0_] ;
  CoinFillN(rdone_,nrows_,PRESENT_IN_REDUCED) ;
  CoinZeroN(rdone_+nrows_,nrows0_-nrows_) ;
# else
  cdone_ = 0 ;
  rdone_ = 0 ;
# endif

# if PRESOLVE_CONSISTENCY
  presolve_check_free_list(this,true) ;
  presolve_check_threads(this) ;
# endif

  return ; }
Пример #20
0
//#############################################################################
bfSol*
MibSHeuristic::getBilevelSolution1(const double * sol)
{

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


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

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

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

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

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

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

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

#ifndef COIN_HAS_SYMPHONY
  dynamic_cast<OsiCbcSolverInterface *> 
     (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0);
#else
  dynamic_cast<OsiSymSolverInterface *> 
     (lSolver)->setSymParam("prep_level", -1);
  
  dynamic_cast<OsiSymSolverInterface *> 
     (lSolver)->setSymParam("verbosity", -2);
  
  dynamic_cast<OsiSymSolverInterface *> 
     (lSolver)->setSymParam("max_active_nodes", 1);
#endif

  lSolver->branchAndBound();

  if(lSolver->isProvenOptimal()){

    double objVal(0.0);

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

}
Пример #21
0
/* Factorize - filling in rowsDropped and returning number dropped */
int
ClpCholeskyMumps::factorize(const double * diagonal, int * rowsDropped)
{
     const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts();
     const int * columnLength = model_->clpMatrix()->getVectorLengths();
     const int * row = model_->clpMatrix()->getIndices();
     const double * element = model_->clpMatrix()->getElements();
     const CoinBigIndex * rowStart = rowCopy_->getVectorStarts();
     const int * rowLength = rowCopy_->getVectorLengths();
     const int * column = rowCopy_->getIndices();
     const double * elementByRow = rowCopy_->getElements();
     int numberColumns = model_->clpMatrix()->getNumCols();
     int iRow;
     double * work = new double[numberRows_];
     CoinZeroN(work, numberRows_);
     const double * diagonalSlack = diagonal + numberColumns;
     int newDropped = 0;
     double largest;
     //double smallest;
     //perturbation
     double perturbation = model_->diagonalPerturbation() * model_->diagonalNorm();
     perturbation = 0.0;
     perturbation = perturbation * perturbation;
     if (perturbation > 1.0) {
#ifdef COIN_DEVELOP
          //if (model_->model()->logLevel()&4)
          std::cout << "large perturbation " << perturbation << std::endl;
#endif
          perturbation = sqrt(perturbation);;
          perturbation = 1.0;
     }
     double delta2 = model_->delta(); // add delta*delta to diagonal
     delta2 *= delta2;
     for (iRow = 0; iRow < numberRows_; iRow++) {
          double * put = sparseFactor_ + choleskyStart_[iRow] - 1; // Fortran
          int * which = choleskyRow_ + choleskyStart_[iRow] - 1; // Fortran
          int number = choleskyStart_[iRow+1] - choleskyStart_[iRow];
          if (!rowLength[iRow])
               rowsDropped_[iRow] = 1;
          if (!rowsDropped_[iRow]) {
               CoinBigIndex startRow = rowStart[iRow];
               CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow];
               work[iRow] = diagonalSlack[iRow] + delta2;
               for (CoinBigIndex k = startRow; k < endRow; k++) {
                    int iColumn = column[k];
                    if (!whichDense_ || !whichDense_[iColumn]) {
                         CoinBigIndex start = columnStart[iColumn];
                         CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn];
                         double multiplier = diagonal[iColumn] * elementByRow[k];
                         for (CoinBigIndex j = start; j < end; j++) {
                              int jRow = row[j];
                              if (jRow >= iRow && !rowsDropped_[jRow]) {
                                   double value = element[j] * multiplier;
                                   work[jRow] += value;
                              }
                         }
                    }
               }
               int j;
               for (j = 0; j < number; j++) {
                    int jRow = which[j] - 1; // to Fortran
                    put[j] = work[jRow];
                    work[jRow] = 0.0;
               }
          } else {
               // dropped
               int j;
               for (j = 1; j < number; j++) {
                    put[j] = 0.0;
               }
               put[0] = 1.0;
          }
     }
     //check sizes
     double largest2 = maximumAbsElement(sparseFactor_, sizeFactor_);
     largest2 *= 1.0e-20;
     largest = CoinMin(largest2, 1.0e-11);
     int numberDroppedBefore = 0;
     for (iRow = 0; iRow < numberRows_; iRow++) {
          int dropped = rowsDropped_[iRow];
          // Move to int array
          rowsDropped[iRow] = dropped;
          if (!dropped) {
               CoinBigIndex start = choleskyStart_[iRow] - 1; // to Fortran
               double diagonal = sparseFactor_[start];
               if (diagonal > largest2) {
                    sparseFactor_[start] = CoinMax(diagonal, 1.0e-10);
               } else {
                    sparseFactor_[start] = CoinMax(diagonal, 1.0e-10);
                    rowsDropped[iRow] = 2;
                    numberDroppedBefore++;
               }
          }
     }
     delete [] work;
     // code here
     mumps_->a_elt = sparseFactor_;
     mumps_->rhs = NULL;
     mumps_->job = 2; // factorize
     dmumps_c(mumps_);
     if (mumps_->infog[0]) {
          COIN_DETAIL_PRINT(printf("MUMPS factorization failed -error %d %d\n",
				   mumps_->infog[0], mumps_->infog[1]));
     }
     choleskyCondition_ = 1.0;
     bool cleanCholesky;
     if (model_->numberIterations() < 2000)
          cleanCholesky = true;
     else
          cleanCholesky = false;
     if (cleanCholesky) {
          //drop fresh makes some formADAT easier
          //int oldDropped=numberRowsDropped_;
          if (newDropped || numberRowsDropped_) {
               //std::cout <<"Rank "<<numberRows_-newDropped<<" ( "<<
               //  newDropped<<" dropped)";
               //if (newDropped>oldDropped)
               //std::cout<<" ( "<<newDropped-oldDropped<<" dropped this time)";
               //std::cout<<std::endl;
               newDropped = 0;
               for (int i = 0; i < numberRows_; i++) {
                    int dropped = rowsDropped[i];
                    rowsDropped_[i] = (char)dropped;
                    if (dropped == 2) {
                         //dropped this time
                         rowsDropped[newDropped++] = i;
                         rowsDropped_[i] = 0;
                    }
               }
               numberRowsDropped_ = newDropped;
               newDropped = -(2 + newDropped);
          }
     } else {
          if (newDropped) {
               newDropped = 0;
               for (int i = 0; i < numberRows_; i++) {
                    int dropped = rowsDropped[i];
                    rowsDropped_[i] = (char)dropped;
                    if (dropped == 2) {
                         //dropped this time
                         rowsDropped[newDropped++] = i;
                         rowsDropped_[i] = 1;
                    }
               }
          }
          numberRowsDropped_ += newDropped;
          if (numberRowsDropped_ && 0) {
               std::cout << "Rank " << numberRows_ - numberRowsDropped_ << " ( " <<
                         numberRowsDropped_ << " dropped)";
               if (newDropped) {
                    std::cout << " ( " << newDropped << " dropped this time)";
               }
               std::cout << std::endl;
          }
     }
     status_ = 0;
     return newDropped;
}
Пример #22
0
//#############################################################################
mcSol 
MibSHeuristic::solveSubproblem(double beta)
{

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

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

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

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


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

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


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

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

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

#ifndef COIN_HAS_SYMPHONY
  dynamic_cast<OsiCbcSolverInterface *> 
     (sSolver)->getModelPtr()->messageHandler()->setLogLevel(0);
#else
  dynamic_cast<OsiSymSolverInterface *> 
     (sSolver)->setSymParam("prep_level", -1);
  
  dynamic_cast<OsiSymSolverInterface *> 
     (sSolver)->setSymParam("verbosity", -2);
  
  dynamic_cast<OsiSymSolverInterface *> 
     (sSolver)->setSymParam("max_active_nodes", 1);
#endif

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

  sSolver->branchAndBound();

  if(sSolver->isProvenOptimal()){

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

    for(i = 0; i < tCols; i++){
      upperObjVal += 
	sSolver->getColSolution()[i] * oSolver->getObjCoefficients()[i];
      if(0){
	std::cout << "sSolver->getColSolution()[" << i << "] :"
		  << sSolver->getColSolution()[i] << std::endl;
      }
    }
    lowerObjVal = getLowerObj(sSolver->getColSolution(), lObjSense);
    
    if(beta == 1.0){
      
      /*
	fix upper-level objective to current value and 
	reoptimize wrt to lower-level objective
      */
      
#ifndef COIN_HAS_SYMPHONY
       OsiSolverInterface * nSolver = new OsiCbcSolverInterface();
#else
       OsiSolverInterface * nSolver = new OsiSymSolverInterface();
#endif

       nSolver->loadProblem(*oSolver->getMatrixByCol(),
			    oSolver->getColLower(), oSolver->getColUpper(),
			    oSolver->getObjCoefficients(),
			    oSolver->getRowLower(), oSolver->getRowUpper());
       for(j = 0; j < tCols; j++){
	  if(oSolver->isInteger(j))
	     nSolver->setInteger(j);
       }
       

      CoinZeroN(nObjCoeffs, tCols);
      
      for(i = 0; i < lCols; i++){
	index = lColIndices[i];
	nObjCoeffs[index] = lObjCoeffs[i] * lObjSense;
      }
      
      nSolver->setObjective(nObjCoeffs);
      
      CoinPackedVector objCon;
      
      for(i = 0; i < tCols; i++){
	objCon.insert(i, uObjCoeffs[i] * uObjSense);
      }
      
      nSolver->addRow(objCon, upperObjVal, upperObjVal);
      nSolver->writeLp("beta1");

#ifndef COIN_HAS_SYMPHONY
      dynamic_cast<OsiCbcSolverInterface *> 
	 (nSolver)->getModelPtr()->messageHandler()->setLogLevel(0);
#else
      dynamic_cast<OsiSymSolverInterface *> 
	 (nSolver)->setSymParam("prep_level", -1);
      
      dynamic_cast<OsiSymSolverInterface *> 
	 (nSolver)->setSymParam("verbosity", -2);
      
      dynamic_cast<OsiSymSolverInterface *> 
	 (nSolver)->setSymParam("max_active_nodes", 1);
#endif

      nSolver->branchAndBound();
     

      double * colsol = new double[tCols];

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

      delete[] nObjCoeffs;
      nObjCoeffs = 0;
      delete sSolver;
      delete nSolver;
      return mcSol(std::make_pair(upperObjVal, lowerObjVal), colsol);
    }
    else if(beta == 0.0){
      
      /*
	fix lower-level objective to current value and 
	reoptimize wrt to upper-level objective
      */
      
#ifndef COIN_HAS_SYMPHONY
      OsiSolverInterface * nSolver = new OsiCbcSolverInterface();
#else
      OsiSolverInterface * nSolver = new OsiSymSolverInterface();
#endif

      nSolver->loadProblem(*oSolver->getMatrixByCol(),
			   oSolver->getColLower(), oSolver->getColUpper(),
			   oSolver->getObjCoefficients(),
			   oSolver->getRowLower(), oSolver->getRowUpper());
      for(j = 0; j < tCols; j++){
	if(oSolver->isInteger(j))
	  nSolver->setInteger(j);
      }
      
      CoinZeroN(nObjCoeffs, tCols);
	
      for(i = 0; i < tCols; i++)
	nObjCoeffs[i] = uObjCoeffs[i] * uObjSense;
      
      nSolver->setObjective(nObjCoeffs);
	
      CoinPackedVector objCon;
	
      for(i = 0; i < lCols; i++){
	index = lColIndices[i];
	objCon.insert(index, lObjCoeffs[i] * lObjSense);  
      }
      
      nSolver->addRow(objCon, lowerObjVal, lowerObjVal);
      
#ifndef COIN_HAS_SYMPHONY
      dynamic_cast<OsiCbcSolverInterface *> 
	 (nSolver)->getModelPtr()->messageHandler()->setLogLevel(0);
#else
      dynamic_cast<OsiSymSolverInterface *> 
	 (nSolver)->setSymParam("prep_level", -1);
      
      dynamic_cast<OsiSymSolverInterface *> 
	 (nSolver)->setSymParam("verbosity", -2);
      
      dynamic_cast<OsiSymSolverInterface *> 
	 (nSolver)->setSymParam("max_active_nodes", 1);
#endif

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

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

      delete[] nObjCoeffs;
      nObjCoeffs = 0;
      delete sSolver;
      delete nSolver;
      return mcSol(std::make_pair(upperObjVal, lowerObjVal), colsol);
	
    }
    else{
      
      //no optimality cut needed here.  all solutions are supported.
      
      double * colsol = new double[tCols];
      CoinCopyN(sSolver->getColSolution(), tCols, colsol);	
      
      delete[] nObjCoeffs;
      nObjCoeffs = 0;
      delete sSolver;
      return mcSol(std::make_pair(upperObjVal, lowerObjVal), colsol);
      
    }
    
  }
  else{
    //FIXME:SHOULD JUST TAKE THIS OUT.  DELETE sSolver and remove it from above
    
    nObjCoeffs = 0;
    delete[] nObjCoeffs;
    delete sSolver;
    std::cout << "Subproblem is not proven optimal." << std::endl;
    //return NULL;
    //abort();
  }
}
Пример #23
0
DSP_RTN_CODE BlkModel::updateBlocks() {
#define FREE_MEMORY \
	FREE_ARRAY_PTR(ncols_coupled);

	int* ncols_coupled = NULL;

	BGN_TRY_CATCH

	std::vector<int> blockids;
	for (Blocks::iterator it = blocks_.begin(); it != blocks_.end(); ++it)
		blockids.push_back(it->first);

	double stime = CoinGetTimeOfDay();
	/** number of blocks */
	if (blockids.size() > 0) {
		/** coupling columns and rows */
		std::vector<int> master_coupling_cols;

		/** retrieve master information */
		DetBlock* master = block(blockids[0]);
		if (master == NULL)
			return DSP_RTN_ERR;
		const CoinPackedMatrix* master_mat = master->getConstraintMatrix();

		/** get number of columns, rows and integers */
		ncols_full_ = master->getNumCols();
		nrows_full_ = master->getNumRows();
		nints_full_ = master->getNumIntegers();

		/** to count how many subproblems are coupled with each column of the master. */
		ncols_coupled = new int [master->getNumCols()];
		CoinZeroN(ncols_coupled, master->getNumCols());

		for (unsigned i = 1; i < blockids.size(); ++i) {
			/** coupling columns and rows */
			std::vector<int> sub_coupling_cols;
			std::vector<int> sub_coupling_rows;

			/** retrieve subproblem */
			int id = blockids[i];
			DetBlock* sub = block(id);
			if (sub == NULL)
				return DSP_RTN_ERR;

			/** mark it is a dual block angular matrix */
			if (sub->getNumCols() > master->getNumCols())
				dual_block_angular_ = true;

			/** retrieve subproblem column indices */
			const CoinPackedMatrix* sub_mat = sub->getConstraintMatrix();
			int sub_num_col_indices = sub_mat->isColOrdered() ?
					sub_mat->getNumCols() : sub_mat->getNumElements();
			int* sub_col_indices = new int [sub_num_col_indices];
			if (sub_mat->isColOrdered())
				CoinCopyN(sub_mat->getVectorStarts(), sub_num_col_indices, sub_col_indices);
			else
				CoinCopyN(sub_mat->getIndices(), sub_num_col_indices, sub_col_indices);

			/** add number of columns, rows and integers */
			ncols_full_ += sub->getNumCols() - master->getNumCols();
			nrows_full_ += sub->getNumRows() - master->getNumRows();
			nints_full_ += sub->getNumIntegers() - master->getNumIntegers();

			/** sort indices to speed up the search */
			std::sort(sub_col_indices, sub_col_indices + sub_num_col_indices);

			/** find coupling columns and rows */
			for (int j = 0; j < sub_num_col_indices; ++j) {
				if (j > 0 && sub_col_indices[j-1] == sub_col_indices[j])
					continue;
				if (sub_col_indices[j] < master_mat->getNumCols()) {
					master_coupling_cols.push_back(sub_col_indices[j]);
					sub_coupling_cols.push_back(sub_col_indices[j]);
					/** find all the coupling rows */
					for (int row = 0; row < master->getNumRows(); ++row) {
						if (fabs(master_mat->getCoefficient(row, sub_col_indices[j])) > 1.0e-8)
							sub_coupling_rows.push_back(row);
					}
				}
			}

			/** erase duplicates */
			std::sort(sub_coupling_cols.begin(), sub_coupling_cols.end());
			sub_coupling_cols.erase(
					std::unique(sub_coupling_cols.begin(), sub_coupling_cols.end()),
					sub_coupling_cols.end());
			std::sort(sub_coupling_rows.begin(), sub_coupling_rows.end());
			sub_coupling_rows.erase(
					std::unique(sub_coupling_rows.begin(), sub_coupling_rows.end()),
					sub_coupling_rows.end());

			/** set coupling columns and rows */
			sub->setCouplingCols(sub_coupling_cols.size(), &sub_coupling_cols[0]);
			sub->setCouplingRows(sub_coupling_rows.size(), &sub_coupling_rows[0]);
			DSPdebugMessage("Coupling columns of block %d:\n", id);
			DSPdebug(DspMessage::printArray(sub->getNumCouplingCols(), sub->getCouplingCols()));
			DSPdebugMessage("Coupling rows of block %d:\n", id);
			DSPdebug(DspMessage::printArray(sub->getNumCouplingRows(), sub->getCouplingRows()));

			/** count the master columns coupled */
			for (unsigned j = 0; j < sub_coupling_cols.size(); ++j)
				ncols_coupled[sub_coupling_cols[j]]++;
		}

		/** erase duplicates */
		std::sort(master_coupling_cols.begin(), master_coupling_cols.end());
		master_coupling_cols.erase(
				std::unique(master_coupling_cols.begin(), master_coupling_cols.end()),
				master_coupling_cols.end());

		/** set coupling columns */
		master->setCouplingCols(master_coupling_cols.size(), &master_coupling_cols[0]);
		/** set coupling rows */
		int* master_coupling_rows = new int [master->getNumRows()];
		for (int i = 0; i < master->getNumRows(); ++i)
			master_coupling_rows[i] = i;
		master->setCouplingRows(master->getNumRows(), master_coupling_rows);
		FREE_ARRAY_PTR(master_coupling_rows);
#if 0
		/** check if the full matrix is of a primal block angular form. */
		primal_block_angular_ = true;
		for (int j = 0; j < master->getNumCols(); ++j)
			if (ncols_coupled[j] > 1)
				primal_block_angular_ = false;

		if (primal_block_angular_ == true)
			printf("The constraint matrix is of a primal block angular.\n");
		if (dual_block_angular_ == true)
			printf("The constraint matrix is of a dual block angular.\n");
#endif
	}
	DSPdebugMessage("Update block time: %.4f\n", CoinGetTimeOfDay() - stime);

	END_TRY_CATCH_RTN(FREE_MEMORY,DSP_RTN_ERR)

	FREE_MEMORY

	return DSP_RTN_OK;
#undef FREE_MEMORY
}
Пример #24
0
//#############################################################################
void 
MibSHeuristic::objCutHeuristic()
{

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

  MibSModel * model = MibSModel_;

  //OsiSolverInterface * oSolver = model->origLpSolver_;
  OsiSolverInterface * oSolver = model->getSolver();
#ifndef COIN_HAS_SYMPHONY
  OsiSolverInterface * hSolver = new OsiCbcSolverInterface();
#else
  OsiSolverInterface * hSolver = new OsiSymSolverInterface();
#endif
  
  double objSense(model->getLowerObjSense());  
  int lCols(model->getLowerDim());
  int uCols(model->getUpperDim());
  int tCols(lCols + uCols);
  int * lColIndices = model->getLowerColInd();
  int * uColIndices = model->getUpperColInd();
  double * lObjCoeffs = model->getLowerObjCoeffs();

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

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

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

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

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

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

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

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

  hSolver->branchAndBound();

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

  if(hSolver->isProvenOptimal()){

    MibSSolution *mibSol = NULL;

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

#ifndef COIN_HAS_SYMPHONY
    dynamic_cast<OsiCbcSolverInterface *> 
	  (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0);
#else
    dynamic_cast<OsiSymSolverInterface *> 
       (lSolver)->setSymParam("prep_level", -1);
    
    dynamic_cast<OsiSymSolverInterface *> 
       (lSolver)->setSymParam("verbosity", -2);
    
    dynamic_cast<OsiSymSolverInterface *> 
       (lSolver)->setSymParam("max_active_nodes", 1);
#endif

    lSolver->branchAndBound();

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

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

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

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

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

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

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

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

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

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

  delete hSolver;

}
Пример #25
0
/* Factorize - filling in rowsDropped and returning number dropped */
int
ClpCholeskyWssmpKKT::factorize(const double * diagonal, int * rowsDropped)
{
     int numberRowsModel = model_->numberRows();
     int numberColumns = model_->numberColumns();
     int numberTotal = numberColumns + numberRowsModel;
     int newDropped = 0;
     double largest = 0.0;
     double smallest;
     //perturbation
     double perturbation = model_->diagonalPerturbation() * model_->diagonalNorm();
     perturbation = perturbation * perturbation;
     if (perturbation > 1.0) {
#ifdef COIN_DEVELOP
          //if (model_->model()->logLevel()&4)
          std::cout << "large perturbation " << perturbation << std::endl;
#endif
          perturbation = sqrt(perturbation);;
          perturbation = 1.0;
     }
     // need to recreate every time
     int iRow, iColumn;
     const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts();
     const int * columnLength = model_->clpMatrix()->getVectorLengths();
     const int * row = model_->clpMatrix()->getIndices();
     const double * element = model_->clpMatrix()->getElements();

     CoinBigIndex numberElements = 0;
     CoinPackedMatrix * quadratic = NULL;
     ClpQuadraticObjective * quadraticObj =
          (dynamic_cast< ClpQuadraticObjective*>(model_->objectiveAsObject()));
     if (quadraticObj)
          quadratic = quadraticObj->quadraticObjective();
     // matrix
     if (!quadratic) {
          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
               choleskyStart_[iColumn] = numberElements;
               double value = diagonal[iColumn];
               if (fabs(value) > 1.0e-100) {
                    value = 1.0 / value;
                    largest = CoinMax(largest, fabs(value));
                    sparseFactor_[numberElements] = -value;
                    choleskyRow_[numberElements++] = iColumn;
                    CoinBigIndex start = columnStart[iColumn];
                    CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn];
                    for (CoinBigIndex j = start; j < end; j++) {
                         choleskyRow_[numberElements] = row[j] + numberTotal;
                         sparseFactor_[numberElements++] = element[j];
                         largest = CoinMax(largest, fabs(element[j]));
                    }
               } else {
                    sparseFactor_[numberElements] = -1.0e100;
                    choleskyRow_[numberElements++] = iColumn;
               }
          }
     } else {
          // Quadratic
          const int * columnQuadratic = quadratic->getIndices();
          const CoinBigIndex * columnQuadraticStart = quadratic->getVectorStarts();
          const int * columnQuadraticLength = quadratic->getVectorLengths();
          const double * quadraticElement = quadratic->getElements();
          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
               choleskyStart_[iColumn] = numberElements;
               CoinBigIndex savePosition = numberElements;
               choleskyRow_[numberElements++] = iColumn;
               double value = diagonal[iColumn];
               if (fabs(value) > 1.0e-100) {
                    value = 1.0 / value;
                    for (CoinBigIndex j = columnQuadraticStart[iColumn];
                              j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) {
                         int jColumn = columnQuadratic[j];
                         if (jColumn > iColumn) {
                              sparseFactor_[numberElements] = -quadraticElement[j];
                              choleskyRow_[numberElements++] = jColumn;
                         } else if (iColumn == jColumn) {
                              value += quadraticElement[j];
                         }
                    }
                    largest = CoinMax(largest, fabs(value));
                    sparseFactor_[savePosition] = -value;
                    CoinBigIndex start = columnStart[iColumn];
                    CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn];
                    for (CoinBigIndex j = start; j < end; j++) {
                         choleskyRow_[numberElements] = row[j] + numberTotal;
                         sparseFactor_[numberElements++] = element[j];
                         largest = CoinMax(largest, fabs(element[j]));
                    }
               } else {
                    value = 1.0e100;
                    sparseFactor_[savePosition] = -value;
               }
          }
     }
     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
          assert (sparseFactor_[choleskyStart_[iColumn]] < 0.0);
     }
     // slacks
     for (iColumn = numberColumns; iColumn < numberTotal; iColumn++) {
          choleskyStart_[iColumn] = numberElements;
          double value = diagonal[iColumn];
          if (fabs(value) > 1.0e-100) {
               value = 1.0 / value;
               largest = CoinMax(largest, fabs(value));
          } else {
               value = 1.0e100;
          }
          sparseFactor_[numberElements] = -value;
          choleskyRow_[numberElements++] = iColumn;
          choleskyRow_[numberElements] = iColumn - numberColumns + numberTotal;
          sparseFactor_[numberElements++] = -1.0;
     }
     // Finish diagonal
     double delta2 = model_->delta(); // add delta*delta to bottom
     delta2 *= delta2;
     for (iRow = 0; iRow < numberRowsModel; iRow++) {
          choleskyStart_[iRow+numberTotal] = numberElements;
          choleskyRow_[numberElements] = iRow + numberTotal;
          sparseFactor_[numberElements++] = delta2;
     }
     choleskyStart_[numberRows_] = numberElements;
     int i1 = 1;
     int i0 = 0;
     integerParameters_[1] = 3;
     integerParameters_[2] = 3;
     integerParameters_[10] = 2;
     //integerParameters_[11]=1;
     integerParameters_[12] = 2;
     // LDLT
     integerParameters_[30] = 1;
     doubleParameters_[20] = 1.0e100;
     double largest2 = largest * 1.0e-20;
     largest = CoinMin(largest2, 1.0e-11);
     doubleParameters_[10] = CoinMax(1.0e-20, largest);
     if (doubleParameters_[10] > 1.0e-3)
          integerParameters_[9] = 1;
     else
          integerParameters_[9] = 0;
#ifndef WSMP
     // Set up LDL cutoff
     integerParameters_[34] = numberTotal;
     doubleParameters_[20] = 1.0e-15;
     doubleParameters_[34] = 1.0e-12;
     //printf("tol is %g\n",doubleParameters_[10]);
     //doubleParameters_[10]=1.0e-17;
#endif
     int * rowsDropped2 = new int[numberRows_];
     CoinZeroN(rowsDropped2, numberRows_);
     wssmp(&numberRows_, choleskyStart_, choleskyRow_, sparseFactor_,
           NULL, permute_, permuteInverse_, NULL, &numberRows_, &i1,
           NULL, &i0, rowsDropped2, integerParameters_, doubleParameters_);
     //std::cout<<"factorization took "<<doubleParameters_[0]<<std::endl;
     if (integerParameters_[9]) {
          std::cout << "scaling applied" << std::endl;
     }
     newDropped = integerParameters_[20];
#if 1
     // Should save adjustments in ..R_
     int n1 = 0, n2 = 0;
     double * primalR = model_->primalR();
     double * dualR = model_->dualR();
     for (iRow = 0; iRow < numberTotal; iRow++) {
          if (rowsDropped2[iRow]) {
               n1++;
               //printf("row region1 %d dropped\n",iRow);
               //rowsDropped_[iRow]=1;
               rowsDropped_[iRow] = 0;
               primalR[iRow] = doubleParameters_[20];
          } else {
               rowsDropped_[iRow] = 0;
               primalR[iRow] = 0.0;
          }
     }
     for (; iRow < numberRows_; iRow++) {
          if (rowsDropped2[iRow]) {
               n2++;
               //printf("row region2 %d dropped\n",iRow);
               //rowsDropped_[iRow]=1;
               rowsDropped_[iRow] = 0;
               dualR[iRow-numberTotal] = doubleParameters_[34];
          } else {
               rowsDropped_[iRow] = 0;
               dualR[iRow-numberTotal] = 0.0;
          }
     }
     //printf("%d rows dropped in region1, %d in region2\n",n1,n2);
#endif
     delete [] rowsDropped2;
     //if (integerParameters_[20])
     //std::cout<<integerParameters_[20]<<" rows dropped"<<std::endl;
     largest = doubleParameters_[3];
     smallest = doubleParameters_[4];
     if (model_->messageHandler()->logLevel() > 1)
          std::cout << "Cholesky - largest " << largest << " smallest " << smallest << std::endl;
     choleskyCondition_ = largest / smallest;
     if (integerParameters_[63] < 0)
          return -1; // out of memory
     status_ = 0;
     return 0;
}
Пример #26
0
//#############################################################################
void 
MibSHeuristic::greedyHeuristic()
{

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

  int tCols(uCols + lCols); 

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

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

  std::multimap<double, int> lObjCoeffsOrd;

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

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

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

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


  double cost(0.0);

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

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

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

  CoinZeroN(colsol, tCols);

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

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

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

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

  delete [] incumbentSol;
  delete [] testsol;
  //delete [] colsol;
  //delete [] fixedVars;
  //delete sol;
}
Пример #27
0
void
OsiPresolve::postsolve(bool updateStatus)
{
  // Messages
  CoinMessages messages = CoinMessage(presolvedModel_->messages().language());
  if (!presolvedModel_->isProvenOptimal()) {
    presolvedModel_->messageHandler()->message(COIN_PRESOLVE_NONOPTIMAL,
					     messages)
					       <<CoinMessageEol;
  }

  // this is the size of the original problem
  const int ncols0  = ncols_;
  const int nrows0  = nrows_;
  const CoinBigIndex nelems0 = nelems_;

  // reality check
  assert(ncols0==originalModel_->getNumCols());
  assert(nrows0==originalModel_->getNumRows());

  // this is the reduced problem
  int ncols = presolvedModel_->getNumCols();
  int nrows = presolvedModel_->getNumRows();

  double *acts = new double [nrows0];
  double *sol = new double [ncols0];
  CoinZeroN(acts,nrows0);
  CoinZeroN(sol,ncols0);

  unsigned char * rowstat=NULL;
  unsigned char * colstat = NULL;
  CoinWarmStartBasis * presolvedBasis  =
    dynamic_cast<CoinWarmStartBasis*>(presolvedModel_->getWarmStart());
  if (!presolvedBasis)
    updateStatus=false;
  if (updateStatus) {
    colstat = new unsigned char[ncols0+nrows0];
#   ifdef ZEROFAULT
    memset(colstat,0,((ncols0+nrows0)*sizeof(char))) ;
#   endif
    rowstat = colstat + ncols0;
    int i;
    for (i=0;i<ncols;i++) {
      colstat[i] = presolvedBasis->getStructStatus(i);
    }
    for (i=0;i<nrows;i++) {
      rowstat[i] = presolvedBasis->getArtifStatus(i);
    }
  }
  delete presolvedBasis;

# if PRESOLVE_CONSISTENCY > 0
  if (updateStatus)
  { int basicCnt = 0 ;
    int i ;
    for (i = 0 ; i < ncols ; i++)
    { if (colstat[i] == CoinWarmStartBasis::basic) basicCnt++ ; }
    for (i = 0 ; i < nrows ; i++)
    { if (rowstat[i] == CoinWarmStartBasis::basic) basicCnt++ ; }

    assert (basicCnt == nrows) ;
  }
# endif

/*
  Postsolve back to the original problem.  The CoinPostsolveMatrix object
  assumes ownership of sol, acts, colstat, and rowstat.
*/
  CoinPostsolveMatrix prob(presolvedModel_, ncols0, nrows0, nelems0,
			   presolvedModel_->getObjSense(),
			   sol, acts, colstat, rowstat);

  postsolve(prob);


# if PRESOLVE_CONSISTENCY > 0
  if (updateStatus)
  { int basicCnt = 0 ;
    int i ;
    for (i = 0 ; i < ncols0 ; i++)
    { if (prob.getColumnStatus(i) == CoinWarmStartBasis::basic) basicCnt++ ; }
    for (i = 0 ; i < nrows0 ; i++)
    { if (prob.getRowStatus(i) == CoinWarmStartBasis::basic) basicCnt++ ; }

    assert (basicCnt == nrows0) ;
  }
# endif

  originalModel_->setColSolution(sol);
  if (updateStatus) {
    CoinWarmStartBasis *basis =
      dynamic_cast<CoinWarmStartBasis *>(presolvedModel_->getEmptyWarmStart());
    basis->setSize(ncols0,nrows0);
    int i;
    for (i=0;i<ncols0;i++) {
      CoinWarmStartBasis::Status status = static_cast<CoinWarmStartBasis::Status> (prob.getColumnStatus(i));
      /* FIXME: these asserts seem correct, but seem to reveal some bugs in CoinPresolve */
      // assert(status != CoinWarmStartBasis::atLowerBound || originalModel_->getColLower()[i] > -originalModel_->getInfinity());
      // assert(status != CoinWarmStartBasis::atUpperBound || originalModel_->getColUpper()[i] <  originalModel_->getInfinity());
      basis->setStructStatus(i,status);
    }
    for (i=0;i<nrows0;i++) {
      CoinWarmStartBasis::Status status = static_cast<CoinWarmStartBasis::Status> (prob.getRowStatus(i));
      /* FIXME: these asserts seem correct, but seem to reveal some bugs in CoinPresolve */
      // assert(status != CoinWarmStartBasis::atUpperBound || originalModel_->getRowLower()[i] > -originalModel_->getInfinity());
      // assert(status != CoinWarmStartBasis::atLowerBound || originalModel_->getRowUpper()[i] <  originalModel_->getInfinity());
      basis->setArtifStatus(i,status);
    }
    originalModel_->setWarmStart(basis);
    delete basis ;
  }

}
Пример #28
0
//#############################################################################
void 
MibSHeuristic::lowerObjHeuristic()
{

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

  MibSModel * model = MibSModel_;

  OsiSolverInterface * oSolver = model->getSolver();
#ifndef COIN_HAS_SYMPHONY
  OsiSolverInterface * hSolver = new OsiCbcSolverInterface();
#else
  OsiSolverInterface* hSolver = new OsiSymSolverInterface();
#endif
  
  double objSense(model->getLowerObjSense());  
  int lCols(model->getLowerDim());
  int uCols(model->getUpperDim());
  int * lColIndices = model->getLowerColInd();
  int * uColIndices = model->getUpperColInd();
  double * lObjCoeffs = model->getLowerObjCoeffs();
  
  //int tCols(lCols + uCols);
  int tCols(oSolver->getNumCols());
  //assert(tCols == oSolver->getNumCols());

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

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

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

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

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

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

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

#ifndef COIN_HAS_SYMPHONY
  dynamic_cast<OsiCbcSolverInterface *> 
     (hSolver)->getModelPtr()->messageHandler()->setLogLevel(0);
#else
  dynamic_cast<OsiSymSolverInterface *> 
     (hSolver)->setSymParam("prep_level", -1);
  
  dynamic_cast<OsiSymSolverInterface *> 
     (hSolver)->setSymParam("verbosity", -2);
  
  dynamic_cast<OsiSymSolverInterface *> 
     (hSolver)->setSymParam("max_active_nodes", 1);
#endif

  hSolver->branchAndBound();

  if(hSolver->isProvenOptimal()){

    double upperObjVal(0.0);

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

    MibSSolution *mibSol = NULL;

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

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

#ifndef COIN_HAS_SYMPHONY
    dynamic_cast<OsiCbcSolverInterface *> 
       (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0);
#else
    dynamic_cast<OsiSymSolverInterface *> 
       (lSolver)->setSymParam("prep_level", -1);
    
    dynamic_cast<OsiSymSolverInterface *> 
       (lSolver)->setSymParam("verbosity", -2);
    
    dynamic_cast<OsiSymSolverInterface *> 
       (lSolver)->setSymParam("max_active_nodes", 1);
#endif

    lSolver->branchAndBound();

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

}
Пример #29
0
bool
ClpInterior::createWorkingData()
{
     bool goodMatrix = true;
     //check matrix
     if (!matrix_->allElementsInRange(this, 1.0e-12, 1.0e20)) {
          problemStatus_ = 4;
          goodMatrix = false;
     }
     int nTotal = numberRows_ + numberColumns_;
     delete [] solution_;
     solution_ = new CoinWorkDouble[nTotal];
     CoinMemcpyN(columnActivity_,	numberColumns_, solution_);
     CoinMemcpyN(rowActivity_,	numberRows_, solution_ + numberColumns_);
     delete [] cost_;
     cost_ = new CoinWorkDouble[nTotal];
     int i;
     CoinWorkDouble direction = optimizationDirection_ * objectiveScale_;
     // direction is actually scale out not scale in
     if (direction)
          direction = 1.0 / direction;
     const double * obj = objective();
     for (i = 0; i < numberColumns_; i++)
          cost_[i] = direction * obj[i];
     memset(cost_ + numberColumns_, 0, numberRows_ * sizeof(CoinWorkDouble));
     // do scaling if needed
     if (scalingFlag_ > 0 && !rowScale_) {
          if (matrix_->scale(this))
               scalingFlag_ = -scalingFlag_; // not scaled after all
     }
     delete [] lower_;
     delete [] upper_;
     lower_ = new CoinWorkDouble[nTotal];
     upper_ = new CoinWorkDouble[nTotal];
     rowLowerWork_ = lower_ + numberColumns_;
     columnLowerWork_ = lower_;
     rowUpperWork_ = upper_ + numberColumns_;
     columnUpperWork_ = upper_;
     CoinMemcpyN(rowLower_, numberRows_, rowLowerWork_);
     CoinMemcpyN(rowUpper_, numberRows_, rowUpperWork_);
     CoinMemcpyN(columnLower_, numberColumns_, columnLowerWork_);
     CoinMemcpyN(columnUpper_, numberColumns_, columnUpperWork_);
     // clean up any mismatches on infinity
     for (i = 0; i < numberColumns_; i++) {
          if (columnLowerWork_[i] < -1.0e30)
               columnLowerWork_[i] = -COIN_DBL_MAX;
          if (columnUpperWork_[i] > 1.0e30)
               columnUpperWork_[i] = COIN_DBL_MAX;
     }
     // clean up any mismatches on infinity
     for (i = 0; i < numberRows_; i++) {
          if (rowLowerWork_[i] < -1.0e30)
               rowLowerWork_[i] = -COIN_DBL_MAX;
          if (rowUpperWork_[i] > 1.0e30)
               rowUpperWork_[i] = COIN_DBL_MAX;
     }
     // check rim of problem okay
     if (!sanityCheck())
          goodMatrix = false;
     if(rowScale_) {
          for (i = 0; i < numberColumns_; i++) {
               CoinWorkDouble multiplier = rhsScale_ / columnScale_[i];
               cost_[i] *= columnScale_[i];
               if (columnLowerWork_[i] > -1.0e50)
                    columnLowerWork_[i] *= multiplier;
               if (columnUpperWork_[i] < 1.0e50)
                    columnUpperWork_[i] *= multiplier;

          }
          for (i = 0; i < numberRows_; i++) {
               CoinWorkDouble multiplier = rhsScale_ * rowScale_[i];
               if (rowLowerWork_[i] > -1.0e50)
                    rowLowerWork_[i] *= multiplier;
               if (rowUpperWork_[i] < 1.0e50)
                    rowUpperWork_[i] *= multiplier;
          }
     } else if (rhsScale_ != 1.0) {
          for (i = 0; i < numberColumns_ + numberRows_; i++) {
               if (lower_[i] > -1.0e50)
                    lower_[i] *= rhsScale_;
               if (upper_[i] < 1.0e50)
                    upper_[i] *= rhsScale_;

          }
     }
     assert (!errorRegion_);
     errorRegion_ = new CoinWorkDouble [numberRows_];
     assert (!rhsFixRegion_);
     rhsFixRegion_ = new CoinWorkDouble [numberRows_];
     assert (!deltaY_);
     deltaY_ = new CoinWorkDouble [numberRows_];
     CoinZeroN(deltaY_, numberRows_);
     assert (!upperSlack_);
     upperSlack_ = new CoinWorkDouble [nTotal];
     assert (!lowerSlack_);
     lowerSlack_ = new CoinWorkDouble [nTotal];
     assert (!diagonal_);
     diagonal_ = new CoinWorkDouble [nTotal];
     assert (!deltaX_);
     deltaX_ = new CoinWorkDouble [nTotal];
     CoinZeroN(deltaX_, nTotal);
     assert (!deltaZ_);
     deltaZ_ = new CoinWorkDouble [nTotal];
     CoinZeroN(deltaZ_, nTotal);
     assert (!deltaW_);
     deltaW_ = new CoinWorkDouble [nTotal];
     CoinZeroN(deltaW_, nTotal);
     assert (!deltaSU_);
     deltaSU_ = new CoinWorkDouble [nTotal];
     CoinZeroN(deltaSU_, nTotal);
     assert (!deltaSL_);
     deltaSL_ = new CoinWorkDouble [nTotal];
     CoinZeroN(deltaSL_, nTotal);
     assert (!primalR_);
     assert (!dualR_);
     // create arrays if we are doing KKT
     if (cholesky_->type() >= 20) {
          primalR_ = new CoinWorkDouble [nTotal];
          CoinZeroN(primalR_, nTotal);
          dualR_ = new CoinWorkDouble [numberRows_];
          CoinZeroN(dualR_, numberRows_);
     }
     assert (!rhsB_);
     rhsB_ = new CoinWorkDouble [numberRows_];
     CoinZeroN(rhsB_, numberRows_);
     assert (!rhsU_);
     rhsU_ = new CoinWorkDouble [nTotal];
     CoinZeroN(rhsU_, nTotal);
     assert (!rhsL_);
     rhsL_ = new CoinWorkDouble [nTotal];
     CoinZeroN(rhsL_, nTotal);
     assert (!rhsZ_);
     rhsZ_ = new CoinWorkDouble [nTotal];
     CoinZeroN(rhsZ_, nTotal);
     assert (!rhsW_);
     rhsW_ = new CoinWorkDouble [nTotal];
     CoinZeroN(rhsW_, nTotal);
     assert (!rhsC_);
     rhsC_ = new CoinWorkDouble [nTotal];
     CoinZeroN(rhsC_, nTotal);
     assert (!workArray_);
     workArray_ = new CoinWorkDouble [nTotal];
     CoinZeroN(workArray_, nTotal);
     assert (!zVec_);
     zVec_ = new CoinWorkDouble [nTotal];
     CoinZeroN(zVec_, nTotal);
     assert (!wVec_);
     wVec_ = new CoinWorkDouble [nTotal];
     CoinZeroN(wVec_, nTotal);
     assert (!dj_);
     dj_ = new CoinWorkDouble [nTotal];
     if (!status_)
          status_ = new unsigned char [numberRows_+numberColumns_];
     memset(status_, 0, numberRows_ + numberColumns_);
     return goodMatrix;
}
Пример #30
0
// Returns gradient
int
ClpConstraintQuadratic::gradient(const ClpSimplex * model,
                                 const double * solution,
                                 double * gradient,
                                 double & functionValue,
                                 double & offset,
                                 bool useScaling,
                                 bool refresh) const
{
     if (refresh || !lastGradient_) {
          offset_ = 0.0;
          functionValue_ = 0.0;
          if (!lastGradient_)
               lastGradient_ = new double[numberColumns_];
          CoinZeroN(lastGradient_, numberColumns_);
          bool scaling = (model && model->rowScale() && useScaling);
          if (!scaling) {
               int iColumn;
               for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) {
                    double valueI = solution[iColumn];
                    CoinBigIndex j;
                    for (j = start_[iColumn]; j < start_[iColumn+1]; j++) {
                         int jColumn = column_[j];
                         if (jColumn >= 0) {
                              double valueJ = solution[jColumn];
                              double elementValue = coefficient_[j];
                              if (iColumn != jColumn) {
                                   offset_ -= valueI * valueJ * elementValue;
                                   double gradientI = valueJ * elementValue;
                                   double gradientJ = valueI * elementValue;
                                   lastGradient_[iColumn] += gradientI;
                                   lastGradient_[jColumn] += gradientJ;
                              } else {
                                   offset_ -= 0.5 * valueI * valueI * elementValue;
                                   double gradientI = valueI * elementValue;
                                   lastGradient_[iColumn] += gradientI;
                              }
                         } else {
                              // linear part
                              lastGradient_[iColumn] += coefficient_[j];
                              functionValue_ += valueI * coefficient_[j];
                         }
                    }
               }
               functionValue_ -= offset_;
          } else {
               abort();
               // do scaling
               const double * columnScale = model->columnScale();
               for (int i = 0; i < numberCoefficients_; i++) {
                    int iColumn = column_[i];
                    double value = solution[iColumn]; // already scaled
                    double coefficient = coefficient_[i] * columnScale[iColumn];
                    functionValue_ += value * coefficient;
                    lastGradient_[iColumn] = coefficient;
               }
          }
     }
     functionValue = functionValue_;
     offset = offset_;
     CoinMemcpyN(lastGradient_, numberColumns_, gradient);
     return 0;
}