Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/JuMP.jl
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ mutable struct GenericModel{T<:Real} <: AbstractModel
enable_macro_timing::Bool
macro_times::Dict{Tuple{LineNumberNode,String},Float64}
# A cache to track common subexpressions based on their `objectid`.
subexpressions::Dict{UInt64,MOI.ScalarNonlinearFunction}
subexpressions::Base.IdDict{Any,MOI.ScalarNonlinearFunction}
end

value_type(::Type{GenericModel{T}}) where {T} = T
Expand Down Expand Up @@ -278,7 +278,7 @@ function direct_generic_model(
Dict{Any,MOI.ConstraintIndex}(),
false,
Dict{Tuple{LineNumberNode,String},Float64}(),
Dict{UInt64,MOI.ScalarNonlinearFunction}(),
Base.IdDict{Any,MOI.ScalarNonlinearFunction}(),
)
end

Expand Down
20 changes: 9 additions & 11 deletions src/jump_moi_function.jl
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,9 @@ end
moi_function_type(::Type{<:GenericNonlinearExpr}) = MOI.ScalarNonlinearFunction

function moi_function(model::GenericModel, f::GenericNonlinearExpr{V}) where {V}
# key = objectid(f)
# if haskey(model.subexpressions, key)
# return model.subexpressions[key]
# end
if (subexpression = get(model.subexpressions, f, nothing)) !== nothing
return subexpression
end
ret = MOI.ScalarNonlinearFunction(f.head, similar(f.args))
stack = Tuple{MOI.ScalarNonlinearFunction,Int,GenericNonlinearExpr{V}}[]
for i in length(f.args):-1:1
Expand All @@ -182,11 +181,10 @@ function moi_function(model::GenericModel, f::GenericNonlinearExpr{V}) where {V}
end
while !isempty(stack)
parent, i, arg = pop!(stack)
# arg_key = objectid(arg)
# if haskey(model.subexpressions, arg_key)
# parent.args[i] = model.subexpressions[arg_key]
# continue
# end
if (subexpression = get(model.subexpressions, arg, nothing)) !== nothing
parent.args[i] = subexpression
continue
end
child = MOI.ScalarNonlinearFunction(arg.head, similar(arg.args))
parent.args[i] = child
for j in length(arg.args):-1:1
Expand All @@ -196,9 +194,9 @@ function moi_function(model::GenericModel, f::GenericNonlinearExpr{V}) where {V}
child.args[j] = moi_function(model, arg.args[j])
end
end
# model.subexpressions[arg_key] = child
model.subexpressions[arg] = child
end
# model.subexpressions[key] = ret
model.subexpressions[f] = ret
return ret
end

Expand Down
75 changes: 43 additions & 32 deletions test/test_nlp_expr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1390,38 +1390,38 @@ function test_custom_array()
return
end

# function test_scalar_nonlinear_moi_function()
# model = Model()
# @variable(model, x)
# y1 = atan(x, 2)
# y1_moi = MOI.ScalarNonlinearFunction(:atan, Any[index(x), 2])
# y2 = y1 + y1
# y2_moi = MOI.ScalarNonlinearFunction(:+, Any[y1_moi, y1_moi])
# y3 = exp(y2)
# y3_moi = MOI.ScalarNonlinearFunction(:exp, Any[y2_moi])
# # Test y1
# @test isapprox(moi_function(y1), y1_moi)
# @test length(model.subexpressions) == 1
# @test isapprox(moi_function(model, y1), y1_moi)
# @test length(model.subexpressions) == 1
# @test isapprox(model.subexpressions[objectid(y1)], y1_moi)
# # Test y2
# @test isapprox(moi_function(y2), y2_moi)
# @test length(model.subexpressions) == 2
# @test isapprox(moi_function(model, y2), y2_moi)
# @test length(model.subexpressions) == 2
# @test isapprox(model.subexpressions[objectid(y1)], y1_moi)
# @test isapprox(model.subexpressions[objectid(y2)], y2_moi)
# # Test y3
# @test isapprox(moi_function(y3), y3_moi)
# @test length(model.subexpressions) == 3
# @test isapprox(moi_function(model, y3), y3_moi)
# @test length(model.subexpressions) == 3
# @test isapprox(model.subexpressions[objectid(y1)], y1_moi)
# @test isapprox(model.subexpressions[objectid(y2)], y2_moi)
# @test isapprox(model.subexpressions[objectid(y3)], y3_moi)
# return
# end
function test_scalar_nonlinear_moi_function()
model = Model()
@variable(model, x)
y1 = atan(x, 2)
y1_moi = MOI.ScalarNonlinearFunction(:atan, Any[index(x), 2])
y2 = y1 + y1
y2_moi = MOI.ScalarNonlinearFunction(:+, Any[y1_moi, y1_moi])
y3 = exp(y2)
y3_moi = MOI.ScalarNonlinearFunction(:exp, Any[y2_moi])
# Test y1
@test isapprox(moi_function(y1), y1_moi)
@test length(model.subexpressions) == 1
@test isapprox(moi_function(model, y1), y1_moi)
@test length(model.subexpressions) == 1
@test isapprox(model.subexpressions[y1], y1_moi)
# Test y2
@test isapprox(moi_function(y2), y2_moi)
@test length(model.subexpressions) == 2
@test isapprox(moi_function(model, y2), y2_moi)
@test length(model.subexpressions) == 2
@test isapprox(model.subexpressions[y1], y1_moi)
@test isapprox(model.subexpressions[y2], y2_moi)
# Test y3
@test isapprox(moi_function(y3), y3_moi)
@test length(model.subexpressions) == 3
@test isapprox(moi_function(model, y3), y3_moi)
@test length(model.subexpressions) == 3
@test isapprox(model.subexpressions[y1], y1_moi)
@test isapprox(model.subexpressions[y2], y2_moi)
@test isapprox(model.subexpressions[y3], y3_moi)
return
end

function test_addition_with_zero_Base_sum()
model = Model()
Expand Down Expand Up @@ -1482,4 +1482,15 @@ function test_extension_expression_bedmas_parentheses(
return
end

function test_issue_4203()
n = 25_000
model = Model()
@variable(model, x)
@constraint(model, cons[i in 1:n], sin(x) * i <= 0)
@testset "$i" for i in 1:n
@test isequal_canonical(constraint_object(cons[i]).func, sin(x) * i - 0)
end
return
end

end # module
Loading