Skip to content

Commit

Permalink
seems a good idea to check for redundant rows in crunch
Browse files Browse the repository at this point in the history
  • Loading branch information
jjhforrest committed Mar 4, 2024
1 parent 95fd6a6 commit e2ad9f5
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 28 deletions.
5 changes: 4 additions & 1 deletion src/ClpSimplex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// This code is licensed under the terms of the Eclipse Public License (EPL).

//#undef NDEBUG

#include "ClpConfig.h"

#include "CoinPragma.hpp"
Expand Down Expand Up @@ -11455,6 +11454,7 @@ int ClpSimplex::fathom(void *stuff)
int *whichColumn = new int[2 * numberColumns_];
int nBound;
bool tightenBounds = ((specialOptions_ & 64) == 0) ? false : true;
//numberRows_=-numberRows_;//!! flag to say do more work (if test in crunch)
ClpSimplex *small = static_cast< ClpSimplexOther * >(this)->crunch(rhs, whichRow, whichColumn,
nBound, false, tightenBounds);
if (small) {
Expand Down Expand Up @@ -12177,6 +12177,7 @@ int ClpSimplex::fathomMany(void *stuff)
int *whichRow = new int[3 * numberRows_];
int *whichColumn = new int[2 * numberColumns_];
int nBound;
//numberRows_=-numberRows_;//!! flag to say do more work (if test in crunch)
bool tightenBounds = ((specialOptions_ & 64) == 0) ? false : true;
ClpSimplex *small = static_cast< ClpSimplexOther * >(this)->crunch(rhs, whichRow, whichColumn,
nBound, false, tightenBounds);
Expand Down Expand Up @@ -13034,6 +13035,8 @@ int ClpSimplex::fastDual2(ClpNodeStuff *info)
#endif
if (goodWeights)
status = 100;
if (!problemStatus_)
computeObjectiveValue(); // be on safe side
return status;
}
// Stop Fast dual
Expand Down
180 changes: 153 additions & 27 deletions src/ClpSimplexOther.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1775,6 +1775,19 @@ ClpSimplex *
ClpSimplexOther::crunch(double *rhs, int *whichRow, int *whichColumn,
int &nBound, bool moreBounds, bool tightenBounds)
{
#if 0
/* If you only want to find redundant rows before fathom then
use this and set numberRows_ negative before this call (in ClpSimplex.cpp)
*/
bool takeOutSome=false;
if (numberRows_<0) {
numberRows_ = -numberRows_;
takeOutSome=true;
}
#else
assert (numberRows_>=0);
bool takeOutSome=true;
#endif
//#define CHECK_STATUS
#ifdef CHECK_STATUS
{
Expand All @@ -1794,7 +1807,21 @@ ClpSimplexOther::crunch(double *rhs, int *whichRow, int *whichColumn,
const int *row = matrix_->getIndices();
const CoinBigIndex *columnStart = matrix_->getVectorStarts();
const int *columnLength = matrix_->getVectorLengths();

char * flags;
double * maxdown;
double * maxup;
if (takeOutSome) {
flags = new char [numberRows_];
maxdown = new double [2*numberRows_];
maxup = maxdown+numberRows_;
for (int i=0;i<numberRows_;i++) {
if (getRowStatus(i)==ClpSimplex::basic)
flags[i] = 0;
else
flags[i]=3;
}
memset(maxdown,0,2*sizeof(double)*numberRows_);
}
CoinZeroN(rhs, numberRows_);
int iColumn;
int iRow;
Expand All @@ -1805,41 +1832,127 @@ ClpSimplexOther::crunch(double *rhs, int *whichRow, int *whichColumn,
double offset = 0.0;
const double *objective = this->objective();
double *solution = columnActivity_;
for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
double lower = columnLower_[iColumn];
double upper = columnUpper_[iColumn];
if (upper > lower || getColumnStatus(iColumn) == ClpSimplex::basic) {
backColumn[iColumn] = numberColumns2;
whichColumn[numberColumns2++] = iColumn;
for (CoinBigIndex j = columnStart[iColumn];
j < columnStart[iColumn] + columnLength[iColumn]; j++) {
int iRow = row[j];
int n = whichRow[iRow];
if (n == 0 && element[j])
whichRow[iRow] = -iColumn - 1;
else if (n < 0)
whichRow[iRow] = 2;
if (!takeOutSome) {
for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
double lower = columnLower_[iColumn];
double upper = columnUpper_[iColumn];
if (upper > lower || getColumnStatus(iColumn) == ClpSimplex::basic) {
backColumn[iColumn] = numberColumns2;
whichColumn[numberColumns2++] = iColumn;
for (CoinBigIndex j = columnStart[iColumn];
j < columnStart[iColumn] + columnLength[iColumn]; j++) {
int iRow = row[j];
int n = whichRow[iRow];
if (n == 0 && element[j])
whichRow[iRow] = -iColumn - 1;
else if (n < 0)
whichRow[iRow] = 2;
}
} else {
// fixed
backColumn[iColumn] = -1;
solution[iColumn] = upper;
if (upper) {
offset += objective[iColumn] * upper;
for (CoinBigIndex j = columnStart[iColumn];
j < columnStart[iColumn] + columnLength[iColumn]; j++) {
int iRow = row[j];
double value = element[j];
rhs[iRow] += upper * value;
}
}
}
} else {
// fixed
backColumn[iColumn] = -1;
solution[iColumn] = upper;
if (upper) {
offset += objective[iColumn] * upper;
for (CoinBigIndex j = columnStart[iColumn];
j < columnStart[iColumn] + columnLength[iColumn]; j++) {
int iRow = row[j];
double value = element[j];
rhs[iRow] += upper * value;
}
}
} else {
for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
double lower = columnLower_[iColumn];
double upper = columnUpper_[iColumn];
if (upper > lower || getColumnStatus(iColumn) == ClpSimplex::basic) {
backColumn[iColumn] = numberColumns2;
whichColumn[numberColumns2++] = iColumn;
for (CoinBigIndex j = columnStart[iColumn];
j < columnStart[iColumn] + columnLength[iColumn]; j++) {
int iRow = row[j];
double value = element[j];
if (value<0.0) {
if (upper < 1.0e12)
maxdown[iRow] += upper * value;
else
flags[iRow] |= 1;;
if (lower > -1.0e12)
maxup[iRow] += lower * value;
else
flags[iRow] |= 2;;
} else {
if (upper < 1.0e12)
maxup[iRow] += upper * value;
else
flags[iRow] |= 2;;
if (lower > -1.0e12)
maxdown[iRow] += lower * value;
else
flags[iRow] |= 1;;
}
int n = whichRow[iRow];
if (n == 0 && element[j])
whichRow[iRow] = -iColumn - 1;
else if (n < 0)
whichRow[iRow] = 2;
}
} else {
// fixed
backColumn[iColumn] = -1;
solution[iColumn] = upper;
if (upper) {
offset += objective[iColumn] * upper;
for (CoinBigIndex j = columnStart[iColumn];
j < columnStart[iColumn] + columnLength[iColumn]; j++) {
int iRow = row[j];
double value = element[j];
rhs[iRow] += upper * value;
maxup[iRow] += upper * value;
maxdown[iRow] += upper * value;
}
}
}
}
}
int returnCode = 0;
double tolerance = primalTolerance();
nBound = 2 * numberRows_;
//#define PRINT_AB
#ifdef PRINT_AB
static int abcdef1 = 0;
static int abcdef2 = 0;
static int abcdef3 = 0;
bool anyDropped = false;
abcdef1++;
#endif
for (iRow = 0; iRow < numberRows_; iRow++) {
int n = whichRow[iRow];
if (takeOutSome) {
// check if redundant
bool redundant = true;
double rowBound = rowLower_[iRow];
if (rowBound>-1.0e100) {
if ((flags[iRow]&1)!=0||maxdown[iRow]<rowBound-1.0e-9)
redundant = false;
}
if (redundant) {
rowBound = rowUpper_[iRow];
if (rowBound<1.0e100) {
if ((flags[iRow]&2)!=0||maxup[iRow]>rowBound+1.0e-9)
redundant = false;
}
}
if (redundant) {
#ifdef PRINT_AB
abcdef2++;
anyDropped= true;
#endif
continue; // ignore
}
}
if (n > 0) {
whichRow[numberRows2++] = iRow;
} else if (n < 0) {
Expand All @@ -1865,6 +1978,17 @@ ClpSimplexOther::crunch(double *rhs, int *whichRow, int *whichColumn,
}
}
}
#ifdef PRINT_AB
if (anyDropped)
abcdef3++;
if ((abcdef1%1000)==0)
printf("crunch %d times, %d dropped in %d occasions\n",
abcdef1,abcdef2,abcdef3);
#endif
if (takeOutSome) {
delete [] flags;
delete [] maxdown;
}
ClpSimplex *small = NULL;
if (!returnCode) {
//printf("CRUNCH from (%d,%d) to (%d,%d)\n",
Expand Down Expand Up @@ -2260,6 +2384,8 @@ void ClpSimplexOther::afterCrunch(const ClpSimplex &small,
assert (n == numberRows);
}
#endif
// be on safe side
computeObjectiveValue();
}
/* Tightens integer bounds - returns number tightened or -1 if infeasible
*/
Expand Down

0 comments on commit e2ad9f5

Please sign in to comment.