Skip to content

Commit

Permalink
Merge branch 'fix_delayed_separators' into 'master'
Browse files Browse the repository at this point in the history
add call of delayed separators

See merge request integer/scip!3247
  • Loading branch information
svigerske committed Dec 10, 2023
2 parents 8495933 + e60aa52 commit 6b951bc
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Features
- extended obbt propagator to handle variables of the linear constraints corresponding to indicator constraints
- added new heuristic heur_scheduler that models the selection of LNS and diving heuristics as a multi-armed bandit problem
- added nonlinear handler for signomial expressions: adds cuts based on a difference of convex functions representation
- Delayed separators are now called if no other cuts have been found. Previously, such separators were only called near stalling or when the separation rounds limit was reached.

Performance improvements
------------------------
Expand Down
46 changes: 36 additions & 10 deletions src/scip/solve.c
Original file line number Diff line number Diff line change
Expand Up @@ -2636,6 +2636,8 @@ SCIP_RETCODE priceAndCutLoop(
assert(lp->flushed);
assert(lp->solved);
assert(SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_UNBOUNDEDRAY);
assert(!(*lperror));
assert(!(*cutoff));

olddomchgcount = stat->domchgcount;
oldninitconssadded = stat->ninitconssadded;
Expand All @@ -2657,13 +2659,14 @@ SCIP_RETCODE priceAndCutLoop(
assert(lp->flushed);
assert(lp->solved);
assert(SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_UNBOUNDEDRAY);

/* constraint separation */
SCIPsetDebugMsg(set, "constraint separation\n");
assert(!(*lperror));

/* separate constraints and LP */
if( !(*cutoff) && !(*lperror) && !enoughcuts && lp->solved )
if( !(*cutoff) && !enoughcuts )
{
/* constraint and LP separation */
SCIPsetDebugMsg(set, "constraint and LP separation\n");

/* apply a separation round */
SCIP_CALL( separationRoundLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, transprob, primal, tree,
lp, sepastore, actdepth, bounddist, allowlocal, delayedsepa,
Expand All @@ -2683,7 +2686,7 @@ SCIP_RETCODE priceAndCutLoop(
}

/* call global cut pool separation again since separators may add cuts to the pool instead of the sepastore */
if( !(*cutoff) && !(*lperror) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && !enoughcuts && lp->solved )
if( !(*cutoff) && !(*lperror) && lp->solved && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && !enoughcuts )
{
SCIP_CALL( cutpoolSeparate(cutpool, blkmem, set, stat, eventqueue, eventfilter, lp, sepastore, FALSE, root,
actdepth, &enoughcuts, cutoff) );
Expand All @@ -2695,21 +2698,44 @@ SCIP_RETCODE priceAndCutLoop(
}

/* delayed global cut pool separation */
if( !(*cutoff) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && SCIPsepastoreGetNCuts(sepastore) == 0 &&
!enoughcuts )
if( !(*cutoff) && !(*lperror) && lp->solved && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && SCIPsepastoreGetNCuts(sepastore) == 0 && !enoughcuts )
{
assert( !(*lperror) );

SCIP_CALL( cutpoolSeparate(delayedcutpool, blkmem, set, stat, eventqueue, eventfilter, lp, sepastore, TRUE,
root, actdepth, &enoughcuts, cutoff) );

if( *cutoff )
{
SCIPsetDebugMsg(set, " -> delayed global cut pool detected cutoff\n");
}
assert(lp->solved);
assert(SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL);
assert(lp->flushed);
assert(lp->solved);
}

/* delayed separation if no cuts where produced */
if( !(*cutoff) && !(*lperror) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && SCIPsepastoreGetNCuts(sepastore) == 0 && delayedsepa )
{
SCIP_CALL( separationRoundLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, transprob, primal,
tree, lp, sepastore, actdepth, bounddist, allowlocal, delayedsepa,
&delayedsepa, &enoughcuts, cutoff, lperror, &mustsepa, &mustprice) );
assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);

/* call delayed cut pool separation again, since separators may add cuts to the pool instead of the sepastore */
if( !(*cutoff) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
{
assert( !(*lperror) );

SCIP_CALL( cutpoolSeparate(delayedcutpool, blkmem, set, stat, eventqueue, eventfilter, lp, sepastore, TRUE,
root, actdepth, &enoughcuts, cutoff) );

if( *cutoff )
{
SCIPsetDebugMsg(set, " -> delayed global cut pool detected cutoff\n");
}
assert(SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL);
assert(lp->flushed);
assert(lp->solved);
}
}

assert(*cutoff || *lperror || SCIPlpIsSolved(lp));
Expand Down

0 comments on commit 6b951bc

Please sign in to comment.