Beispiel #1
0
// We could have implemented this by having each postsolve routine
// directly call the next one, but this may make it easier to add debugging checks.
void OsiPresolve::postsolve(CoinPostsolveMatrix &prob)
{
  const CoinPresolveAction *paction = paction_;

#if	PRESOLVE_DEBUG
  printf("Begin POSTSOLVING\n") ;
  if (prob.colstat_)
  { presolve_check_nbasic(&prob);
    presolve_check_sol(&prob); }
  presolve_check_duals(&prob);
#endif


  while (paction) {
#   if PRESOLVE_DEBUG
    printf("POSTSOLVING %s\n", paction->name());
#   endif

    paction->postsolve(&prob);

#   if PRESOLVE_DEBUG
    if (prob.colstat_)
    { presolve_check_nbasic(&prob);
      presolve_check_sol(&prob); }
#   endif
    paction = paction->next;
#   if PRESOLVE_DEBUG
    presolve_check_duals(&prob);
#   endif
  }
# if PRESOLVE_DEBUG
    printf("End POSTSOLVING\n") ;
# endif

#if	0 && PRESOLVE_DEBUG

  << This block of checks will require some work to get it to compile. >>
Beispiel #2
0
/*
  Undo the substitutions from presolve and reintroduce the target constraint
  and column.
*/
void subst_constraint_action::postsolve(CoinPostsolveMatrix *prob) const
{

# if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0
# if PRESOLVE_DEBUG > 0
  std::cout
    << "Entering subst_constraint_action::postsolve, "
    << nactions_ << " constraints to process." << std::endl ;
# endif
  int ncols = prob->ncols_ ;
  char *cdone = prob->cdone_ ;
  char *rdone = prob->rdone_ ;
  const double ztolzb = prob->ztolzb_ ;

  presolve_check_threads(prob) ;
  presolve_check_free_list(prob) ;
  presolve_check_reduced_costs(prob) ;
  presolve_check_duals(prob) ;
  presolve_check_sol(prob,2,2,2) ;
  presolve_check_nbasic(prob) ;
# endif

/*
  Unpack the column-major representation.
*/
  CoinBigIndex *colStarts = prob->mcstrt_ ;
  int *colLengths = prob->hincol_ ;
  int *rowIndices = prob->hrow_ ;
  double *colCoeffs = prob->colels_ ;
/*
  Rim vectors, solution, reduced costs, duals, row activity.
*/
  double *rlo = prob->rlo_ ;
  double *rup = prob->rup_ ;
  double *cost = prob->cost_ ;
  double *sol = prob->sol_ ;
  double *rcosts = prob->rcosts_ ;
  double *acts = prob->acts_ ;
  double *rowduals = prob->rowduals_ ;

  CoinBigIndex *link = prob->link_ ;
  CoinBigIndex &free_list = prob->free_list_ ;

  const double maxmin = prob->maxmin_ ;

  const action *const actions = actions_ ;
  const int nactions = nactions_ ;

/*
  Open the main loop to step through the postsolve objects.

  First activity is to unpack the postsolve object. We have the target
  column and row indices, the full target column, and complete copies of
  all entangled rows (column indices, coefficients, lower and upper bounds).
  There may be a vector of objective coefficients which we'll get to later.
*/
  for (const action *f = &actions[nactions-1] ; actions <= f ; f--) {
    const int tgtcol = f->col ;
    const int tgtrow = f->rowy ;

    const int tgtcol_len = f->nincol ;
    const double *tgtcol_coeffs = f->coeffxs ;

    const int *entngld_rows = f->rows ;
    const int *entngld_lens = f->ninrowxs ;
    const int *entngld_colndxs = f->rowcolsxs ;
    const double *entngld_colcoeffs = f->rowelsxs ;
    const double *entngld_rlos = f->rlos ;
    const double *entngld_rups = f->rups ;
    const double *costs = f->costsx ;

#   if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0
#   if PRESOLVE_DEBUG > 1
    std::cout
      << "  reintroducing column x(" << tgtcol << ") and row " << tgtrow ;
      if (costs) std::cout << ", nonzero costs" ;
      std::cout << "." << std::endl ;
#   endif
/*
  We're about to reintroduce the target row and column; empty stubs should be
  present. All other rows should already be present.
*/
    PRESOLVEASSERT(cdone[tgtcol] == DROP_COL) ;
    PRESOLVEASSERT(colLengths[tgtcol] == 0) ;
    PRESOLVEASSERT(rdone[tgtrow] == DROP_ROW) ;
    for (int cndx = 0 ; cndx < tgtcol_len ; ++cndx) {
      if (entngld_rows[cndx] != tgtrow)
	PRESOLVEASSERT(rdone[entngld_rows[cndx]]) ;
    }
/*
  In a postsolve matrix, we can't just check that the length of the row is
  zero. We need to look at all columns and confirm its absence.
*/
    for (int j = 0 ; j < ncols ; ++j) {
      if (colLengths[j] > 0 && cdone[j]) {
        const CoinBigIndex kcs = colStarts[j] ;
        const int lenj = colLengths[j] ;
	CoinBigIndex krow =
	  presolve_find_row3(tgtrow,kcs,lenj,rowIndices,link) ;
	if (krow >= 0) {
	  std::cout
	    << "  BAD COEFF! row " << tgtrow << " present in column " << j
	    << " before reintroduction; a(" << tgtrow << "," << j
	    << ") = " << colCoeffs[krow] << "; x(" << j << ") = " << sol[j]
	    << "; cdone " << static_cast<int>(cdone[j]) << "." << std::endl ;
	}
      }
    }
#   endif

/*
  Find the copy of the target row. Restore the upper and lower bounds
  of entangled rows while we're looking. Recall that the target row is
  an equality.
*/
    int tgtrow_len = -1 ;
    const int *tgtrow_colndxs = NULL ;
    const double *tgtrow_coeffs = NULL ;
    double tgtcoeff = 0.0 ;
    double tgtrhs = 1.0e50 ;

    int nel = 0 ;
    for (int cndx = 0 ; cndx < tgtcol_len ; ++cndx) {
      int i = entngld_rows[cndx] ;
      rlo[i] = entngld_rlos[cndx] ;
      rup[i] = entngld_rups[cndx] ;
      if (i == tgtrow) {
	tgtrow_len = entngld_lens[cndx] ;
	tgtrow_colndxs = &entngld_colndxs[nel] ;
	tgtrow_coeffs  = &entngld_colcoeffs[nel] ;
	tgtcoeff = tgtcol_coeffs[cndx] ;
	tgtrhs = rlo[i] ;
      }
      nel += entngld_lens[cndx] ;
    }
/*
  Solve the target equality to find the solution for the eliminated col.
  tgtcol is present in tgtrow_colndxs, so initialise sol[tgtcol] to zero
  to make sure it doesn't contribute.

  If we're debugging, check that the result is within bounds.
*/
    double tgtexp = tgtrhs ;
    sol[tgtcol] = 0.0 ;
    for (int ndx = 0 ; ndx < tgtrow_len ; ++ndx) {
      int j = tgtrow_colndxs[ndx] ;
      double coeffj = tgtrow_coeffs[ndx] ;
      tgtexp -= coeffj*sol[j] ;
    }
    sol[tgtcol] = tgtexp/tgtcoeff ;

#   if PRESOLVE_DEBUG > 0
    double *clo = prob->clo_ ;
    double *cup = prob->cup_ ;

    if (!(sol[tgtcol] > (clo[tgtcol]-ztolzb) &&
	  (cup[tgtcol]+ztolzb) > sol[tgtcol])) {
      std::cout
	<< "BAD SOL: x(" << tgtcol << ") " << sol[tgtcol]
	<< "; lb " << clo[tgtcol] << "; ub " << cup[tgtcol] << "."
	<< std::endl ;
    }
#   endif
/*
  Now restore the original entangled rows. We first delete any columns present
  in tgtrow. This will remove any fillin, but may also remove columns that
  were originally present in both the entangled row and the target row.

  Note that even cancellations (explicit zeros) are present at this
  point --- in presolve, they were removed after the substition transform
  completed, hence they're already restored. What isn't present is the target
  column, which is deleted as part of the transform.
*/
    {
#     if PRESOLVE_DEBUG > 2
      std::cout << "    removing coefficients:" ;
#     endif
      for (int rndx = 0 ; rndx < tgtrow_len ; ++rndx) {
	int j = tgtrow_colndxs[rndx] ;
	if (j != tgtcol)
	  for (int cndx = 0 ; cndx < tgtcol_len ; ++cndx) {
	    if (entngld_rows[cndx] != tgtrow) {
#             if PRESOLVE_DEBUG > 2
	      std::cout << " a(" << entngld_rows[cndx] << "," << j << ")" ;
#             endif
	      presolve_delete_from_col2(entngld_rows[cndx],j,colStarts,
				      colLengths,rowIndices,link,&free_list) ;
	    }
	  }
      }
#     if PRESOLVE_DEBUG > 2
      std::cout << std::endl ;
#     endif
#     if PRESOLVE_CONSISTENCY > 0
      presolve_check_threads(prob) ;
      presolve_check_free_list(prob) ;
#     endif
/*
  Next we restore the original coefficients. The outer loop walks tgtcol;
  cols_i and coeffs_i are advanced as we go to point to each entangled
  row. The inner loop walks the entangled row and restores the row's
  coefficients. Tgtcol is handled as any other column. Skip tgtrow, we'll
  do it below.

  Since we don't have a row-major representation, we have to look for a(i,j)
  from entangled row i in the existing column j. If we find a(i,j), simply
  update it (and a(tgtrow,j) should not exist). If we don't find a(i,j),
  introduce it (and a(tgtrow,j) should exist).

  Recalculate the row activity while we're at it.
*/
#     if PRESOLVE_DEBUG > 2
      std::cout << "    restoring coefficients:" ;
#     endif

      colLengths[tgtcol] = 0 ;
      const int *cols_i = entngld_colndxs ;
      const double *coeffs_i = entngld_colcoeffs ;

      for (int cndx = 0 ; cndx < tgtcol_len ; ++cndx) {
	const int leni = entngld_lens[cndx] ;
	const int i = entngld_rows[cndx] ;

	if (i != tgtrow) {
	  double acti = 0.0 ;
	  for (int rndx = 0 ; rndx < leni ; ++rndx) {
	    const int j = cols_i[rndx] ;
	    CoinBigIndex kcoli =
	      presolve_find_row3(i,colStarts[j],
	      			 colLengths[j],rowIndices,link) ;
	    if (kcoli != -1) {
#             if PRESOLVE_DEBUG > 2
	      std::cout << " u a(" << i << "," << j << ")" ;
	      PRESOLVEASSERT(presolve_find_col1(j,0,tgtrow_len,
	      					tgtrow_colndxs) == tgtrow_len) ;
#	      endif
	      colCoeffs[kcoli] = coeffs_i[rndx] ;
	    } else {
#             if PRESOLVE_DEBUG > 2
	      std::cout << " f a(" << i << "," << j << ")" ;
	      PRESOLVEASSERT(presolve_find_col1(j,0,tgtrow_len,
						tgtrow_colndxs) < tgtrow_len) ;
#	      endif
	      CoinBigIndex kk = free_list ;
	      assert(kk >= 0 && kk < prob->bulk0_) ;
	      free_list = link[free_list] ;
	      link[kk] = colStarts[j] ;
	      colStarts[j] = kk ;
	      colCoeffs[kk] = coeffs_i[rndx] ;
	      rowIndices[kk] = i ;
	      ++colLengths[j] ;
	    }
	    acti += coeffs_i[rndx]*sol[j] ;
	  }
	  acts[i] = acti ;
	}
	cols_i += leni ;
	coeffs_i += leni ;
      }
#     if PRESOLVE_DEBUG > 2
      std::cout << std::endl ;
#     endif
#     if PRESOLVE_CONSISTENCY > 0
      presolve_check_threads(prob) ;
      presolve_check_free_list(prob) ;
#     endif
/*
  Restore tgtrow. Arguably we could to this in the previous loop, but we'd do
  a lot of unnecessary work. By construction, the target row is tight.
*/
#     if PRESOLVE_DEBUG > 2
      std::cout << "    restoring row " << tgtrow << ":" ;
#     endif

      for (int rndx = 0 ; rndx < tgtrow_len ; ++rndx) {
	int j = tgtrow_colndxs[rndx] ;
#       if PRESOLVE_DEBUG > 2
	std::cout << " a(" << tgtrow << "," << j << ")" ;
#       endif
	CoinBigIndex kk = free_list ;
	assert(kk >= 0 && kk < prob->bulk0_) ;
	free_list = link[free_list] ;
	link[kk] = colStarts[j] ;
	colStarts[j] = kk ;
	colCoeffs[kk] = tgtrow_coeffs[rndx] ;
	rowIndices[kk] = tgtrow ;
	++colLengths[j] ;
      }
      acts[tgtrow] = tgtrhs ;

#     if PRESOLVE_DEBUG > 2
      std::cout << std::endl ;
#     endif
#     if PRESOLVE_CONSISTENCY > 0
      presolve_check_threads(prob) ;
      presolve_check_free_list(prob) ;
#     endif
    }
/*
  Restore original cost coefficients, if necessary.
*/
    if (costs) {
      for (int ndx = 0 ; ndx < tgtrow_len ; ++ndx) {
	cost[tgtrow_colndxs[ndx]] = costs[ndx] ;
      }
    }
/*
  Calculate the reduced cost for the column absent any contribution from
  tgtrow, then set the dual for tgtrow so that the reduced cost of tgtcol
  is zero.
*/
    double dj = maxmin*cost[tgtcol] ;
    rowduals[tgtrow] = 0.0 ;
    for (int cndx = 0 ; cndx < tgtcol_len ; ++cndx) {
      int i = entngld_rows[cndx] ;
      double coeff = tgtcol_coeffs[cndx] ;
      dj -= rowduals[i]*coeff ;
    }
    rowduals[tgtrow] = dj/tgtcoeff ;
    rcosts[tgtcol] = 0.0 ;
    if (rowduals[tgtrow] > 0)
      prob->setRowStatus(tgtrow,CoinPrePostsolveMatrix::atUpperBound) ;
    else
      prob->setRowStatus(tgtrow,CoinPrePostsolveMatrix::atLowerBound) ;
    prob->setColumnStatus(tgtcol,CoinPrePostsolveMatrix::basic) ;

#   if PRESOLVE_DEBUG > 2
    std::cout
      << "  row " << tgtrow << " "
      << prob->rowStatusString(prob->getRowStatus(tgtrow))
      << " dual " << rowduals[tgtrow] << std::endl ;
    std::cout
      << "  col " << tgtcol << " "
      << prob->columnStatusString(prob->getColumnStatus(tgtcol))
      << " dj " << dj << std::endl ;
#   endif

#   if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0
    cdone[tgtcol] = SUBST_ROW ;
    rdone[tgtrow] = SUBST_ROW ;
#   endif
  }

# if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0
  presolve_check_threads(prob) ;
  presolve_check_free_list(prob) ;
  presolve_check_reduced_costs(prob) ;
  presolve_check_duals(prob) ;
  presolve_check_sol(prob,2,2,2) ;
  presolve_check_nbasic(prob) ;
# if PRESOLVE_DEBUG > 0
  std::cout << "Leaving subst_constraint_action::postsolve." << std::endl ;
# endif
# endif

  return ;
}