Skip to content

Conversation

@nguidotti
Copy link
Contributor

@nguidotti nguidotti commented Sep 9, 2025

This PR extract the LU factorisation from the dual_phase2 to a separated method. It also added a new methods in the dual simplex to allow the basis_update_mpf_t to persist between calls.
This allows the branch-and-bound to pass the basis_update from parent to child in the future.

Checklist

  • I am familiar with the Contributing Guidelines.
  • Testing
    • New or existing tests cover these changes
    • Added tests
    • Created an issue to follow-up
    • [] NA
  • Documentation
    • The documentation is up to date with these changes
    • Added new documentation
    • NA

Summary by CodeRabbit

  • Bug Fixes

    • Fixed condition evaluation in steepest-edge pricing logic.
  • New Features

    • Added an advanced basis-refactoring workflow with automated repair, refactor, and basis-preservation steps for more robust solves.
    • Exposed new basis-management APIs (refactor, reset, resize, configurable refactor frequency) and solver entry points that preserve and reuse basis state across Phase 1/2.

@nguidotti nguidotti requested a review from a team as a code owner September 9, 2025 13:44
@nguidotti nguidotti requested review from kaatish and rg20 September 9, 2025 13:44
@nguidotti
Copy link
Contributor Author

/ok to test a3e50f8

@nguidotti nguidotti added non-breaking Introduces a non-breaking change dual_simplex labels Sep 9, 2025
@nguidotti nguidotti requested a review from chris-maes September 9, 2025 14:18
@nguidotti nguidotti added this to the 25.10 milestone Sep 9, 2025
@nguidotti nguidotti added the improvement Improves an existing functionality label Sep 15, 2025
@github-actions
Copy link

🔔 Hi @anandhkb, this pull request has had no activity for 7 days. Please update or let us know if it can be closed. Thank you!

If this is an "epic" issue, then please add the "epic" label to this issue.
If it is a PR and not ready for review, then please convert this to draft.
If you just want to switch off this notification, then use the "skip inactivity reminder" label.

@nguidotti
Copy link
Contributor Author

nguidotti commented Sep 26, 2025

This PR solves 89/92 instances from netlib with high precision, same as the main branch. The only "problematic" instances are: cycle , e226 and pilot87.

Below are the errors for each instance with both absolute-dual-tolerance and relative-dual-tolerance set to 1E-8.

================================================================================
    Problem        Computed        Reference       Abs Error       Rel Error   
