heur_alns.c:1379: void tryAdd2variableBuffer(SCIP *, SCIP_VAR *, double, SCIP_VAR **, double *, int *, unsigned int): Assertion `SCIPisFeasIntegral(scip, val) || ! SCIPvarIsIntegral(var)' failed.
This instance trigger a crash in scip with parameters:
numerics/feastol = 1e-9
numerics/epsilon = 1e-9
numerics/sumepsilon = 1e-9
lp/scaling = 0
The log:
$> scip -f seed.lp -s options.set
SCIP version 10.0.0 [precision: 8 byte] [memory: block] [mode: debug] [LP solver: SoPlex 8.0.0] [GitHash: e21c1fda6a]
Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB)
External libraries:
SoPlex 8.0.0 Linear programming solver developed at Zuse Institute Berlin (soplex.zib.de) [GitHash: 85549f2c]
CppAD 20180000.0 Algorithmic Differentiation of C++ algorithms developed by B. Bell (github.com/coin-or/CppAD)
ZLIB 1.2.11 General purpose compression library by J. Gailly and M. Adler (zlib.net)
TinyCThread 1.2 small portable implementation of the C11 threads API (tinycthread.github.io)
GMP 6.2.1 GNU Multiple Precision Arithmetic Library developed by T. Granlund (gmplib.org)
AMPL/MP 4.0.0 AMPL .nl file reader library (github.com/ampl/mp)
Nauty 2.8.8 Computing Graph Automorphism Groups by Brendan D. McKay (users.cecs.anu.edu.au/~bdm/nauty)
sassy 2.0 Symmetry preprocessor by Markus Anders (github.com/markusa4/sassy)
reading user parameter file <options.set>
read problem <seed.lp>
============
original problem has 5 variables (0 bin, 5 int, 0 cont) and 9 constraints
solve problem
=============
presolving:
(round 1, fast) 0 del vars, 1 del conss, 0 add conss, 6 chg bounds, 0 chg sides, 0 chg coeffs, 0 upgd conss, 0 impls, 0 clqs
(round 2, fast) 0 del vars, 1 del conss, 0 add conss, 10 chg bounds, 0 chg sides, 0 chg coeffs, 0 upgd conss, 0 impls, 0 clqs
(round 3, exhaustive) 0 del vars, 1 del conss, 0 add conss, 10 chg bounds, 0 chg sides, 0 chg coeffs, 4 upgd conss, 0 impls, 0 clqs
(0.0s) symmetry computation started: requiring (bin +, int +, cont +), (fixed: bin -, int -, cont -)
(0.0s) no symmetry present (symcode time: 0.00)
presolving (4 rounds: 4 fast, 2 medium, 2 exhaustive):
0 deleted vars, 1 deleted constraints, 0 added constraints, 10 tightened bounds, 0 added holes, 0 changed sides, 0 changed coefficients
0 implications, 0 cliques
presolved problem has 5 variables (0 bin, 5 int, 0 cont) and 8 constraints
presolved problem has 0 implied integral variables (0 bin, 0 int, 0 cont)
4 constraints of type <varbound>
4 constraints of type <linear>
transformed objective value is always integral (scale: 0.01)
Presolving Time: 0.00
time | node | left |LP iter|LP it/n|mem/heur|mdpt |vars |cons |rows |cuts |sepa|confs|strbr| dualbound | primalbound | gap | compl.
p 0.0s| 1 | 0 | 0 | - | vbounds| 0 | 5 | 8 | 8 | 0 | 0 | 0 | 0 |-5.244360e+04 | 3.783592e+04 | Inf | unknown
p 0.0s| 1 | 0 | 0 | - | vbounds| 0 | 5 | 8 | 8 | 0 | 0 | 0 | 0 |-5.244360e+04 | 2.906320e+04 | Inf | unknown
0.0s| 1 | 0 | 4 | - | 670k | 0 | 5 | 8 | 8 | 0 | 0 | 0 | 0 |-2.612922e+03 | 2.906320e+04 | Inf | unknown
r 0.0s| 1 | 0 | 4 | - |shifting| 0 | 5 | 8 | 8 | 0 | 0 | 0 | 0 |-2.612922e+03 |-2.303060e+03 | 13.45%| unknown
0.0s| 1 | 0 | 5 | - | 727k | 0 | 5 | 8 | 9 | 1 | 1 | 0 | 0 |-2.609142e+03 |-2.303060e+03 | 13.29%| unknown
0.0s| 1 | 0 | 6 | - | 732k | 0 | 5 | 8 | 10 | 2 | 2 | 0 | 0 |-2.608853e+03 |-2.303060e+03 | 13.28%| unknown
r 0.0s| 1 | 0 | 6 | - |shifting| 0 | 5 | 8 | 10 | 2 | 2 | 0 | 0 |-2.608853e+03 |-2.505780e+03 | 4.11%| unknown
0.0s| 1 | 0 | 7 | - | 746k | 0 | 5 | 8 | 11 | 3 | 3 | 0 | 0 |-2.608822e+03 |-2.505780e+03 | 4.11%| unknown
0.0s| 1 | 0 | 8 | - | 749k | 0 | 5 | 8 | 12 | 4 | 4 | 0 | 0 |-2.608753e+03 |-2.505780e+03 | 4.11%| unknown
0.0s| 1 | 0 | 9 | - | 752k | 0 | 5 | 8 | 13 | 5 | 5 | 0 | 0 |-2.608744e+03 |-2.505780e+03 | 4.11%| unknown
0.0s| 1 | 0 | 10 | - | 760k | 0 | 5 | 8 | 14 | 6 | 6 | 0 | 0 |-2.608709e+03 |-2.505780e+03 | 4.11%| unknown
0.0s| 1 | 0 | 11 | - | 761k | 0 | 5 | 8 | 15 | 7 | 7 | 0 | 0 |-2.608709e+03 |-2.505780e+03 | 4.11%| unknown
0.0s| 1 | 0 | 12 | - | 763k | 0 | 5 | 8 | 16 | 8 | 8 | 0 | 0 |-2.608708e+03 |-2.505780e+03 | 4.11%| unknown
0.0s| 1 | 0 | 13 | - | 782k | 0 | 5 | 8 | 17 | 9 | 9 | 0 | 0 |-2.608703e+03 |-2.505780e+03 | 4.11%| unknown
0.0s| 1 | 0 | 14 | - | 792k | 0 | 5 | 8 | 18 | 10 | 10 | 0 | 0 |-2.608696e+03 |-2.505780e+03 | 4.11%| unknown
time | node | left |LP iter|LP it/n|mem/heur|mdpt |vars |cons |rows |cuts |sepa|confs|strbr| dualbound | primalbound | gap | compl.
r 0.0s| 1 | 0 | 14 | - |shifting| 0 | 5 | 8 | 18 | 10 | 10 | 0 | 0 |-2.608696e+03 |-2.505780e+03*| 4.11%| unknown
scip: scip/src/scip/heur_alns.c:1379: void tryAdd2variableBuffer(SCIP *, SCIP_VAR *, double, SCIP_VAR **, double *, int *, unsigned int): Assertion `SCIPisFeasIntegral(scip, val) || ! SCIPvarIsIntegral(var)' failed.
Aborted (core dumped)
The instance triggers an assertion failure in tryAdd2variableBuffer():
assert(SCIPisFeasIntegral(scip, val) || !SCIPvarIsIntegral(var))
The assert fails because, during presolving, dual reductions may tighten bounds or transform variables such that certain variables become integral. The reference solution used by ALNS may still contain slightly fractional values for these variables (e.g. values like 3.000000001), which with tight feastol (1e-9) are no longer treated as integral by SCIPisFeasIntegral().
The code already contains a TODO comment in heur_alns.c mentioning this situation.
The approach might be improved with the new implied integrality convention (enforced integral variables of type SCIP_VARTYPE_BINARY and SCIP_VARTYPE_INTEGER must be integral in every feasible solution independent of implied integrality). But since this is a pure integer program without implied integral variables, the issue is probably unrelated to the todo. Why is the reference solution value not checked integral?
Yes, you're right, this likely isn't about implied integrality. After a second look, the assertion likely fails because it assumes that the given solution values are integral. But LP solutions, like in this case (e.g. used in RINS), can be slightly fractional. With very tight tolerances, even "almost" integral values can cause the assertion to fail.
Replacing the assertion with an explicit SCIPisFeasIntegral() check might help, even if that means skipping some possible fixings. Not entirely sure if that's the best solution though, maybe I'm overlooking something.
This would be possible. But I believe a reference value should pass this assertion (at least when relaxed to enforced integral variables), so maybe this can be achieved before calling tryAdd2variableBuffer(). In varFixingsRins() and varFixingsDins() not only LP solutions seem to be available, so why not take one of the others as reference?
This is fixed with c57aadf7789d9f3e951c0ba7082c6ed0c6107556 as explained above.