Skip to content

Keep binary bounds in nested add_variable_dicts and add_variable_matrix - #964

Merged
pchtsp merged 1 commit into
coin-or:masterfrom
cristianchiriac:binary-variable-dicts
Oct 17, 2026
Merged

pchtsp merged 1 commit into
coin-or:masterfrom
cristianchiriac:binary-variable-dicts

Conversation

@cristianchiriac

Copy link
Copy Markdown
Contributor

Fixes #963.

The bug only shows up with two or more index sets, which is probably why it works for some people and not others.

add_variable_dicts() and add_variable_matrix() turn cat=LpBinary into bounds [0, 1] and category LpInteger, but they do it by reassigning cat. With more than one index set they then recurse with that cat (now LpInteger) and the original lowBound/upBound (None), so the leaf call never sees LpBinary and creates integer variables with bounds (-inf, inf). A 1-D call never recurses and gets the right bounds, and add_variable_dict() doesn't recurse either.

On master (4.0.1):

prob = LpProblem("t", LpMaximize)
y = prob.add_variable_dicts("y", ([1, 2], [1, 2]), cat=LpBinary)
# y_1_1 ... y_2_2: cat=Integer, LB=-inf, UB=inf
prob.setObjective(lpSum(v for d in y.values() for v in d.values()))
prob.solve(HiGHS(msg=False))
# master:     status Undefined, no solution (the variables are unbounded)
# this PR:    status Optimal, objective 4.0

Change

Both functions now use a separate local for the converted category, so the recursive calls get the original cat and do the binary conversion at the leaf as before.

Tests

  • New PuLPModelTest.test_binary_variables_with_several_indices builds a 2-D binary dict and matrix and checks every variable is Integer with bounds [0, 1]. On master it fails with AssertionError: -inf != 0; with the fix it passes.
  • uv run --all-extras --no-extra mosek python -m unittest discover -s pulp/tests (Windows, Python 3.14): 1041 tests, OK (skipped=605).
  • ruff check pulp and ruff format pulp --check pass. ty check pulp reports the same 2 warnings as on master (resource.getrusage in pulp/utilities.py, which doesn't exist on Windows).

Both functions turned cat=LpBinary into LpInteger before recursing over
the remaining index sets, so the inner calls no longer saw LpBinary and
created integer variables with (-inf, inf) bounds. Keep the original
category for the recursive calls.

Fixes #963.
@pchtsp
pchtsp merged commit b6d3f5a into coin-or:master Oct 17, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wrong definition of binary variables with add_variable_dicts

2 participants