================================================================================
25fv47             5.501846e+03    5.501846e+03    3.170000e-05    5.761703e-09
80bau3b            9.872242e+05    9.872322e+05    7.968720e+00    8.071779e-06
adlittle           2.254950e+05    2.254950e+05    1.600000e-04    7.095503e-10
afiro             -4.647531e+02   -4.647531e+02    1.400000e-07    3.012352e-10
agg               -3.599177e+07   -3.599177e+07    1.300000e-02    3.611936e-10
agg2              -2.023925e+07   -2.023925e+07    4.400000e-02    2.173993e-09
agg3               1.031212e+07    1.031212e+07    3.500000e-02    3.394066e-09
bandm             -1.586280e+02   -1.586280e+02    4.500000e-07    2.836826e-09
beaconfd           3.359249e+04    3.359249e+04    6.999995e-06    2.083798e-10
blend             -3.081215e+01   -3.081215e+01    4.600000e-08    1.492918e-09
bnl1               1.977630e+03    1.977629e+03    2.744000e-04    1.387520e-07
bnl2               1.811237e+03    1.811237e+03    3.999999e-07    2.208435e-10
boeing1           -3.352136e+02   -3.352136e+02    4.900000e-07    1.461755e-09
boeing2           -3.150187e+02   -3.150187e+02    2.000002e-08    6.348834e-11
bore3d             1.373080e+03    1.373080e+03    4.200000e-06    3.058816e-09
brandy             1.518510e+03    1.518510e+03    3.500000e-06    2.304891e-09
capri              2.690013e+03    2.690013e+03    3.800000e-06    1.412633e-09
cycle             -5.224928e+00   -5.226393e+00    1.465115e-03    2.803300e-04
czprob             2.185197e+06    2.185197e+06    1.100000e-03    5.033872e-10
d2q06c             1.227842e+05    1.227842e+05    2.515000e-02    2.048309e-07
d6cube             3.154917e+02    3.154917e+02    3.300000e-07    1.045987e-09
degen2            -1.435178e+03   -1.435178e+03    0.000000e+00    0.000000e+00
degen3            -9.872940e+02   -9.872940e+02    0.000000e+00    0.000000e+00
dfl001             1.126640e+07    1.126640e+07    4.000000e+00    3.550380e-07
e226              -1.163893e+01   -1.875193e+01    7.113000e+00    3.793210e-01
etamacro          -7.557152e+02   -7.557152e+02    9.260000e-06    1.225329e-08
fffff800           5.556796e+05    5.556796e+05    4.165000e-02    7.495326e-08
finnis             1.727911e+05    1.727910e+05    1.005300e-01    5.818013e-07
fit1d             -9.146378e+03   -9.146378e+03    2.400000e-06    2.623990e-10
fit1p              9.146378e+03    9.146378e+03    2.400000e-06    2.623990e-10
fit2d             -6.846429e+04   -6.846429e+04    6.000002e-06    8.763695e-11
fit2p              6.846429e+04    6.846429e+04    6.800001e-05    9.932186e-10
forplan           -6.642190e+02   -6.642187e+02    2.214700e-04    3.334293e-07
ganges            -1.095857e+05   -1.095864e+05    6.275600e-01    5.726625e-06
gfrd-pnc           6.902236e+06    6.902236e+06    5.000001e-04    7.244031e-11
greenbea          -7.255525e+07   -7.255525e+07    2.984600e-02    4.113555e-10
greenbeb          -4.302260e+06   -4.302148e+06    1.126535e+02    2.618541e-05
grow15            -1.068709e+08   -1.068709e+08    2.900000e-01    2.713553e-09
grow22            -1.608343e+08   -1.608343e+08    4.800000e-01    2.984437e-09
grow7             -4.778781e+07   -4.778781e+07    1.500000e-02    3.138876e-10
israel            -8.966448e+05   -8.966448e+05    1.400000e-04    1.561377e-10
kb2               -1.749900e+03   -1.749900e+03    1.000001e-07    5.714616e-11
lotfi             -2.526471e+01   -2.526471e+01    3.800000e-08    1.504075e-09
maros-r7           1.497146e+06    1.497185e+06    3.930650e+01    2.625360e-05
maros             -5.806374e+04   -5.806374e+04    1.000000e-06    1.722246e-11
modszk1            3.206197e+02    3.206197e+02    5.999999e-08    1.871376e-10
nesm               1.407604e+07    1.407607e+07    3.653500e+01    2.595539e-06
perold            -9.380755e+03   -9.380758e+03    2.787300e-03    2.971295e-07
pilot             -5.574865e+02   -5.574897e+02    3.190284e-03    5.722588e-06
pilot4            -2.581139e+03   -2.581139e+03    4.100000e-06    1.588446e-09
pilot87            3.018934e+02    3.017103e+02    1.830477e-01    6.067000e-04
pilot_ja          -6.113135e+03   -6.113134e+03    5.789000e-04    9.469774e-08
pilot_we          -2.720108e+06   -2.720103e+06    4.786100e+00    1.759529e-06
pilotnov          -4.497276e+03   -4.497276e+03    1.799999e-06    4.002421e-10
recipe            -2.666160e+02   -2.666160e+02    0.000000e+00    0.000000e+00
sc105             -5.220206e+01   -5.220206e+01    1.199999e-08    2.298759e-10
sc205             -5.220206e+01   -5.220206e+01    1.199999e-08    2.298759e-10
sc50a             -6.457508e+01   -6.457508e+01    4.100001e-08    6.349200e-10
sc50b             -7.000000e+01   -7.000000e+01    0.000000e+00    0.000000e+00
scagr25           -1.475343e+07   -1.475343e+07    3.900000e-02    2.643452e-09
scagr7            -2.331390e+06   -2.331389e+06    5.652000e-01    2.424306e-07
scfxm1             1.841676e+04    1.841676e+04    2.800000e-05    1.520354e-09
scfxm2             3.666026e+04    3.666026e+04    3.500000e-05    9.547122e-10
scfxm3             5.490125e+04    5.490125e+04    5.000000e-05    9.107259e-10
scorpion           1.878125e+03    1.878125e+03    2.700000e-06    1.437604e-09
scrs8              9.042970e+02    9.043000e+02    3.032190e-03    3.353080e-06
scsd1              8.666667e+00    8.666667e+00    4.300000e-09    4.961539e-10
scsd6              5.050000e+01    5.050000e+01    2.200000e-08    4.356436e-10
scsd8              9.050000e+02    9.050000e+02    7.000006e-08    7.734813e-11
sctap1             1.412250e+03    1.412250e+03    0.000000e+00    0.000000e+00
sctap2             1.724807e+03    1.724807e+03    2.900000e-06    1.681347e-09
sctap3             1.424000e+03    1.424000e+03    0.000000e+00    0.000000e+00
seba               1.571160e+04    1.571160e+04    0.000000e+00    0.000000e+00
share1b           -7.658932e+04   -7.658932e+04    2.100000e-05    2.741897e-10
share2b           -4.157322e+02   -4.157322e+02    2.600000e-07    6.254025e-10
shell              1.208825e+09    1.208825e+09    4.000000e+00    3.308997e-09
ship04l            1.793325e+06    1.793325e+06    2.000000e-03    1.115247e-09
ship04s            1.798715e+06    1.798715e+06    4.000000e-04    2.223810e-10
ship08l            1.909055e+06    1.909055e+06    1.400000e-03    7.333470e-10
ship08s            1.920098e+06    1.920098e+06    5.000001e-04    2.604034e-10
ship12l            1.470188e+06    1.470188e+06    7.000000e-04    4.761296e-10
ship12s            1.489236e+06    1.489236e+06    4.400000e-03    2.954535e-09
sierra             1.539436e+07    1.539436e+07    1.600000e-02    1.039341e-09
stair             -2.512670e+02   -2.512670e+02    1.900000e-07    7.561678e-10
standata           1.257699e+03    1.257699e+03    0.000000e+00    0.000000e+00
standmps           1.406017e+03    1.406017e+03    0.000000e+00    0.000000e+00
stocfor1          -4.113198e+04   -4.113198e+04    1.900000e-05    4.619277e-10
stocfor2          -3.902441e+04   -3.902441e+04    3.800001e-05    9.737497e-10
tuff               2.921478e-01    2.921478e-01    9.000001e-11    3.080633e-10
vtp_base           1.298315e+05    1.298315e+05    4.600000e-04    3.543055e-09
wood1p             1.442902e+00    1.442902e+00    1.600000e-09    1.108876e-09
woodw              1.304556e+00    1.304476e+00    7.934690e-05    6.082663e-05
================================================================================

