Skip to content
Open
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
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ JuMP = "1"
LazyArrays = "1, 2"
MathOptInterface = "1.18"
MathOptSetDistances = "0.2.9"
ParametricOptInterface = "=0.15.1"
ParametricOptInterface = "0.15.2"
julia = "1.6"
9 changes: 9 additions & 0 deletions src/ConicProgram/ConicProgram.jl
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,15 @@ function MOI.supports_constraint(
return false
end

# Disambiguate when T = Float64
function MOI.supports_constraint(
::Model,
::Type{MOI.VectorAffineFunction{Float64}},
::Type{MOI.PositiveSemidefiniteConeSquare},
)
return false
end

function MOI.set(
model::Model,
::MOI.ConstraintPrimalStart,
Expand Down
92 changes: 92 additions & 0 deletions src/bridges.jl
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,98 @@ function MOI.set(
return MOI.set(model, attr, bridge.constraint, mapped_func)
end

"""
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @blegat

_square_offset(s::MOI.AbstractSymmetricMatrixSetSquare)

Number of extra entries before the matrix in a square-form set.
Own implementation to avoid depending on the private
`MOI.Bridges.Constraint._square_offset`.
"""
_square_offset(::MOI.AbstractSymmetricMatrixSetSquare) = 0
_square_offset(::MOI.RootDetConeSquare) = 1
_square_offset(::MOI.LogDetConeSquare) = 2

# Similar to `MOI.set` for `MOI.ConstraintPrimalStart` on `SquareBridge` in
# MathOptInterface/src/Bridges/Constraint/bridges/SquareBridge.jl
function MOI.set(
model::MOI.ModelLike,
attr::DiffOpt.ForwardConstraintFunction,
bridge::MOI.Bridges.Constraint.SquareBridge{T},
func::MOI.VectorAffineFunction{T},
) where {T}
dim = MOI.side_dimension(bridge.square_set)
offset = _square_offset(bridge.square_set)
scalars = MOI.Utilities.eachscalar(func)
tri_scalars =
Vector{eltype(scalars)}(undef, offset + div(dim * (dim + 1), 2))
for i in 1:offset
tri_scalars[i] = scalars[i]
end
k = offset
for j in 1:dim, i in 1:j
k += 1
tri_scalars[k] = scalars[offset+j+(i-1)*dim]
end
MOI.set(
model,
attr,
bridge.triangle,
MOI.Utilities.operate(vcat, T, tri_scalars...),
)
for ((i, j), ci) in bridge.sym
f_ij = scalars[offset+i+(j-1)*dim]
f_ji = scalars[offset+j+(i-1)*dim]
MOI.set(model, attr, ci, MOI.Utilities.operate(-, T, f_ij, f_ji))
end
return
end

# Adjoint of `MOI.set` for `ForwardConstraintFunction` on `SquareBridge` above.
# The forward map extracts upper triangle and sym diffs; this is its transpose.
# Similar structure to `MOI.get` for `MOI.ConstraintPrimal` on `SquareBridge` in
# MathOptInterface/src/Bridges/Constraint/bridges/SquareBridge.jl
function MOI.get(
model::MOI.ModelLike,
attr::DiffOpt.ReverseConstraintFunction,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I followed very closely the MOI code

bridge::MOI.Bridges.Constraint.SquareBridge{T},
) where {T}
tri_func = DiffOpt.standard_form(MOI.get(model, attr, bridge.triangle))
tri = MOI.Utilities.eachscalar(tri_func)
dim = MOI.side_dimension(bridge.square_set)
offset = _square_offset(bridge.square_set)
square = Vector{eltype(tri)}(undef, offset + dim^2)
for i in 1:offset
square[i] = tri[i]
end
k = offset
sym_index = 1
for j in 1:dim, i in 1:j
k += 1
upper_index = offset + i + (j - 1) * dim
lower_index = offset + j + (i - 1) * dim
if i == j
square[upper_index] = tri[k]
elseif sym_index <= length(bridge.sym) &&
bridge.sym[sym_index].first == (i, j)
π = DiffOpt.standard_form(
MOI.get(model, attr, bridge.sym[sym_index].second),
)
square[upper_index] = MOI.Utilities.operate(
+,
T,
MOI.Utilities.operate(+, T, tri[k], tri[k]),
π,
)
square[lower_index] = MOI.Utilities.operate(-, T, π)
sym_index += 1
else
square[upper_index] = tri[k]
square[lower_index] = tri[k]
end
end
return MOI.Utilities.operate(vcat, T, square...)
end

function _variable_to_index_map(bridge)
return Dict{MOI.VariableIndex,MOI.VariableIndex}(
v => MOI.VariableIndex(i) for
Expand Down
20 changes: 20 additions & 0 deletions src/jump_moi_overloads.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# done after the model is optimized, so we add function to bypass the
# dirty state.

# DEPRECATE
function MOI.set(
model::JuMP.Model,
attr::ForwardObjectiveFunction,
Expand All @@ -37,6 +38,7 @@ function MOI.set(
return MOI.set(JuMP.backend(model), attr, allow)
end

# DEPRECATE
function MOI.set(
model::JuMP.Model,
attr::ForwardObjectiveFunction,
Expand All @@ -45,6 +47,7 @@ function MOI.set(
return MOI.set(model, attr, JuMP.AffExpr(func))
end

# DEPRECATE
function MOI.set(
model::JuMP.Model,
attr::ForwardConstraintFunction,
Expand All @@ -55,6 +58,7 @@ function MOI.set(
return MOI.set(model, attr, con_ref, JuMP.moi_function(func))
end

# DEPRECATE
function MOI.set(
model::JuMP.Model,
attr::ForwardConstraintFunction,
Expand All @@ -64,6 +68,7 @@ function MOI.set(
return MOI.set(model, attr, con_ref, JuMP.AffExpr(func))
end

# DEPRECATE - then modify
function MOI.get(
model::JuMP.Model,
attr::ForwardConstraintDual,
Expand All @@ -74,11 +79,13 @@ function MOI.get(
return JuMP.jump_function(model, moi_func)
end

# DEPRECATE - then modify
function MOI.get(model::JuMP.Model, attr::ReverseObjectiveFunction)
func = MOI.get(JuMP.backend(model), attr)
return JuMP.jump_function(model, func)
end

# DEPRECATE - then modify
function MOI.get(
model::JuMP.Model,
attr::ReverseConstraintFunction,
Expand Down Expand Up @@ -106,6 +113,7 @@ function _moi_get_result(model::MOI.Utilities.CachingOptimizer, args...)
return MOI.get(model, args...)
end

# DEPRECATE
function MOI.get(
model::JuMP.Model,
attr::ForwardVariablePrimal,
Expand All @@ -115,6 +123,7 @@ function MOI.get(
return _moi_get_result(JuMP.backend(model), attr, JuMP.index(var_ref))
end

# REVIEW
function MOI.get(
model::JuMP.Model,
attr::ReverseConstraintSet,
Expand All @@ -134,6 +143,9 @@ function MOI.set(
return MOI.set(JuMP.backend(model), attr, JuMP.index(con_ref), set)
end

# there is no set_forward_constraint_set because there is set_forward_parameter

# DEPRECATE
function MOI.set(
model::JuMP.Model,
attr::ForwardConstraintSet,
Expand Down Expand Up @@ -255,6 +267,14 @@ function JuMP.coefficient(func::IndexMappedFunction, vi::MOI.VariableIndex)
return JuMP.coefficient(func.func, func.index_map[vi])
end

function JuMP.coefficient(
func::IndexMappedFunction,
vi::MOI.VariableIndex,
output_index::Int,
)
return JuMP.coefficient(func.func, func.index_map[vi], output_index)
end

function quad_sym_half(
func::IndexMappedFunction,
vi1::MOI.VariableIndex,
Expand Down
Loading
Loading