Skip to content

Adds support for VectorQuadraticFunction #179

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: jg/newdo
Choose a base branch
from
Open
73 changes: 73 additions & 0 deletions src/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,22 @@ function _has_parameters(f::MOI.ScalarQuadraticFunction{T}) where {T}
return false
end

function _has_parameters(f::MOI.VectorQuadraticFunction)
# quadratic part
for qt in f.quadratic_terms
if _is_parameter(qt.scalar_term.variable_1) || _is_parameter(qt.scalar_term.variable_2)
return true
end
end
# affine part
for at in f.affine_terms
if _is_parameter(at.scalar_term.variable)
return true
end
end
return false
end

function _cache_multiplicative_params!(
model::Optimizer{T},
f::ParametricQuadraticFunction{T},
Expand All @@ -65,6 +81,21 @@ function _cache_multiplicative_params!(
return
end

function _cache_multiplicative_params!(
model::Optimizer{T},
f::ParametricVectorQuadraticFunction{T},
) where {T}
for term in f.pv
push!(model.multiplicative_parameters_pv,
term.scalar_term.variable_1.value)
end
for term in f.pp
push!(model.multiplicative_parameters_pp, term.scalar_term.variable_1.value)
push!(model.multiplicative_parameters_pp, term.scalar_term.variable_2.value)
end
return
end

#
# Empty
#
Expand Down Expand Up @@ -858,6 +889,41 @@ function MOI.add_constraint(
end
end

function _is_vector_affine(f::MOI.VectorQuadraticFunction{T}) where {T}
return isempty(f.quadratic_terms)
end

function _is_vector_affine(::MOI.VectorAffineFunction{T}) where {T}
return true # VectorAffineFunction is always affine
end

function _add_constraint_with_parameters_on_function(
model::Optimizer,
f::MOI.VectorQuadraticFunction{T},
set::S,
) where {T,S}
# Create parametric vector quadratic function
pf = ParametricVectorQuadraticFunction(f)
_cache_multiplicative_params!(model, pf)
_update_cache!(pf, model)

# Get the current function after parameter substitution
current_func = _current_function(pf)
# TODO: XXXXX STOPED HERE
end

function MOI.add_constraint(
model::Optimizer,
f::MOI.VectorQuadraticFunction{T},
set::MOI.AbstractVectorSet,
) where {T}
if !_has_parameters(f)
return _add_constraint_direct_and_cache_map!(model, f, set)
else
return _add_constraint_with_parameters_on_function(model, f, set)
end
end

function MOI.delete(
model::Optimizer,
c::MOI.ConstraintIndex{F,S},
Expand Down Expand Up @@ -1411,6 +1477,13 @@ function MOI.get(
return model.quadratic_constraint_cache[F, S]
end

function MOI.get(
model::Optimizer,
::DictOfParametricConstraintIndicesAndFunctions{F,S,P},
) where {F,S,P<:ParametricVectorQuadraticFunction}
return model.vector_quadratic_constraint_cache[F, S]
end

"""
NumberOfPureVariables

Expand Down
3 changes: 3 additions & 0 deletions src/ParametricOptInterface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ mutable struct Optimizer{T,OT<:MOI.ModelLike} <: MOI.AbstractOptimizer
quadratic_constraint_cache::DoubleDict{ParametricQuadraticFunction{T}}
# Store original constraint set (inner key)
quadratic_constraint_cache_set::DoubleDict{MOI.AbstractScalarSet}
# Vector quadratic function data
vector_quadratic_constraint_cache::DoubleDict{ParametricVectorQuadraticFunction{T}}

# objective function data
# Clever cache of data (at most one can be !== nothing)
Expand Down Expand Up @@ -209,6 +211,7 @@ mutable struct Optimizer{T,OT<:MOI.ModelLike} <: MOI.AbstractOptimizer
DoubleDict{MOI.ConstraintIndex}(),
DoubleDict{ParametricQuadraticFunction{T}}(),
DoubleDict{MOI.AbstractScalarSet}(),
DoubleDict{ParametricVectorQuadraticFunction{T}}(),
# objective
nothing,
nothing,
Expand Down
31 changes: 31 additions & 0 deletions src/duals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ function _compute_dual_of_parameters!(model::Optimizer{T}) where {T}
_update_duals_from_affine_constraints!(model)
_update_duals_from_vector_affine_constraints!(model)
_update_duals_from_quadratic_constraints!(model)
_update_duals_from_vector_quadratic_constraints!(model)
if model.affine_objective_cache !== nothing
_update_duals_from_objective!(model, model.affine_objective_cache)
end
Expand Down Expand Up @@ -174,3 +175,33 @@ function _is_additive(model::Optimizer, cp::MOI.ConstraintIndex)
end
return true
end

function _update_duals_from_vector_quadratic_constraints!(model::Optimizer)
for (F, S) in keys(model.vector_quadratic_constraint_cache.dict)
vector_quadratic_constraint_cache_inner = model.vector_quadratic_constraint_cache[F, S]
_compute_parameters_in_ci!(model, vector_quadratic_constraint_cache_inner)
end
return
end

function _compute_parameters_in_ci!(
model::Optimizer{T},
pf::ParametricVectorQuadraticFunction{T},
ci::MOI.ConstraintIndex{F,S},
) where {F,S,T}
cons_dual = MOI.get(model.optimizer, MOI.ConstraintDual(), ci)
for term in pf.p
model.dual_value_of_parameters[p_val(term.scalar_term.variable)] -=
cons_dual[term.output_index] * term.scalar_term.coefficient
end
for term in pf.pp
coef = ifelse(term.scalar_term.variable_1 == term.scalar_term.variable_2, T(1 // 2), T(1))
model.dual_value_of_parameters[p_val(term.scalar_term.variable_1)] -=
coef * cons_dual[term.output_index] * term.scalar_term.coefficient *
MOI.get(model, ParameterValue(), term.scalar_term.variable_2)
model.dual_value_of_parameters[p_val(term.scalar_term.variable_2)] -=
coef * cons_dual[term.output_index] * term.scalar_term.coefficient *
MOI.get(model, ParameterValue(), term.scalar_term.variable_1)
end
return
end
Loading