@nguidotti nguidotti modified the milestones: 25.10, 25.12 Sep 26, 2025
@github-actions
Copy link

github-actions bot commented Oct 4, 2025

🔔 Hi @anandhkb, this pull request has had no activity for 7 days. Please update or let us know if it can be closed. Thank you!

If this is an "epic" issue, then please add the "epic" label to this issue.
If it is a PR and not ready for review, then please convert this to draft.
If you just want to switch off this notification, then use the "skip inactivity reminder" label.

@nguidotti nguidotti force-pushed the dual-simplex-update-basis branch from 7422762 to 181aef4 Compare October 7, 2025 14:14
@rgsl888prabhu rgsl888prabhu changed the base branch from branch-25.10 to branch-25.12 October 13, 2025 15:32
@rgsl888prabhu rgsl888prabhu requested review from a team as code owners October 13, 2025 15:32
@rgsl888prabhu rgsl888prabhu requested review from KyleFromNVIDIA and rgsl888prabhu and removed request for a team October 13, 2025 15:32
@chris-maes
Copy link
Contributor

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Oct 22, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@chris-maes
Copy link
Contributor

/ok to test deffe68

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
cpp/src/dual_simplex/basis_updates.cpp (1)

2111-2114: Preserve Q after refactorization

reset() calls clear(), which rewrites col_permutation_/inverse_col_permutation_ to the identity. That destroys the Q permutation produced by factorize_basis, so every subsequent b_*/u_* solve uses the wrong permuted LU and produces incorrect results. Please keep the existing permutations and only clear the incremental update structures. Suggested fix:

   reorder_basic_list(col_permutation_, basic_list);
-  reset();
+  inverse_permutation(row_permutation_, inverse_row_permutation_);
+  inverse_permutation(col_permutation_, inverse_col_permutation_);
+  pivot_indices_.clear();
+  pivot_indices_.reserve(L0_.m);
+  S_.col_start.assign(refactor_frequency_ + 1, 0);
+  S_.i.clear();
+  S_.x.clear();
+  S_.n = 0;
+  mu_values_.clear();
+  num_updates_ = 0;
+  compute_transposes();
+  reset_stats();
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 73b7ad1 and deffe68.

📒 Files selected for processing (5)
  • cpp/src/dual_simplex/basis_updates.cpp (2 hunks)
  • cpp/src/dual_simplex/basis_updates.hpp (6 hunks)
  • cpp/src/dual_simplex/phase2.cpp (5 hunks)
  • cpp/src/dual_simplex/phase2.hpp (2 hunks)
  • cpp/src/dual_simplex/solve.cpp (3 hunks)
🧰 Additional context used
🪛 Clang (14.0.6)
cpp/src/dual_simplex/basis_updates.cpp

[error] 18-18: 'dual_simplex/basis_solves.hpp' file not found

(clang-diagnostic-error)

cpp/src/dual_simplex/basis_updates.hpp

[error] 20-20: 'dual_simplex/initial_basis.hpp' file not found

(clang-diagnostic-error)

cpp/src/dual_simplex/phase2.hpp

[error] 20-20: 'dual_simplex/basis_updates.hpp' file not found

(clang-diagnostic-error)

Comment on lines 229 to 259
junk.clear();
dual_phase2(1,
0,
start_time,
phase1_problem,
settings,
phase1_vstatus,
phase1_solution,
iter,
edge_norms);
initialize_basis_update = false;
dual_phase2_with_advanced_basis(1,
0,
initialize_basis_update,
start_time,
phase1_problem,
settings,
phase1_vstatus,
ft,
basic_list,
nonbasic_list,
phase1_solution,
iter,
edge_norms);
vstatus = phase1_vstatus;
edge_norms.clear();
status = dual_phase2(2, 0, start_time, lp, settings, vstatus, solution, iter, edge_norms);
status = dual_phase2_with_advanced_basis(2,
0,
initialize_basis_update,
start_time,
lp,
settings,
vstatus,
ft,
basic_list,
nonbasic_list,
solution,
iter,
edge_norms);
}
Copy link

@coderabbitai coderabbitai bot Oct 22, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Re-initialize basis before switching problems

When Phase 2 returns NUMERICAL, you set initialize_basis_update = false and immediately reuse ft for phase1_problem and then for the original lp. However, ft (and the associated basic_list/nonbasic_list) still contain the LU factorization of the previous matrix, so the very first solve after this point works with the wrong basis. Please rebuild the basis before each call on a different problem:

-    initialize_basis_update = false;
-    dual_phase2_with_advanced_basis(1,
-                                    0,
-                                    initialize_basis_update,
+    initialize_basis_update = true;
+    dual_phase2_with_advanced_basis(1,
+                                    0,
+                                    initialize_basis_update,
                                     start_time,
                                     phase1_problem,
                                     settings,
                                     phase1_vstatus,
                                     ft,
                                     basic_list,
                                     nonbasic_list,
                                     phase1_solution,
                                     iter,
                                     edge_norms);
     vstatus = phase1_vstatus;
     edge_norms.clear();
-    status = dual_phase2_with_advanced_basis(2,
-                                             0,
-                                             initialize_basis_update,
+    initialize_basis_update = true;
+    status = dual_phase2_with_advanced_basis(2,
+                                             0,
+                                             initialize_basis_update,
                                              start_time,
                                              lp,
                                              settings,
                                              vstatus,
                                              ft,
                                              basic_list,
                                              nonbasic_list,
                                              solution,
                                              iter,
                                              edge_norms);

Without this change we operate on stale LU factors, which corrupts the pivot operations and produces incorrect results.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
junk.clear();
dual_phase2(1,
0,
start_time,
phase1_problem,
settings,
phase1_vstatus,
phase1_solution,
iter,
edge_norms);
initialize_basis_update = false;
dual_phase2_with_advanced_basis(1,
0,
initialize_basis_update,
start_time,
phase1_problem,
settings,
phase1_vstatus,
ft,
basic_list,
nonbasic_list,
phase1_solution,
iter,
edge_norms);
vstatus = phase1_vstatus;
edge_norms.clear();
status = dual_phase2(2, 0, start_time, lp, settings, vstatus, solution, iter, edge_norms);
status = dual_phase2_with_advanced_basis(2,
0,
initialize_basis_update,
start_time,
lp,
settings,
vstatus,
ft,
basic_list,
nonbasic_list,
solution,
iter,
edge_norms);
}
junk.clear();
initialize_basis_update = true;
dual_phase2_with_advanced_basis(1,
0,
initialize_basis_update,
start_time,
phase1_problem,
settings,
phase1_vstatus,
ft,
basic_list,
nonbasic_list,
phase1_solution,
iter,
edge_norms);
vstatus = phase1_vstatus;
edge_norms.clear();
initialize_basis_update = true;
status = dual_phase2_with_advanced_basis(2,
0,
initialize_basis_update,
start_time,
lp,
settings,
vstatus,
ft,
basic_list,
nonbasic_list,
solution,
iter,
edge_norms);
}
🤖 Prompt for AI Agents
In cpp/src/dual_simplex/solve.cpp around lines 229 to 259, the code reuses ft
and the basic/nonbasic lists (LU factorization) across different problems;
before calling dual_phase2_with_advanced_basis on a different problem you must
rebuild the basis so the LU matches the new matrix. Fix this by reinitializing
the basis between problem switches: clear or reconstruct ft and the
basic_list/nonbasic_list (or call the existing basis-initialization helper) and
set initialize_basis_update appropriately so the next
dual_phase2_with_advanced_basis call computes a fresh LU for that problem rather
than using stale factors.

