Skip to content
Merged
1 change: 1 addition & 0 deletions .vale.ini
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ BasedOnStyles = Vale, Google

# TODO(odow): fix all of these
Google.Ellipses = OFF
Google.EmDash = OF
Google.Exclamation = OFF
Google.FirstPerson = OFF
Google.OptionalPlurals = OFF
Expand Down
3 changes: 3 additions & 0 deletions src/JuMP.jl
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ mutable struct GenericModel{T<:Real} <: AbstractModel
# A dictionary to store timing information from the JuMP macros.
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}
end

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

Expand Down
19 changes: 17 additions & 2 deletions src/constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,10 @@ function moi_function(constraint::AbstractConstraint)
return moi_function(jump_function(constraint))
end

function moi_function(model, constraint::AbstractConstraint)
return moi_function(model, jump_function(constraint))
end

"""
moi_set(constraint::AbstractConstraint)

Expand Down Expand Up @@ -1028,6 +1032,18 @@ function _moi_add_constraint(
return MOI.add_constraint(model, f, s)
end

function check_belongs_to_model(f::Vector, model)
for func in f
check_belongs_to_model(func, model)
end
return
end

function moi_function(model, f)
check_belongs_to_model(f, model)
return moi_function(f)
end

"""
add_constraint(
model::GenericModel,
Expand All @@ -1044,10 +1060,9 @@ function add_constraint(
name::String = "",
)
con = model_convert(model, con)
func, set = moi_function(model, con), moi_set(con)
# The type of backend(model) is unknown so we directly redirect to another
# function.
check_belongs_to_model(con, model)
func, set = moi_function(con), moi_set(con)
cindex = _moi_add_constraint(
backend(model),
func,
Expand Down
25 changes: 20 additions & 5 deletions src/nlp_expr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -596,18 +596,29 @@ moi_function(x::Number) = x
# `moi_function(AbstractArray{<:AbstractVariableRef})`
moi_function(x::AbstractArray) = moi_function.(x)

function moi_function(f::GenericNonlinearExpr{V}) where {V}
function moi_function(model::GenericModel, f::GenericNonlinearExpr{V}) where {V}
key = objectid(f)
if haskey(model.subexpressions, key)
return model.subexpressions[key]
end
ret = MOI.ScalarNonlinearFunction(f.head, similar(f.args))
stack = Tuple{MOI.ScalarNonlinearFunction,Int,GenericNonlinearExpr{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 AbstractJuMPScalar
ret.args[i] = moi_function(model, f.args[i])
else
ret.args[i] = moi_function(f.args[i])
end
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
child = MOI.ScalarNonlinearFunction(arg.head, similar(arg.args))
parent.args[i] = child
for j in length(arg.args):-1:1
Expand All @@ -617,7 +628,9 @@ function moi_function(f::GenericNonlinearExpr{V}) where {V}
child.args[j] = moi_function(arg.args[j])
end
end
model.subexpressions[arg_key] = child
end
model.subexpressions[key] = ret
return ret
end

Expand Down Expand Up @@ -1239,7 +1252,8 @@ function moi_function(f::AbstractVector{<:GenericNonlinearExpr})
end

function MOI.VectorNonlinearFunction(f::Vector{<:AbstractJuMPScalar})
return MOI.VectorNonlinearFunction(map(moi_function, f))
model = owner_model(first(f))
return MOI.VectorNonlinearFunction(moi_function.(model, f))
end

"""
Expand Down Expand Up @@ -1285,7 +1299,7 @@ x
```
"""
function simplify(model::GenericModel, f::AbstractJuMPScalar)
g = MOI.Nonlinear.SymbolicAD.simplify(moi_function(f))
g = MOI.Nonlinear.SymbolicAD.simplify(moi_function(model, f))
return jump_function(model, g)
end

Expand Down Expand Up @@ -1336,7 +1350,8 @@ function derivative(
f::AbstractJuMPScalar,
x::GenericVariableRef{T},
) where {T}
df_dx = MOI.Nonlinear.SymbolicAD.derivative(moi_function(f), index(x))
df_dx =
MOI.Nonlinear.SymbolicAD.derivative(moi_function(model, f), index(x))
return jump_function(model, MOI.Nonlinear.SymbolicAD.simplify!(df_dx))
end

Expand Down Expand Up @@ -1381,7 +1396,7 @@ julia> ∇f[y]
```
"""
function gradient(model::GenericModel{T}, f::AbstractJuMPScalar) where {T}
g = moi_function(f)
g = moi_function(model, f)
∇f = Dict{GenericVariableRef{T},Any}()
for xi in MOI.Nonlinear.SymbolicAD.variables(g)
df_dx = MOI.Nonlinear.SymbolicAD.simplify!(
Expand Down
4 changes: 2 additions & 2 deletions src/objective.jl
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ end

function set_objective_function(model::GenericModel, func::AbstractJuMPScalar)
check_belongs_to_model(func, model)
set_objective_function(model, moi_function(func))
set_objective_function(model, moi_function(model, func))
return
end

Expand All @@ -299,7 +299,7 @@ function set_objective_function(
for f in func
check_belongs_to_model(f, model)
end
set_objective_function(model, moi_function(func))
set_objective_function(model, moi_function(model, func))
return
end

Expand Down
Loading
Loading