Skip to content

Support PuLP 4.0 while keeping PuLP 3.x fallback (#131) - #134

Open
ishikaghosh2201 wants to merge 1 commit into
masterfrom
131-pulp-new-version-400-breaks-the-current-ilp
Open

ishikaghosh2201 wants to merge 1 commit into
masterfrom
131-pulp-new-version-400-breaks-the-current-ilp

Conversation

@ishikaghosh2201

Copy link
Copy Markdown
Collaborator

Description

PuLP 4.0.0 removed several APIs that cereeberus/distance/ilp.py relied on. This PR moves the ILP code to the PuLP 4 API and keeps working with PuLP 3.x.

ilp.py

  • Added three small helpers that detect which PuLP API is available:
    • _new_var(prob, name, cat) uses prob.add_variable (PuLP 4), with pulp.LpVariable as the fallback (PuLP 3).
    • _new_var_dict(prob, name, indices, cat) replaces pulp.LpVariable.dicts. It keeps the same (a, b) / (a, b, c) tuple keys, so build_map_matrices is unchanged.
    • _solve(prob, solver) returns (status_code, status_str). On PuLP 4 it reads the LpSolveStats object returned by prob.solve(). On PuLP 3 it uses prob.status / pulp.LpStatus. Status strings shared by both versions are normalized to the PuLP 3 spelling (e.g. "Not Solved"), so return values don't depend on the installed version.
  • solve_ilp and solve_ilp_dist now use these helpers. Their inputs, outputs and constraints are unchanged.
  • select_pulp_solver:
    • Solver classes are now looked up with getattr, so the missing PULP_CBC_CMD is skipped instead of raising AttributeError.
    • Added HiGHS / HiGHS_CMD to the fallback order, after the CBC options, so CBC is still preferred when available.
    • "HIGHS" is now accepted as a solver name.
  • Removed a duplicated return line at the end of solve_ilp_dist.

Dependencies

  • Added highspy; python_version >= '3.12' to pyproject.toml and requirements.txt. PuLP 4 no longer bundles a CBC binary, so without this a fresh install on Python 3.12+ has no solver. Python 3.9–3.11 still gets PuLP 3.x with its bundled CBC.

Motivation and Context

Fixes #131.

The pulp dependency has no version cap. PuLP 4.0 (released 2026-09-25) requires Python ≥3.12, so CI on Python 3.12 started installing it, and test_interleaving.py failed with:

  • AttributeError: type object 'LpVariable' has no attribute 'dicts'
  • AttributeError: module 'pulp' has no attribute 'PULP_CBC_CMD'

Anyone on Python 3.12+ who ran pip install cereeberus got a broken optimize(). Rather than pinning pulp<4, this PR supports both versions.

How has this been tested?

  • Ran the full test suite with PuLP 4.0.0 (with highspy) and with PuLP 3.x: all tests pass on both.
  • Ran the suite on PuLP 4.0.0 with CBC from cbcbox instead of HiGHS: all tests pass.
  • Added tests/test_ilp_pulp_compatibility.py (14 tests). Most use mocks, so both code paths are tested whichever PuLP version is installed:
    • _new_var / _new_var_dict on the PuLP 4 and PuLP 3 paths: tuple, triple and scalar keys, unique names, empty indices.
    • _solve: PuLP 4 status codes map to the PuLP 3 strings, new PuLP 4 codes (e.g. TimeLimit) pass through, and the PuLP 3 path uses prob.status.
    • select_pulp_solver: skips the missing PULP_CBC_CMD, still prefers COIN_CMD over HiGHS, and accepts "highs" by name.
    • One end-to-end solve of a small ILP with the installed PuLP.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Checklist

  • [] I have incremented the version number in the pyproject.toml file if a new version needs to be pushed to pypi. Note that if the number isn't incremented, the package will not be pushed to pypi, which is useful if this PR is only for updating documentation.
  • [] My code follows the code style of this project and I have run make format to clean up the code with black.
  • My change requires a change to the documentation. I have updated the documentation as necessary and compiled locally to ensure it is clean.
  • I have added tests to cover my changes, and all new and existing tests passed (run make tests).

@ishikaghosh2201 ishikaghosh2201 linked an issue Oct 3, 2026 that may be closed by this pull request
@ishikaghosh2201
ishikaghosh2201 requested review from lizliz and a balanced review from Copilot and removed request for lizliz October 3, 2026 05:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The unbounded highspy dependency can install versions explicitly excluded by PuLP 4, and the real HiGHS fallback is not exercised in CI.

Review effort: Balanced
Findings: 1 Medium severity · 1 Low severity

Open (2)

Comment thread pyproject.toml
"pandas",
"scipy",
"pulp",
"highspy; python_version >= '3.12'",
prob += pulp.lpSum(x.values()) >= 3
prob += t >= pulp.lpSum(x.values())

code, status = _solve(prob, select_pulp_solver())

This branch has not been deployed

No deployments
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.

Pulp new version 4.0.0 breaks the current ILP

2 participants