Copy link
Contributor

Choose a reason for hiding this comment

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

The basis and ft is valid in this case. We can force a refactorization of the basis in the phase 1 problem if we run into numerical difficults. But it should not be required for the algorithm to work correctly.

Copy link

Choose a reason for hiding this comment

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

@chris-maes, thank you for the clarification! I understand now that the basis and ft remain valid when switching between the lp and phase1_problem in this scenario, and that reusing the factorization is intentional to avoid unnecessary recomputation. I appreciate you confirming that the algorithm's correctness is maintained and that refactorization can be forced if numerical issues arise. I'll dismiss this concern.

@chris-maes
Copy link
Contributor

cpp/src/dual_simplex/basis_updates.cpp (1)> 2111-2114: Preserve Q after refactorization

reset() calls clear(), which rewrites col_permutation_/inverse_col_permutation_ to the identity. That destroys the Q permutation produced by factorize_basis, so every subsequent b_*/u_* solve uses the wrong permuted LU and produces incorrect results. Please keep the existing permutations and only clear the incremental update structures.

The member variable col_permutation_ stores the permutation applied to U (in the Forrest-Tomlin update). In refactor_basis we compute a column permutation Q such that PBQ = LU, but calling reorder_basic_list removes that permutation, so we have PB' = LU, where B' = B(:, basic_list_after_being_permuted_by_q). To make this clear I'm adding a vector q in the code and not reusing col_permutation_

@chris-maes
Copy link
Contributor

/ok to test f779cb7

@nguidotti
Copy link
Contributor Author

/ok to test ad756d1

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
cpp/src/dual_simplex/basis_updates.hpp (1)

254-264: Guard stats updates against divide‑by‑zero.

sum_* accumulators are updated using ratios like size/denominator in b_[transpose]_solve paths; when the input has 0 NZ, denominator can be 0 → NaN/inf. Add guards.

Apply this patch in cpp/src/dual_simplex/basis_updates.cpp:

@@
-  sum_U_transpose_ += static_cast<f_t>(solution.i.size()) / input_size;
+  if (input_size > 0) {
+    sum_U_transpose_ += static_cast<f_t>(solution.i.size()) / input_size;
+  }
@@
-  sum_L_transpose_ += static_cast<f_t>(solution.i.size()) / rhs_size;
+  if (rhs_size > 0) {
+    sum_L_transpose_ += static_cast<f_t>(solution.i.size()) / rhs_size;
+  }
@@
-  sum_L_ += static_cast<f_t>(solution.i.size()) / input_size;
+  if (input_size > 0) {
+    sum_L_ += static_cast<f_t>(solution.i.size()) / input_size;
+  }
@@
-  sum_U_ += static_cast<f_t>(solution.i.size()) / rhs_size;
+  if (rhs_size > 0) {
+    sum_U_ += static_cast<f_t>(solution.i.size()) / rhs_size;
+  }
♻️ Duplicate comments (2)
cpp/src/dual_simplex/basis_updates.cpp (1)

