Skip to content

Refactor moi_function and jump_function into separate file#4190

Open
odow wants to merge 7 commits into
masterfrom
od/moi-function-2
Open

Refactor moi_function and jump_function into separate file#4190
odow wants to merge 7 commits into
masterfrom
od/moi-function-2

Conversation

@odow

@odow odow commented Jul 1, 2026

Copy link
Copy Markdown
Member

x-ref #4189

We don't necessarily need to merge this. But these functions were spread all over the place. I'll comment in-line on something.

Comment thread src/callbacks.jl
function MOI.submit(model::GenericModel, cb::MOI.UserCut, con::ScalarConstraint)
return MOI.submit(backend(model), cb, moi_function(con.func), con.set)
f = moi_function(model, con.func)
return MOI.submit(backend(model), cb, f, con.set)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

These ones were missing from #4032

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

How did we miss them ? Removing the moi_function method was precisely done to catch them

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We don't have any nonlinear callbacks.

Comment thread src/constraints.jl
check_belongs_to_model(f, model)
return moi_function(f)
end

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

So this is a very weird method. It's not just a fallback. I think the only reason it was needed was because of check_belongs_to_model?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, since we moved to requiring the user to call moi_function, I thought we might as well do check_belongs_to_model there since these two are always called one after the other

Comment thread src/constraints.jl
name::String = "",
)
con = model_convert(model, con)
check_belongs_to_model(con, model)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We just do it explicitly here now instead.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If we're going to call check_belongs_to_model every time we call moi_function (which makes sense), we might as well just call it inside moi_function no ? Since moi_function takes 2 arguments, it makes sense to check that they model is indeed the correct one, doesn't it ?

Comment thread src/jump_moi_function.jl

# A default fallback for backwards compatibility. The first argument `model` was
# introduced in JuMP@1.31.0.
moi_function(model, f) = moi_function(f)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

And now I have a much more sensible fallback.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think the definition should be: The user should always call moi_function(model, f). When you implement, you can either implement moi_function(model, f) (and checking that the model match) or just implement moi_function(f).
To me, it makes sense to check that the model match precisely when we transform the JuMP function to MOI since that's when the variable references are going to be turned into indices (so without the model). Implementing it in two steps 1) check membership and then 2) do a moi_function(f) is one way to do it but they could also just be done together, which is what we do for NonlinearExpr

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We can't do that because that's then a breaking change. People can and have been calling moi_function(f).

@codecov

codecov Bot commented Jul 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.25287% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 99.69%. Comparing base (19eb40e) to head (44f2498).

Files with missing lines Patch % Lines
src/jump_moi_function.jl 94.01% 10 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4190      +/-   ##
==========================================
- Coverage   99.93%   99.69%   -0.24%     
==========================================
  Files          42       43       +1     
  Lines        6305     6307       +2     
==========================================
- Hits         6301     6288      -13     
- Misses          4       19      +15     

☔ 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.

Base automatically changed from od/restore-moi-function to master July 7, 2026 03:15
@odow
odow force-pushed the od/moi-function-2 branch from a5d35f1 to 546c7e5 Compare July 7, 2026 03:17
@odow odow changed the title RFC: Refactor moi_function and jump_function into separate file Refactor moi_function and jump_function into separate file Jul 7, 2026
@odow
odow requested a review from blegat July 7, 2026 03:28
@odow odow mentioned this pull request Jul 8, 2026
14 tasks
Comment thread src/jump_moi_function.jl

# A backwards-compatible function to preserve behavior prior to #4032. This was
# used by Plasmo.jl
function moi_function(f::GenericNonlinearExpr{V}) where {V}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I still think that this should just grab model from the expression graph and then redirect to moi_function(model, f). Having such a subtle behavior (aliases kept or not), depend on whether you call two very similar methods.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

There are trivial examples where the model doesn't exist. NonlinearExpr(:+, Any[0.0])

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Okay, updated.

@odow
odow force-pushed the od/moi-function-2 branch from 615429a to 1453209 Compare July 16, 2026 08:15
@odow

odow commented Jul 17, 2026

Copy link
Copy Markdown
Member Author

Okay @blegat how is this.

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants