-
-
Notifications
You must be signed in to change notification settings - Fork 398
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix adjoint of GenericNonlinearExpr #3724
Conversation
Note sure about this. Here, you could even have a |
Actually, we could also do function Base.real(x::GenericNonlinearExpr{V}) where {V}
return GenericNonlinearExpr{V}(:real, x)
end and support it in the AD |
In view of jump-dev/MathOptInterface.jl#2468, we probably indeed need a way to tell if we have a guarantee that a
In the third case, we should use a We should have a bridge that converts For the user-defined function, we could add a way for the user to say that it's always real (and maybe it should be the default). Whenever the operator is evaluated, we should check that it's indeed real with a type assert probably then. For complex ones, we could have a |
I guess the issue is that Let's ignore |
We probably replied at the same time. I think in the case we can guarantee that the expression is real, we |
The other option is But it's also not obvious what to do for Part of the problem is that we don't have a solver, or an AD system that is capable of I'll check through MOI, but we shouldn't have any users relying on this yet. Here's an email I sent to @ccoffrin in August:
We don't have complex-valued nonlinear expressions, but we have complex values with nonlinear components. We wouldn't support something like |
My only worry is that users might input complex expressions into nonlinear expression and it would lead here to silent bugs with this PR. Unless the AD throws an error later if it encounters complex values ? |
Yes, currently AD errors on things it doesn't understand |
Here's a extension-tests: https://github.com/jump-dev/JuMP.jl/actions/runs/8623134630 |
Yes but other solvers like Convex.jl might not error. We may be passing incorrect (because of methods of this PR) models with complex expressions to a solver assuming it will error of there are complex expressions. I think it would be safer to error in the conversion from the JuMP expression to the MOI function as well |
Do you mean erroring if the input is complex in the You can't create complex nonlinear expressions without manually constructing them: Lines 296 to 334 in 05d4876
|
The check doesn't seem to be always called: julia> model = Model();
julia> @variable(model, x in ComplexPlane())
real(x) + imag(x) im
julia> cos(x)
ERROR: Cannot build `GenericNonlinearExpr` because a term is complex-valued: `(real(x) + imag(x) im)::GenericAffExpr{ComplexF64, VariableRef}`
Stacktrace:
[1] error(s::String)
@ Base ./error.jl:35
[2] _throw_if_not_real(x::GenericAffExpr{ComplexF64, VariableRef})
@ JuMP ~/.julia/dev/JuMP/src/nlp_expr.jl:307
[3] cos(x::GenericAffExpr{ComplexF64, VariableRef})
@ JuMP ~/.julia/dev/JuMP/src/nlp_expr.jl:325
[4] top-level scope
@ REPL[23]:1
julia> x^3
(real(x) + imag(x) im) ^ 3
julia> @constraint(model, x^3 == 1)
((real(x) + imag(x) im) ^ 3.0) - 1.0 = 0 |
Ah. I think you found the one method that has a bug: Lines 210 to 218 in 05d4876
|
You can also still do this: julia> model = Model();
julia> @variable(model, x in ComplexPlane())
real(x) + imag(x) im
julia> GenericNonlinearExpr(:+, x)
+(real(x) + imag(x) im) |
If people are manually constructing expressions then we don't check anything, correct. |
We can add a check right here: Line 95 in 05d4876
for arg in args; _throw_if_not_real(arg); end
|
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #3724 +/- ##
==========================================
- Coverage 98.42% 97.03% -1.40%
==========================================
Files 43 43
Lines 5825 5287 -538
==========================================
- Hits 5733 5130 -603
- Misses 92 157 +65 ☔ View full report in Codecov by Sentry. |
Checking https://github.com/jump-dev/JuMP.jl/actions/runs/8637031676 again before merging |
Closes #3723
So I didn't really think through the implications of this prior.
We kinda punted on the question of whether
ScalarNonlinearFunction
is<:Real
or<:Complex
. But I think it's time to pick<:Real
, and if we need it, we can introduce something like: