Jump.jl: Feature request: implement getindex for expressions

Created on 9 Nov 2020  路  4Comments  路  Source: jump-dev/JuMP.jl

I would like to access the objective coefficients yet it just possible to access the function as an expression.
My solution would be:

"""
    objective_coefficient(model::Model, variable::VariableRef)

Return the coefficient associated with `variable` in the objective function. See
also [`set_objective_coefficient`](@ref).

Note: this function will throw an error if a nonlinear objective is set.
"""
function objective_coefficient(model::Model, variable::VariableRef)
    return get(objective_function(model).terms, variable, 0.0)
end

Yet, I have no idea how quadratic objective functions should be handled and what to do if someone tries the following

model_1 = Model()
@variable(model_1, x >= 0)
@objective(model_1, Min, x)
model_2 = Model()
@variable(model_2, y >= 0)
@objective(model_2, Min, y)

objective_coefficient(model_1, y)
feature request good first issue help wanted

Most helpful comment

I agree with @mlubin. We already provide objective_function, and the returned data-structure is pretty transparent.

What we could implement are getindex methods along the likes of;

function Base.getindex(ex::GenericAffExpr{V, K}, x::K) where {K, V}
    return get(ex.terms, x, zero(V))
end

That would permit

model = Model()
@variable(model, x)
@variable(model, y)
@objective(model, Min, x)
obj = objective_function(model)
obj[x]  # 1.0
obj[y]  # 0.0
@objective(model, Min, x^2 + x * y + x)
obj = objective_function(model)
obj[x, x]  # 1.0
obj[x, y]  # 1.0  # What about obj[y, x]?
obj[y, y]  # 0.0
obj[x]  # 1.0
obj[y]  # 0.0

All 4 comments

This is already a one-liner (as you show above), and the proposed version is slow inside a loop because objective_function(model) may be expensive. I'm not really seeing the benefit of adding this to JuMP.

I'm not really seeing the benefit of adding this to JuMP.

Actually, when I needed this function I was sure I would find it in JuMP. With CPLEX.jl there is CPLEX.get_obj(model::CPLEX.Model), which returns a vector of coefficients.

I'd say that objective_function(model) is the analogue of CPLEX.get_obj. It returns a data structure that represents the objective function. The proposed implementation of objective_coefficient is not a clear win because objective_coefficient.(model, all_variables(model)) could be O(N^2).

I agree with @mlubin. We already provide objective_function, and the returned data-structure is pretty transparent.

What we could implement are getindex methods along the likes of;

function Base.getindex(ex::GenericAffExpr{V, K}, x::K) where {K, V}
    return get(ex.terms, x, zero(V))
end

That would permit

model = Model()
@variable(model, x)
@variable(model, y)
@objective(model, Min, x)
obj = objective_function(model)
obj[x]  # 1.0
obj[y]  # 0.0
@objective(model, Min, x^2 + x * y + x)
obj = objective_function(model)
obj[x, x]  # 1.0
obj[x, y]  # 1.0  # What about obj[y, x]?
obj[y, y]  # 0.0
obj[x]  # 1.0
obj[y]  # 0.0
Was this page helpful?
0 / 5 - 0 ratings