[FEA] PDLP warm start through presolve (today: warm start works only without presolve and loses 3x net) + silent-NaN failure modes
@tmckayus is already working on this.
Since Sep 6, 2026.
- Dominant language
- Cuda
- Stars
- 1k
- Forks
- 233
- Avg merge
- 4d 4h
- Merged PRs (30d)
- 95
Description
Is your feature request related to a problem?
We repeatedly solve the same large LP (7.2M rows × 2.27M cols, 14.3M nnz)
where only variable bounds change between solves (a subset of variables is
fixed via lo = hi, and the fixed values move slightly from one solve to the
next). Consecutive optimal solutions are nearly identical, so warm starting
should save most of the work. This is a standard pattern in iterative /
decomposition-style workflows.
With cuOpt 26.04 (nvidia/cuopt:latest-cuda12.9-py3.13, method=1 PDLP,
RTX 3060 12 GB, CUDA 12.9) we measured the whole option space:
DataModel.set_initial_primal_solution/set_initial_dual_solution:
accepted without error, but the solve returns termination status 0 with
nanprimal/dual objectives after ~4 s — no warning, no diagnostic.SolverSettings.set_pdlp_warm_start_datafrom a prior solve of a
same-shape LP, default solver mode: termination status 0 withnan
objectives after ~1.3 s — again silent.- Same, but with
pdlp_solver_mode = Stable2(per the docs, warm start is
supported in Stable2/Fast1) andpresolve=0on both solves so the spaces
match: warm start works — 1,683 s vs 2,375 s cold in the same
configuration (~1.4× saving). However:- cold with presolve solves the same LP in 547 s: presolve is
worth ~11× on this instance, and warm-start data is incompatible with it
(with presolve on:Invalid PDLPWarmStart data ... same amount of variables, since the presolved spaces differ). Net effect:
warm+no-presolve loses ~3× against cold+presolve, so the feature cannot
pay for itself today; - the warm-started solve reports optimal but its objective lands 0.34 %
above the cold reference for the same LP (759,027 vs 756,484 at
1e-4relative tolerance) — far outside tolerance, suggesting the
warm-started run terminates at a materially different point.
- cold with presolve solves the same LP in 547 s: presolve is
- Minor:
set_parameter("presolve", False)raises
ValueError: ... not an integer, and
set_parameter("pdlp_solver_mode", "Stable2")is accepted at set time but
fails insideSolvewithValueError: ... not an integer— both want
ints despite doc examples.
Describe the solution you'd like
In order of usefulness:
- Warm start mapped through presolve on the solver side — accept
warm-start data (or plain primal/dual seed vectors) for a problem with the
same structure and modified bounds, and translate it into the presolved
space. That is the version of this feature that can actually win, given
presolve's ~11× value. - When warm-start input is rejected or unusable (wrong mode, wrong space),
fail loudly with a clear status/exception instead of returning
termination status 0 withnanobjectives. - Either wire
set_initial_primal_solution/set_initial_dual_solutionas
a true initial-iterate seed for LP, or document them as unsupported for LP
and warn when they are set.
Additional context
All timings are from the same machine and instance and are reproducible; happy
to share exact call sequences and logs. Possibly related: the 0.34 % objective
deviation of the warm-started Stable2 run may deserve its own look.
(Same environment as #1859.)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.