Skip to content

Fourier-Motzkin presolve - #3191

Open
fwesselm wants to merge 237 commits into
latestfrom
FMPresolve5
Open

Fourier-Motzkin presolve#3191
fwesselm wants to merge 237 commits into
latestfrom
FMPresolve5

Conversation

@fwesselm

@fwesselm fwesselm commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

This PR adds the Fourier-Motzkin presolve reduction as described by Zhang, Y., Ploskas, N. & Sahinidis, N.V. A novel linear optimization presolve technique based on Fourier-Motzkin elimination. Math. Prog. Comp. 18, 345–378 (2026):

  • Currently, impact on MIP solver performance is very small (around 1% slowdown on average). The reduction is enabled in the default settings, which may need to be changed.
  • I made changes to postsolve that allow for adding rows/columns (during presolve).

@codecov

codecov Bot commented Aug 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.55672% with 28 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.20%. Comparing base (b196d7a) to head (915b51d).
⚠️ Report is 3 commits behind head on latest.

Files with missing lines Patch % Lines
highs/presolve/HPresolve.cpp 97.42% 15 Missing ⚠️
highs/presolve/HighsPostsolveStack.cpp 97.88% 6 Missing ⚠️
highs/presolve/HighsPostsolveStack.h 96.72% 6 Missing ⚠️
highs/lp_data/HighsOptions.h 75.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           latest    #3191      +/-   ##
==========================================
+ Coverage   72.77%   73.20%   +0.42%     
==========================================
  Files         444      444              
  Lines      107469   108401     +932     
  Branches    17290    17504     +214     
==========================================
+ Hits        78213    79350    +1137     
+ Misses      28979    28774     -205     
  Partials      277      277              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Opt-Mucca
Opt-Mucca self-requested a review August 3, 2026 14:21

@Opt-Mucca Opt-Mucca left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I've finished my first round of review. I've got the general gist, but I failed completely at some point to keep track of the lambdas and the basis postsolve is brutal...... I'm hoping all my comments are still valid. I'm just going to put down some comments and questions here:

  • The functionality to add rows and columns during presolve is a must. This opens the door for other techniques. Is super cool that you've added it!
  • In general I'm against adding "dead-code" to the repository, and I'd prefer not adding such a large feature if it's not enabled by default.
  • Do you think there's a window of MIP instances where this is super helpful? 1% performance degradation isn't too bad, and I'd still be fine merging it if (1) we're confident that the chance of worst-case performance is near zero (2) it is really helpful for some family of instances we care about
  • Is it helpful for LPs over a general test set? If so then I'd just enable it there by default.

Comment thread highs/presolve/HPresolve.cpp
Comment thread check/TestPresolveRules.cpp
Comment thread highs/presolve/HighsPostsolveStack.h
if (problemSizeReduction() > 0.05) continue;
// check if there were reductions
bool haveReductions = problemSizeReduction() > 0.05;
tryFourierMotzkin = haveReductions || numColsEliminatedFourierMotzkin > 0;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Were there any cases where it found further reductions in a second round?

Comment thread highs/presolve/HPresolve.cpp
Comment thread highs/presolve/HPresolve.cpp
Comment thread highs/presolve/HighsPostsolveStack.cpp Outdated
for (const auto& e : newRowEntries) newRowMark[e.col] = -1;

// remove near-zero entries
newRowEntries.erase(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Does any relaxation need to be done here as opposed to directly removing the coefficient?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good point. I checked the remaining presolve code, and currently coefficients with absolute value less than or equal to options->small_matrix_value are just treated as zero. Therefore, I would like to keep the code as it is right now for the time being. I am open to revisit this in the future.

@jajhall

jajhall commented Aug 4, 2026

Copy link
Copy Markdown
Member
  • Is it helpful for LPs over a general test set? If so then I'd just enable it there by default.

Depending on what LP testing @fwesselm has done, I'll test over a good set of LPs - for both performance and number of iterations after postsolve (which can be a test of correctness for the dual/basis postsolve).

@fwesselm

Copy link
Copy Markdown
Collaborator Author

I have merged latest (including presolve light) into this branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants