Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/v9-minor'
Browse files Browse the repository at this point in the history
  • Loading branch information
scip-ci committed Nov 13, 2024
2 parents ec77cc7 + 48a7b39 commit 05b834d
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 70 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ Fixed bugs
----------

- apply same feasibility definition in PaPILO as SCIP to avoid numerical inconsistencies
- check variable cancellation in SCIPvarAddVlb() and SCIPvarAddVub() to avert wrong infeasibility

Unit tests
----------
Expand Down
1 change: 1 addition & 0 deletions check/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,7 @@ set(pairs_Issue
"instances/Issue/3688.cip\;131882\;reduced_presolving"
"instances/Issue/3691.cip\;1.862908\;presolvingnolinear"
"instances/Issue/3693.cip\;7812672.2316\;default"
"instances/Issue/3700.cip\;0\;default"
"instances/Issue/3719.cip\;0\;presolving_off"
"instances/Issue/3722.cip\;1200008400.00755\;default"
"instances/Issue/3723.cip\;0\;default"
Expand Down
13 changes: 13 additions & 0 deletions check/instances/Issue/3700.cip
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
STATISTICS
Problem name : model
Variables : 3 (1 binary, 0 integer, 0 implicit integer, 2 continuous)
Constraints : 0 initial, 1 maximal
OBJECTIVE
Sense : minimize
VARIABLES
[binary] <feature_0_0_6>: obj=0, original bounds=[0,1]
[continuous] <predictor_3_layer_0_0_3>: obj=0, original bounds=[0,0.156662443660021]
[continuous] <predictor_3_layer_0_slack_0_3>: obj=0, original bounds=[0,0.15749458370186]
CONSTRAINTS
[linear] <predictor_3_layer_0_slack_0_3>: -0.314157027361881<feature_0_0_6>[B] +<predictor_3_layer_0_0_3>[C] -<predictor_3_layer_0_slack_0_3>[C] == -0.157494584183939;
END
161 changes: 91 additions & 70 deletions src/scip/var.c
Original file line number Diff line number Diff line change
Expand Up @@ -10051,44 +10051,17 @@ SCIP_RETCODE SCIPvarAddVlb(
case SCIP_VARSTATUS_FIXED:
/* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n",
SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);

/* if the vlb coefficient is zero, just update the lower bound of the variable */
if( SCIPsetIsZero(set, vlbcoef) )
{
if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
*infeasible = TRUE;
else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
{
/* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
* with the local bound, in this case we need to store the bound change as pending bound change
*/
if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
{
assert(tree != NULL);
assert(transprob != NULL);
assert(SCIPprobIsTransformed(transprob));

SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
}
else
{
SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
}

if( nbdchgs != NULL )
(*nbdchgs)++;
}
}
else if( var == vlbvar )
/* if the variables are the same, just update the corresponding bound */
if( var == vlbvar )
{
/* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
/* if the variables cancel out, the variable bound constraint is redundant or proves global infeasibility */
if( SCIPsetIsEQ(set, vlbcoef, 1.0) )
{
if( SCIPsetIsPositive(set, vlbconstant) )
if( SCIPsetIsFeasPositive(set, vlbconstant) )
*infeasible = TRUE;
return SCIP_OKAY;
}
else
{
Expand Down Expand Up @@ -10173,6 +10146,34 @@ SCIP_RETCODE SCIPvarAddVlb(
}
}
}
/* if the vlb coefficient is zero, just update the lower bound of the variable */
else if( SCIPsetIsZero(set, vlbcoef) )
{
if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
*infeasible = TRUE;
else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
{
/* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
* with the local bound, in this case we need to store the bound change as pending bound change
*/
if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
{
assert(tree != NULL);
assert(transprob != NULL);
assert(SCIPprobIsTransformed(transprob));

SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
}
else
{
SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
}

if( nbdchgs != NULL )
(*nbdchgs)++;
}
}
else if( SCIPvarIsActive(vlbvar) )
{
SCIP_Real xlb;
Expand Down Expand Up @@ -10314,7 +10315,7 @@ SCIP_RETCODE SCIPvarAddVlb(
maxvlb = adjustedLb(set, SCIPvarGetType(var), maxvlb);

/* check bounds for feasibility */
if( SCIPsetIsFeasGT(set, minvlb, xub) || (var == vlbvar && SCIPsetIsEQ(set, vlbcoef, 1.0) && SCIPsetIsFeasPositive(set, vlbconstant)) )
if( SCIPsetIsFeasGT(set, minvlb, xub) )
{
*infeasible = TRUE;
return SCIP_OKAY;
Expand Down Expand Up @@ -10421,8 +10422,18 @@ SCIP_RETCODE SCIPvarAddVlb(
/* x = a*y + c: x >= b*z + d <=> a*y + c >= b*z + d <=> y >= b/a * z + (d-c)/a, if a > 0
* y <= b/a * z + (d-c)/a, if a < 0
*/

/* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );

/* if the variables cancel out, the variable bound constraint is redundant or proves global infeasibility */
assert(var->data.aggregate.var != NULL);
if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
if( var->data.aggregate.var == vlbvar && SCIPsetIsEQ(set, var->data.aggregate.scalar, vlbcoef) )
{
if( SCIPsetIsFeasLT(set, var->data.aggregate.constant, vlbconstant) )
*infeasible = TRUE;
}
else if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
{
/* a > 0 -> add variable lower bound */
SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
Expand Down Expand Up @@ -10516,44 +10527,16 @@ SCIP_RETCODE SCIPvarAddVub(
/* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
SCIPsetDebugMsg(set, " -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);

/* if the vub coefficient is zero, just update the upper bound of the variable */
if( SCIPsetIsZero(set, vubcoef) )
{
if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
*infeasible = TRUE;
else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
{
/* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
* with the local bound, in this case we need to store the bound change as pending bound change
*/
if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
{
assert(tree != NULL);
assert(transprob != NULL);
assert(SCIPprobIsTransformed(transprob));

SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
}
else
{
SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
}

if( nbdchgs != NULL )
(*nbdchgs)++;
}
}
else if( var == vubvar )
/* if the variables are the same, just update the corresponding bound */
if( var == vubvar )
{
/* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
/* if the variables cancel out, the variable bound constraint is redundant or proves global infeasibility */
if( SCIPsetIsEQ(set, vubcoef, 1.0) )
{
if( SCIPsetIsNegative(set, vubconstant) )
if( SCIPsetIsFeasNegative(set, vubconstant) )
*infeasible = TRUE;
return SCIP_OKAY;
}
else
{
Expand Down Expand Up @@ -10638,6 +10621,34 @@ SCIP_RETCODE SCIPvarAddVub(
}
}
}
/* if the vub coefficient is zero, just update the upper bound of the variable */
else if( SCIPsetIsZero(set, vubcoef) )
{
if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
*infeasible = TRUE;
else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
{
/* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
* with the local bound, in this case we need to store the bound change as pending bound change
*/
if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
{
assert(tree != NULL);
assert(transprob != NULL);
assert(SCIPprobIsTransformed(transprob));

SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
}
else
{
SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
}

if( nbdchgs != NULL )
(*nbdchgs)++;
}
}
else if( SCIPvarIsActive(vubvar) )
{
SCIP_Real xlb;
Expand Down Expand Up @@ -10769,7 +10780,7 @@ SCIP_RETCODE SCIPvarAddVub(
maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);

/* check bounds for feasibility */
if( SCIPsetIsFeasLT(set, maxvub, xlb) || (var == vubvar && SCIPsetIsEQ(set, vubcoef, 1.0) && SCIPsetIsFeasNegative(set, vubconstant)) )
if( SCIPsetIsFeasLT(set, maxvub, xlb) )
{
*infeasible = TRUE;
return SCIP_OKAY;
Expand Down Expand Up @@ -10866,8 +10877,18 @@ SCIP_RETCODE SCIPvarAddVub(
/* x = a*y + c: x <= b*z + d <=> a*y + c <= b*z + d <=> y <= b/a * z + (d-c)/a, if a > 0
* y >= b/a * z + (d-c)/a, if a < 0
*/

/* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );

/* if the variables cancel out, the variable bound constraint is redundant or proves global infeasibility */
assert(var->data.aggregate.var != NULL);
if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
if( var->data.aggregate.var == vubvar && SCIPsetIsEQ(set, var->data.aggregate.scalar, vubcoef) )
{
if( SCIPsetIsFeasGT(set, var->data.aggregate.constant, vubconstant) )
*infeasible = TRUE;
}
else if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
{
/* a > 0 -> add variable upper bound */
SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
Expand Down

0 comments on commit 05b834d

Please sign in to comment.