Extension of INFEASIBLE model reported as satisfiable
hanno-becker opened this issue · comments
What version of OR-Tools and what language are you using?
Version: main
Language: Python
Which solver are you using (e.g. CP-SAT, Routing Solver, GLOP, BOP, Gurobi)
CP-SAT
What operating system (Linux, Windows, ...) and version?
Linux
What did you do?
Extend a model reported as INFEASIBLE by further constraints.
What did you expect to see
Still see an INFEASIBLE
model.
What did you see instead?
An OPTIMAL
satisfying assignment.
Minimal example
The following Python script creates a small model and finds it (incorrectly, as far as I can tell) being reported as INFEASIBLE. The namings can be ignored but may be helpful for me in case the bug is somehow on my end.
from ortools.sat.python import cp_model
s = cp_model.CpSolver()
s.parameters.num_workers = 1
model = cp_model.CpModel()
IVAR6540400 = model.NewIntVar(0,16, 'mov_r1___42_start')
IVAR6540544 = model.NewIntVar(0,16, 'mov_r1___42_end')
IVAR6540640 = model.NewIntVar(0,16, 'mov_r0___42_start')
IVAR6540784 = model.NewIntVar(0,16, 'mov_r0___42_end')
IVAR6540880 = model.NewIntVar(0,16, 'vldrw32_q0__r3__start')
IVAR6540976 = model.NewIntVar(0,16, 'vldrw32_q0__r3__end')
IVAR6541072 = model.NewIntVar(0,16, 'vaddu32_q0__q0__q0_start')
IVAR6541168 = model.NewIntVar(0,16, 'vaddu32_q0__q0__q0_end')
IVAR6541264 = model.NewIntVar(0,16, 'vstrwu32_q0__r3__start')
IVAR6541360 = model.NewIntVar(0,16, 'vstrwu32_q0__r3__end')
IVAR6541456 = model.NewIntVar(0,16, 'add_r__r0___42_start')
IVAR6541552 = model.NewIntVar(0,16, 'add_r__r0___42_end')
IVAR6541648 = model.NewIntVar(0,16, 'add_s__r1___42_start')
IVAR6541744 = model.NewIntVar(0,16, 'add_s__r1___42_end')
IVAR6541840 = model.NewIntVar(0,16, 'add_r2__r2___42_start')
IVAR6541936 = model.NewIntVar(0,16, 'add_r2__r2___42_end')
IVAR6542176 = model.NewIntVar(0,16, 'mov_r1___42_out_0_lifetime_end')
IVAR6542224 = model.NewIntVar(0,16, 'mov_r1___42_out_0_lifetime_dur')
IVAR6542320 = model.NewIntVar(0,16, 'mov_r0___42_out_0_lifetime_end')
IVAR6542416 = model.NewIntVar(0,16, 'mov_r0___42_out_0_lifetime_dur')
IVAR6542512 = model.NewIntVar(0,16, 'vldrw32_q0__r3__out_0_lifetime_end')
IVAR6542608 = model.NewIntVar(0,16, 'vldrw32_q0__r3__out_0_lifetime_dur')
IVAR6542704 = model.NewIntVar(0,16, 'vaddu32_q0__q0__q0_out_0_lifetime_end')
IVAR6542800 = model.NewIntVar(0,16, 'vaddu32_q0__q0__q0_out_0_lifetime_dur')
IVAR6542896 = model.NewIntVar(0,16, 'add_r__r0___42_out_0_lifetime_end')
IVAR6542992 = model.NewIntVar(0,16, 'add_r__r0___42_out_0_lifetime_dur')
IVAR6543088 = model.NewIntVar(0,16, 'add_s__r1___42_out_0_lifetime_end')
IVAR6543184 = model.NewIntVar(0,16, 'add_s__r1___42_out_0_lifetime_dur')
IVAR6543280 = model.NewIntVar(0,16, 'add_r2__r2___42_out_0_lifetime_end')
IVAR6543376 = model.NewIntVar(0,16, 'add_r2__r2___42_out_0_lifetime_dur')
BOOLVAR6432112 = model.NewBoolVar('ALLOC(mov r1, #42)(r0)')
INTVAR6430816 = model.NewOptionalIntervalVar(IVAR6540400, IVAR6542224, IVAR6542176,
BOOLVAR6432112,
'USAGE(mov r1, #42)(r0)<ALLOC(mov r1, #42)(r0)>')
BOOLVAR5048240 = model.NewBoolVar('ALLOC(vldrw.32 q0, [r3] )(q0)')
INTVAR5046944 = model.NewOptionalIntervalVar(IVAR6540880, IVAR6542608,
IVAR6542512, BOOLVAR5048240,
'USAGE(vldrw.32 q0, [r3] )(q0)<ALLOC(vldrw.32 q0, [r3] )(q0)>')
BOOLVAR5047856 = model.NewBoolVar('ALLOC(vldrw.32 q0, [r3] )(q1)')
INTVAR5046704 = model.NewOptionalIntervalVar(IVAR6540880, IVAR6542608,
IVAR6542512, BOOLVAR5047856,
'USAGE(vldrw.32 q0, [r3] )(q1)<ALLOC(vldrw.32 q0, [r3] )(q1)>')
BOOLVAR5047472 = model.NewBoolVar('ALLOC(vldrw.32 q0, [r3] )(q2)')
INTVAR5046224 = model.NewOptionalIntervalVar(IVAR6540880, IVAR6542608,
IVAR6542512, BOOLVAR5047472,
'USAGE(vldrw.32 q0, [r3] )(q2)<ALLOC(vldrw.32 q0, [r3] )(q2)>')
BOOLVAR5047088 = model.NewBoolVar('ALLOC(vadd.u32 q0, q0, q0)(q0)')
INTVAR5045936 = model.NewOptionalIntervalVar(IVAR6541072, IVAR6542800,
IVAR6542704, BOOLVAR5047088,
'USAGE(vadd.u32 q0, q0, q0)(q0)<ALLOC(vadd.u32 q0, q0, q0)(q0)>')
BOOLVAR5046800 = model.NewBoolVar('ALLOC(vadd.u32 q0, q0, q0)(q1)')
INTVAR5045504 = model.NewOptionalIntervalVar(IVAR6541072, IVAR6542800,
IVAR6542704, BOOLVAR5046800,
'USAGE(vadd.u32 q0, q0, q0)(q1)<ALLOC(vadd.u32 q0, q0, q0)(q1)>')
BOOLVAR5046416 = model.NewBoolVar('ALLOC(vadd.u32 q0, q0, q0)(q2)')
INTVAR5045120 = model.NewOptionalIntervalVar(IVAR6541072, IVAR6542800,
IVAR6542704, BOOLVAR5046416,
'USAGE(vadd.u32 q0, q0, q0)(q2)<ALLOC(vadd.u32 q0, q0, q0)(q2)>')
BOOLVAR5045600 = model.NewBoolVar('ALLOC(add r, r0, #42)(r)')
INTVAR5045696 = model.NewOptionalIntervalVar(IVAR6541456, IVAR6542992,
IVAR6542896, BOOLVAR5045600,
'USAGE(add r, r0, #42)(r)<ALLOC(add r, r0, #42)(r)>')
BOOLVAR5048624 = model.NewBoolVar('ALLOC(add s, r1, #42)(s)')
INTVAR5045216 = model.NewOptionalIntervalVar(IVAR6541648, IVAR6543184,
IVAR6543088, BOOLVAR5048624,
'USAGE(add s, r1, #42)(s)<ALLOC(add s, r1, #42)(s)>')
BOOLVAR5048912 = model.NewBoolVar('ALLOC(add r2, r2, #42)(r2)')
INTVAR5048432 = model.NewOptionalIntervalVar(IVAR6541840, IVAR6543376,
IVAR6543280, BOOLVAR5048912,
'USAGE(add r2, r2, #42)(r2)<ALLOC(add r2, r2, #42)(r2)>')
model.AddNoOverlap([INTVAR5046944,INTVAR5045936])
model.AddNoOverlap([INTVAR5046704,INTVAR5045504])
model.AddNoOverlap([INTVAR5046224,INTVAR5045120])
model.AddExactlyOne([BOOLVAR5048240, BOOLVAR5047856,
BOOLVAR5047472])
model.AddExactlyOne([BOOLVAR5047088, BOOLVAR5046800,
BOOLVAR5046416])
model.AddExactlyOne([BOOLVAR5045600])
model.AddExactlyOne([BOOLVAR5048624])
model.AddExactlyOne([BOOLVAR5048912])
model.ExportToFile("model_unsatisfiable.txt")
stat = s.Solve(model)
print(s.ResponseStats())
This results in
CpSolverResponse summary:
status: INFEASIBLE
objective: NA
best_bound: NA
booleans: 11
conflicts: 3
branches: 17
propagations: 30
integer_propagations: 0
restarts: 16
lp_iterations: 0
walltime: 0.0023828
usertime: 0.00238286
deterministic_time: 1.42e-05
gap_integral: 0
However, forcing one integer variable turns it into a satisfiable model:
model.Add(IVAR6541456 == 5)
model.ExportToFile("model_satisfiable.txt")
s.Solve(model)
print(s.ResponseStats())
This returns
CpSolverResponse summary:
status: OPTIMAL
objective: 0
best_bound: 0
booleans: 15
conflicts: 0
branches: 18
propagations: 1
integer_propagations: 18
restarts: 4
lp_iterations: 0
walltime: 0.00117795
usertime: 0.001178
deterministic_time: 6.52e-06
gap_integral: 0
The model files are attached:
model_satisfiable.txt
model_unsatisfiable.txt
Apologies if I the mistake is on my end... maybe I'm missing the forest for the trees here.
Anything else we should know about your project / environment
This came up as part of my work on our CP-SAT based assembly optimizer HeLight
Thanks!
I highly suspect that there is a bug with our symmetry handling code that trigger on your particular example.
You can run with the parameter "symmetry_level" set to 0 or 1 (but not 2, the default) until we fix the issue.
Thanks.
@fdidier Thanks a lot for the fast reply.
Out of interest, what's the "symmetry level" parameter about?
it is a parameter.
solver.parameters.symmetry_level = 1 (in python).
@lperron Yes, that was clear, I meant to ask what's behind, technically. Also, what's the expected performance impact?
I confirm that the example works with symmetry_level = 1
-- I'll see if it also fixes the original problem which dealt with a much larger model.