From 0c788e49e05a251a9cb0f37b0cc2023b1a34a575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Tue, 15 Aug 2023 14:37:43 +0200 Subject: [PATCH 1/2] [POC] Allow array in nonlinear expressions --- src/nlp_expr.jl | 6 ++++++ test/test_nlp_expr.jl | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/nlp_expr.jl b/src/nlp_expr.jl index 45f3ac3496d..d19db6e898b 100644 --- a/src/nlp_expr.jl +++ b/src/nlp_expr.jl @@ -575,6 +575,8 @@ function moi_function(f::GenericNonlinearExpr{V}) where {V} for i in length(f.args):-1:1 if f.args[i] isa GenericNonlinearExpr{V} push!(stack, (ret, i, f.args[i])) + elseif f.args[i] isa AbstractArray + ret.args[i] = moi_function.(f.args[i]) else ret.args[i] = moi_function(f.args[i]) end @@ -586,6 +588,8 @@ function moi_function(f::GenericNonlinearExpr{V}) where {V} for j in length(arg.args):-1:1 if arg.args[j] isa GenericNonlinearExpr{V} push!(stack, (child, j, arg.args[j])) + elseif arg.args[j] isa AbstractArray + child.args[j] = moi_function.(arg.args[j]) else child.args[j] = moi_function(arg.args[j]) end @@ -611,6 +615,8 @@ function jump_function(model::GenericModel, f::MOI.ScalarNonlinearFunction) for child in reverse(arg.args) push!(stack, (new_ret, child)) end + elseif arg isa AbstractArray + push!(parent.args, jump_function.(model, arg)) else push!(parent.args, jump_function(model, arg)) end diff --git a/test/test_nlp_expr.jl b/test/test_nlp_expr.jl index d854b9348a1..1ae4440087c 100644 --- a/test/test_nlp_expr.jl +++ b/test/test_nlp_expr.jl @@ -6,6 +6,7 @@ module TestNLPExpr using JuMP +using LinearAlgebra using Test import LinearAlgebra @@ -1232,4 +1233,14 @@ function test_extension_euler_to_exp( return end +function test_array() + model = Model() + @variable(model, x) + op_norm = NonlinearOperator(:det, det) + @objective(model, Min, op_norm([x])) + f = MOI.get(model, MOI.ObjectiveFunction{MOI.ScalarNonlinearFunction}()) + @test f.head == :norm + @test f.args == [[index(x)]] +end + end # module From cd3c0ec382b2a63ac15dd07a3ae709b2f6406fdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Sun, 8 Mar 2026 07:25:36 +0100 Subject: [PATCH 2/2] is_real based on type --- src/nlp_expr.jl | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/nlp_expr.jl b/src/nlp_expr.jl index d19db6e898b..e6fe705d7a9 100644 --- a/src/nlp_expr.jl +++ b/src/nlp_expr.jl @@ -330,14 +330,16 @@ Base.isreal(::GenericNonlinearExpr) = true # Univariate operators -_is_real(::Any) = false -_is_real(::Real) = true -_is_real(::AbstractVariableRef) = true -_is_real(::GenericAffExpr{<:Real}) = true -_is_real(::GenericQuadExpr{<:Real}) = true -_is_real(::GenericNonlinearExpr) = true -_is_real(::NonlinearExpression) = true -_is_real(::NonlinearParameter) = true +_is_real(::Type) = false +_is_real(::Type{<:Real}) = true +_is_real(::Type{<:AbstractVariableRef}) = true +_is_real(::Type{<:GenericAffExpr{<:Real}}) = true +_is_real(::Type{<:GenericQuadExpr{<:Real}}) = true +_is_real(::Type{<:GenericNonlinearExpr}) = true +_is_real(::Type{<:NonlinearExpression}) = true +_is_real(::Type{<:NonlinearParameter}) = true +_is_real(::Type{<:AbstractArray{T}}) where {T} = _is_real(T) +_is_real(x) = _is_real(typeof(x)) function _throw_if_not_real(x) if !_is_real(x)