Skip to content

Commit

Permalink
Merge branch '3694-delete-emtpy-linear-constraints' into 'master'
Browse files Browse the repository at this point in the history
3694: delete empty linear and knapsack constraints before constructing the matrix

See merge request integer/scip!3362
  • Loading branch information
alexhoen committed Jan 2, 2025
2 parents bb0ac50 + d092603 commit 233bd23
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 105 deletions.
8 changes: 5 additions & 3 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@

Features
--------
- Added new fields in history to store ancestral pseudo cost updates, used in the pseudo costs branching rule to compute discounted pseudo costs.
- Copy variable data pointer if no copy routine was supplied.

- added new fields in history to store ancestral pseudo cost updates, used in the pseudo costs branching rule to compute discounted pseudo costs.
- copy variable data pointer if no copy routine was supplied.
- added more techniques to handle reflection symmetries, in particular, for orbitopes with column reflections and matrices whose rows and columns can be permuted by a symmetry
- implemented symmetry detection callbacks for cons_disjunction and cons_superindicator
- detailed information about applied symmetry handling techniques can be printed to the terminal
Expand All @@ -18,7 +19,7 @@ Features
Performance improvements
------------------------

- Reimplemented SCIPvarGetActiveRepresentatives() by using dense arrays to avoid repeated resorting.
- reimplemented SCIPvarGetActiveRepresentatives() by using dense arrays to avoid repeated resorting.

Examples and applications
-------------------------
Expand All @@ -36,6 +37,7 @@ Interface changes
- SCIPcreateRow*(), SCIPaddVarToRow(), SCIPaddVarsToRow(), SCIPaddVarsToRowSameCoef() can now only be called in the solving stage,
because otherwise the LP is not yet available and the row data is invalid.
- intvar removed from arguments for SCIPcreateConsPseudobooleanWithConss(), SCIPcreateConsPseudoboolean(), and SCIPcreateConsBasicPseudoboolean() due to dysfunctionality of non-linear objective reformulation with pseudoboolean constraint
- ndelconss added to arguments for SCIPcleanupConssLinear() and SCIPcleanupConssKnapsack() to directly delete empty redundant constraints before creating problem matrix

### New API functions

Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ set(SCIP_VERSION_MAJOR 10)
set(SCIP_VERSION_MINOR 0)
set(SCIP_VERSION_PATCH 0)
set(SCIP_VERSION_SUB 0)
set(SCIP_VERSION_API 129)
set(SCIP_VERSION_API 130)

project(SCIP
VERSION ${SCIP_VERSION_MAJOR}.${SCIP_VERSION_MINOR}.${SCIP_VERSION_PATCH}.${SCIP_VERSION_SUB}
Expand Down
2 changes: 1 addition & 1 deletion make/make.project
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ SCIP_VERSION_MAJOR = 10
SCIP_VERSION_MINOR = 0
SCIP_VERSION_PATCH = 0
SCIP_VERSION_SUB = 0
SCIP_VERSION_API = 129
SCIP_VERSION_API = 130
SCIP_VERSION = $(SCIP_VERSION_MAJOR).$(SCIP_VERSION_MINOR).$(SCIP_VERSION_PATCH).$(SCIP_VERSION_SUB)

# compiling and linking parameters
Expand Down
12 changes: 10 additions & 2 deletions src/scip/cons_knapsack.c
Original file line number Diff line number Diff line change
Expand Up @@ -13949,7 +13949,8 @@ SCIP_ROW* SCIPgetRowKnapsack(
SCIP_RETCODE SCIPcleanupConssKnapsack(
SCIP* scip, /**< SCIP data structure */
SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
SCIP_Bool* infeasible /**< pointer to return whether the problem was detected to be infeasible */
SCIP_Bool* infeasible, /**< pointer to return whether the problem was detected to be infeasible */
int* ndelconss /**< pointer to count number of deleted constraints */
)
{
SCIP_CONSHDLR* conshdlr;
Expand All @@ -13967,12 +13968,19 @@ SCIP_RETCODE SCIPcleanupConssKnapsack(
nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);

for( i = 0; i < nconss; ++i )
/* loop backwards since then deleted constraints do not interfere with the loop */
for( i = nconss - 1; i >= 0; --i )
{
SCIP_CALL( applyFixings(scip, conss[i], infeasible) );

if( *infeasible )
break;

if( SCIPconsGetData(conss[i])->nvars >= 1 )
continue;

SCIP_CALL( SCIPdelCons(scip, conss[i]) );
++(*ndelconss);
}

return SCIP_OKAY;
Expand Down
3 changes: 2 additions & 1 deletion src/scip/cons_knapsack.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,8 @@ SCIP_EXPORT
SCIP_RETCODE SCIPcleanupConssKnapsack(
SCIP* scip, /**< SCIP data structure */
SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
SCIP_Bool* infeasible /**< pointer to return whether the problem was detected to be infeasible */
SCIP_Bool* infeasible, /**< pointer to return whether the problem was detected to be infeasible */
int* ndelconss /**< pointer to count number of deleted constraints */
);

/** @} */
Expand Down
12 changes: 10 additions & 2 deletions src/scip/cons_linear.c
Original file line number Diff line number Diff line change
Expand Up @@ -19006,7 +19006,8 @@ SCIP_RETCODE SCIPupgradeConsLinear(
SCIP_RETCODE SCIPcleanupConssLinear(
SCIP* scip, /**< SCIP data structure */
SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
SCIP_Bool* infeasible /**< pointer to return whether the problem was detected to be infeasible */
SCIP_Bool* infeasible, /**< pointer to return whether the problem was detected to be infeasible */
int* ndelconss /**< pointer to count number of deleted constraints */
)
{
SCIP_CONSHDLR* conshdlr;
Expand All @@ -19024,12 +19025,19 @@ SCIP_RETCODE SCIPcleanupConssLinear(
nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);

for( i = 0; i < nconss; ++i )
/* loop backwards since then deleted constraints do not interfere with the loop */
for( i = nconss - 1; i >= 0; --i )
{
SCIP_CALL( applyFixings(scip, conss[i], infeasible) );

if( *infeasible )
break;

if( SCIPconsGetData(conss[i])->nvars >= 1 )
continue;

SCIP_CALL( SCIPdelCons(scip, conss[i]) );
++(*ndelconss);
}

return SCIP_OKAY;
Expand Down
5 changes: 3 additions & 2 deletions src/scip/cons_linear.h
Original file line number Diff line number Diff line change
Expand Up @@ -380,8 +380,9 @@ SCIP_EXPORT
SCIP_RETCODE SCIPcleanupConssLinear(
SCIP* scip, /**< SCIP data structure */
SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
SCIP_Bool* infeasible /**< pointer to return whether the problem was detected to be infeasible */
);
SCIP_Bool* infeasible, /**< pointer to return whether the problem was detected to be infeasible */
int* ndelconss /**< pointer to count number of deleted constraints */
);

/** @} */

Expand Down
153 changes: 60 additions & 93 deletions src/scip/matrix.c
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,6 @@ SCIP_RETCODE SCIPmatrixCreate(
{
SCIP_MATRIX* matrix;
SCIP_CONSHDLR** conshdlrs;
SCIP_CONSHDLR* conshdlr;
const char* conshdlrname;
SCIP_Bool stopped;
SCIP_VAR** vars;
Expand Down Expand Up @@ -518,9 +517,9 @@ SCIP_RETCODE SCIPmatrixCreate(
{
conshdlrname = SCIPconshdlrGetName(conshdlrs[i]);

if( (strcmp(conshdlrname, "linear") == 0) || (strcmp(conshdlrname, "setppc") == 0)
|| (strcmp(conshdlrname, "logicor") == 0) || (strcmp(conshdlrname, "knapsack") == 0)
|| (strcmp(conshdlrname, "varbound") == 0) )
if( strcmp(conshdlrname, "linear") == 0 || strcmp(conshdlrname, "knapsack") == 0
|| strcmp(conshdlrname, "setppc") == 0 || strcmp(conshdlrname, "logicor") == 0
|| strcmp(conshdlrname, "varbound") == 0 )
{
/* increment number of supported constraints */
nconss += nconshdlrconss;
Expand Down Expand Up @@ -583,46 +582,14 @@ SCIP_RETCODE SCIPmatrixCreate(
* can come up due to downgrading and the remaining cleanup methods cannot fix any more variables
*/

SCIP_CALL( SCIPcleanupConssKnapsack(scip, TRUE, infeasible) );
SCIP_CALL( SCIPcleanupConssKnapsack(scip, TRUE, infeasible, ndelconss) );
if( *infeasible )
return SCIP_OKAY;

/* delete empty redundant knapsack constraints */
conshdlr = SCIPfindConshdlr(scip, "knapsack");
if( conshdlr != NULL )
{
nconshdlrconss = SCIPconshdlrGetNCheckConss(conshdlr);
conshdlrconss = SCIPconshdlrGetCheckConss(conshdlr);
for( i = nconshdlrconss - 1; i >= 0; --i )
{
if( SCIPgetNVarsKnapsack(scip, conshdlrconss[i]) == 0 )
{
SCIP_CALL( SCIPdelCons(scip, conshdlrconss[i]) );
++(*ndelconss);
}
}
}

SCIP_CALL( SCIPcleanupConssLinear(scip, TRUE, infeasible) );
SCIP_CALL( SCIPcleanupConssLinear(scip, TRUE, infeasible, ndelconss) );
if( *infeasible )
return SCIP_OKAY;

/* delete empty redundant linear constraints */
conshdlr = SCIPfindConshdlr(scip, "linear");
if( conshdlr != NULL )
{
nconshdlrconss = SCIPconshdlrGetNCheckConss(conshdlr);
conshdlrconss = SCIPconshdlrGetCheckConss(conshdlr);
for( i = nconshdlrconss - 1; i >= 0; --i )
{
if( SCIPgetNVarsLinear(scip, conshdlrconss[i]) == 0 )
{
SCIP_CALL( SCIPdelCons(scip, conshdlrconss[i]) );
++(*ndelconss);
}
}
}

vars = SCIPgetVars(scip);
nvars = SCIPgetNVars(scip);

Expand Down Expand Up @@ -736,6 +703,61 @@ SCIP_RETCODE SCIPmatrixCreate(
}
}
}
else if( strcmp(conshdlrname, "knapsack") == 0 )
{
if( nconshdlrconss > 0 )
{
SCIP_Real* consvals;
int valssize;

valssize = 100;
SCIP_CALL( SCIPallocBufferArray(scip, &consvals, valssize) );

for( c = 0; c < nconshdlrconss && (c % 1000 != 0 || !SCIPisStopped(scip)); ++c )
{
SCIP_Longint* weights;

cons = conshdlrconss[c];
assert(SCIPconsIsTransformed(cons));

/* do not include constraints that can be altered due to column generation */
if( SCIPconsIsModifiable(cons) )
{
*complete = FALSE;

if( onlyifcomplete )
break;

continue;
}

weights = SCIPgetWeightsKnapsack(scip, cons);
nvars = SCIPgetNVarsKnapsack(scip, cons);

if( nvars > valssize )
{
valssize = (int) (1.5 * nvars);
SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, valssize) );
}

for( v = 0; v < nvars; v++ )
consvals[v] = (SCIP_Real)weights[v];

SCIP_CALL( addConstraint(scip, matrix, SCIPgetVarsKnapsack(scip, cons), consvals,
SCIPgetNVarsKnapsack(scip, cons), -SCIPinfinity(scip),
(SCIP_Real)SCIPgetCapacityKnapsack(scip, cons), nnonzstmp, &rowadded) );

if(rowadded)
{
assert(cnt < nconss);
matrix->cons[cnt] = cons;
cnt++;
}
}

SCIPfreeBufferArray(scip, &consvals);
}
}
else if( strcmp(conshdlrname, "setppc") == 0 )
{
for( c = 0; c < nconshdlrconss && (c % 1000 != 0 || !SCIPisStopped(scip)); ++c )
Expand Down Expand Up @@ -815,61 +837,6 @@ SCIP_RETCODE SCIPmatrixCreate(
}
}
}
else if( strcmp(conshdlrname, "knapsack") == 0 )
{
if( nconshdlrconss > 0 )
{
SCIP_Real* consvals;
int valssize;

valssize = 100;
SCIP_CALL( SCIPallocBufferArray(scip, &consvals, valssize) );

for( c = 0; c < nconshdlrconss && (c % 1000 != 0 || !SCIPisStopped(scip)); ++c )
{
SCIP_Longint* weights;

cons = conshdlrconss[c];
assert(SCIPconsIsTransformed(cons));

/* do not include constraints that can be altered due to column generation */
if( SCIPconsIsModifiable(cons) )
{
*complete = FALSE;

if( onlyifcomplete )
break;

continue;
}

weights = SCIPgetWeightsKnapsack(scip, cons);
nvars = SCIPgetNVarsKnapsack(scip, cons);

if( nvars > valssize )
{
valssize = (int) (1.5 * nvars);
SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, valssize) );
}

for( v = 0; v < nvars; v++ )
consvals[v] = (SCIP_Real)weights[v];

SCIP_CALL( addConstraint(scip, matrix, SCIPgetVarsKnapsack(scip, cons), consvals,
SCIPgetNVarsKnapsack(scip, cons), -SCIPinfinity(scip),
(SCIP_Real)SCIPgetCapacityKnapsack(scip, cons), nnonzstmp, &rowadded) );

if(rowadded)
{
assert(cnt < nconss);
matrix->cons[cnt] = cons;
cnt++;
}
}

SCIPfreeBufferArray(scip, &consvals);
}
}
else if( strcmp(conshdlrname, "varbound") == 0 )
{
if( nconshdlrconss > 0 )
Expand Down

0 comments on commit 233bd23

Please sign in to comment.