Skip to content
Merged
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
134 changes: 1 addition & 133 deletions src/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ function MOI.is_empty(model::Optimizer)
model.affine_objective_cache === nothing &&
model.quadratic_objective_cache === nothing &&
MOI.is_empty(model.original_objective_cache) &&
isempty(model.quadratic_objective_cache_product) &&
#
isempty(model.vector_affine_constraint_cache) &&
#
Expand Down Expand Up @@ -172,7 +171,6 @@ function MOI.empty!(model::Optimizer{T}) where {T}
model.affine_objective_cache = nothing
model.quadratic_objective_cache = nothing
MOI.empty!(model.original_objective_cache)
empty!(model.quadratic_objective_cache_product)
#
empty!(model.vector_affine_constraint_cache)
#
Expand Down Expand Up @@ -1232,8 +1230,7 @@ function MOI.modify(
chg::Union{MOI.ScalarConstantChange{T},MOI.ScalarCoefficientChange{T}},
) where {F<:MathOptInterface.AbstractScalarFunction,T}
if model.quadratic_objective_cache !== nothing ||
model.affine_objective_cache !== nothing ||
!isempty(model.quadratic_objective_cache_product)
model.affine_objective_cache !== nothing
error(
"A parametric objective cannot be modified as it would conflict with the parameter update mechanism. Please set a new objective or use parameters to perform such updates.",
)
Expand Down Expand Up @@ -1946,128 +1943,6 @@ function MOI.set(
return model.constraints_interpretation = value
end

struct QuadraticObjectiveCoef <: MOI.AbstractModelAttribute end

function _set_quadratic_product_in_obj!(model::Optimizer{T}) where {T}
n = length(model.quadratic_objective_cache_product)

f = if model.affine_objective_cache !== nothing
_current_function(model.affine_objective_cache)
elseif model.quadratic_objective_cache !== nothing
_current_function(model.quadratic_objective_cache)
else
F = MOI.get(model.original_objective_cache, MOI.ObjectiveFunctionType())
MOI.get(model.original_objective_cache, MOI.ObjectiveFunction{F}())
end
F = typeof(f)

quadratic_prods_vector = MOI.ScalarQuadraticTerm{T}[]
sizehint!(quadratic_prods_vector, n)

for ((x, y), fparam) in model.quadratic_objective_cache_product
# x, y = prod_var
evaluated_fparam = _evaluate_parametric_expression(model, fparam)
push!(
quadratic_prods_vector,
MOI.ScalarQuadraticTerm(evaluated_fparam, x, y),
)
end

f_new = if F <: MOI.VariableIndex
MOI.ScalarQuadraticFunction(
quadratic_prods_vector,
MOI.ScalarAffineTerm{T}[MOI.ScalarAffineTerm{T}(1.0, f)],
0.0,
)
elseif F <: MOI.ScalarAffineFunction{T}
MOI.ScalarQuadraticFunction(quadratic_prods_vector, f.terms, f.constant)
elseif F <: MOI.ScalarQuadraticFunction{T}
quadratic_terms = vcat(f.quadratic_terms, quadratic_prods_vector)
MOI.ScalarQuadraticFunction(quadratic_terms, f.affine_terms, f.constant)
end

MOI.set(
model.optimizer,
MOI.ObjectiveFunction{MOI.ScalarQuadraticFunction{T}}(),
f_new,
)

return
end

function _evaluate_parametric_expression(model::Optimizer, p::MOI.VariableIndex)
return model.parameters[p_idx(p)]
end

function _evaluate_parametric_expression(
model::Optimizer,
fparam::MOI.ScalarAffineFunction{T},
) where {T}
constant = fparam.constant
terms = fparam.terms
evaluated_parameter_expression = zero(T)
for term in terms
coef = term.coefficient
p = term.variable
evaluated_parameter_expression += coef * model.parameters[p_idx(p)]
evaluated_parameter_expression += constant
end
return evaluated_parameter_expression
end

function MOI.set(
model::Optimizer,
::QuadraticObjectiveCoef,
(x1, x2)::Tuple{MOI.VariableIndex,MOI.VariableIndex},
::Nothing,
)
if x1.value > x2.value
aux = x1
x1 = x2
x2 = aux
end
delete!(model.quadratic_objective_cache_product, (x1, x2))
model.quadratic_objective_cache_product_changed = true
return
end

function MOI.set(
model::Optimizer,
::QuadraticObjectiveCoef,
(x1, x2)::Tuple{MOI.VariableIndex,MOI.VariableIndex},
f_param::Union{MOI.VariableIndex,MOI.ScalarAffineFunction{T}},
) where {T}
if x1.value > x2.value
aux = x1
x1 = x2
x2 = aux
end
model.quadratic_objective_cache_product[(x1, x2)] = f_param
model.quadratic_objective_cache_product_changed = true
return
end

function MOI.get(
model::Optimizer,
::QuadraticObjectiveCoef,
(x1, x2)::Tuple{MOI.VariableIndex,MOI.VariableIndex},
)
if x1.value > x2.value
aux = x1
x1 = x2
x2 = aux
end
if haskey(model.quadratic_objective_cache_product, (x1, x2))
return model.quadratic_objective_cache_product[(x1, x2)]
else
throw(
ErrorException(
"Parameter not set in product of variables ($x1,$x2)",
),
)
end
end

#
# Optimize
#
Expand All @@ -2076,13 +1951,6 @@ function MOI.optimize!(model::Optimizer)
if !isempty(model.updated_parameters)
update_parameters!(model)
end
if (
!isempty(model.quadratic_objective_cache_product) ||
model.quadratic_objective_cache_product_changed
)
model.quadratic_objective_cache_product_changed = false
_set_quadratic_product_in_obj!(model)
end
MOI.optimize!(model.optimizer)
if MOI.get(model, MOI.DualStatus()) != MOI.NO_SOLUTION &&
model.evaluate_duals
Expand Down
11 changes: 0 additions & 11 deletions src/ParametricOptInterface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,6 @@ mutable struct Optimizer{T,OT<:MOI.ModelLike} <: MOI.AbstractOptimizer
quadratic_objective_cache::Union{Nothing,ParametricQuadraticFunction{T}}
cubic_objective_cache::Union{Nothing,ParametricCubicFunction{T}}
original_objective_cache::MOI.Utilities.ObjectiveContainer{T}
# Store parametric expressions for product of variables
quadratic_objective_cache_product::Dict{
Tuple{MOI.VariableIndex,MOI.VariableIndex},
MOI.AbstractFunction,
}
quadratic_objective_cache_product_changed::Bool

# vector affine function data
# vector_constraint_cache::DoubleDict{Vector{MOI.VectorAffineTerm{T}}}
Expand Down Expand Up @@ -273,11 +267,6 @@ mutable struct Optimizer{T,OT<:MOI.ModelLike} <: MOI.AbstractOptimizer
nothing,
nothing, # cubic_objective_cache
MOI.Utilities.ObjectiveContainer{T}(),
Dict{
Tuple{MOI.VariableIndex,MOI.VariableIndex},
MOI.AbstractFunction,
}(),
false,
# vec affine
# DoubleDict{Vector{MOI.VectorAffineTerm{T}}}(),
DoubleDict{ParametricVectorAffineFunction{T}}(),
Expand Down
77 changes: 0 additions & 77 deletions test/test_JuMP.jl
Original file line number Diff line number Diff line change
Expand Up @@ -964,83 +964,6 @@ function test_jump_direct_soc_parameters()
return
end

function test_jump_direct_qp_objective()
optimizer = POI.Optimizer(Ipopt.Optimizer)
model = direct_model(optimizer)
MOI.set(model, MOI.Silent(), true)
@variable(model, x >= 0)
@variable(model, y >= 0)
@variable(model, p in MOI.Parameter(1.0))
@constraint(model, 2x + y <= 4)
@constraint(model, x + 2y <= 4)
@objective(model, Max, (x^2 + y^2) / 2)
optimize!(model)
@test objective_value(model) ≈ 16 / 9 atol = ATOL
@test value(x) ≈ 4 / 3 atol = ATOL
@test value(y) ≈ 4 / 3 atol = ATOL
MOI.set(
backend(model),
POI.QuadraticObjectiveCoef(),
(index(x), index(y)),
2index(p) + 3,
)
optimize!(model)
@test canonical_compare(
MOI.get(
backend(model),
POI.QuadraticObjectiveCoef(),
(index(x), index(y)),
),
MOI.ScalarAffineFunction{Int64}(
MOI.ScalarAffineTerm{Int64}[MOI.ScalarAffineTerm{Int64}(
2,
MOI.VariableIndex(POI.PARAMETER_INDEX_THRESHOLD + 1),
)],
3,
),
)
@test objective_value(model) ≈ 32 / 3 atol = ATOL
@test value(x) ≈ 4 / 3 atol = ATOL
@test value(y) ≈ 4 / 3 atol = ATOL
MOI.set(model, POI.ParameterValue(), p, 2.0)
optimize!(model)
@test objective_value(model) ≈ 128 / 9 atol = ATOL
@test value(x) ≈ 4 / 3 atol = ATOL
@test value(y) ≈ 4 / 3 atol = ATOL
MOI.set(
backend(model),
POI.QuadraticObjectiveCoef(),
(index(x), index(y)),
nothing,
)
optimize!(model)
@test objective_value(model) ≈ 16 / 9 atol = ATOL
@test value(x) ≈ 4 / 3 atol = ATOL
@test value(y) ≈ 4 / 3 atol = ATOL
# now in reverse order
MOI.set(
backend(model),
POI.QuadraticObjectiveCoef(),
(index(y), index(x)),
2index(p) + 3,
)
optimize!(model)
@test objective_value(model) ≈ 128 / 9 atol = ATOL
@test value(x) ≈ 4 / 3 atol = ATOL
@test value(y) ≈ 4 / 3 atol = ATOL
MOI.set(
backend(model),
POI.QuadraticObjectiveCoef(),
(index(y), index(x)),
nothing,
)
optimize!(model)
@test objective_value(model) ≈ 16 / 9 atol = ATOL
@test value(x) ≈ 4 / 3 atol = ATOL
@test value(y) ≈ 4 / 3 atol = ATOL
return
end

function test_jump_direct_rsoc_constraints()
"""
Problem RSOC
Expand Down
Loading
Loading