2077-2092: Debug-check fixes look correct.

Using A.m to size B and L0_ in the check blocks resolves the undefined identifiers noted earlier. LGTM.

cpp/src/dual_simplex/solve.cpp (1)

230-259: Reuse across Phase1/Phase2 acknowledged; no change requested.

Reusing ft and lists with initialize_basis_update=false here is intentional per prior review discussion.

If helpful, add a brief comment in code noting that reusing the factorization across problems is by design and refactorization will be forced on numerical issues.

🧹 Nitpick comments (2)
cpp/src/dual_simplex/basis_updates.hpp (2)

281-287: Minor: consider recomputing inverse_row_permutation_ in reset().

If row_permutation_ were externally modified before reset(), recomputing its inverse here would keep invariants local to the type.

 i_t reset()
 {
   clear();
+  inverse_permutation(row_permutation_, inverse_row_permutation_);
   compute_transposes();
   reset_stats();
   return 0;
 }

289-303: Resize should recompute transposes to keep object usable post‑call.

Currently resize() doesn’t call compute_transposes(); subsequent solves relying on L0_transpose_/U0_transpose_ could misbehave if resize() is used stand‑alone. Call compute_transposes() or document that resize() must be followed by refactor_basis().

 void resize(i_t n)
 {
   L0_.resize(n, n, 1);
   U0_.resize(n, n, 1);
   row_permutation_.resize(n);
   inverse_row_permutation_.resize(n);
   S_.resize(n, 0, 0);
   xi_workspace_.resize(2 * n, 0);
   x_workspace_.resize(n, 0.0);
-  U0_transpose_.resize(1, 1, 1);
-  L0_transpose_.resize(1, 1, 1);
+  U0_transpose_.resize(1, 1, 1);
+  L0_transpose_.resize(1, 1, 1);
   clear();
   reset_stats();
+  compute_transposes();
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between deffe68 and f669f64.

📒 Files selected for processing (3)
  • cpp/src/dual_simplex/basis_updates.cpp (2 hunks)
  • cpp/src/dual_simplex/basis_updates.hpp (6 hunks)
  • cpp/src/dual_simplex/solve.cpp (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
cpp/src/dual_simplex/solve.cpp (1)
cpp/src/dual_simplex/phase2.cpp (9)
  • settings (2129-2151)
  • settings (2129-2129)
  • basic_list (2186-2186)
  • dual_phase2 (2174-2204)
  • dual_phase2 (2174-2182)
  • dual_phase2 (2998-3007)
  • dual_phase2_with_advanced_basis (2207-2994)
  • dual_phase2_with_advanced_basis (2207-2219)
  • dual_phase2_with_advanced_basis (3009-3022)
cpp/src/dual_simplex/basis_updates.cpp (2)
cpp/src/dual_simplex/basis_updates.hpp (3)
  • A (384-388)
  • j (148-148)
  • j (407-407)
cpp/src/dual_simplex/basis_solves.cpp (12)
  • factorize_basis (167-594)
  • factorize_basis (167-176)
  • factorize_basis (822-831)
  • basis_repair (597-648)
  • basis_repair (597-603)
  • basis_repair (833-839)
  • form_b (651-680)
  • form_b (651-653)
  • form_b (841-843)
  • reorder_basic_list (29-37)
  • reorder_basic_list (29-29)
  • reorder_basic_list (814-814)
🪛 Clang (14.0.6)
cpp/src/dual_simplex/basis_updates.hpp

[error] 20-20: 'dual_simplex/initial_basis.hpp' file not found

(clang-diagnostic-error)

cpp/src/dual_simplex/basis_updates.cpp

[error] 18-18: 'dual_simplex/basis_solves.hpp' file not found

(clang-diagnostic-error)

🔇 Additional comments (8)
cpp/src/dual_simplex/basis_updates.cpp (2)

2112-2116: Reset after reordering: safe for MPF, confirm intent.

Calling reset() here clears update state and recomputes transposes without any Q state in MPF (no col_permutation_), so it won’t clobber permutations. Please confirm this path won’t be used with basis_update_t (FT), where reset() would reinit Q.


18-21: No action required—includes are properly configured.

All four headers exist at cpp/src/dual_simplex/ and the CMakeLists.txt correctly configures "${CMAKE_CURRENT_SOURCE_DIR}/src" (resolving to cpp/src/) in the include path. The angle-bracket includes will resolve correctly. The static analysis warning is a false positive.

Likely an incorrect or invalid review comment.

cpp/src/dual_simplex/solve.cpp (3)

119-135: Wrapper looks good and aligns with advanced basis flow.

Constructing basis_update_mpf_t once and delegating to solve_linear_program_with_advanced_basis is clean.


137-148: New advanced-basis entrypoint is coherent.

Signature and parameter threading match the rest of the solver stack.


211-224: Correct: initialize_basis_update=true on first advanced Phase 2.

This ensures refactorization/init happens once before updates persist.

cpp/src/dual_simplex/basis_updates.hpp (3)

181-205: Constructor initializes MPF state appropriately.

Reserving workspaces, wiring refactor_frequency_, and calling clear()+reset_stats() are appropriate.


383-389: API surface OK—ensure consistency with implementation.

refactor_basis signature matches the implementation; confirm the header and cpp stay in lock‑step as this evolves.


20-22: No changes required. The include configuration is correct as-is.

The headers initial_basis.hpp and simplex_solver_settings.hpp are internal to the dual_simplex module and do not need to be in the public include set. The build system correctly adds cpp/src as a PRIVATE include directory (cpp/CMakeLists.txt line 266), making <dual_simplex/...> angle-bracket includes work correctly for all internal consumers within that directory. All consumers of basis_updates.hpp are located within cpp/src/dual_simplex/, confirming this is an internal module arrangement. Using angle-bracket includes for internal headers is standard practice.

Likely an incorrect or invalid review comment.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
cpp/src/dual_simplex/solve.hpp (1)

60-72: Consider expanding the API documentation.

The function signature is well-designed and consistent with existing patterns. The persistent basis_update_mpf_t parameter enables the branch-and-bound use case mentioned in the PR objectives.

However, the comment could be more informative for API consumers. Consider documenting:

  • When to use this function vs. solve_linear_program_advanced
  • What "future use" means (e.g., passing basis state to child nodes in branch-and-bound)
  • Whether ft, basic_list, and nonbasic_list should be empty on first call or can be pre-populated

Example expanded documentation:

-// Solve the LP using dual simplex and keep the `basis_update_mpf_t`
-// for future use.
+// Solve the LP using dual simplex and preserve the basis factorization state.
+// This variant persists the basis_update_mpf_t (ft), basic/nonbasic lists,
+// variable status, and edge norms for reuse in subsequent solves (e.g.,
+// passing basis state from parent to child in branch-and-bound).
+// On the first call, ft can be default-constructed and lists can be empty.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f669f64 and 8a06d3e.

📒 Files selected for processing (1)
  • cpp/src/dual_simplex/solve.hpp (2 hunks)
🧰 Additional context used
🪛 Clang (14.0.6)
cpp/src/dual_simplex/solve.hpp

[error] 20-20: 'dual_simplex/basis_updates.hpp' file not found

(clang-diagnostic-error)

🔇 Additional comments (1)
cpp/src/dual_simplex/solve.hpp (1)

20-20: LGTM!

The new include is necessary to support the basis_update_mpf_t type in the new function signature below.

Note: The static analysis error about the file not being found is a false positive—the tool is analyzing this header in isolation without the full project context.

@nguidotti
Copy link
Contributor Author

/ok to test 8a06d3e

Copy link
Contributor

@chris-maes chris-maes left a comment

Choose a reason for hiding this comment

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

LGTM

@nguidotti
Copy link
Contributor Author

/ok to test f3450c7

@nguidotti nguidotti marked this pull request as draft October 24, 2025 16:55
@nguidotti nguidotti marked this pull request as ready for review October 24, 2025 16:55
@nguidotti
Copy link
Contributor Author

/ok to test 63969d2

@nguidotti
Copy link
Contributor Author

/ok to test 0b578ad

@akifcorduk
Copy link
Contributor

/merge

@rapids-bot rapids-bot bot merged commit 0676998 into NVIDIA:main Oct 29, 2025
89 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dual_simplex improvement Improves an existing functionality non-breaking Introduces a non-breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants