Skip to content

Bug fix: solution incorrect when simplex presolve removes empty columns - #29

Merged
rapids-bot[bot] merged 4 commits into
NVIDIA:branch-25.05from
chris-maes:fix_presolve_removed_empty_cols
May 23, 2025
Merged

Bug fix: solution incorrect when simplex presolve removes empty columns#29
rapids-bot[bot] merged 4 commits into
NVIDIA:branch-25.05from
chris-maes:fix_presolve_removed_empty_cols

Conversation

@chris-maes

@chris-maes chris-maes commented May 22, 2025

Copy link
Copy Markdown
Contributor

Fixes an issue reported on the following MPS file, where _dummy variable does not appear in the constraints. We remove empty columns (and thus _dummy) in presolve for dual simplex. But do not take this into account when constructing the solution.

Further work, is needed to develop an actual LP presolve.

*SENSE:Minimize
NAME          test_export_dict_LP_no_obj
ROWS
 N  OBJ
 G  c1
 E  c2
 L  c3
 G  c4
COLUMNS
    __dummy   OBJ        1.000000000000e+00
    w         c4         1.000000000000e+00
    x         c1         1.000000000000e+00
    x         c2         1.000000000000e+00
    y         c1         1.000000000000e+00
    y         c3        -1.000000000000e+00
    z         c2         1.000000000000e+00
    z         c3         1.000000000000e+00
RHS
    RHS       c1         5.000000000000e+00
    RHS       c2         1.000000000000e+01
    RHS       c3         7.000000000000e+00
    RHS       c4         0.000000000000e+00
BOUNDS
 FX BND       __dummy    0.000000000000e+00
 FX BND       w          0.000000000000e+00
 UP BND       x          4.000000000000e+00
 LO BND       y         -1.000000000000e+00
 UP BND       y          1.000000000000e+00

Fixes #13 which was caused by an issue in column scaling when the norm of a column is zero.

@chris-maes
chris-maes requested a review from a team as a code owner May 22, 2025 17:37
@chris-maes
chris-maes requested review from Kh4ster and kaatish May 22, 2025 17:37
@copy-pr-bot

copy-pr-bot Bot commented May 22, 2025

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@chris-maes chris-maes self-assigned this May 22, 2025
@chris-maes chris-maes added bug Something isn't working non-breaking Introduces a non-breaking change labels May 22, 2025
@chris-maes chris-maes added this to the 25.05 milestone May 22, 2025
@chris-maes

Copy link
Copy Markdown
Contributor Author

/ok to test f622513

Comment thread cpp/src/dual_simplex/presolve.cpp Outdated
@chris-maes

Copy link
Copy Markdown
Contributor Author

/ok to test 769771f

@chris-maes

Copy link
Copy Markdown
Contributor Author

/ok to test f7d243e

@chris-maes

Copy link
Copy Markdown
Contributor Author

/ok to test de78eb6

@Kh4ster Kh4ster 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.

Thanks!

@akifcorduk

Copy link
Copy Markdown
Contributor

/merge

@rapids-bot
rapids-bot Bot merged commit 8eff792 into NVIDIA:branch-25.05 May 23, 2025
jieyibi pushed a commit to yining043/cuopt that referenced this pull request Mar 26, 2026
…ns (NVIDIA#29)

Fixes an issue reported on the following MPS file, where `_dummy` variable does not appear in the constraints. We remove empty columns (and thus `_dummy`) in presolve for dual simplex. But do not take this into account when constructing the solution. 

Further work, is needed to develop an actual LP presolve. 

```
*SENSE:Minimize
NAME          test_export_dict_LP_no_obj
ROWS
 N  OBJ
 G  c1
 E  c2
 L  c3
 G  c4
COLUMNS
    __dummy   OBJ        1.000000000000e+00
    w         c4         1.000000000000e+00
    x         c1         1.000000000000e+00
    x         c2         1.000000000000e+00
    y         c1         1.000000000000e+00
    y         c3        -1.000000000000e+00
    z         c2         1.000000000000e+00
    z         c3         1.000000000000e+00
RHS
    RHS       c1         5.000000000000e+00
    RHS       c2         1.000000000000e+01
    RHS       c3         7.000000000000e+00
    RHS       c4         0.000000000000e+00
BOUNDS
 FX BND       __dummy    0.000000000000e+00
 FX BND       w          0.000000000000e+00
 UP BND       x          4.000000000000e+00
 LO BND       y         -1.000000000000e+00
 UP BND       y          1.000000000000e+00
```

Fixes NVIDIA#13  which was caused by an issue in column scaling when the norm of a column is zero.

Authors:
  - Chris Maes (https://github.com/chris-maes)

Approvers:
  - Rajesh Gandham (https://github.com/rg20)
  - Nicolas Blin (https://github.com/Kh4ster)

URL: NVIDIA#29
spoorendonk added a commit to spoorendonk/cuopt that referenced this pull request Jun 9, 2026
… reject

Two findings from the multi-agent review of the uniform-resolve refactor:

- Seed the PDLP warm-start iterate BEFORE snapshotting/forcing the presolver,
  so an exception from set_initial_*_solution cannot leave the caller's
  settings handle with presolver=None (the seed sits outside the restoring
  try/catch). The seed still runs after apply_pending_mutations, so the
  warm-start vectors are padded to the post-delta dimensions first.
- Hoist the explicit PSLP/Papilo rejection ABOVE apply_pending_mutations so a
  rejected resolve is a clean no-op: the staged delta is left pending (not
  committed) and the handle stays usable.

spoorendonk/mcfcg#29

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
spoorendonk added a commit to spoorendonk/cuopt that referenced this pull request Jun 10, 2026
Add the dual-simplex basis-persistence layer that re-optimizes a
column-generation / cutting-plane master from the previous optimum
instead of cold-solving on every cuOptResolve.

dual_simplex_warm_state.hpp declares dual_simplex_warm_state_t, which
persists the converted (slack-augmented) lp_problem_t plus its optimal
basis (basis_update_mpf_t, basic_list, nonbasic_list, vstatus,
edge_norms) across resolves. solve.cu implements solve_lp_dual_simplex_warm:

- On a tail-only structural extension (new columns appended, new '<=' rows
  appended, prior rows/columns preserved) the persisted basis is
  transplanted onto the extended LP: appended columns enter nonbasic at
  their lower bound (cheap — the basis matrix B is unchanged); appended
  '<=' rows enter via dual_simplex::add_cuts (26.06 internal: appends row
  + logical slack and updates the LU factor in place). The warm basis then
  seeds dual_phase2_with_advanced_basis.
- Otherwise (first solve, deletes, objective edit, mixed/range/'>=' row
  appends, or any numerical trouble warm-starting) it falls back to a cold
  solve_linear_program_with_advanced_basis (26.06 internal) and recaptures
  the basis.

The warm-solve settings force scale_columns / inner_presolve_optimizations
/ eliminate_singletons / barrier_presolve off so dual_simplex presolve +
scaling are the identity on a clean LP, keeping the captured basis in `lp`
coordinates and transplantable — the same configuration the MIP B&B cut
loop relies on. This mirrors the uniform presolve-off rule of the delta
path (NVIDIA#29); NVIDIA#28 later relaxes it with a restricted forward-mappable
presolve. The layer is objective-equivalent to a cold solve; only the
starting basis differs. Double-only (the wrapped dual_simplex internals
are instantiated for <int,double>).

spoorendonk/mcfcg#22

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working non-breaking Introduces a non-breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] standgub.json from netlib/lp fails if zero-only final column is left in the constraint matrix

4 participants